[Nouveau] [Bug 90888] A trivial fix for a potential crash
https://bugs.freedesktop.org/show_bug.cgi?id=90888 --- Comment #1 from Ilia Mirkin imir...@alum.mit.edu --- Great patch. Please mail it out to nouveau@lists.freedesktop.org, these things are usually just done over email when there's no real bug to keep track of. One small thing is I normally use nv50/ir prefix when modifying stuff in codegen. I'm away from computers where I can check this out for another week or so, but I'll be able to take a detailed look then. [And your other bug too.] -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 90888] New: A trivial fix for a potential crash
https://bugs.freedesktop.org/show_bug.cgi?id=90888 Bug ID: 90888 Summary: A trivial fix for a potential crash Product: Mesa Version: git Hardware: All OS: All Status: NEW Severity: trivial Priority: medium Component: Drivers/DRI/nouveau Assignee: nouveau@lists.freedesktop.org Reporter: j...@online.de QA Contact: nouveau@lists.freedesktop.org Created attachment 116340 -- https://bugs.freedesktop.org/attachment.cgi?id=116340action=edit Candidate patch OP_JOIN are static casted to FlowInstruction, but handleTXL creates OP_JOIN that is no FlowInstruction. It probably doesn't matter outside debug builds, since only the IR printer seems to access the additional FlowInstruction fields. -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 90887] PhiMovesPass in register allocator broken
https://bugs.freedesktop.org/show_bug.cgi?id=90887 --- Comment #3 from Ilia Mirkin imir...@alum.mit.edu --- Gah! The inbound edge ordering having to be the same as in phi nodes has bit me before as well. I wonder if it wouldn't be simpler to just fix that, i.e. make phi nodes attach a bb reference to each argument. In any case, I'll be able to take a closer look in a week or so. Great detective work btw. FTR, nva5 should be able to allow manual reclocking on kernel 3.19+ (if you add nouveau.pstate=1), which should help decrease some of the perf difference wrt blob. Also, bug 90347 is completely different... that findFirstUse stuff is pretty dodgy in the first place, and it happens post-RA. (And only on kepler+) -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 90887] PhiMovesPass in register allocator broken
https://bugs.freedesktop.org/show_bug.cgi?id=90887 --- Comment #1 from jr j...@online.de --- This is the minified shader I did the debugging with. translating program of type 4 FRAG DCL IN[0], GENERIC[9], PERSPECTIVE DCL OUT[0], COLOR DCL SAMP[0] DCL TEMP[0..2], LOCAL IMM[0] FLT32 {0., 1.9632, 0.8750, 0.} 0: MOV TEMP[0].xy, IN[0].xyyy 1: MOV TEMP[0].w, IMM[0]. 2: TXL TEMP[0].xyz, TEMP[0], SAMP[0], 2D 3: MOV TEMP[1].xyz, TEMP[0].xyzx 4: MAD TEMP[0].x, TEMP[0]., IMM[0]., TEMP[0]. 5: FSLT TEMP[0].x, TEMP[0]., IMM[0]. 6: UIF TEMP[0]. :0 7: MOV TEMP[0].xy, TEMP[2].xyyy 8: MOV TEMP[0].w, TEMP[2]. 9: TXL TEMP[0].xyz, TEMP[0], SAMP[0], 2D 10: MOV TEMP[1].xyz, TEMP[0].zyxz 11: ENDIF 12: MOV TEMP[0].xyz, TEMP[1].xyzx 13: MOV TEMP[0].w, IMM[0]. 14: MOV OUT[0], TEMP[0] 15: END -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 19/20] sw/nv50: add some private functions to factorize code
These functions will be also used by the interface for controlling performance counters. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/nvkm/engine/sw/nv50.c | 56 ++- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/drm/nouveau/nvkm/engine/sw/nv50.c b/drm/nouveau/nvkm/engine/sw/nv50.c index 401fcd7..b7c0227 100644 --- a/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drm/nouveau/nvkm/engine/sw/nv50.c @@ -36,27 +36,58 @@ **/ static int -nv50_sw_mthd_dma_vblsem(struct nvkm_object *object, u32 mthd, - void *args, u32 size) +nv50_priv_ctxdma_get(struct nv50_sw_chan *chan, u32 name, u32 *ctxdma) { - struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); struct nvkm_fifo_chan *fifo = (void *)nv_object(chan)-parent; struct nvkm_handle *handle; int ret = -EINVAL; - handle = nvkm_namedb_get(nv_namedb(fifo), *(u32 *)args); + handle = nvkm_namedb_get(nv_namedb(fifo), name); if (!handle) return -ENOENT; if (nv_iclass(handle-object, NV_GPUOBJ_CLASS)) { struct nvkm_gpuobj *gpuobj = nv_gpuobj(handle-object); - chan-vblank.ctxdma = gpuobj-node-offset 4; + *ctxdma = gpuobj-node-offset 4; ret = 0; } nvkm_namedb_put(handle); return ret; } +static void +nv50_priv_ctxdma_flush(struct nv50_sw_chan *chan, u32 channel, u32 ctxdma) +{ + struct nv50_sw_priv *priv = (void *)nv_object(chan)-engine; + struct nvkm_bar *bar = nvkm_bar(priv); + + nv_wr32(priv, 0x001704, channel); + nv_wr32(priv, 0x001710, 0x8000 | ctxdma); + bar-flush(bar); +} + +static void +nv50_priv_ctxdma_wr32(struct nv50_sw_chan *chan, u64 offset, u32 value) +{ + struct nv50_sw_priv *priv = (void *)nv_object(chan)-engine; + + if (nv_device(priv)-chipset == 0x50) { + nv_wr32(priv, 0x001570, offset); + nv_wr32(priv, 0x001574, value); + } else { + nv_wr32(priv, 0x060010, offset); + nv_wr32(priv, 0x060014, value); + } +} + +static int +nv50_sw_mthd_dma_vblsem(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + return nv50_priv_ctxdma_get(chan, *(u32 *)args, chan-vblank.ctxdma); +} + static int nv50_sw_mthd_vblsem_offset(struct nvkm_object *object, u32 mthd, void *args, u32 size) @@ -122,20 +153,9 @@ nv50_sw_vblsem_release(struct nvkm_notify *notify) { struct nv50_sw_chan *chan = container_of(notify, typeof(*chan), vblank.notify[notify-index]); - struct nv50_sw_priv *priv = (void *)nv_object(chan)-engine; - struct nvkm_bar *bar = nvkm_bar(priv); - - nv_wr32(priv, 0x001704, chan-vblank.channel); - nv_wr32(priv, 0x001710, 0x8000 | chan-vblank.ctxdma); - bar-flush(bar); - if (nv_device(priv)-chipset == 0x50) { - nv_wr32(priv, 0x001570, chan-vblank.offset); - nv_wr32(priv, 0x001574, chan-vblank.value); - } else { - nv_wr32(priv, 0x060010, chan-vblank.offset); - nv_wr32(priv, 0x060014, chan-vblank.value); - } + nv50_priv_ctxdma_flush(chan, chan-vblank.channel, chan-vblank.ctxdma); + nv50_priv_ctxdma_wr32(chan, chan-vblank.offset, chan-vblank.value); return NVKM_NOTIFY_DROP; } -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 09/20] pm: change signal iter to u16
16 bits is large enough to store the maximum number of signals available for one domain (i.e. 256). Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- bin/nv_perfmon.c | 4 ++-- drm/nouveau/include/nvif/class.h | 7 --- drm/nouveau/nvkm/engine/pm/base.c | 10 +- drm/nouveau/nvkm/engine/pm/priv.h | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c index 958520e..043d864 100644 --- a/bin/nv_perfmon.c +++ b/bin/nv_perfmon.c @@ -289,7 +289,7 @@ ui_perfmon_query_signals(struct nvif_object *perfmon, args.domain = dom-id; do { - u32 prev_iter = args.iter; + u16 prev_iter = args.iter; args.name[0] = '\0'; ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_SIGNAL, @@ -308,7 +308,7 @@ ui_perfmon_query_signals(struct nvif_object *perfmon, args, sizeof(args)); assert(ret == 0); } - } while (args.iter != 0x); + } while (args.iter != 0x); } static void diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index cf2af89..871247c 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -259,14 +259,15 @@ struct nvif_perfmon_query_domain_v0 { __u8 id; __u8 counter_nr; __u8 iter; - __u32 signal_nr; + __u16 signal_nr; + __u8 pad05[2]; }; struct nvif_perfmon_query_signal_v0 { __u8 version; __u8 domain; - __u8 pad02[2]; - __u32 iter; + __u16 iter; + __u8 pad03[4]; char name[64]; }; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index d61beff..fab0598 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -45,10 +45,10 @@ nvkm_pm_count_perfdom(struct nvkm_pm *ppm) return domain_nr; } -static u32 +static u16 nvkm_perfdom_count_perfsig(struct nvkm_perfdom *dom) { - u32 signal_nr = 0; + u16 signal_nr = 0; int i; if (dom) { @@ -183,9 +183,9 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) nv_ioctl(object, perfmon query signal size %d\n, size); if (nvif_unpack(args-v0, 0, 0, false)) { nv_ioctl(object, -perfmon query signal vers %d dom %d iter %08x\n, +perfmon query signal vers %d dom %d iter %04x\n, args-v0.version, args-v0.domain, args-v0.iter); - si = (args-v0.iter 0x) - 1; + si = (args-v0.iter 0x) - 1; } else return ret; @@ -209,7 +209,7 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) } } - args-v0.iter = 0x; + args-v0.iter = 0x; return 0; } diff --git a/drm/nouveau/nvkm/engine/pm/priv.h b/drm/nouveau/nvkm/engine/pm/priv.h index 06a6e60..71667fc 100644 --- a/drm/nouveau/nvkm/engine/pm/priv.h +++ b/drm/nouveau/nvkm/engine/pm/priv.h @@ -44,7 +44,7 @@ struct nvkm_perfdom { char name[32]; u32 addr; u8 quad; - u32 signal_nr; + u16 signal_nr; struct nvkm_perfsig signal[]; }; -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 17/20] pm: allow the userspace to configure sources
Signed-off-by: Samuel Pitoiset samuel.pitoiset at gmail.com --- drm/nouveau/include/nvif/class.h | 1 + drm/nouveau/nvkm/engine/pm/base.c | 102 ++ drm/nouveau/nvkm/engine/pm/priv.h | 2 + 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index 1a76a7f..3b7f49f 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -297,6 +297,7 @@ struct nvif_perfdom_v0 { __u8 pad03[1]; struct { __u8 signal[4]; + __u64 source[4][8]; __u16 logic_op; } ctr[4]; }; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 8960bf4..a4bb6fe 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -125,6 +125,66 @@ nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si) return NULL; } +static int +nvkm_perfsrc_enable(struct nvkm_pm *ppm, struct nvkm_perfctr *ctr) +{ + struct nvkm_perfdom *dom = NULL; + struct nvkm_perfsig *sig; + struct nvkm_perfsrc *src; + u32 mask, value; + int i, j; + + for (i = 0; i 4 ctr-signal[i]; i++) { + for (j = 0; j 8 ctr-source[i][j]; j++) { + sig = nvkm_perfsig_find(ppm, ctr-domain, + ctr-signal[i], dom); + if (!sig) + return -EINVAL; + + src = nvkm_perfsrc_find(ppm, sig, ctr-source[i][j]); + if (!src) + return -EINVAL; + + /* set enable bit if needed */ + mask = value = 0x; + if (src-enable) + mask = value = 0x8000; + mask |= (src-mask src-shift); + value |= ((ctr-source[i][j] 32) src-shift); + + /* enable the source */ + nv_mask(ppm, src-addr, mask, value); + } + } + return 0; +} + +static int +nvkm_perfsrc_disable(struct nvkm_pm *ppm, struct nvkm_perfctr *ctr) +{ + struct nvkm_perfdom *dom = NULL; + struct nvkm_perfsig *sig; + struct nvkm_perfsrc *src; + int i, j; + + for (i = 0; i 4 ctr-signal[i]; i++) { + for (j = 0; j 8 ctr-source[i][j]; j++) { + sig = nvkm_perfsig_find(ppm, ctr-domain, + ctr-signal[i], dom); + if (!sig) + return -EINVAL; + + src = nvkm_perfsrc_find(ppm, sig, ctr-source[i][j]); + if (!src) + return -EINVAL; + + /* disable the source */ + nv_mask(ppm, src-addr, src-mask src-shift, 0); + } + } + return 0; +} + /*** * Perfmon object classes **/ @@ -319,10 +379,15 @@ nvkm_perfdom_init(struct nvkm_object *object, void *data, u32 size) } else return ret; - for (i = 0; i 4; i++) - if (dom-ctr[i]) + for (i = 0; i 4; i++) { + if (dom-ctr[i]) { dom-func-init(ppm, dom, dom-ctr[i]); + /* enable sources */ + nvkm_perfsrc_enable(ppm, dom-ctr[i]); + } + } + /* start next batch of counters for sampling */ dom-func-next(ppm, dom); return 0; @@ -402,13 +467,17 @@ nvkm_perfdom_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) static void nvkm_perfdom_dtor(struct nvkm_object *object) { + struct nvkm_pm *ppm = (void *)object-engine; struct nvkm_perfdom *dom = (void *)object; int i; for (i = 0; i 4; i++) { struct nvkm_perfctr *ctr = dom-ctr[i]; - if (ctr ctr-head.next) - list_del(ctr-head); + if (ctr) { + nvkm_perfsrc_disable(ppm, ctr); + if (ctr-head.next) + list_del(ctr-head); + } kfree(ctr); } nvkm_object_destroy(dom-base); @@ -416,11 +485,11 @@ nvkm_perfdom_dtor(struct nvkm_object *object) static int nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot, -struct nvkm_perfsig *signal[4], uint16_t logic_op, -struct nvkm_perfctr **pctr) +struct nvkm_perfsig *signal[4], uint64_t source[4][8], +uint16_t logic_op, struct nvkm_perfctr **pctr) { struct nvkm_perfctr
[Nouveau] [PATCH RFC 13/20] pm: allow to query the number of sources for a signal
Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/include/nvif/class.h | 3 ++- drm/nouveau/nvkm/engine/pm/base.c | 22 +++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index 9e4db3a..caae193 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -268,7 +268,8 @@ struct nvif_perfmon_query_signal_v0 { __u8 domain; __u16 iter; __u8 signal; - __u8 pad04[3]; + __u8 source_nr; + __u8 pad05[2]; char name[64]; }; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index dfafefd..a9c57a2 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -91,6 +91,18 @@ nvkm_perfsig_find(struct nvkm_pm *ppm, uint8_t di, uint8_t si, return dom-signal[si]; } +static u8 +nvkm_perfsig_count_perfsrc(struct nvkm_perfsig *sig) +{ + u8 source_nr = 0, i; + + for (i = 0; i ARRAY_SIZE(sig-source); i++) { + if (sig-source[i]) + source_nr++; + } + return source_nr; +} + /*** * Perfmon object classes **/ @@ -148,9 +160,9 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) struct nvkm_device *device = nv_device(object); struct nvkm_pm *ppm = (void *)object-engine; struct nvkm_perfdom *dom; + struct nvkm_perfsig *sig; const bool all = nvkm_boolopt(device-cfgopt, NvPmShowAll, false); const bool raw = nvkm_boolopt(device-cfgopt, NvPmUnnamed, all); - const char *name; int ret, si; nv_ioctl(object, perfmon query signal size %d\n, size); @@ -167,13 +179,17 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) return -EINVAL; if (si = 0) { - if (raw || !(name = dom-signal[si].name)) { + sig = dom-signal[si]; + if (raw || !sig-name) { snprintf(args-v0.name, sizeof(args-v0.name), /%s/%02x, dom-name, si); } else { - strncpy(args-v0.name, name, sizeof(args-v0.name)); + strncpy(args-v0.name, sig-name, + sizeof(args-v0.name)); } + args-v0.signal = si; + args-v0.source_nr = nvkm_perfsig_count_perfsrc(sig); } while (++si dom-signal_nr) { -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 14/20] pm: implement NVIF_PERFMON_V0_QUERY_SOURCE method
This allows to query the ID, the mask and the user-readable name of sources for each signal. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/include/nvif/class.h | 12 ++ drm/nouveau/nvkm/engine/pm/base.c | 77 +++ 2 files changed, 89 insertions(+) diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index caae193..d85fb0d 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -253,6 +253,7 @@ struct gf110_dma_v0 { #define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00 #define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01 +#define NVIF_PERFMON_V0_QUERY_SOURCE 0x02 struct nvif_perfmon_query_domain_v0 { __u8 version; @@ -273,6 +274,17 @@ struct nvif_perfmon_query_signal_v0 { char name[64]; }; +struct nvif_perfmon_query_source_v0 { + __u8 version; + __u8 domain; + __u8 signal; + __u8 iter; + __u8 pad04[4]; + __u32 source; + __u32 mask; + char name[64]; +}; + /*** * perfctr diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index a9c57a2..ec02abf 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -103,6 +103,31 @@ nvkm_perfsig_count_perfsrc(struct nvkm_perfsig *sig) return source_nr; } +static struct nvkm_perfsrc * +nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si) +{ + struct nvkm_perfsrc *src; + bool found = false; + int tmp = 1; /* Sources ID start from 1 */ + u8 i; + + for (i = 0; i ARRAY_SIZE(sig-source) sig-source[i]; i++) { + if (sig-source[i] == si) { + found = true; + break; + } + } + + if (found) { + list_for_each_entry(src, ppm-sources, head) { + if (tmp++ == si) + return src; + } + } + + return NULL; +} + /*** * Perfmon object classes **/ @@ -204,6 +229,56 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) } static int +nvkm_perfmon_mthd_query_source(struct nvkm_object *object, void *data, u32 size) +{ + union { + struct nvif_perfmon_query_source_v0 v0; + } *args = data; + struct nvkm_pm *ppm = (void *)object-engine; + struct nvkm_perfdom *dom = NULL; + struct nvkm_perfsig *sig; + struct nvkm_perfsrc *src; + u8 source_nr = 0; + int si, ret; + + nv_ioctl(object, perfmon query source size %d\n, size); + if (nvif_unpack(args-v0, 0, 0, false)) { + nv_ioctl(object, +perfmon source vers %d dom %d sig %02x iter %02x\n, +args-v0.version, args-v0.domain, args-v0.signal, +args-v0.iter); + si = (args-v0.iter 0xff) - 1; + } else + return ret; + + sig = nvkm_perfsig_find(ppm, args-v0.domain, args-v0.signal, dom); + if (!sig) + return -EINVAL; + + source_nr = nvkm_perfsig_count_perfsrc(sig); + if (si = (int)source_nr) + return -EINVAL; + + if (si = 0) { + src = nvkm_perfsrc_find(ppm, sig, sig-source[si]); + if (!src) + return -EINVAL; + + args-v0.source = sig-source[si]; + args-v0.mask = src-mask; + strncpy(args-v0.name, src-name, sizeof(args-v0.name)); + } + + if (++si source_nr) { + args-v0.iter = ++si; + return 0; + } + + args-v0.iter = 0xff; + return 0; +} + +static int nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { switch (mthd) { @@ -211,6 +286,8 @@ nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return nvkm_perfmon_mthd_query_domain(object, data, size); case NVIF_PERFMON_V0_QUERY_SIGNAL: return nvkm_perfmon_mthd_query_signal(object, data, size); + case NVIF_PERFMON_V0_QUERY_SOURCE: + return nvkm_perfmon_mthd_query_source(object, data, size); default: break; } -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 15/20] pm: allow the userspace to schedule hardware counters
This adds a new method NVIF_PERFCTR_V0_INIT which starts a batch of hardware counters for sampling. This will allow the userspace to start a monitoring session using the INIT method and to stop it with SAMPLE, for example before and after a frame is rendered. This commit temporarily breaks nv_perfmon but this is going to be fixed with the upcoming patch. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/include/nvif/class.h | 8 +++-- drm/nouveau/nvkm/engine/pm/base.c | 64 +-- drm/nouveau/nvkm/engine/pm/priv.h | 1 + 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index d85fb0d..528eac8 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -300,8 +300,12 @@ struct nvif_perfctr_v0 { __u8 pad06[4]; }; -#define NVIF_PERFCTR_V0_SAMPLE 0x00 -#define NVIF_PERFCTR_V0_READ 0x01 +#define NVIF_PERFCTR_V0_INIT 0x00 +#define NVIF_PERFCTR_V0_SAMPLE 0x01 +#define NVIF_PERFCTR_V0_READ 0x02 + +struct nvif_perfctr_init { +}; struct nvif_perfctr_sample { }; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index ec02abf..5dbb3b4 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -307,13 +307,43 @@ nvkm_perfmon_ofuncs = { * Perfctr object classes **/ static int +nvkm_perfctr_init(struct nvkm_object *object, void *data, u32 size) +{ + union { + struct nvif_perfctr_init none; + } *args = data; + struct nvkm_pm *ppm = (void *)object-engine; + struct nvkm_perfctr *ctr = (void *)object; + struct nvkm_perfdom *dom = ctr-dom; + int ret; + + nv_ioctl(object, perfctr init size %d\n, size); + if (nvif_unvers(args-none)) { + nv_ioctl(object, perfctr init\n); + } else + return ret; + + ctr-slot = ffs(dom-quad) - 1; + if (ctr-slot 0) { + /* no free slots are available */ + return -EINVAL; + } + dom-quad = ~(QUAD_FREE ctr-slot); + dom-func-init(ppm, dom, ctr); + + /* start next batch of counters for sampling */ + dom-func-next(ppm, dom); + return 0; +} + +static int nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size) { union { struct nvif_perfctr_sample none; } *args = data; struct nvkm_pm *ppm = (void *)object-engine; - struct nvkm_perfctr *ctr, *tmp; + struct nvkm_perfctr *ctr; struct nvkm_perfdom *dom; int ret; @@ -328,32 +358,15 @@ nvkm_perfctr_sample(struct nvkm_object *object, void *data, u32 size) /* sample previous batch of counters */ if (dom-quad != QUAD_MASK) { dom-func-next(ppm, dom); - tmp = NULL; - while (!list_empty(dom-list)) { - ctr = list_first_entry(dom-list, - typeof(*ctr), head); - if (ctr-slot 0) break; - if ( tmp tmp == ctr) break; - if (!tmp) tmp = ctr; + + /* read counter values */ + list_for_each_entry(ctr, dom-list, head) { dom-func-read(ppm, dom, ctr); - ctr-slot = -1; - list_move_tail(ctr-head, dom-list); + ctr-slot = -1; } - } - - dom-quad = QUAD_MASK; - /* setup next batch of counters for sampling */ - list_for_each_entry(ctr, dom-list, head) { - ctr-slot = ffs(dom-quad) - 1; - if (ctr-slot 0) - break; - dom-quad = ~(QUAD_FREE ctr-slot); - dom-func-init(ppm, dom, ctr); + dom-quad = QUAD_MASK; } - - if (dom-quad != QUAD_MASK) - dom-func-next(ppm, dom); } return 0; @@ -386,6 +399,8 @@ static int nvkm_perfctr_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { switch (mthd) { + case NVIF_PERFCTR_V0_INIT: + return nvkm_perfctr_init(object, data, size); case NVIF_PERFCTR_V0_SAMPLE: return nvkm_perfctr_sample(object, data, size); case NVIF_PERFCTR_V0_READ: @@ -400,6 +415,8 @@ static
[Nouveau] [Bug 90887] New: PhiMovesPass in register allocator broken
https://bugs.freedesktop.org/show_bug.cgi?id=90887 Bug ID: 90887 Summary: PhiMovesPass in register allocator broken Product: Mesa Version: git Hardware: All OS: All Status: NEW Severity: normal Priority: medium Component: Drivers/DRI/nouveau Assignee: nouveau@lists.freedesktop.org Reporter: j...@online.de QA Contact: nouveau@lists.freedesktop.org Created attachment 116339 -- https://bugs.freedesktop.org/attachment.cgi?id=116339action=edit Candidate Fix for nv50 PhiMovesPass The PhiMovesPass depends on strict correspondence between phi argument and incoming flow edge order. Unfortunately it destroys this correspondence itself in the needNewElseBlock case resulting in the wrong (potentially uninitialized) registers being copied. The attached patch fixes problems in the following games on NVA5 (Debian Jessie, wine git): Costume Quest (with FXAA option), Lifeless Planet, and Eidolon. These are not present when using the LLVMPIPE driver. I have analyzed the situation starting with Lifeless Planet (but simplifying the shader until I could handle the problem): the postprocessing shader modifies part of the rendered image with a shader like this 1. sample the vincinity of the current position 2. sample the current position 2. compute something based on all of these pixels 3. if some condition is reached 4. do some more computations (including TEXL) 5. replace current position value sampled above by computed value 6. return current position value or computed value (see if) The PhiMovesPass detects needNewElseBlock conditions and splits the 'else' edge incoming from the if thereby switching the order of incoming edges leading to adding copies from the sampled value to the if branch (discarding the computed values) and copies from the (unitialized) computed values to the new else block corrupting the result for all pixels except the ones where the condition is true (where it produces the originally sampled value). The fix slightly modifies the needNewElseBlock logic to not detach/attach the incoming edge. Costume Quest (with FXAA) and Eidolon look correct with this fix. Lifeless Planet is much better but still somewhat bad, but that may be intended (it looks similarly crappy with LLVMPIPE). The latter may also be a problem with wine). NB: This might be related to bug #90347. The shader code given there looks like it could trigger this case, but I haven't tried it. -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 90887] PhiMovesPass in register allocator broken
https://bugs.freedesktop.org/show_bug.cgi?id=90887 --- Comment #2 from jr j...@online.de --- Forgot to add: Interestingly without the additional blocks inserted by TXL in the if block the bug is not triggered (i.e. other tex operations work fine). -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 05/20] pm: reorganize the nvif interface
This commit introduces the NVIF_IOCTL_NEW_V0_PERFMON class which will be used in order to query domains, signals and sources. This separates the querying and the counting interface. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- bin/nv_perfmon.c | 12 ++-- drm/nouveau/include/nvif/class.h | 26 -- drm/nouveau/include/nvif/ioctl.h | 5 +++-- drm/nouveau/nvkm/engine/pm/base.c | 38 -- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c index a8c5838..30a3138 100644 --- a/bin/nv_perfmon.c +++ b/bin/nv_perfmon.c @@ -600,7 +600,7 @@ main(int argc, char **argv) const char *cfg = NULL; const char *dbg = error; u64 dev = ~0ULL; - struct nvif_perfctr_query_v0 args = {}; + struct nvif_perfmon_query_signal_v0 args = {}; struct nvif_client *client; struct nvif_object object; int ret, c, k; @@ -644,15 +644,14 @@ main(int argc, char **argv) } ret = nvif_object_init(nvif_object(device), NULL, 0xdeadbeef, - NVIF_IOCTL_NEW_V0_PERFCTR, - (struct nvif_perfctr_v0) { - }, sizeof(struct nvif_perfctr_v0), object); + NVIF_IOCTL_NEW_V0_PERFMON, NULL, 0, object); assert(ret == 0); do { u32 prev_iter = args.iter; args.name[0] = '\0'; - ret = nvif_mthd(object, NVIF_PERFCTR_V0_QUERY, args, sizeof(args)); + ret = nvif_mthd(object, NVIF_PERFMON_V0_QUERY_SIGNAL, + args, sizeof(args)); assert(ret == 0); if (prev_iter) { @@ -663,7 +662,8 @@ main(int argc, char **argv) args.iter = prev_iter; strncpy(signals[nr_signals - 1], args.name, sizeof(args.name)); - ret = nvif_mthd(object, NVIF_PERFCTR_V0_QUERY, args, sizeof(args)); + ret = nvif_mthd(object, NVIF_PERFMON_V0_QUERY_SIGNAL, + args, sizeof(args)); assert(ret == 0); } } while (args.iter != 0x); diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index 64f8b2f..11935a0 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -251,6 +251,20 @@ struct gf110_dma_v0 { * perfmon **/ +#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x00 + +struct nvif_perfmon_query_signal_v0 { + __u8 version; + __u8 pad01[3]; + __u32 iter; + char name[64]; +}; + + +/*** + * perfctr + **/ + struct nvif_perfctr_v0 { __u8 version; __u8 pad01[1]; @@ -259,16 +273,8 @@ struct nvif_perfctr_v0 { char name[4][64]; }; -#define NVIF_PERFCTR_V0_QUERY 0x00 -#define NVIF_PERFCTR_V0_SAMPLE 0x01 -#define NVIF_PERFCTR_V0_READ 0x02 - -struct nvif_perfctr_query_v0 { - __u8 version; - __u8 pad01[3]; - __u32 iter; - char name[64]; -}; +#define NVIF_PERFCTR_V0_SAMPLE 0x00 +#define NVIF_PERFCTR_V0_READ 0x01 struct nvif_perfctr_sample { }; diff --git a/drm/nouveau/include/nvif/ioctl.h b/drm/nouveau/include/nvif/ioctl.h index 4cd8e32..517cd27 100644 --- a/drm/nouveau/include/nvif/ioctl.h +++ b/drm/nouveau/include/nvif/ioctl.h @@ -49,8 +49,9 @@ struct nvif_ioctl_new_v0 { __u64 token; __u32 handle; /* these class numbers are made up by us, and not nvidia-assigned */ -#define NVIF_IOCTL_NEW_V0_PERFCTR0x -#define NVIF_IOCTL_NEW_V0_CONTROL0xfffe +#define NVIF_IOCTL_NEW_V0_PERFMON0x +#define NVIF_IOCTL_NEW_V0_PERFCTR0xfffe +#define NVIF_IOCTL_NEW_V0_CONTROL0xfffd __u32 oclass; __u8 data[]; /* class data (class.h) */ }; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 7b07e8b..cb88170 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -83,10 +83,10 @@ nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size, * Perfmon object classes
[Nouveau] [PATCH RFC 08/20] pm: allow to query signals by domain
This will allow to configure performance counters with hardware signal indexes instead of user-readable names in an upcoming patch. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- bin/nv_perfmon.c | 185 -- drm/nouveau/include/nvif/class.h | 3 +- drm/nouveau/nvkm/engine/pm/base.c | 36 +++- 3 files changed, 150 insertions(+), 74 deletions(-) diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c index 30a3138..958520e 100644 --- a/bin/nv_perfmon.c +++ b/bin/nv_perfmon.c @@ -36,8 +36,7 @@ #include sys/time.h static struct nvif_device *device; -static char **signals; -static int nr_signals; +static int nr_signals; /* number of signals for all domains */ #define SEC_US 100 #define REFRESH_PERIOD SEC_US @@ -247,6 +246,17 @@ ui_menu_win = { * **/ +struct ui_perfmon_dom { + struct list_head head; + struct list_head list; + u8 id; +}; + +struct ui_perfmon_sig { + struct list_head head; + char *name; +}; + struct ui_main { struct list_head head; u32 handle; @@ -258,6 +268,7 @@ struct ui_main { }; static struct list_head ui_main_list = LIST_HEAD_INIT(ui_main_list); +static struct list_head ui_doms_list = LIST_HEAD_INIT(ui_doms_list); static u32 ui_main_handle = 0xc000; static void @@ -269,32 +280,134 @@ ui_main_remove(struct ui_main *item) } static void +ui_perfmon_query_signals(struct nvif_object *perfmon, +struct ui_perfmon_dom *dom) +{ + struct nvif_perfmon_query_signal_v0 args = {}; + struct ui_perfmon_sig *sig; + int ret; + + args.domain = dom-id; + do { + u32 prev_iter = args.iter; + + args.name[0] = '\0'; + ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_SIGNAL, + args, sizeof(args)); + assert(ret == 0); + + if (prev_iter) { + nr_signals++; + sig = calloc(1, sizeof(*sig)); + sig-name = malloc(sizeof(args.name)); + strncpy(sig-name, args.name, sizeof(args.name)); + list_add_tail(sig-head, dom-list); + + args.iter = prev_iter; + ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_SIGNAL, + args, sizeof(args)); + assert(ret == 0); + } + } while (args.iter != 0x); +} + +static void +ui_perfmon_query_domains(struct nvif_object *perfmon) +{ + struct nvif_perfmon_query_domain_v0 args = {}; + struct ui_perfmon_dom *dom; + int ret; + + assert(ret == 0); + do { + u8 prev_iter = args.iter; + + ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_DOMAIN, + args, sizeof(args)); + assert(ret == 0); + + if (prev_iter) { + dom = calloc(1, sizeof(*dom)); + dom-id = args.id; + INIT_LIST_HEAD(dom-list); + list_add_tail(dom-head, ui_doms_list); + + args.iter = prev_iter; + ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_DOMAIN, + args, sizeof(args)); + assert(ret == 0); + + /* query available signals for the domain */ + ui_perfmon_query_signals(perfmon, dom); + } + } while (args.iter != 0xff); +} + +static void +ui_perfmon_init(void) +{ + struct nvif_object perfmon; + int ret; + + ret = nvif_object_init(nvif_object(device), NULL, 0xdeadbeef, + NVIF_IOCTL_NEW_V0_PERFMON, NULL, 0, perfmon); + assert(ret == 0); + + /* query available domains for the device */ + ui_perfmon_query_domains(perfmon); + + nvif_object_fini(perfmon); +} + +static void +ui_perfmon_fini(void) +{ + struct ui_perfmon_dom *dom, *next_dom; + struct ui_perfmon_sig *sig, *next_sig; + + list_for_each_entry_safe(dom, next_dom, ui_doms_list, head) { + list_for_each_entry_safe(sig, next_sig, dom-list, head) { + list_del(sig-head); + free(sig-name); + free(sig); + } + list_del(dom-head); + free(dom); + } +} + +static void ui_main_select(void) { struct ui_main *item, *temp; - int ret, i; + struct ui_perfmon_dom *dom; + struct ui_perfmon_sig *sig; + int ret; list_for_each_entry_safe(item, temp, ui_main_list, head) { ui_main_remove(item); } - for (i = 0; i nr_signals; i++) { - struct nvif_perfctr_v0
[Nouveau] [PATCH RFC 07/20] pm: implement NVIF_PERFMON_V0_QUERY_DOMAIN method
This allows to query the number of available domains, including the number of hardware counter and the number of signals per domain. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/include/nvif/class.h | 11 - drm/nouveau/nvkm/engine/pm/base.c | 86 +++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index 11935a0..0b28929 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -251,7 +251,16 @@ struct gf110_dma_v0 { * perfmon **/ -#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x00 +#define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00 +#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01 + +struct nvif_perfmon_query_domain_v0 { + __u8 version; + __u8 id; + __u8 counter_nr; + __u8 iter; + __u32 signal_nr; +}; struct nvif_perfmon_query_signal_v0 { __u8 version; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 2f85147..3d9bcbc 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -34,6 +34,45 @@ #define QUAD_MASK 0x0f #define QUAD_FREE 0x01 +static u8 +nvkm_pm_count_perfdom(struct nvkm_pm *ppm) +{ + struct nvkm_perfdom *dom; + u8 domain_nr = 0; + + list_for_each_entry(dom, ppm-domains, head) + domain_nr++; + return domain_nr; +} + +static u32 +nvkm_perfdom_count_perfsig(struct nvkm_perfdom *dom) +{ + u32 signal_nr = 0; + int i; + + if (dom) { + for (i = 0; i dom-signal_nr; i++) { + if (dom-signal[i].name) + signal_nr++; + } + } + return signal_nr; +} + +static struct nvkm_perfdom * +nvkm_perfdom_find(struct nvkm_pm *ppm, int di) +{ + struct nvkm_perfdom *dom; + int tmp = 0; + + list_for_each_entry(dom, ppm-domains, head) { + if (tmp++ == di) + return dom; + } + return NULL; +} + static struct nvkm_perfsig * nvkm_perfsig_find_(struct nvkm_perfdom *dom, const char *name, u32 size) { @@ -83,6 +122,51 @@ nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size, * Perfmon object classes **/ static int +nvkm_perfmon_mthd_query_domain(struct nvkm_object *object, void *data, u32 size) +{ + union { + struct nvif_perfmon_query_domain_v0 v0; + } *args = data; + struct nvkm_pm *ppm = (void *)object-engine; + struct nvkm_perfdom *dom; + u8 domain_nr; + int di, ret; + + nv_ioctl(object, perfmon query domain size %d\n, size); + if (nvif_unpack(args-v0, 0, 0, false)) { + nv_ioctl(object, perfmon domain vers %d iter %02x\n, +args-v0.version, args-v0.iter); + di = (args-v0.iter 0xff) - 1; + } else + return ret; + + domain_nr = nvkm_pm_count_perfdom(ppm); + if (di = (int)domain_nr) + return -EINVAL; + + if (di = 0) { + dom = nvkm_perfdom_find(ppm, di); + if (dom == NULL) + return -EINVAL; + + args-v0.id = di; + args-v0.signal_nr = nvkm_perfdom_count_perfsig(dom); + + /* Currently only global counters (PCOUNTER) are implemented +* but this will be different for local counters (MP). */ + args-v0.counter_nr = 4; + } + + if (++di domain_nr) { + args-v0.iter = ++di; + return 0; + } + + args-v0.iter = 0xff; + return 0; +} + +static int nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) { union { @@ -145,6 +229,8 @@ static int nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { switch (mthd) { + case NVIF_PERFMON_V0_QUERY_DOMAIN: + return nvkm_perfmon_mthd_query_domain(object, data, size); case NVIF_PERFMON_V0_QUERY_SIGNAL: return nvkm_perfmon_mthd_query_signal(object, data, size); default: -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 03/20] pm: remove pmu signals
PDAEMON signals don't have to be exposed by the perfmon engine. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com Reviewed-by: Martin Peres martin.pe...@free.fr --- drm/nouveau/include/nvkm/engine/pm.h | 4 -- drm/nouveau/nvkm/engine/pm/Kbuild| 1 - drm/nouveau/nvkm/engine/pm/daemon.c | 108 --- drm/nouveau/nvkm/engine/pm/gf100.c | 5 -- drm/nouveau/nvkm/engine/pm/gk104.c | 6 -- drm/nouveau/nvkm/engine/pm/gk110.c | 4 -- drm/nouveau/nvkm/engine/pm/gt215.c | 20 +-- drm/nouveau/nvkm/engine/pm/priv.h| 4 -- 8 files changed, 1 insertion(+), 151 deletions(-) delete mode 100644 drm/nouveau/nvkm/engine/pm/daemon.c diff --git a/drm/nouveau/include/nvkm/engine/pm.h b/drm/nouveau/include/nvkm/engine/pm.h index 93181bb..6c2d057 100644 --- a/drm/nouveau/include/nvkm/engine/pm.h +++ b/drm/nouveau/include/nvkm/engine/pm.h @@ -12,10 +12,6 @@ struct nvkm_pm { struct list_head domains; u32 sequence; - - /*XXX: temp for daemon backend */ - u32 pwr[8]; - u32 last; }; static inline struct nvkm_pm * diff --git a/drm/nouveau/nvkm/engine/pm/Kbuild b/drm/nouveau/nvkm/engine/pm/Kbuild index 413b609..c5ee8d5 100644 --- a/drm/nouveau/nvkm/engine/pm/Kbuild +++ b/drm/nouveau/nvkm/engine/pm/Kbuild @@ -1,5 +1,4 @@ nvkm-y += nvkm/engine/pm/base.o -nvkm-y += nvkm/engine/pm/daemon.o nvkm-y += nvkm/engine/pm/nv40.o nvkm-y += nvkm/engine/pm/nv50.o nvkm-y += nvkm/engine/pm/g84.o diff --git a/drm/nouveau/nvkm/engine/pm/daemon.c b/drm/nouveau/nvkm/engine/pm/daemon.c deleted file mode 100644 index a7a5f3a..000 --- a/drm/nouveau/nvkm/engine/pm/daemon.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the Software), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include priv.h - -static void -pwr_perfctr_init(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, -struct nvkm_perfctr *ctr) -{ - u32 mask = 0x; - u32 ctrl = 0x0001; - int i; - - for (i = 0; i ARRAY_SIZE(ctr-signal) ctr-signal[i]; i++) - mask |= 1 (ctr-signal[i] - dom-signal); - - nv_wr32(ppm, 0x10a504 + (ctr-slot * 0x10), mask); - nv_wr32(ppm, 0x10a50c + (ctr-slot * 0x10), ctrl); - nv_wr32(ppm, 0x10a50c + (ppm-last * 0x10), 0x0003); -} - -static void -pwr_perfctr_read(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, -struct nvkm_perfctr *ctr) -{ - ctr-ctr = ppm-pwr[ctr-slot]; - ctr-clk = ppm-pwr[ppm-last]; -} - -static void -pwr_perfctr_next(struct nvkm_pm *ppm, struct nvkm_perfdom *dom) -{ - int i; - - for (i = 0; i = ppm-last; i++) { - ppm-pwr[i] = nv_rd32(ppm, 0x10a508 + (i * 0x10)); - nv_wr32(ppm, 0x10a508 + (i * 0x10), 0x8000); - } -} - -static const struct nvkm_funcdom -pwr_perfctr_func = { - .init = pwr_perfctr_init, - .read = pwr_perfctr_read, - .next = pwr_perfctr_next, -}; - -const struct nvkm_specdom -gt215_pm_pwr[] = { - { 0x20, (const struct nvkm_specsig[]) { - { 0x00, pwr_gr_idle }, - { 0x04, pwr_bsp_idle }, - { 0x05, pwr_vp_idle }, - { 0x06, pwr_ppp_idle }, - { 0x13, pwr_ce0_idle }, - {} - }, pwr_perfctr_func }, - {} -}; - -const struct nvkm_specdom -gf100_pm_pwr[] = { - { 0x20, (const struct nvkm_specsig[]) { - { 0x00, pwr_gr_idle }, - { 0x04, pwr_bsp_idle }, - { 0x05, pwr_vp_idle }, - { 0x06, pwr_ppp_idle }, - { 0x13, pwr_ce0_idle }, - { 0x14, pwr_ce1_idle }, - {} - }, pwr_perfctr_func }, - {} -}; - -const struct nvkm_specdom -gk104_pm_pwr[] = { - { 0x20, (const
[Nouveau] [PATCH RFC 20/20] sw/nv50: add and interface for controlling performance counters
This software methods interface will allow the userspace to tie monitoring of performance counters to the command stream. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/nvkm/engine/sw/nv50.c | 160 ++ drm/nouveau/nvkm/engine/sw/nv50.h | 6 ++ 2 files changed, 166 insertions(+) diff --git a/drm/nouveau/nvkm/engine/sw/nv50.c b/drm/nouveau/nvkm/engine/sw/nv50.c index b7c0227..b5f8263 100644 --- a/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drm/nouveau/nvkm/engine/sw/nv50.c @@ -29,7 +29,9 @@ #include engine/disp.h #include subdev/bar.h +#include nvif/class.h #include nvif/event.h +#include nvif/ioctl.h /*** * software object classes @@ -80,6 +82,14 @@ nv50_priv_ctxdma_wr32(struct nv50_sw_chan *chan, u64 offset, u32 value) } } +static u64 +nv50_priv_pm_get_offset(struct nv50_sw_chan *chan, u32 sequence) +{ + u32 max_queries = chan-pm.max_queries; + u32 ring_size = chan-pm.ring_size; + return (1 + (sequence % ring_size) * max_queries * 3) * 4; +} + static int nv50_sw_mthd_dma_vblsem(struct nvkm_object *object, u32 mthd, void *args, u32 size) @@ -128,13 +138,163 @@ nv50_sw_mthd_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) return -EINVAL; } +static int +nv50_sw_mthd_dma_pm(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + return nv50_priv_ctxdma_get(chan, *(u32 *)args, chan-pm.ctxdma); +} + +static int +nv50_sw_mthd_pm_ring_size(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + chan-pm.ring_size = *(u32 *)args; + return 0; +} + +static int +nv50_sw_mthd_pm_max_queries(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + chan-pm.max_queries = *(u32 *)args; + return 0; +} + +static int +nv50_sw_mthd_pm_mthd_init(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + struct nvkm_fifo_chan *fifo = (void *)nv_object(chan)-parent; + struct nvkm_handle *handle; + struct nvkm_object *namedb; + int ret = -EINVAL; + + namedb = nv_object(fifo)-parent; + while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) + namedb = namedb-parent; + + handle = nvkm_namedb_get(nv_namedb(namedb), *(u32 *)args); + if (!handle) + return -ENOENT; + + if (nv_iclass(handle-object, NVIF_IOCTL_NEW_V0_PERFMON)) { + struct nvkm_object *object = handle-object; + struct nvkm_ofuncs *ofuncs = object-oclass-ofuncs; + struct nvif_perfdom_init args = {}; + + ret = ofuncs-mthd(object, NVIF_PERFDOM_V0_INIT, + args, sizeof(args)); + } + nvkm_namedb_put(handle); + return ret; +} + +static int +nv50_sw_mthd_pm_mthd_sample(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + struct nvkm_fifo_chan *fifo = (void *)nv_object(chan)-parent; + struct nvkm_handle *handle; + struct nvkm_object *namedb; + int ret = -EINVAL; + + namedb = nv_object(fifo)-parent; + while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) + namedb = namedb-parent; + + handle = nvkm_namedb_get(nv_namedb(namedb), *(u32 *)args); + if (!handle) + return -ENOENT; + + if (nv_iclass(handle-object, NVIF_IOCTL_NEW_V0_PERFMON)) { + struct nvkm_object *object = handle-object; + struct nvkm_ofuncs *ofuncs = object-oclass-ofuncs; + struct nvif_perfdom_sample args = {}; + + ret = ofuncs-mthd(object, NVIF_PERFDOM_V0_SAMPLE, + args, sizeof(args)); + } + nvkm_namedb_put(handle); + return ret; +} + +static int +nv50_sw_mthd_pm_mthd_read(struct nvkm_object *object, u32 mthd, + void *args, u32 size) +{ + struct nv50_sw_chan *chan = (void *)nv_engctx(object-parent); + struct nvkm_fifo_chan *fifo = (void *)nv_object(chan)-parent; + struct nvkm_handle *handle; + struct nvkm_object *namedb; + u32 seq = *(u32 *)args; + int ret = -ENOENT; + u64 offset; + int i; + + nv50_priv_ctxdma_flush(chan, chan-vblank.channel, chan-pm.ctxdma); + offset = nv50_priv_pm_get_offset(chan, seq); + + namedb = nv_object(fifo)-parent; + while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) +
[Nouveau] [PATCH RFC 18/20] pm/nv50: add compute and graphics signals/sources
These signals and sources have been reverse engineered from NVIDIA PerfKit (Windows) and CUPTI (Linux), they will be used to build complex hardware events from the userspace. This commit also adds a new class for GT200. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/include/nvkm/engine/pm.h | 1 + drm/nouveau/nvkm/engine/device/nv50.c | 2 +- drm/nouveau/nvkm/engine/pm/Kbuild | 1 + drm/nouveau/nvkm/engine/pm/g84.c | 101 - drm/nouveau/nvkm/engine/pm/gt200.c| 163 ++ drm/nouveau/nvkm/engine/pm/gt215.c| 84 +- drm/nouveau/nvkm/engine/pm/nv50.c | 136 ++-- drm/nouveau/nvkm/engine/pm/priv.h | 8 ++ 8 files changed, 485 insertions(+), 11 deletions(-) create mode 100644 drm/nouveau/nvkm/engine/pm/gt200.c diff --git a/drm/nouveau/include/nvkm/engine/pm.h b/drm/nouveau/include/nvkm/engine/pm.h index 130b545..82f1c7f 100644 --- a/drm/nouveau/include/nvkm/engine/pm.h +++ b/drm/nouveau/include/nvkm/engine/pm.h @@ -24,6 +24,7 @@ nvkm_pm(void *obj) extern struct nvkm_oclass *nv40_pm_oclass; extern struct nvkm_oclass *nv50_pm_oclass; extern struct nvkm_oclass *g84_pm_oclass; +extern struct nvkm_oclass *gt200_pm_oclass; extern struct nvkm_oclass *gt215_pm_oclass; extern struct nvkm_oclass gf100_pm_oclass; extern struct nvkm_oclass gk104_pm_oclass; diff --git a/drm/nouveau/nvkm/engine/device/nv50.c b/drm/nouveau/nvkm/engine/device/nv50.c index 249b844..a2627ec 100644 --- a/drm/nouveau/nvkm/engine/device/nv50.c +++ b/drm/nouveau/nvkm/engine/device/nv50.c @@ -288,7 +288,7 @@ nv50_identify(struct nvkm_device *device) device-oclass[NVDEV_ENGINE_CIPHER ] = g84_cipher_oclass; device-oclass[NVDEV_ENGINE_BSP] = g84_bsp_oclass; device-oclass[NVDEV_ENGINE_DISP ] = gt200_disp_oclass; - device-oclass[NVDEV_ENGINE_PM ] = g84_pm_oclass; + device-oclass[NVDEV_ENGINE_PM ] = gt200_pm_oclass; break; case 0xaa: device-cname = MCP77/MCP78; diff --git a/drm/nouveau/nvkm/engine/pm/Kbuild b/drm/nouveau/nvkm/engine/pm/Kbuild index c5ee8d5..cc01048 100644 --- a/drm/nouveau/nvkm/engine/pm/Kbuild +++ b/drm/nouveau/nvkm/engine/pm/Kbuild @@ -2,6 +2,7 @@ nvkm-y += nvkm/engine/pm/base.o nvkm-y += nvkm/engine/pm/nv40.o nvkm-y += nvkm/engine/pm/nv50.o nvkm-y += nvkm/engine/pm/g84.o +nvkm-y += nvkm/engine/pm/gt200.o nvkm-y += nvkm/engine/pm/gt215.o nvkm-y += nvkm/engine/pm/gf100.o nvkm-y += nvkm/engine/pm/gk104.o diff --git a/drm/nouveau/nvkm/engine/pm/g84.c b/drm/nouveau/nvkm/engine/pm/g84.c index d54c670..dda539c 100644 --- a/drm/nouveau/nvkm/engine/pm/g84.c +++ b/drm/nouveau/nvkm/engine/pm/g84.c @@ -23,15 +23,112 @@ */ #include nv40.h +const struct nvkm_specsrc +g84_vfetch_sources[] = { + { 0x400c0c, (const struct nvkm_specmux[]) { + { 0x3, 0, unk0 }, + {} + }, pgraph_vfetch_unk0c }, + {} +}; + +static const struct nvkm_specsrc +g84_crop_sources[] = { + { 0x407008, (const struct nvkm_specmux[]) { + { 0xf, 0, sel0, true }, + { 0x7, 16, sel1, true }, + {} + }, pgraph_rop0_crop_pm_mux }, + {} +}; + +static const struct nvkm_specsrc +g84_tex_sources[] = { + { 0x408808, (const struct nvkm_specmux[]) { + { 0xf, 0, unk0 }, + {} + }, pgraph_tpc0_tex_unk08 }, + {} +}; + static const struct nvkm_specdom g84_pm[] = { { 0x20, (const struct nvkm_specsig[]) { {} }, nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { + { 0xf0, (const struct nvkm_specsig[]) { + { 0xbd, pc01_gr_idle }, + { 0x5e, pc01_strmout_00 }, + { 0x5f, pc01_strmout_01 }, + { 0xd2, pc01_trast_00 }, + { 0xd3, pc01_trast_01 }, + { 0xd4, pc01_trast_02 }, + { 0xd5, pc01_trast_03 }, + { 0xd8, pc01_trast_04 }, + { 0xd9, pc01_trast_05 }, + { 0x5c, pc01_vattr_00 }, + { 0x5d, pc01_vattr_01 }, + { 0x66, pc01_vfetch_00, g84_vfetch_sources }, + { 0x67, pc01_vfetch_01, g84_vfetch_sources }, + { 0x68, pc01_vfetch_02, g84_vfetch_sources }, + { 0x69, pc01_vfetch_03, g84_vfetch_sources }, + { 0x6a, pc01_vfetch_04, g84_vfetch_sources }, + { 0x6b, pc01_vfetch_05, g84_vfetch_sources }, + { 0x6c, pc01_vfetch_06, g84_vfetch_sources }, + { 0x6d, pc01_vfetch_07, g84_vfetch_sources }, +
[Nouveau] [PATCH RFC 12/20] pm: add concept of sources
From: Samuel Pitoiset samuel.pitoisetÅgmail.com A source (or multiplexer) is a tuple addr+mask+shift which allows to control a block of signals. The maximum number of sources that a signal can define is arbitrary limited to 8 and this should be large enough. This patch allows to define multi-level of sources for a signal. Each different sources are stored to a global list and will be exposed to the userspace through the nvif interface in order to avoid conflicts. Signed-off-by: Samuel Pitoiset samuel.pitoiset at gmail.com --- drm/nouveau/include/nvkm/engine/pm.h | 1 + drm/nouveau/nvkm/engine/pm/base.c| 82 ++-- drm/nouveau/nvkm/engine/pm/priv.h| 24 +++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvkm/engine/pm.h b/drm/nouveau/include/nvkm/engine/pm.h index 6c2d057..130b545 100644 --- a/drm/nouveau/include/nvkm/engine/pm.h +++ b/drm/nouveau/include/nvkm/engine/pm.h @@ -11,6 +11,7 @@ struct nvkm_pm { void *profile_data; struct list_head domains; + struct list_head sources; u32 sequence; }; diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 610c0ca..dfafefd 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -434,6 +434,67 @@ nvkm_pm_cclass = { * PPM engine/subdev functions **/ int +nvkm_perfsrc_new(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, +const struct nvkm_specsrc *spec) +{ + const struct nvkm_specsrc *ssrc; + const struct nvkm_specmux *smux; + struct nvkm_perfsrc *src; + u8 source_nr = 0; + + if (!spec) { + /* No sources are defined for this signal. */ + return 0; + } + + ssrc = spec; + while (ssrc-name) { + smux = ssrc-mux; + while (smux-name) { + bool found = false; + u8 source_id = 0; + u32 len; + + list_for_each_entry(src, ppm-sources, head) { + if (src-addr == ssrc-addr + src-shift == smux-shift) { + found = true; + break; + } + source_id++; + } + + if (!found) { + src = kzalloc(sizeof(*src), GFP_KERNEL); + if (!src) + return -ENOMEM; + + src-addr = ssrc-addr; + src-mask = smux-mask; + src-shift = smux-shift; + src-enable = smux-enable; + + len = strlen(ssrc-name) + + strlen(smux-name) + 2; + src-name = kzalloc(len, GFP_KERNEL); + if (!src-name) + return -ENOMEM; + snprintf(src-name, len, %s_%s, ssrc-name, +smux-name); + + list_add_tail(src-head, ppm-sources); + } + + sig-source[source_nr++] = source_id + 1; + smux++; + } + ssrc++; + } + + return 0; +} + +int nvkm_perfdom_new(struct nvkm_pm *ppm, const char *name, u32 mask, u32 base, u32 size_unit, u32 size_domain, const struct nvkm_specdom *spec) @@ -441,7 +502,7 @@ nvkm_perfdom_new(struct nvkm_pm *ppm, const char *name, u32 mask, const struct nvkm_specdom *sdom; const struct nvkm_specsig *ssig; struct nvkm_perfdom *dom; - int i; + int ret, i; for (i = 0; i == 0 || mask; i++) { u32 addr = base + (i * size_unit); @@ -473,7 +534,12 @@ nvkm_perfdom_new(struct nvkm_pm *ppm, const char *name, u32 mask, ssig = (sdom++)-signal; while (ssig-name) { - dom-signal[ssig-signal].name = ssig-name; + struct nvkm_perfsig *sig = + dom-signal[ssig-signal]; + sig-name = ssig-name; + ret = nvkm_perfsrc_new(ppm, sig, ssig-source); + if (ret) + return ret; ssig++; } @@ -504,13 +570,20 @@ void _nvkm_pm_dtor(struct nvkm_object *object) { struct nvkm_pm *ppm = (void *)object; - struct nvkm_perfdom *dom, *tmp; +
[Nouveau] [PATCH RFC 16/20] pm: allow to configure domains instead of simple counters
Configuring counters from the userspace require the kernel to handle some logic related to performance counters. Basically, it has to find a free slot to assign a counter, to handle extra counting modes like B4/B6 and it must return and error when it can't configure a counter. In my opinion, the kernel should not handle all of that logic but it should only write the configuration sent by the userspace without checking anything. In other words, it should overwrite the configuration even if it's already counting and do not return any errors. This patch allows the userspace to configure a domain instead of separate counters. This has the advantage to move all of the logic to the userspace. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- bin/nv_perfmon.c | 193 ++ drm/nouveau/include/nvif/class.h | 30 +++--- drm/nouveau/include/nvif/ioctl.h | 2 +- drm/nouveau/nvkm/engine/pm/base.c | 208 + drm/nouveau/nvkm/engine/pm/gf100.c | 10 +- drm/nouveau/nvkm/engine/pm/nv40.c | 10 +- drm/nouveau/nvkm/engine/pm/priv.h | 10 +- 7 files changed, 293 insertions(+), 170 deletions(-) diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c index 50c..47b2fef 100644 --- a/bin/nv_perfmon.c +++ b/bin/nv_perfmon.c @@ -248,7 +248,8 @@ ui_menu_win = { struct ui_perfmon_dom { struct list_head head; - struct list_head list; + struct list_head signals; + struct list_head perfdoms; u8 id; }; @@ -260,22 +261,27 @@ struct ui_perfmon_sig { struct ui_main { struct list_head head; - u32 handle; - struct nvif_object object; - const char *name; + struct ui_perfmon_sig *sig; u32 clk; u32 ctr; u64 incr; }; +struct ui_perfdom { + struct nvif_object object; + struct list_head head; + struct ui_main *ctr[4]; + u32 handle; +}; + static struct list_head ui_main_list = LIST_HEAD_INIT(ui_main_list); static struct list_head ui_doms_list = LIST_HEAD_INIT(ui_doms_list); +static struct list_head ui_perfdom_list = LIST_HEAD_INIT(ui_perfdom_list); static u32 ui_main_handle = 0xc000; static void ui_main_remove(struct ui_main *item) { - nvif_object_fini(item-object); list_del(item-head); free(item); } @@ -303,7 +309,7 @@ ui_perfmon_query_signals(struct nvif_object *perfmon, sig-signal = args.signal; sig-name = malloc(sizeof(args.name)); strncpy(sig-name, args.name, sizeof(args.name)); - list_add_tail(sig-head, dom-list); + list_add_tail(sig-head, dom-signals); args.iter = prev_iter; ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_SIGNAL, @@ -331,7 +337,8 @@ ui_perfmon_query_domains(struct nvif_object *perfmon) if (prev_iter) { dom = calloc(1, sizeof(*dom)); dom-id = args.id; - INIT_LIST_HEAD(dom-list); + INIT_LIST_HEAD(dom-signals); + INIT_LIST_HEAD(dom-perfdoms); list_add_tail(dom-head, ui_doms_list); args.iter = prev_iter; @@ -346,6 +353,49 @@ ui_perfmon_query_domains(struct nvif_object *perfmon) } static void +ui_perfdom_init(struct ui_perfdom *dom) +{ + struct nvif_perfdom_init args = {}; + int ret; + + ret = nvif_mthd(dom-object, NVIF_PERFDOM_V0_INIT, + args, sizeof(args)); + assert(ret == 0); +} + +static void +ui_perfdom_sample(struct ui_perfdom *dom) +{ + struct nvif_perfdom_sample args = {}; + int ret; + + ret = nvif_mthd(dom-object, NVIF_PERFDOM_V0_SAMPLE, + args, sizeof(args)); + assert(ret == 0); +} + +static void +ui_perfdom_read(struct ui_perfdom *dom) +{ + struct nvif_perfdom_read_v0 args = {}; + int ret, i; + + ret = nvif_mthd(dom-object, NVIF_PERFDOM_V0_READ, + args, sizeof(args)); + assert(ret == 0 || ret == -EAGAIN); + + if (ret == 0) { + for (i = 0; i 4; i++) { + if (!dom-ctr[i]) + continue; + dom-ctr[i]-ctr = args.ctr[i]; + dom-ctr[i]-incr += args.ctr[i]; + dom-ctr[i]-clk = args.clk; + } + } +} + +static void ui_perfmon_init(void) { struct nvif_object perfmon; @@ -362,17 +412,37 @@ ui_perfmon_init(void) } static void +ui_perfmon_free_signals(struct ui_perfmon_dom *dom) +{ + struct ui_perfmon_sig *sig, *next; + + list_for_each_entry_safe(sig, next, dom-signals, head) { + list_del(sig-head); + free(sig-name); + free(sig); + } +} + +static void
[Nouveau] [PATCH RFC 01/20] pm: prevent freeing the wrong engine context
This fixes a crash when multiple PM engine contexts are created. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com Reviewed-by: Martin Peres martin.pe...@free.fr --- drm/nouveau/nvkm/engine/pm/base.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 2006c44..274457c 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -332,9 +332,12 @@ static void nvkm_perfctx_dtor(struct nvkm_object *object) { struct nvkm_pm *ppm = (void *)object-engine; + struct nvkm_perfctx *ctx = (void *)object; + mutex_lock(nv_subdev(ppm)-mutex); - nvkm_engctx_destroy(ppm-context-base); - ppm-context = NULL; + nvkm_engctx_destroy(ctx-base); + if (ppm-context == ctx) + ppm-context = NULL; mutex_unlock(nv_subdev(ppm)-mutex); } -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 00/20] expose global performance counters
Hello, This series exposes global performance counters (PCOUNTER) to the userspace through the nvif interface by reworking most of the code related to the PM engine. This interface will allow the userspace to control and monitor complex hardware events like the proprietary driver already does, for example with CUPTI and PerfKit. For now, this series only exposes performance counters on NV50, but this is going to be pretty similar for other families. My plan is to submit more patches for Fermi and Kepler after this series will be reviewed. The code of this series can be found here: http://cgit.freedesktop.org/~hakzsam/nouveau/log/?h=nouveau_perfmon And the corresponding libdrm branch can be found here: http://cgit.freedesktop.org/~hakzsam/drm/log/?h=nouveau_perfmon A full example which exposes both compute and graphics hardware events on NV50 can be found here: http://cgit.freedesktop.org/~hakzsam/perfevent Most of the code will be implemented in mesa once the kernel interface is going to be upstream and stable. Below, you can find a summary of the series: Patches 1-2:fix a bug related to the PM engine context Patches 3-4:remove useless PMU signals and unused functions Patches 5-6:reorganize the nvif interface to expose more stuff Patches 7-11: expose PCOUNTER domains to the userspace Patches 12-14: implement concept of sources (ie. multiplexers) Patches 15-17: allow to monitor complex hardware events Patches 18: add compute/graphics signals/sources Patches 19-20: expose a software methods interface for controlling PM Feel free to make a review. Thanks in advance! Samuel Pitoiset (20): pm: prevent freeing the wrong engine context pm: fix a potential race condition when creating an engine context pm: remove pmu signals pm: remove unused nvkm_perfsig_wrap() function pm: reorganize the nvif interface pm: prevent creating a perfctr object when signals are not found pm: implement NVIF_PERFMON_V0_QUERY_DOMAIN method pm: allow to query signals by domain pm: change signal iter to u16 pm: use hardware signals indexes instead of user-readable names pm: allow to monitor hardware signal index 0x00 pm: add concept of sources pm: allow to query the number of sources for a signal pm: implement NVIF_PERFMON_V0_QUERY_SOURCE method pm: allow the userspace to schedule hardware counters pm: allow to configure domains instead of simple counters pm: allow the userspace to configure sources pm/nv50: add compute and graphics signals/sources sw/nv50: add some private functions to factorize code sw/nv50: add and interface for controlling performance counters bin/nv_perfmon.c | 324 drm/nouveau/include/nvif/class.h | 68 +++- drm/nouveau/include/nvif/ioctl.h | 5 +- drm/nouveau/include/nvkm/engine/pm.h | 6 +- drm/nouveau/nvkm/engine/device/nv50.c | 2 +- drm/nouveau/nvkm/engine/pm/Kbuild | 2 +- drm/nouveau/nvkm/engine/pm/base.c | 685 +- drm/nouveau/nvkm/engine/pm/daemon.c | 108 -- drm/nouveau/nvkm/engine/pm/g84.c | 101 - drm/nouveau/nvkm/engine/pm/gf100.c| 13 +- drm/nouveau/nvkm/engine/pm/gk104.c| 6 - drm/nouveau/nvkm/engine/pm/gk110.c| 4 - drm/nouveau/nvkm/engine/pm/gt200.c| 163 drm/nouveau/nvkm/engine/pm/gt215.c| 104 -- drm/nouveau/nvkm/engine/pm/nv40.c | 8 +- drm/nouveau/nvkm/engine/pm/nv50.c | 136 ++- drm/nouveau/nvkm/engine/pm/priv.h | 53 ++- drm/nouveau/nvkm/engine/sw/nv50.c | 216 ++- drm/nouveau/nvkm/engine/sw/nv50.h | 6 + 19 files changed, 1561 insertions(+), 449 deletions(-) delete mode 100644 drm/nouveau/nvkm/engine/pm/daemon.c create mode 100644 drm/nouveau/nvkm/engine/pm/gt200.c -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 02/20] pm: fix a potential race condition when creating an engine context
There is always the possiblity that the ppm-context pointer would get partially updated and accidentally would equal ctx. This would allow two contexts to co-exist, which is not acceptable. Moving the test to the critical section takes care of this problem. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com Signed-off-by: Martin Peres martin.pe...@free.fr --- drm/nouveau/nvkm/engine/pm/base.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 274457c..4cf36a3 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -358,12 +358,11 @@ nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine, mutex_lock(nv_subdev(ppm)-mutex); if (ppm-context == NULL) ppm-context = ctx; - mutex_unlock(nv_subdev(ppm)-mutex); - if (ctx != ppm-context) - return -EBUSY; + ret = -EBUSY; + mutex_unlock(nv_subdev(ppm)-mutex); - return 0; + return ret; } struct nvkm_oclass -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 06/20] pm: prevent creating a perfctr object when signals are not found
Since a new class has been introduced to query signals, we can now return an error when the userspace wants to monitor unknown signals. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/nvkm/engine/pm/base.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index cb88170..2f85147 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -294,6 +294,9 @@ nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, return -EINVAL; } + if (!dom) + return -EINVAL; + ret = nvkm_object_create(parent, engine, oclass, 0, ctr); *pobject = nv_object(ctr); if (ret) @@ -305,8 +308,7 @@ nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ctr-signal[1] = sig[1]; ctr-signal[2] = sig[2]; ctr-signal[3] = sig[3]; - if (dom) - list_add_tail(ctr-head, dom-list); + list_add_tail(ctr-head, dom-list); return 0; } -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 04/20] pm: remove unused nvkm_perfsig_wrap() function
Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com Reviewed-by: Martin Peres martin.pe...@free.fr --- drm/nouveau/nvkm/engine/pm/base.c | 20 drm/nouveau/nvkm/engine/pm/priv.h | 4 2 files changed, 24 deletions(-) diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 4cf36a3..7b07e8b 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -79,26 +79,6 @@ nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size, return nvkm_perfsig_find_(dom, name, size); } -struct nvkm_perfctr * -nvkm_perfsig_wrap(struct nvkm_pm *ppm, const char *name, - struct nvkm_perfdom **pdom) -{ - struct nvkm_perfsig *sig; - struct nvkm_perfctr *ctr; - - sig = nvkm_perfsig_find(ppm, name, strlen(name), pdom); - if (!sig) - return NULL; - - ctr = kzalloc(sizeof(*ctr), GFP_KERNEL); - if (ctr) { - ctr-signal[0] = sig; - ctr-logic_op = 0x; - } - - return ctr; -} - /*** * Perfmon object classes **/ diff --git a/drm/nouveau/nvkm/engine/pm/priv.h b/drm/nouveau/nvkm/engine/pm/priv.h index 95796c7..06a6e60 100644 --- a/drm/nouveau/nvkm/engine/pm/priv.h +++ b/drm/nouveau/nvkm/engine/pm/priv.h @@ -31,10 +31,6 @@ struct nvkm_perfsig { const char *name; }; -struct nvkm_perfdom; -struct nvkm_perfctr * -nvkm_perfsig_wrap(struct nvkm_pm *, const char *, struct nvkm_perfdom **); - struct nvkm_specdom { u16 signal_nr; const struct nvkm_specsig *signal; -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH RFC 10/20] pm: use hardware signals indexes instead of user-readable names
Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- bin/nv_perfmon.c | 6 +++-- drm/nouveau/include/nvif/class.h | 11 ++--- drm/nouveau/nvkm/engine/pm/base.c | 52 +-- 3 files changed, 23 insertions(+), 46 deletions(-) diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c index 043d864..50c 100644 --- a/bin/nv_perfmon.c +++ b/bin/nv_perfmon.c @@ -255,6 +255,7 @@ struct ui_perfmon_dom { struct ui_perfmon_sig { struct list_head head; char *name; + u8 signal; }; struct ui_main { @@ -299,6 +300,7 @@ ui_perfmon_query_signals(struct nvif_object *perfmon, if (prev_iter) { nr_signals++; sig = calloc(1, sizeof(*sig)); + sig-signal = args.signal; sig-name = malloc(sizeof(args.name)); strncpy(sig-name, args.name, sizeof(args.name)); list_add_tail(sig-head, dom-list); @@ -392,14 +394,14 @@ ui_main_select(void) list_for_each_entry(sig, dom-list, head) { struct nvif_perfctr_v0 args = { .logic_op = 0x, + .domain = dom-id, }; item = calloc(1, sizeof(*item)); item-handle = ui_main_handle++; item-name = sig-name; - strncpy(args.name[0], item-name, sizeof(args.name[0])); - + args.signal[0] = sig-signal; ret = nvif_object_init(nvif_object(device), NULL, item-handle, NVIF_IOCTL_NEW_V0_PERFCTR, diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index 871247c..9e4db3a 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -267,7 +267,8 @@ struct nvif_perfmon_query_signal_v0 { __u8 version; __u8 domain; __u16 iter; - __u8 pad03[4]; + __u8 signal; + __u8 pad04[3]; char name[64]; }; @@ -278,10 +279,12 @@ struct nvif_perfmon_query_signal_v0 { struct nvif_perfctr_v0 { __u8 version; - __u8 pad01[1]; + __u8 domain; + __u8 pad02[2]; __u16 logic_op; - __u8 pad04[4]; - char name[4][64]; + __u8 pad04[2]; + __u8 signal[4]; + __u8 pad06[4]; }; #define NVIF_PERFCTR_V0_SAMPLE 0x00 diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index fab0598..71834b9 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -73,49 +73,22 @@ nvkm_perfdom_find(struct nvkm_pm *ppm, int di) return NULL; } -static struct nvkm_perfsig * -nvkm_perfsig_find_(struct nvkm_perfdom *dom, const char *name, u32 size) -{ - char path[64]; - int i; - - if (name[0] != '/') { - for (i = 0; i dom-signal_nr; i++) { - if ( dom-signal[i].name - !strncmp(name, dom-signal[i].name, size)) - return dom-signal[i]; - } - } else { - for (i = 0; i dom-signal_nr; i++) { - snprintf(path, sizeof(path), /%s/%02x, dom-name, i); - if (!strncmp(name, path, size)) - return dom-signal[i]; - } - } - - return NULL; -} - struct nvkm_perfsig * -nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size, +nvkm_perfsig_find(struct nvkm_pm *ppm, uint8_t di, uint8_t si, struct nvkm_perfdom **pdom) { struct nvkm_perfdom *dom = *pdom; - struct nvkm_perfsig *sig; if (dom == NULL) { - list_for_each_entry(dom, ppm-domains, head) { - sig = nvkm_perfsig_find_(dom, name, size); - if (sig) { - *pdom = dom; - return sig; - } - } - - return NULL; + dom = nvkm_perfdom_find(ppm, di); + if (dom == NULL) + return NULL; + *pdom = dom; } - return nvkm_perfsig_find_(dom, name, size); + if (!dom-signal[si].name) + return NULL; + return dom-signal[si]; } /*** @@ -200,6 +173,7 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) } else { strncpy(args-v0.name, name, sizeof(args-v0.name)); } + args-v0.signal = si; } while (++si
[Nouveau] [PATCH RFC 11/20] pm: allow to monitor hardware signal index 0x00
This signal index must be always allowed even if it's not clearly defined in a domain in order to monitor a counter like 0x03020100 because it's the default value of signals. Signed-off-by: Samuel Pitoiset samuel.pitoi...@gmail.com --- drm/nouveau/nvkm/engine/pm/base.c | 4 ++-- drm/nouveau/nvkm/engine/pm/gf100.c | 6 -- drm/nouveau/nvkm/engine/pm/nv40.c | 6 -- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index 71834b9..610c0ca 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -333,10 +333,10 @@ nvkm_perfctr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, } else return ret; - for (i = 0; i ARRAY_SIZE(args-v0.signal) args-v0.signal[i]; i++) { + for (i = 0; i ARRAY_SIZE(args-v0.signal); i++) { sig[i] = nvkm_perfsig_find(ppm, args-v0.domain, args-v0.signal[i], dom); - if (!sig[i]) + if (args-v0.signal[i] !sig[i]) return -EINVAL; } diff --git a/drm/nouveau/nvkm/engine/pm/gf100.c b/drm/nouveau/nvkm/engine/pm/gf100.c index 69303b5..41350d6 100644 --- a/drm/nouveau/nvkm/engine/pm/gf100.c +++ b/drm/nouveau/nvkm/engine/pm/gf100.c @@ -48,8 +48,10 @@ gf100_perfctr_init(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, u32 src = 0x; int i; - for (i = 0; i 4 ctr-signal[i]; i++) - src |= (ctr-signal[i] - dom-signal) (i * 8); + for (i = 0; i 4; i++) { + if (ctr-signal[i]) + src |= (ctr-signal[i] - dom-signal) (i * 8); + } nv_wr32(priv, dom-addr + 0x09c, 0x00040002); nv_wr32(priv, dom-addr + 0x100, 0x); diff --git a/drm/nouveau/nvkm/engine/pm/nv40.c b/drm/nouveau/nvkm/engine/pm/nv40.c index ff22f06..603874e 100644 --- a/drm/nouveau/nvkm/engine/pm/nv40.c +++ b/drm/nouveau/nvkm/engine/pm/nv40.c @@ -33,8 +33,10 @@ nv40_perfctr_init(struct nvkm_pm *ppm, struct nvkm_perfdom *dom, u32 src = 0x; int i; - for (i = 0; i 4 ctr-signal[i]; i++) - src |= (ctr-signal[i] - dom-signal) (i * 8); + for (i = 0; i 4; i++) { + if (ctr-signal[i]) + src |= (ctr-signal[i] - dom-signal) (i * 8); + } nv_wr32(priv, 0x00a7c0 + dom-addr, 0x0001); nv_wr32(priv, 0x00a400 + dom-addr + (cntr-base.slot * 0x40), src); -- 2.4.2 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 83897] [NVE6] GK106 (GeForce GTX 660): Frequent GPU lockups
https://bugs.freedesktop.org/show_bug.cgi?id=83897 freedesk.apri...@spamgourmet.com changed: What|Removed |Added CC||freedesk.apriori@spamgourme ||t.com --- Comment #6 from freedesk.apri...@spamgourmet.com --- Created attachment 116335 -- https://bugs.freedesktop.org/attachment.cgi?id=116335action=edit Recent lock-up logs, on Linux 4.0.3 and 4.0.4 I tried running Nouveau on Linux 4 again for a while, but the driver still locks up frequently. Here’s some of the recent logs in case it helps. -- You are receiving this mail because: You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 90883] Random text characters partially or completely missing
https://bugs.freedesktop.org/show_bug.cgi?id=90883 Michel Dänzer mic...@daenzer.net changed: What|Removed |Added Component|Server/General |Driver/nouveau Assignee|xorg-t...@lists.x.org |nouveau@lists.freedesktop.o ||rg -- You are receiving this mail because: You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau