aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-11 00:38:10 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-09-15 08:22:12 -0400
commitb38a2322df62dbcd423d3e329f401eb14c1f0e4a (patch)
tree077c38ef3ea2c1d446e2e7961c96ed3d15c92c2e
parent996f5a08235b27a7adcd01fe2b3f79e2f0f20ced (diff)
drm/nv50-/disp: add support for completion events
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/gm107.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c89
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c49
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvif/class.h9
11 files changed, 173 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
index d54da8b5f87e..c8e4e60b86f1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
@@ -68,6 +68,10 @@ gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
68 if (ret) 68 if (ret)
69 return ret; 69 return ret;
70 70
71 ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent);
72 if (ret)
73 return ret;
74
71 nv_engine(priv)->sclass = gm107_disp_base_oclass; 75 nv_engine(priv)->sclass = gm107_disp_base_oclass;
72 nv_engine(priv)->cclass = &nv50_disp_cclass; 76 nv_engine(priv)->cclass = &nv50_disp_cclass;
73 nv_subdev(priv)->intr = nvd0_disp_intr; 77 nv_subdev(priv)->intr = nvd0_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 4b5bb5d58a54..86fda5d51ed4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -29,6 +29,7 @@
29#include <core/enum.h> 29#include <core/enum.h>
30#include <nvif/unpack.h> 30#include <nvif/unpack.h>
31#include <nvif/class.h> 31#include <nvif/class.h>
32#include <nvif/event.h>
32 33
33#include <subdev/bios.h> 34#include <subdev/bios.h>
34#include <subdev/bios/dcb.h> 35#include <subdev/bios/dcb.h>
@@ -82,6 +83,71 @@ nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
82 nouveau_namedb_destroy(&chan->base); 83 nouveau_namedb_destroy(&chan->base);
83} 84}
84 85
86static void
87nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index)
88{
89 struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent);
90 nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000000 << index);
91}
92
93static void
94nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
95{
96 struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent);
97 nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000001 << index);
98}
99
100void
101nv50_disp_chan_uevent_send(struct nv50_disp_priv *priv, int chid)
102{
103 struct nvif_notify_uevent_rep {
104 } rep;
105
106 nvkm_event_send(&priv->uevent, 1, chid, &rep, sizeof(rep));
107}
108
109int
110nv50_disp_chan_uevent_ctor(struct nouveau_object *object, void *data, u32 size,
111 struct nvkm_notify *notify)
112{
113 struct nv50_disp_dmac *dmac = (void *)object;
114 union {
115 struct nvif_notify_uevent_req none;
116 } *args = data;
117 int ret;
118
119 if (nvif_unvers(args->none)) {
120 notify->size = sizeof(struct nvif_notify_uevent_rep);
121 notify->types = 1;
122 notify->index = dmac->base.chid;
123 return 0;
124 }
125
126 return ret;
127}
128
129const struct nvkm_event_func
130nv50_disp_chan_uevent = {
131 .ctor = nv50_disp_chan_uevent_ctor,
132 .init = nv50_disp_chan_uevent_init,
133 .fini = nv50_disp_chan_uevent_fini,
134};
135
136int
137nv50_disp_chan_ntfy(struct nouveau_object *object, u32 type,
138 struct nvkm_event **pevent)
139{
140 struct nv50_disp_priv *priv = (void *)object->engine;
141 switch (type) {
142 case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT:
143 *pevent = &priv->uevent;
144 return 0;
145 default:
146 break;
147 }
148 return -EINVAL;
149}
150
85int 151int
86nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size) 152nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size)
87{ 153{
@@ -195,7 +261,7 @@ nv50_disp_dmac_init(struct nouveau_object *object)
195 return ret; 261 return ret;
196 262
197 /* enable error reporting */ 263 /* enable error reporting */
198 nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00010001 << chid); 264 nv_mask(priv, 0x610028, 0x00010000 << chid, 0x00010000 << chid);
199 265
200 /* initialise channel for dma command submission */ 266 /* initialise channel for dma command submission */
201 nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push); 267 nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push);
@@ -232,7 +298,7 @@ nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend)
232 return -EBUSY; 298 return -EBUSY;
233 } 299 }
234 300
235 /* disable error reporting */ 301 /* disable error reporting and completion notifications */
236 nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid); 302 nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid);
237 303
238 return nv50_disp_chan_fini(&dmac->base, suspend); 304 return nv50_disp_chan_fini(&dmac->base, suspend);
@@ -454,7 +520,7 @@ nv50_disp_mast_init(struct nouveau_object *object)
454 return ret; 520 return ret;
455 521
456 /* enable error reporting */ 522 /* enable error reporting */
457 nv_mask(priv, 0x610028, 0x00010001, 0x00010001); 523 nv_mask(priv, 0x610028, 0x00010000, 0x00010000);
458 524
459 /* attempt to unstick channel from some unknown state */ 525 /* attempt to unstick channel from some unknown state */
460 if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000) 526 if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000)
@@ -494,7 +560,7 @@ nv50_disp_mast_fini(struct nouveau_object *object, bool suspend)
494 return -EBUSY; 560 return -EBUSY;
495 } 561 }
496 562
497 /* disable error reporting */ 563 /* disable error reporting and completion notifications */
498 nv_mask(priv, 0x610028, 0x00010001, 0x00000000); 564 nv_mask(priv, 0x610028, 0x00010001, 0x00000000);
499 565
500 return nv50_disp_chan_fini(&mast->base, suspend); 566 return nv50_disp_chan_fini(&mast->base, suspend);
@@ -507,6 +573,7 @@ nv50_disp_mast_ofuncs = {
507 .base.init = nv50_disp_mast_init, 573 .base.init = nv50_disp_mast_init,
508 .base.fini = nv50_disp_mast_fini, 574 .base.fini = nv50_disp_mast_fini,
509 .base.map = nv50_disp_chan_map, 575 .base.map = nv50_disp_chan_map,
576 .base.ntfy = nv50_disp_chan_ntfy,
510 .base.rd32 = nv50_disp_chan_rd32, 577 .base.rd32 = nv50_disp_chan_rd32,
511 .base.wr32 = nv50_disp_chan_wr32, 578 .base.wr32 = nv50_disp_chan_wr32,
512 .chid = 0, 579 .chid = 0,
@@ -607,6 +674,7 @@ nv50_disp_sync_ofuncs = {
607 .base.dtor = nv50_disp_dmac_dtor, 674 .base.dtor = nv50_disp_dmac_dtor,
608 .base.init = nv50_disp_dmac_init, 675 .base.init = nv50_disp_dmac_init,
609 .base.fini = nv50_disp_dmac_fini, 676 .base.fini = nv50_disp_dmac_fini,
677 .base.ntfy = nv50_disp_chan_ntfy,
610 .base.map = nv50_disp_chan_map, 678 .base.map = nv50_disp_chan_map,
611 .base.rd32 = nv50_disp_chan_rd32, 679 .base.rd32 = nv50_disp_chan_rd32,
612 .base.wr32 = nv50_disp_chan_wr32, 680 .base.wr32 = nv50_disp_chan_wr32,
@@ -696,6 +764,7 @@ nv50_disp_ovly_ofuncs = {
696 .base.dtor = nv50_disp_dmac_dtor, 764 .base.dtor = nv50_disp_dmac_dtor,
697 .base.init = nv50_disp_dmac_init, 765 .base.init = nv50_disp_dmac_init,
698 .base.fini = nv50_disp_dmac_fini, 766 .base.fini = nv50_disp_dmac_fini,
767 .base.ntfy = nv50_disp_chan_ntfy,
699 .base.map = nv50_disp_chan_map, 768 .base.map = nv50_disp_chan_map,
700 .base.rd32 = nv50_disp_chan_rd32, 769 .base.rd32 = nv50_disp_chan_rd32,
701 .base.wr32 = nv50_disp_chan_wr32, 770 .base.wr32 = nv50_disp_chan_wr32,
@@ -813,6 +882,7 @@ nv50_disp_oimm_ofuncs = {
813 .base.dtor = nv50_disp_pioc_dtor, 882 .base.dtor = nv50_disp_pioc_dtor,
814 .base.init = nv50_disp_pioc_init, 883 .base.init = nv50_disp_pioc_init,
815 .base.fini = nv50_disp_pioc_fini, 884 .base.fini = nv50_disp_pioc_fini,
885 .base.ntfy = nv50_disp_chan_ntfy,
816 .base.map = nv50_disp_chan_map, 886 .base.map = nv50_disp_chan_map,
817 .base.rd32 = nv50_disp_chan_rd32, 887 .base.rd32 = nv50_disp_chan_rd32,
818 .base.wr32 = nv50_disp_chan_wr32, 888 .base.wr32 = nv50_disp_chan_wr32,
@@ -860,6 +930,7 @@ nv50_disp_curs_ofuncs = {
860 .base.dtor = nv50_disp_pioc_dtor, 930 .base.dtor = nv50_disp_pioc_dtor,
861 .base.init = nv50_disp_pioc_init, 931 .base.init = nv50_disp_pioc_init,
862 .base.fini = nv50_disp_pioc_fini, 932 .base.fini = nv50_disp_pioc_fini,
933 .base.ntfy = nv50_disp_chan_ntfy,
863 .base.map = nv50_disp_chan_map, 934 .base.map = nv50_disp_chan_map,
864 .base.rd32 = nv50_disp_chan_rd32, 935 .base.rd32 = nv50_disp_chan_rd32,
865 .base.wr32 = nv50_disp_chan_wr32, 936 .base.wr32 = nv50_disp_chan_wr32,
@@ -1846,6 +1917,12 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
1846 intr0 &= ~(0x00010000 << chid); 1917 intr0 &= ~(0x00010000 << chid);
1847 } 1918 }
1848 1919
1920 while (intr0 & 0x0000001f) {
1921 u32 chid = __ffs(intr0 & 0x0000001f);
1922 nv50_disp_chan_uevent_send(priv, chid);
1923 intr0 &= ~(0x00000001 << chid);
1924 }
1925
1849 if (intr1 & 0x00000004) { 1926 if (intr1 & 0x00000004) {
1850 nouveau_disp_vblank(&priv->base, 0); 1927 nouveau_disp_vblank(&priv->base, 0);
1851 nv_wr32(priv, 0x610024, 0x00000004); 1928 nv_wr32(priv, 0x610024, 0x00000004);
@@ -1880,6 +1957,10 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1880 if (ret) 1957 if (ret)
1881 return ret; 1958 return ret;
1882 1959
1960 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent);
1961 if (ret)
1962 return ret;
1963
1883 nv_engine(priv)->sclass = nv50_disp_base_oclass; 1964 nv_engine(priv)->sclass = nv50_disp_base_oclass;
1884 nv_engine(priv)->cclass = &nv50_disp_cclass; 1965 nv_engine(priv)->cclass = &nv50_disp_cclass;
1885 nv_subdev(priv)->intr = nv50_disp_intr; 1966 nv_subdev(priv)->intr = nv50_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 8ab14461f70c..a288a7f454aa 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -26,6 +26,8 @@ struct nv50_disp_priv {
26 struct work_struct supervisor; 26 struct work_struct supervisor;
27 u32 super; 27 u32 super;
28 28
29 struct nvkm_event uevent;
30
29 struct { 31 struct {
30 int nr; 32 int nr;
31 } head; 33 } head;
@@ -116,9 +118,16 @@ struct nv50_disp_chan {
116 int chid; 118 int chid;
117}; 119};
118 120
121int nv50_disp_chan_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
119int nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *); 122int nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *);
120u32 nv50_disp_chan_rd32(struct nouveau_object *, u64); 123u32 nv50_disp_chan_rd32(struct nouveau_object *, u64);
121void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32); 124void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32);
125extern const struct nvkm_event_func nv50_disp_chan_uevent;
126int nv50_disp_chan_uevent_ctor(struct nouveau_object *, void *, u32,
127 struct nvkm_notify *);
128void nv50_disp_chan_uevent_send(struct nv50_disp_priv *, int);
129
130extern const struct nvkm_event_func nvd0_disp_chan_uevent;
122 131
123#define nv50_disp_chan_init(a) \ 132#define nv50_disp_chan_init(a) \
124 nouveau_namedb_init(&(a)->base) 133 nouveau_namedb_init(&(a)->base)
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index 788ced1b6182..d36284715b2a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -236,6 +236,10 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
236 if (ret) 236 if (ret)
237 return ret; 237 return ret;
238 238
239 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent);
240 if (ret)
241 return ret;
242
239 nv_engine(priv)->sclass = nv84_disp_base_oclass; 243 nv_engine(priv)->sclass = nv84_disp_base_oclass;
240 nv_engine(priv)->cclass = &nv50_disp_cclass; 244 nv_engine(priv)->cclass = &nv50_disp_cclass;
241 nv_subdev(priv)->intr = nv50_disp_intr; 245 nv_subdev(priv)->intr = nv50_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index fa79de906eae..a117064002b1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -95,6 +95,10 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
95 if (ret) 95 if (ret)
96 return ret; 96 return ret;
97 97
98 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent);
99 if (ret)
100 return ret;
101
98 nv_engine(priv)->sclass = nv94_disp_base_oclass; 102 nv_engine(priv)->sclass = nv94_disp_base_oclass;
99 nv_engine(priv)->cclass = &nv50_disp_cclass; 103 nv_engine(priv)->cclass = &nv50_disp_cclass;
100 nv_subdev(priv)->intr = nv50_disp_intr; 104 nv_subdev(priv)->intr = nv50_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index 7af15f5d48dc..c67e68aadd45 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -112,6 +112,10 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
112 if (ret) 112 if (ret)
113 return ret; 113 return ret;
114 114
115 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent);
116 if (ret)
117 return ret;
118
115 nv_engine(priv)->sclass = nva0_disp_base_oclass; 119 nv_engine(priv)->sclass = nva0_disp_base_oclass;
116 nv_engine(priv)->cclass = &nv50_disp_cclass; 120 nv_engine(priv)->cclass = &nv50_disp_cclass;
117 nv_subdev(priv)->intr = nv50_disp_intr; 121 nv_subdev(priv)->intr = nv50_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index 6bd39448f8da..22969f355aae 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -67,6 +67,10 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
67 if (ret) 67 if (ret)
68 return ret; 68 return ret;
69 69
70 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent);
71 if (ret)
72 return ret;
73
70 nv_engine(priv)->sclass = nva3_disp_base_oclass; 74 nv_engine(priv)->sclass = nva3_disp_base_oclass;
71 nv_engine(priv)->cclass = &nv50_disp_cclass; 75 nv_engine(priv)->cclass = &nv50_disp_cclass;
72 nv_subdev(priv)->intr = nv50_disp_intr; 76 nv_subdev(priv)->intr = nv50_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index a4bb3c774ee1..a571c4fd6d53 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -43,6 +43,31 @@
43#include "nv50.h" 43#include "nv50.h"
44 44
45/******************************************************************************* 45/*******************************************************************************
46 * EVO channel base class
47 ******************************************************************************/
48
49static void
50nvd0_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index)
51{
52 struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent);
53 nv_mask(priv, 0x610090, 0x00000001 << index, 0x00000000 << index);
54}
55
56static void
57nvd0_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
58{
59 struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent);
60 nv_mask(priv, 0x610090, 0x00000001 << index, 0x00000001 << index);
61}
62
63const struct nvkm_event_func
64nvd0_disp_chan_uevent = {
65 .ctor = nv50_disp_chan_uevent_ctor,
66 .init = nvd0_disp_chan_uevent_init,
67 .fini = nvd0_disp_chan_uevent_fini,
68};
69
70/*******************************************************************************
46 * EVO DMA channel base class 71 * EVO DMA channel base class
47 ******************************************************************************/ 72 ******************************************************************************/
48 73
@@ -77,7 +102,6 @@ nvd0_disp_dmac_init(struct nouveau_object *object)
77 return ret; 102 return ret;
78 103
79 /* enable error reporting */ 104 /* enable error reporting */
80 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
81 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); 105 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
82 106
83 /* initialise channel for dma command submission */ 107 /* initialise channel for dma command submission */
@@ -115,7 +139,7 @@ nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)
115 return -EBUSY; 139 return -EBUSY;
116 } 140 }
117 141
118 /* disable error reporting */ 142 /* disable error reporting and completion notification */
119 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); 143 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000);
120 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); 144 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000);
121 145
@@ -278,7 +302,6 @@ nvd0_disp_mast_init(struct nouveau_object *object)
278 return ret; 302 return ret;
279 303
280 /* enable error reporting */ 304 /* enable error reporting */
281 nv_mask(priv, 0x610090, 0x00000001, 0x00000001);
282 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001); 305 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001);
283 306
284 /* initialise channel for dma command submission */ 307 /* initialise channel for dma command submission */
@@ -313,7 +336,7 @@ nvd0_disp_mast_fini(struct nouveau_object *object, bool suspend)
313 return -EBUSY; 336 return -EBUSY;
314 } 337 }
315 338
316 /* disable error reporting */ 339 /* disable error reporting and completion notification */
317 nv_mask(priv, 0x610090, 0x00000001, 0x00000000); 340 nv_mask(priv, 0x610090, 0x00000001, 0x00000000);
318 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000); 341 nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000);
319 342
@@ -326,6 +349,7 @@ nvd0_disp_mast_ofuncs = {
326 .base.dtor = nv50_disp_dmac_dtor, 349 .base.dtor = nv50_disp_dmac_dtor,
327 .base.init = nvd0_disp_mast_init, 350 .base.init = nvd0_disp_mast_init,
328 .base.fini = nvd0_disp_mast_fini, 351 .base.fini = nvd0_disp_mast_fini,
352 .base.ntfy = nv50_disp_chan_ntfy,
329 .base.map = nv50_disp_chan_map, 353 .base.map = nv50_disp_chan_map,
330 .base.rd32 = nv50_disp_chan_rd32, 354 .base.rd32 = nv50_disp_chan_rd32,
331 .base.wr32 = nv50_disp_chan_wr32, 355 .base.wr32 = nv50_disp_chan_wr32,
@@ -419,6 +443,7 @@ nvd0_disp_sync_ofuncs = {
419 .base.dtor = nv50_disp_dmac_dtor, 443 .base.dtor = nv50_disp_dmac_dtor,
420 .base.init = nvd0_disp_dmac_init, 444 .base.init = nvd0_disp_dmac_init,
421 .base.fini = nvd0_disp_dmac_fini, 445 .base.fini = nvd0_disp_dmac_fini,
446 .base.ntfy = nv50_disp_chan_ntfy,
422 .base.map = nv50_disp_chan_map, 447 .base.map = nv50_disp_chan_map,
423 .base.rd32 = nv50_disp_chan_rd32, 448 .base.rd32 = nv50_disp_chan_rd32,
424 .base.wr32 = nv50_disp_chan_wr32, 449 .base.wr32 = nv50_disp_chan_wr32,
@@ -499,6 +524,7 @@ nvd0_disp_ovly_ofuncs = {
499 .base.dtor = nv50_disp_dmac_dtor, 524 .base.dtor = nv50_disp_dmac_dtor,
500 .base.init = nvd0_disp_dmac_init, 525 .base.init = nvd0_disp_dmac_init,
501 .base.fini = nvd0_disp_dmac_fini, 526 .base.fini = nvd0_disp_dmac_fini,
527 .base.ntfy = nv50_disp_chan_ntfy,
502 .base.map = nv50_disp_chan_map, 528 .base.map = nv50_disp_chan_map,
503 .base.rd32 = nv50_disp_chan_rd32, 529 .base.rd32 = nv50_disp_chan_rd32,
504 .base.wr32 = nv50_disp_chan_wr32, 530 .base.wr32 = nv50_disp_chan_wr32,
@@ -524,7 +550,6 @@ nvd0_disp_pioc_init(struct nouveau_object *object)
524 return ret; 550 return ret;
525 551
526 /* enable error reporting */ 552 /* enable error reporting */
527 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
528 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); 553 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
529 554
530 /* activate channel */ 555 /* activate channel */
@@ -553,7 +578,7 @@ nvd0_disp_pioc_fini(struct nouveau_object *object, bool suspend)
553 return -EBUSY; 578 return -EBUSY;
554 } 579 }
555 580
556 /* disable error reporting */ 581 /* disable error reporting and completion notification */
557 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); 582 nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000);
558 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); 583 nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000);
559 584
@@ -570,6 +595,7 @@ nvd0_disp_oimm_ofuncs = {
570 .base.dtor = nv50_disp_pioc_dtor, 595 .base.dtor = nv50_disp_pioc_dtor,
571 .base.init = nvd0_disp_pioc_init, 596 .base.init = nvd0_disp_pioc_init,
572 .base.fini = nvd0_disp_pioc_fini, 597 .base.fini = nvd0_disp_pioc_fini,
598 .base.ntfy = nv50_disp_chan_ntfy,
573 .base.map = nv50_disp_chan_map, 599 .base.map = nv50_disp_chan_map,
574 .base.rd32 = nv50_disp_chan_rd32, 600 .base.rd32 = nv50_disp_chan_rd32,
575 .base.wr32 = nv50_disp_chan_wr32, 601 .base.wr32 = nv50_disp_chan_wr32,
@@ -586,6 +612,7 @@ nvd0_disp_curs_ofuncs = {
586 .base.dtor = nv50_disp_pioc_dtor, 612 .base.dtor = nv50_disp_pioc_dtor,
587 .base.init = nvd0_disp_pioc_init, 613 .base.init = nvd0_disp_pioc_init,
588 .base.fini = nvd0_disp_pioc_fini, 614 .base.fini = nvd0_disp_pioc_fini,
615 .base.ntfy = nv50_disp_chan_ntfy,
589 .base.map = nv50_disp_chan_map, 616 .base.map = nv50_disp_chan_map,
590 .base.rd32 = nv50_disp_chan_rd32, 617 .base.rd32 = nv50_disp_chan_rd32,
591 .base.wr32 = nv50_disp_chan_wr32, 618 .base.wr32 = nv50_disp_chan_wr32,
@@ -1153,7 +1180,11 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
1153 1180
1154 if (intr & 0x00000001) { 1181 if (intr & 0x00000001) {
1155 u32 stat = nv_rd32(priv, 0x61008c); 1182 u32 stat = nv_rd32(priv, 0x61008c);
1156 nv_wr32(priv, 0x61008c, stat); 1183 while (stat) {
1184 int chid = __ffs(stat); stat &= ~(1 << chid);
1185 nv50_disp_chan_uevent_send(priv, chid);
1186 nv_wr32(priv, 0x61008c, 1 << chid);
1187 }
1157 intr &= ~0x00000001; 1188 intr &= ~0x00000001;
1158 } 1189 }
1159 1190
@@ -1209,6 +1240,10 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1209 if (ret) 1240 if (ret)
1210 return ret; 1241 return ret;
1211 1242
1243 ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent);
1244 if (ret)
1245 return ret;
1246
1212 nv_engine(priv)->sclass = nvd0_disp_base_oclass; 1247 nv_engine(priv)->sclass = nvd0_disp_base_oclass;
1213 nv_engine(priv)->cclass = &nv50_disp_cclass; 1248 nv_engine(priv)->cclass = &nv50_disp_cclass;
1214 nv_subdev(priv)->intr = nvd0_disp_intr; 1249 nv_subdev(priv)->intr = nvd0_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 47fef1e398c4..3ed47e187f89 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -233,6 +233,10 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
233 if (ret) 233 if (ret)
234 return ret; 234 return ret;
235 235
236 ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent);
237 if (ret)
238 return ret;
239
236 nv_engine(priv)->sclass = nve0_disp_base_oclass; 240 nv_engine(priv)->sclass = nve0_disp_base_oclass;
237 nv_engine(priv)->cclass = &nv50_disp_cclass; 241 nv_engine(priv)->cclass = &nv50_disp_cclass;
238 nv_subdev(priv)->intr = nvd0_disp_intr; 242 nv_subdev(priv)->intr = nvd0_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
index 04bda4ac4ed3..07f337695007 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -68,6 +68,10 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
68 if (ret) 68 if (ret)
69 return ret; 69 return ret;
70 70
71 ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent);
72 if (ret)
73 return ret;
74
71 nv_engine(priv)->sclass = nvf0_disp_base_oclass; 75 nv_engine(priv)->sclass = nvf0_disp_base_oclass;
72 nv_engine(priv)->cclass = &nv50_disp_cclass; 76 nv_engine(priv)->cclass = &nv50_disp_cclass;
73 nv_subdev(priv)->intr = nvd0_disp_intr; 77 nv_subdev(priv)->intr = nvd0_disp_intr;
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h
index 573491f84792..e5a27df0672b 100644
--- a/drivers/gpu/drm/nouveau/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/nvif/class.h
@@ -479,6 +479,8 @@ struct nv50_disp_core_channel_dma_v0 {
479 __u32 pushbuf; 479 __u32 pushbuf;
480}; 480};
481 481
482#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
483
482/* cursor immediate */ 484/* cursor immediate */
483struct nv50_disp_cursor_v0 { 485struct nv50_disp_cursor_v0 {
484 __u8 version; 486 __u8 version;
@@ -486,6 +488,8 @@ struct nv50_disp_cursor_v0 {
486 __u8 pad02[6]; 488 __u8 pad02[6];
487}; 489};
488 490
491#define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00
492
489/* base */ 493/* base */
490struct nv50_disp_base_channel_dma_v0 { 494struct nv50_disp_base_channel_dma_v0 {
491 __u8 version; 495 __u8 version;
@@ -494,6 +498,8 @@ struct nv50_disp_base_channel_dma_v0 {
494 __u32 pushbuf; 498 __u32 pushbuf;
495}; 499};
496 500
501#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
502
497/* overlay */ 503/* overlay */
498struct nv50_disp_overlay_channel_dma_v0 { 504struct nv50_disp_overlay_channel_dma_v0 {
499 __u8 version; 505 __u8 version;
@@ -502,6 +508,8 @@ struct nv50_disp_overlay_channel_dma_v0 {
502 __u32 pushbuf; 508 __u32 pushbuf;
503}; 509};
504 510
511#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
512
505/* overlay immediate */ 513/* overlay immediate */
506struct nv50_disp_overlay_v0 { 514struct nv50_disp_overlay_v0 {
507 __u8 version; 515 __u8 version;
@@ -509,6 +517,7 @@ struct nv50_disp_overlay_v0 {
509 __u8 pad02[6]; 517 __u8 pad02[6];
510}; 518};
511 519
520#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00
512 521
513/******************************************************************************* 522/*******************************************************************************
514 * fermi 523 * fermi