summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-04-26 15:42:02 +1000
committerDave Airlie <airlied@redhat.com>2013-04-26 15:42:02 +1000
commit36d9b1541cedecd59e9d8fff0bbf9b7e9dd9704e (patch)
tree3472ef1eb4c63ecd0b8e98188b42bad9b6c55ad3
parenta90b590e957d66ea357aeff4cee8425f2567ed33 (diff)
parent893e90c554c1ef85684b335655a5030d38a4a1b0 (diff)
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
"Nothing overly exciting here aside from calim's fermi/kepler vram compression patches. The rest is misc fixes I gathered from the list. Most of the stuff from me is fixing issues that have come up from the work on kepler PM, as well as a commit moving all the old-school modesetting out of the way (no code changes here). There's other patches to go on top of that, but, it'll have to wait until I can rip out the old PM code, it's a bit tangled." * 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (38 commits) drm/nouveau/fifo: implement channel creation event generation drm/nouveau/core: allow non-maskable events drm/nouveau/timer: allow alarms to be cancelled drm/nouveau/device: tweak the device/subdev relationship a little drm/nouveau/device: enable proper constructor/destructor drm/nouveau/device: have engine object initialised before creation drm/nouveau/device: convert to engine, rather than subdev drm/nv50-/disp: use self as parent for subobjects drm/nv50-/fifo: use parent as self for subobjects drm/nv20-nv30/gr: use parent as self for subobjects drm/nvc0-/gr: use self as parent for subobjects drm/nv04-nv40/instmem: use self as parent for subobjects drm/nv04-nv40/vm: use self as parent for subobjects drm/nv50-/bar: use self as parent for subobjects drm/nv04-nv40/instmem: remove parent deref hack drm/nouveau/i2c: remove parent deref hack drm/nouveau/core: rebase object ref/use counts after ctor/init/fini events drm/nv50/disp: inform core when we're not creating a new context drm/nouveau/therm: send some messages to debug level drm/nve0/gr: add handling for a bunch of PGRAPH traps ...
-rw-r--r--drivers/gpu/drm/nouveau/Makefile25
-rw-r--r--drivers/gpu/drm/nouveau/core/core/client.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/core/engine.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/core/event.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/core/object.c19
-rw-r--r--drivers/gpu/drm/nouveau/core/core/parent.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/base.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/base.c)183
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv04.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nv04.c)2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv10.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nv10.c)2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv20.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nv20.c)2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv30.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nv30.c)2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv40.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nv40.c)2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv50.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nv50.c)20
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nvc0.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c)30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nve0.c (renamed from drivers/gpu/drm/nouveau/core/subdev/device/nve0.c)2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/base.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c51
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c13
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv20.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv25.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv30.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv34.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv35.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv50.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nve0.c230
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nvc0.c29
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/device.h6
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/parent.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/device.h (renamed from drivers/gpu/drm/nouveau/core/include/subdev/device.h)1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/fifo.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/graph.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h7
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/mc.h30
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/therm.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/os.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/init.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c72
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c20
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c129
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/base.c60
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c175
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c221
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/temp.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c13
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c58
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/Makefile10
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/arb.c (renamed from drivers/gpu/drm/nouveau/nouveau_calc.c)2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c (renamed from drivers/gpu/drm/nouveau/nv04_crtc.c)5
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/cursor.c (renamed from drivers/gpu/drm/nouveau/nv04_cursor.c)3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dac.c (renamed from drivers/gpu/drm/nouveau/nv04_dac.c)2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c (renamed from drivers/gpu/drm/nouveau/nv04_dfp.c)2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c (renamed from drivers/gpu/drm/nouveau/nv04_display.c)2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.h (renamed from drivers/gpu/drm/nouveau/nv04_display.h)0
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.c (renamed from drivers/gpu/drm/nouveau/nouveau_hw.c)2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.h (renamed from drivers/gpu/drm/nouveau/nouveau_hw.h)3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/nvreg.h (renamed from drivers/gpu/drm/nouveau/nvreg.h)0
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c (renamed from drivers/gpu/drm/nouveau/nv17_tv_modes.c)4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv04.c (renamed from drivers/gpu/drm/nouveau/nv04_tv.c)2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.c (renamed from drivers/gpu/drm/nouveau/nv17_tv.c)4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.h (renamed from drivers/gpu/drm/nouveau/nv17_tv.h)0
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c12
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c76
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.h11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c25
-rw-r--r--drivers/gpu/drm/nouveau/nv04_pm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv40_pm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c2
105 files changed, 1316 insertions, 644 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 90f9140eeefd..52930a20d8f8 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -55,11 +55,2 @@ nouveau-y += core/subdev/clock/pllnv04.o
nouveau-y += core/subdev/clock/pllnva3.o
-nouveau-y += core/subdev/device/base.o
-nouveau-y += core/subdev/device/nv04.o
-nouveau-y += core/subdev/device/nv10.o
-nouveau-y += core/subdev/device/nv20.o
-nouveau-y += core/subdev/device/nv30.o
-nouveau-y += core/subdev/device/nv40.o
-nouveau-y += core/subdev/device/nv50.o
-nouveau-y += core/subdev/device/nvc0.o
-nouveau-y += core/subdev/device/nve0.o
nouveau-y += core/subdev/devinit/base.o
@@ -128,2 +119,3 @@ nouveau-y += core/subdev/therm/nv40.o
nouveau-y += core/subdev/therm/nv50.o
+nouveau-y += core/subdev/therm/nv84.o
nouveau-y += core/subdev/therm/nva3.o
@@ -152,2 +144,11 @@ nouveau-y += core/engine/crypt/nv84.o
nouveau-y += core/engine/crypt/nv98.o
+nouveau-y += core/engine/device/base.o
+nouveau-y += core/engine/device/nv04.o
+nouveau-y += core/engine/device/nv10.o
+nouveau-y += core/engine/device/nv20.o
+nouveau-y += core/engine/device/nv30.o
+nouveau-y += core/engine/device/nv40.o
+nouveau-y += core/engine/device/nv50.o
+nouveau-y += core/engine/device/nvc0.o
+nouveau-y += core/engine/device/nve0.o
nouveau-y += core/engine/disp/base.o
@@ -214,3 +215,3 @@ nouveau-y += core/engine/vp/nve0.o
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
-nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o
+nouveau-y += nouveau_vga.o nouveau_agp.o
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
@@ -226,5 +227,3 @@ nouveau-y += nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o
# drm/kms/nv04:nv50
-nouveau-y += nouveau_hw.o nouveau_calc.o
-nouveau-y += nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o
-nouveau-y += nv04_crtc.o nv04_display.o nv04_cursor.o
+include $(src)/dispnv04/Makefile
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c
index 295c22165eac..9079c0ac58e6 100644
--- a/drivers/gpu/drm/nouveau/core/core/client.c
+++ b/drivers/gpu/drm/nouveau/core/core/client.c
@@ -29,3 +29,3 @@
-#include <subdev/device.h>
+#include <engine/device.h>
@@ -60,4 +60,5 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg,
ret = nouveau_namedb_create_(NULL, NULL, &nouveau_client_oclass,
- NV_CLIENT_CLASS, nouveau_device_sclass,
- 0, length, pobject);
+ NV_CLIENT_CLASS, NULL,
+ (1ULL << NVDEV_ENGINE_DEVICE),
+ length, pobject);
client = *pobject;
diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c
index 09b3bd502fd0..c8bed4a26833 100644
--- a/drivers/gpu/drm/nouveau/core/core/engine.c
+++ b/drivers/gpu/drm/nouveau/core/core/engine.c
@@ -35,3 +35,2 @@ nouveau_engine_create_(struct nouveau_object *parent,
{
- struct nouveau_device *device = nv_device(parent);
struct nouveau_engine *engine;
@@ -45,3 +44,4 @@ nouveau_engine_create_(struct nouveau_object *parent,
- if (!nouveau_boolopt(device->cfgopt, iname, enable)) {
+ if ( parent &&
+ !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) {
if (!enable)
diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c
index 6d01e0f0fc8a..7eb81c1b6fab 100644
--- a/drivers/gpu/drm/nouveau/core/core/event.c
+++ b/drivers/gpu/drm/nouveau/core/core/event.c
@@ -29,4 +29,6 @@ nouveau_event_put_locked(struct nouveau_event *event, int index,
{
- if (!--event->index[index].refs)
- event->disable(event, index);
+ if (!--event->index[index].refs) {
+ if (event->disable)
+ event->disable(event, index);
+ }
list_del(&handler->head);
@@ -55,4 +57,6 @@ nouveau_event_get(struct nouveau_event *event, int index,
list_add(&handler->head, &event->index[index].list);
- if (!event->index[index].refs++)
- event->enable(event, index);
+ if (!event->index[index].refs++) {
+ if (event->enable)
+ event->enable(event, index);
+ }
}
diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c
index 3b2e7b6304d3..7f48e288215f 100644
--- a/drivers/gpu/drm/nouveau/core/core/object.c
+++ b/drivers/gpu/drm/nouveau/core/core/object.c
@@ -138,7 +138,7 @@ nouveau_object_ctor(struct nouveau_object *parent,
struct nouveau_ofuncs *ofuncs = oclass->ofuncs;
+ struct nouveau_object *object = NULL;
int ret;
- *pobject = NULL;
-
- ret = ofuncs->ctor(parent, engine, oclass, data, size, pobject);
+ ret = ofuncs->ctor(parent, engine, oclass, data, size, &object);
+ *pobject = object;
if (ret < 0) {
@@ -149,4 +149,4 @@ nouveau_object_ctor(struct nouveau_object *parent,
- if (*pobject) {
- ofuncs->dtor(*pobject);
+ if (object) {
+ ofuncs->dtor(object);
*pobject = NULL;
@@ -157,3 +157,7 @@ nouveau_object_ctor(struct nouveau_object *parent,
- nv_debug(*pobject, "created\n");
+ if (ret == 0) {
+ nv_debug(object, "created\n");
+ atomic_set(&object->refcount, 1);
+ }
+
return 0;
@@ -329,2 +333,3 @@ nouveau_object_inc(struct nouveau_object *object)
ret = nv_ofuncs(object)->init(object);
+ atomic_set(&object->usecount, 1);
if (ret) {
@@ -359,2 +364,3 @@ nouveau_object_decf(struct nouveau_object *object)
ret = nv_ofuncs(object)->fini(object, false);
+ atomic_set(&object->usecount, 0);
if (ret)
@@ -383,2 +389,3 @@ nouveau_object_decs(struct nouveau_object *object)
ret = nv_ofuncs(object)->fini(object, true);
+ atomic_set(&object->usecount, 0);
if (ret) {
diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c
index db7c54943102..313380ce632d 100644
--- a/drivers/gpu/drm/nouveau/core/core/parent.c
+++ b/drivers/gpu/drm/nouveau/core/core/parent.c
@@ -26,2 +26,3 @@
#include <core/parent.h>
+#include <core/client.h>
@@ -52,3 +53,8 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,
- if ((engine = nouveau_engine(parent, i))) {
+ if (nv_iclass(parent, NV_CLIENT_CLASS))
+ engine = nv_engine(nv_client(parent)->device);
+ else
+ engine = nouveau_engine(parent, i);
+
+ if (engine) {
oclass = engine->sclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index 3937ced5c753..86d24904e9d3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -31,3 +31,3 @@
-#include <subdev/device.h>
+#include <engine/device.h>
@@ -57,3 +57,2 @@ struct nouveau_devobj {
struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
- bool created;
};
@@ -240,3 +239,3 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
/* ensure requested subsystems are available for use */
- for (i = 0, c = 0; i < NVDEV_SUBDEV_NR; i++) {
+ for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) {
if (!(oclass = device->oclass[i]) || (disable & (1ULL << i)))
@@ -244,18 +243,16 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
- if (!device->subdev[i]) {
- ret = nouveau_object_ctor(nv_object(device), NULL,
- oclass, NULL, i,
- &devobj->subdev[i]);
- if (ret == -ENODEV)
- continue;
- if (ret)
- return ret;
-
- if (nv_iclass(devobj->subdev[i], NV_ENGINE_CLASS))
- nouveau_subdev_reset(devobj->subdev[i]);
- } else {
+ if (device->subdev[i]) {
nouveau_object_ref(device->subdev[i],
&devobj->subdev[i]);
+ continue;
}
+ ret = nouveau_object_ctor(nv_object(device), NULL,
+ oclass, NULL, i,
+ &devobj->subdev[i]);
+ if (ret == -ENODEV)
+ continue;
+ if (ret)
+ return ret;
+
/* note: can't init *any* subdevs until devinit has been run
@@ -275,2 +272,6 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
return ret;
+ atomic_dec(&nv_object(device)->usecount);
+ } else
+ if (subdev) {
+ nouveau_subdev_reset(subdev);
}
@@ -294,70 +295,2 @@ nouveau_devobj_dtor(struct nouveau_object *object)
-static int
-nouveau_devobj_init(struct nouveau_object *object)
-{
- struct nouveau_devobj *devobj = (void *)object;
- struct nouveau_object *subdev;
- int ret, i;
-
- ret = nouveau_parent_init(&devobj->base);
- if (ret)
- return ret;
-
- for (i = 0; devobj->created && i < NVDEV_SUBDEV_NR; i++) {
- if ((subdev = devobj->subdev[i])) {
- if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
- ret = nouveau_object_inc(subdev);
- if (ret)
- goto fail;
- }
- }
- }
-
- devobj->created = true;
- return 0;
-
-fail:
- for (--i; i >= 0; i--) {
- if ((subdev = devobj->subdev[i])) {
- if (!nv_iclass(subdev, NV_ENGINE_CLASS))
- nouveau_object_dec(subdev, false);
- }
- }
-
- return ret;
-}
-
-static int
-nouveau_devobj_fini(struct nouveau_object *object, bool suspend)
-{
- struct nouveau_devobj *devobj = (void *)object;
- struct nouveau_object *subdev;
- int ret, i;
-
- for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
- if ((subdev = devobj->subdev[i])) {
- if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
- ret = nouveau_object_dec(subdev, suspend);
- if (ret && suspend)
- goto fail;
- }
- }
- }
-
- ret = nouveau_parent_fini(&devobj->base, suspend);
-fail:
- for (; ret && suspend && i < NVDEV_SUBDEV_NR; i++) {
- if ((subdev = devobj->subdev[i])) {
- if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
- ret = nouveau_object_inc(subdev);
- if (ret) {
- /* XXX */
- }
- }
- }
- }
-
- return ret;
-}
-
static u8
@@ -402,4 +335,4 @@ nouveau_devobj_ofuncs = {
.dtor = nouveau_devobj_dtor,
- .init = nouveau_devobj_init,
- .fini = nouveau_devobj_fini,
+ .init = _nouveau_parent_init,
+ .fini = _nouveau_parent_fini,
.rd08 = nouveau_devobj_rd08,
@@ -415,3 +348,3 @@ nouveau_devobj_ofuncs = {
*****************************************************************************/
-struct nouveau_oclass
+static struct nouveau_oclass
nouveau_device_sclass[] = {
@@ -421,2 +354,66 @@ nouveau_device_sclass[] = {
+static int
+nouveau_device_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nouveau_device *device = (void *)object;
+ struct nouveau_object *subdev;
+ int ret, i;
+
+ for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_dec(subdev, suspend);
+ if (ret && suspend)
+ goto fail;
+ }
+ }
+ }
+
+ ret = 0;
+fail:
+ for (; ret && i < NVDEV_SUBDEV_NR; i++) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_inc(subdev);
+ if (ret) {
+ /* XXX */
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+nouveau_device_init(struct nouveau_object *object)
+{
+ struct nouveau_device *device = (void *)object;
+ struct nouveau_object *subdev;
+ int ret, i;
+
+ for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_inc(subdev);
+ if (ret)
+ goto fail;
+ } else {
+ nouveau_subdev_reset(subdev);
+ }
+ }
+ }
+
+ ret = 0;
+fail:
+ for (--i; ret && i >= 0; i--) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS))
+ nouveau_object_dec(subdev, false);
+ }
+ }
+
+ return ret;
+}
+
static void
@@ -430,6 +427,6 @@ nouveau_device_dtor(struct nouveau_object *object)
- if (device->base.mmio)
- iounmap(device->base.mmio);
+ if (nv_subdev(device)->mmio)
+ iounmap(nv_subdev(device)->mmio);
- nouveau_subdev_destroy(&device->base);
+ nouveau_engine_destroy(&device->base);
}
@@ -438,5 +435,7 @@ static struct nouveau_oclass
nouveau_device_oclass = {
- .handle = NV_SUBDEV(DEVICE, 0x00),
+ .handle = NV_ENGINE(DEVICE, 0x00),
.ofuncs = &(struct nouveau_ofuncs) {
.dtor = nouveau_device_dtor,
+ .init = nouveau_device_init,
+ .fini = nouveau_device_fini,
},
@@ -458,3 +457,3 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
- ret = nouveau_subdev_create_(NULL, NULL, &nouveau_device_oclass, 0,
+ ret = nouveau_engine_create_(NULL, NULL, &nouveau_device_oclass, true,
"DEVICE", "device", length, pobject);
@@ -464,3 +463,2 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
- atomic_set(&nv_object(device)->usecount, 2);
device->pdev = pdev;
@@ -472,2 +470,3 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
+ nv_engine(device)->sclass = nouveau_device_sclass;
list_add(&device->head, &nv_devices);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
index 473c5c03d3c9..a0284cf09c0f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -36,2 +35,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
index d0774f5bebe1..1b7809a095c3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -37,2 +36,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
index ab920e0dc45b..12a4005fa619 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -38,2 +37,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
index 5f2110261b04..cef0f1ea4c21 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -37,2 +36,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
index f3d55efe9ac9..1719cb0ee595 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -39,2 +38,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
index 5ed2fa51ddc2..5e8c3de75593 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -40,2 +39,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
@@ -85,3 +85,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -111,3 +111,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -137,3 +137,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -163,3 +163,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -189,3 +189,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -215,3 +215,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -241,3 +241,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -267,3 +267,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
@@ -293,3 +293,3 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
- device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
index 4393eb4d6564..955af122c3a6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -42,2 +41,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
@@ -287,2 +287,30 @@ nvc0_identify(struct nouveau_device *device)
break;
+ case 0xd7:
+ device->cname = "GF117";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = &nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nvc0_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass;
+ break;
default:
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index 5c12391619fd..e6a77944f43b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -24,3 +24,2 @@
-#include <subdev/device.h>
#include <subdev/bios.h>
@@ -42,2 +41,3 @@
+#include <engine/device.h>
#include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
index fa27b02ff829..31cc8fe8e7f0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -193,3 +193,3 @@ dp_link_train_eq(struct dp_state *dp)
{
- bool eq_done, cr_done = true;
+ bool eq_done = false, cr_done = true;
int tries = 0, i;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 02e369f80449..6a38402fa56c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -574,3 +574,4 @@ nv50_disp_base_ctor(struct nouveau_object *parent,
priv->base.vblank->disable = nv50_disp_base_vblank_disable;
- return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
+ return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
+ &base->ramht);
}
@@ -721,3 +722,3 @@ nv50_disp_data_ctor(struct nouveau_object *parent,
*pobject = parent;
- return 0;
+ return 1;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 788dd34ccb54..019eacd8a68f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -475,3 +475,4 @@ nvd0_disp_base_ctor(struct nouveau_object *parent,
- return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
+ return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
+ &base->ramht);
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
index 7341ebe131fa..d3ec436d9cb5 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
@@ -93,2 +93,4 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
+ nouveau_event_trigger(priv->cevent, 0);
+
chan->size = size;
@@ -169,2 +171,3 @@ nouveau_fifo_destroy(struct nouveau_fifo *priv)
nouveau_event_destroy(&priv->uevent);
+ nouveau_event_destroy(&priv->cevent);
nouveau_engine_destroy(&priv->base);
@@ -193,2 +196,6 @@ nouveau_fifo_create_(struct nouveau_object *parent,
+ ret = nouveau_event_create(1, &priv->cevent);
+ if (ret)
+ return ret;
+
ret = nouveau_event_create(1, &priv->uevent);
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
index 840af6172788..ddaeb5572903 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
@@ -212,3 +212,4 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
- ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht);
+ ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
+ &chan->ramht);
if (ret)
@@ -265,3 +266,4 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
- ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht);
+ ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
+ &chan->ramht);
if (ret)
@@ -375,4 +377,4 @@ nv50_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0200, 0x1000,
- NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc);
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x0200,
+ 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc);
if (ret)
@@ -380,3 +382,3 @@ nv50_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x1200, 0,
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x1200, 0,
NVOBJ_FLAG_ZERO_ALLOC, &base->eng);
@@ -385,3 +387,3 @@ nv50_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x4000, 0, 0,
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x4000, 0, 0,
&base->pgd);
@@ -439,3 +441,3 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0,
&priv->playlist[0]);
@@ -444,3 +446,3 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0,
&priv->playlist[1]);
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
index 094000e87871..35b94bd18808 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
@@ -182,3 +182,4 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
- ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht);
+ ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
+ &chan->ramht);
if (ret)
@@ -244,3 +245,4 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
- ret = nouveau_ramht_new(parent, parent, 0x8000, 16, &chan->ramht);
+ ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
+ &chan->ramht);
if (ret)
@@ -338,3 +340,3 @@ nv84_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0200, 0,
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x0200, 0,
NVOBJ_FLAG_ZERO_ALLOC, &base->eng);
@@ -343,3 +345,3 @@ nv84_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x4000, 0,
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x4000, 0,
0, &base->pgd);
@@ -352,4 +354,4 @@ nv84_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x1000, 0x400,
- NVOBJ_FLAG_ZERO_ALLOC, &base->cache);
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x1000,
+ 0x400, NVOBJ_FLAG_ZERO_ALLOC, &base->cache);
if (ret)
@@ -357,4 +359,4 @@ nv84_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, nv_object(base), 0x0100, 0x100,
- NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc);
+ ret = nouveau_gpuobj_new(nv_object(base), nv_object(base), 0x0100,
+ 0x100, NVOBJ_FLAG_ZERO_ALLOC, &base->ramfc);
if (ret)
@@ -409,3 +411,3 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0,
&priv->playlist[0]);
@@ -414,3 +416,3 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 128 * 4, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 4, 0x1000, 0,
&priv->playlist[1]);
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index 4f226afb5591..4d4a6b905370 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -294,3 +294,4 @@ nvc0_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0x1000, 0, &base->pgd);
+ ret = nouveau_gpuobj_new(nv_object(base), NULL, 0x10000, 0x1000, 0,
+ &base->pgd);
if (ret)
@@ -625,3 +626,3 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0,
&priv->playlist[0]);
@@ -630,3 +631,3 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0,
&priv->playlist[1]);
@@ -635,3 +636,3 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 128 * 0x1000, 0x1000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 0x1000, 0x1000, 0,
&priv->user.mem);
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index 4419e40d88e9..9151919fb831 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -98,3 +98,3 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
if (unlikely(cur == NULL)) {
- int ret = nouveau_gpuobj_new(nv_object(priv)->parent, NULL,
+ int ret = nouveau_gpuobj_new(nv_object(priv), NULL,
0x8000, 0x1000, 0, &cur);
@@ -335,3 +335,4 @@ nve0_fifo_context_ctor(struct nouveau_object *parent,
- ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0x1000, 0, &base->pgd);
+ ret = nouveau_gpuobj_new(nv_object(base), NULL, 0x10000, 0x1000, 0,
+ &base->pgd);
if (ret)
@@ -597,3 +598,3 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 4096 * 0x200, 0x1000,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
index 0b7951a85943..4cc6269d4077 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
@@ -38,3 +38,2 @@ nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
struct nouveau_bar *bar = nouveau_bar(priv);
- struct nouveau_object *parent = nv_object(priv);
struct nouveau_gpuobj *chan;
@@ -46,3 +45,3 @@ nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
*/
- ret = nouveau_gpuobj_new(parent, NULL, size, 0x1000,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, size, 0x1000,
NVOBJ_FLAG_ZERO_ALLOC, &info->chan);
@@ -1401,3 +1400,3 @@ nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv)
- for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) {
+ for (i = 0; nv_device(priv)->chipset >= 0xd0 && i < 4; i++) {
nv_mthd(priv, 0x90c0, 0x2700 + (i * 0x40), 0x00000000);
@@ -1417,3 +1416,3 @@ nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv)
nv_mthd(priv, 0x90c0, 0x27ec, 0x00000000);
- for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) {
+ for (i = 0; nv_device(priv)->chipset >= 0xd0 && i < 4; i++) {
nv_mthd(priv, 0x90c0, 0x2710 + (i * 0x40), 0x00014000);
@@ -1617,3 +1616,3 @@ nvc0_grctx_generate_shaders(struct nvc0_graph_priv *priv)
- if (nv_device(priv)->chipset == 0xd9) {
+ if (nv_device(priv)->chipset >= 0xd0) {
nv_wr32(priv, 0x405800, 0x0f8000bf);
@@ -1660,6 +1659,6 @@ nvc0_grctx_generate_unk64xx(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x4064b8, 0x00000000);
- if (nv_device(priv)->chipset == 0xd9)
+ if (nv_device(priv)->chipset >= 0xd0)
nv_wr32(priv, 0x4064bc, 0x00000000);
if (nv_device(priv)->chipset == 0xc1 ||
- nv_device(priv)->chipset == 0xd9) {
+ nv_device(priv)->chipset >= 0xd0) {
nv_wr32(priv, 0x4064c0, 0x80140078);
@@ -1703,3 +1702,3 @@ nvc0_grctx_generate_rop(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x408804, 0x00000040);
- if (chipset == 0xd9) {
+ if (chipset >= 0xd0) {
nv_wr32(priv, 0x408808, 0x1043e005);
@@ -1737,3 +1736,3 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x418410, 0x0fff0fff);
- nv_wr32(priv, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff);
+ nv_wr32(priv, 0x418414, chipset < 0xd0 ? 0x00200fff : 0x02200fff);
nv_wr32(priv, 0x418450, 0x00000000);
@@ -1752,5 +1751,5 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x418708, 0x00000000);
- nv_wr32(priv, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000);
+ nv_wr32(priv, 0x41870c, chipset < 0xd0 ? 0x07c80000 : 0x00000000);
nv_wr32(priv, 0x418710, 0x00000000);
- nv_wr32(priv, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a);
+ nv_wr32(priv, 0x418800, chipset < 0xd0 ? 0x0006860a : 0x7006860a);
nv_wr32(priv, 0x418808, 0x00000000);
@@ -1759,3 +1758,3 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x418828, 0x00008442);
- if (chipset == 0xc1 || chipset == 0xd9)
+ if (chipset == 0xc1 || chipset >= 0xd0)
nv_wr32(priv, 0x418830, 0x10000001);
@@ -1770,3 +1769,3 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x4188f8, 0x00000000);
- if (chipset == 0xd9)
+ if (chipset >= 0xd0)
nv_wr32(priv, 0x4188fc, 0x20100008);
@@ -1789,3 +1788,3 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv)
}
- nv_wr32(priv, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006);
+ nv_wr32(priv, 0x418b00, chipset < 0xd0 ? 0x00000000 : 0x00000006);
nv_wr32(priv, 0x418b08, 0x0a418820);
@@ -1806,3 +1805,3 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x418c2c, 0x00000000);
- if (chipset == 0xc1 || chipset == 0xd9)
+ if (chipset == 0xc1 || chipset >= 0xd0)
nv_wr32(priv, 0x418c6c, 0x00000001);
@@ -1825,3 +1824,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419848, 0x00000000);
- if (chipset == 0xc1 || chipset == 0xd9)
+ if (chipset == 0xc1 || chipset >= 0xd0)
nv_wr32(priv, 0x419864, 0x00000129);
@@ -1838,3 +1837,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419a20, 0x00000800);
- if (chipset == 0xd9)
+ if (chipset >= 0xd0)
nv_wr32(priv, 0x00419ac4, 0x0017f440);
@@ -1849,3 +1848,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419bd0, 0x00900103);
- if (chipset == 0xc1 || chipset == 0xd9)
+ if (chipset == 0xc1 || chipset >= 0xd0)
nv_wr32(priv, 0x419be0, 0x00400001);
@@ -1854,3 +1853,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419be4, 0x00000000);
- nv_wr32(priv, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a);
+ nv_wr32(priv, 0x419c00, chipset < 0xd0 ? 0x00000002 : 0x0000000a);
nv_wr32(priv, 0x419c04, 0x00000006);
@@ -1858,3 +1857,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419c20, 0x00000000);
- if (nv_device(priv)->chipset == 0xd9) {
+ if (nv_device(priv)->chipset >= 0xd0) {
nv_wr32(priv, 0x419c24, 0x00084210);
@@ -1870,3 +1869,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419cf4, 0x00000183);
- if (chipset == 0xc1 || chipset == 0xd9)
+ if (chipset == 0xc1 || chipset >= 0xd0)
nv_wr32(priv, 0x419d20, 0x12180000);
@@ -1875,3 +1874,3 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x419d24, 0x00001fff);
- if (chipset == 0xc1 || chipset == 0xd9)
+ if (chipset == 0xc1 || chipset >= 0xd0)
nv_wr32(priv, 0x419d44, 0x02180218);
@@ -2212,3 +2211,3 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv)
nv_icmd(priv, 0x00000217, 0x00000040);
- if (nv_device(priv)->chipset == 0xd9) {
+ if (nv_device(priv)->chipset >= 0xd0) {
for (i = 0x0400; i <= 0x0417; i++)
@@ -2224,3 +2223,3 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv)
nv_icmd(priv, 0x0000021f, 0x0000c080);
- if (nv_device(priv)->chipset == 0xd9) {
+ if (nv_device(priv)->chipset >= 0xd0) {
for (i = 0x0440; i <= 0x0457; i++)
@@ -2791,3 +2790,3 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv)
if (nv_device(priv)->chipset == 0xc1 ||
- nv_device(priv)->chipset == 0xd9)
+ nv_device(priv)->chipset >= 0xd0)
nv_icmd(priv, 0x0000057b, 0x00000059);
@@ -2893,3 +2892,3 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv)
nv_icmd(priv, 0x0000095f, 0x00000020);
- if (nv_device(priv)->chipset == 0xd9)
+ if (nv_device(priv)->chipset >= 0xd0)
nv_icmd(priv, 0x0000097d, 0x00000020);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c
index 6d8c63931ee6..ae27dae3fe38 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c
@@ -2774,6 +2774,11 @@ nve0_grctx_generate(struct nvc0_graph_priv *priv)
- nv_wr32(priv, 0x405b00, 0x201);
- nv_wr32(priv, 0x408850, 0x2);
- nv_wr32(priv, 0x408958, 0x2);
- nv_wr32(priv, 0x419f78, 0xa);
+ nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr);
+ if (priv->gpc_nr == 1) {
+ nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]);
+ nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]);
+ } else {
+ nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr);
+ nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr);
+ }
+ nv_mask(priv, 0x419f78, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc
index b86cc60dcd56..f7055af0f2a6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc
@@ -89,2 +89,7 @@ chipsets:
.b16 #nvd9_tpc_mmio_tail
+.b8 0xd7 0 0 0
+.b16 #nvd9_gpc_mmio_head
+.b16 #nvd9_gpc_mmio_tail
+.b16 #nvd9_tpc_mmio_head
+.b16 #nvd9_tpc_mmio_tail
.b8 0 0 0 0
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc
index 0bcfa4d447e5..7fbdebb2bafb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc
@@ -64,2 +64,5 @@ chipsets:
.b16 #nvd9_hub_mmio_tail
+.b8 0xd7 0 0 0
+.b16 #nvd9_hub_mmio_head
+.b16 #nvd9_hub_mmio_tail
.b8 0 0 0 0
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
index 0607b9801748..b24559315903 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
@@ -256,3 +256,3 @@ nv20_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
index b2b650dd8b28..7a80d005a974 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
@@ -144,3 +144,3 @@ nv25_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
index 700462fa0ae0..3e1f32ee43d4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
@@ -111,3 +111,3 @@ nv2a_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
index cedadaa92d3f..e451db32e92a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
@@ -145,3 +145,3 @@ nv30_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
index 273f6320027b..9385ac7b44a4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
@@ -145,3 +145,3 @@ nv34_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
index f40ee2116ee1..9ce84b73f86a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
@@ -143,3 +143,3 @@ nv35_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
index 17049d5c723d..193a5de1b482 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
@@ -48,2 +48,10 @@ struct nv40_graph_chan {
+static u64
+nv40_graph_units(struct nouveau_graph *graph)
+{
+ struct nv40_graph_priv *priv = (void *)graph;
+
+ return nv_rd32(priv, 0x1540);
+}
+
/*******************************************************************************
@@ -361,2 +369,4 @@ nv40_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->tile_prog = nv40_graph_tile_prog;
+
+ priv->base.units = nv40_graph_units;
return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
index f2b1a7a124f2..1ac36110ca19 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
@@ -50,2 +50,10 @@ struct nv50_graph_chan {
+static u64
+nv50_graph_units(struct nouveau_graph *graph)
+{
+ struct nv50_graph_priv *priv = (void *)graph;
+
+ return nv_rd32(priv, 0x1540);
+}
+
/*******************************************************************************
@@ -821,2 +829,4 @@ nv50_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ priv->base.units = nv50_graph_units;
+
switch (nv_device(priv)->chipset) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index 0de0dd724aff..f9b9d82c287f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -62,2 +62,15 @@ nvc8_graph_sclass[] = {
+u64
+nvc0_graph_units(struct nouveau_graph *graph)
+{
+ struct nvc0_graph_priv *priv = (void *)graph;
+ u64 cfg;
+
+ cfg = (u32)priv->gpc_nr;
+ cfg |= (u32)priv->tpc_total << 8;
+ cfg |= (u64)priv->rop_nr << 32;
+
+ return cfg;
+}
+
/*******************************************************************************
@@ -91,3 +104,4 @@ nvc0_graph_context_ctor(struct nouveau_object *parent,
*/
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x100, 0, &chan->mmio);
+ ret = nouveau_gpuobj_new(nv_object(chan), NULL, 0x1000, 0x100, 0,
+ &chan->mmio);
if (ret)
@@ -103,4 +117,4 @@ nvc0_graph_context_ctor(struct nouveau_object *parent,
for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) {
- ret = nouveau_gpuobj_new(parent, NULL, data->size, data->align,
- 0, &chan->data[i].mem);
+ ret = nouveau_gpuobj_new(nv_object(chan), NULL, data->size,
+ data->align, 0, &chan->data[i].mem);
if (ret)
@@ -520,5 +534,6 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_graph_priv *priv;
+ bool enable = device->chipset != 0xd7;
int ret, i;
- ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
+ ret = nouveau_graph_create(parent, engine, oclass, enable, &priv);
*pobject = nv_object(priv);
@@ -531,2 +546,4 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ priv->base.units = nvc0_graph_units;
+
if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) {
@@ -553,3 +570,4 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0,
+ &priv->unk4188b4);
if (ret)
@@ -557,3 +575,4 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0,
+ &priv->unk4188b8);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
index a1e78de46456..c870dad0f670 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
@@ -120,2 +120,3 @@ nvc0_graph_class(void *obj)
case 0xd9:
+ case 0xd7:
return 0x9297;
@@ -171,2 +172,4 @@ void nvc0_graph_context_dtor(struct nouveau_object *);
+u64 nvc0_graph_units(struct nouveau_graph *);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
index 4857f913efdd..678c16f63055 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
@@ -79,2 +79,197 @@ nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
+static const struct nouveau_enum nve0_mp_warp_error[] = {
+ { 0x00, "NO_ERROR" },
+ { 0x01, "STACK_MISMATCH" },
+ { 0x05, "MISALIGNED_PC" },
+ { 0x08, "MISALIGNED_GPR" },
+ { 0x09, "INVALID_OPCODE" },
+ { 0x0d, "GPR_OUT_OF_BOUNDS" },
+ { 0x0e, "MEM_OUT_OF_BOUNDS" },
+ { 0x0f, "UNALIGNED_MEM_ACCESS" },
+ { 0x11, "INVALID_PARAM" },
+ {}
+};
+
+static const struct nouveau_enum nve0_mp_global_error[] = {
+ { 2, "MULTIPLE_WARP_ERRORS" },
+ { 3, "OUT_OF_STACK_SPACE" },
+ {}
+};
+
+static const struct nouveau_enum nve0_gpc_rop_error[] = {
+ { 1, "RT_PITCH_OVERRUN" },
+ { 4, "RT_WIDTH_OVERRUN" },
+ { 5, "RT_HEIGHT_OVERRUN" },
+ { 7, "ZETA_STORAGE_TYPE_MISMATCH" },
+ { 8, "RT_STORAGE_TYPE_MISMATCH" },
+ { 10, "RT_LINEAR_MISMATCH" },
+ {}
+};
+
+static const struct nouveau_enum nve0_sked_error[] = {
+ { 7, "CONSTANT_BUFFER_SIZE" },
+ { 9, "LOCAL_MEMORY_SIZE_POS" },
+ { 10, "LOCAL_MEMORY_SIZE_NEG" },
+ { 11, "WARP_CSTACK_SIZE" },
+ { 12, "TOTAL_TEMP_SIZE" },
+ { 13, "REGISTER_COUNT" },
+ { 18, "TOTAL_THREADS" },
+ { 20, "PROGRAM_OFFSET" },
+ { 21, "SHARED_MEMORY_SIZE" },
+ { 25, "SHARED_CONFIG_TOO_SMALL" },
+ { 26, "TOTAL_REGISTER_COUNT" },
+ {}
+};
+
+static void
+nve0_graph_mp_trap(struct nvc0_graph_priv *priv, int gpc, int tp)
+{
+ int i;
+ u32 werr = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x648));
+ u32 gerr = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x650));
+
+ nv_error(priv, "GPC%i/TP%i/MP trap:", gpc, tp);
+
+ for (i = 0; i <= 31; ++i) {
+ if (!(gerr & (1 << i)))
+ continue;
+ pr_cont(" ");
+ nouveau_enum_print(nve0_mp_global_error, i);
+ }
+ if (werr) {
+ pr_cont(" ");
+ nouveau_enum_print(nve0_mp_warp_error, werr & 0xffff);
+ }
+ pr_cont("\n");
+
+ /* disable MP trap to avoid spam */
+ nv_mask(priv, TPC_UNIT(gpc, tp, 0x50c), 0x2, 0x0);
+
+ /* TODO: figure out how to resume after an MP trap */
+}
+
+static void
+nve0_graph_tp_trap(struct nvc0_graph_priv *priv, int gpc, int tp)
+{
+ u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x508));
+
+ if (stat & 0x1) {
+ u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x224));
+ nv_error(priv, "GPC%i/TP%i/TEX trap: %08x\n",
+ gpc, tp, trap);
+
+ nv_wr32(priv, TPC_UNIT(gpc, tp, 0x224), 0xc0000000);
+ stat &= ~0x1;
+ }
+
+ if (stat & 0x2) {
+ nve0_graph_mp_trap(priv, gpc, tp);
+ stat &= ~0x2;
+ }
+
+ if (stat & 0x4) {
+ u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x084));
+ nv_error(priv, "GPC%i/TP%i/POLY trap: %08x\n",
+ gpc, tp, trap);
+
+ nv_wr32(priv, TPC_UNIT(gpc, tp, 0x084), 0xc0000000);
+ stat &= ~0x4;
+ }
+
+ if (stat & 0x8) {
+ u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x48c));
+ nv_error(priv, "GPC%i/TP%i/L1C trap: %08x\n",
+ gpc, tp, trap);
+
+ nv_wr32(priv, TPC_UNIT(gpc, tp, 0x48c), 0xc0000000);
+ stat &= ~0x8;
+ }
+
+ if (stat) {
+ nv_error(priv, "GPC%i/TP%i: unknown stat %08x\n",
+ gpc, tp, stat);
+ }
+}
+
+static void
+nve0_graph_gpc_trap(struct nvc0_graph_priv *priv)
+{
+ const u32 mask = nv_rd32(priv, 0x400118);
+ int gpc;
+
+ for (gpc = 0; gpc < 4; ++gpc) {
+ u32 stat;
+ int tp;
+
+ if (!(mask & (1 << gpc)))
+ continue;
+ stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90));
+
+ if (stat & 0x0001) {
+ u32 trap[4];
+ int i;
+
+ trap[0] = nv_rd32(priv, GPC_UNIT(gpc, 0x0420));
+ trap[1] = nv_rd32(priv, GPC_UNIT(gpc, 0x0434));
+ trap[2] = nv_rd32(priv, GPC_UNIT(gpc, 0x0438));
+ trap[3] = nv_rd32(priv, GPC_UNIT(gpc, 0x043c));
+
+ nv_error(priv, "GPC%i/PROP trap:", gpc);
+ for (i = 0; i <= 29; ++i) {
+ if (!(trap[0] & (1 << i)))
+ continue;
+ pr_cont(" ");
+ nouveau_enum_print(nve0_gpc_rop_error, i);
+ }
+ pr_cont("\n");
+
+ nv_error(priv, "x = %u, y = %u, "
+ "format = %x, storage type = %x\n",
+ trap[1] & 0xffff,
+ trap[1] >> 16,
+ (trap[2] >> 8) & 0x3f,
+ trap[3] & 0xff);
+
+ nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
+ stat &= ~0x0001;
+ }
+
+ if (stat & 0x0002) {
+ u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900));
+ nv_error(priv, "GPC%i/ZCULL trap: %08x\n", gpc,
+ trap);
+ nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
+ stat &= ~0x0002;
+ }
+
+ if (stat & 0x0004) {
+ u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028));
+ nv_error(priv, "GPC%i/CCACHE trap: %08x\n", gpc,
+ trap);
+ nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
+ stat &= ~0x0004;
+ }
+
+ if (stat & 0x0008) {
+ u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824));
+ nv_error(priv, "GPC%i/ESETUP trap %08x\n", gpc,
+ trap);
+ nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
+ stat &= ~0x0008;
+ }
+
+ for (tp = 0; tp < 8; ++tp) {
+ if (stat & (1 << (16 + tp)))
+ nve0_graph_tp_trap(priv, gpc, tp);
+ }
+ stat &= ~0xff0000;
+
+ if (stat) {
+ nv_error(priv, "GPC%i: unknown stat %08x\n",
+ gpc, stat);
+ }
+ }
+}
+
+
static void
@@ -84,2 +279,3 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst,
u32 trap = nv_rd32(priv, 0x400108);
+ int i;
int rop;
@@ -104,2 +300,28 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst,
+ if (trap & 0x00000100) {
+ u32 stat = nv_rd32(priv, 0x407020);
+ nv_error(priv, "SKED ch %d [0x%010llx %s]:",
+ chid, inst, nouveau_client_name(engctx));
+
+ for (i = 0; i <= 29; ++i) {
+ if (!(stat & (1 << i)))
+ continue;
+ pr_cont(" ");
+ nouveau_enum_print(nve0_sked_error, i);
+ }
+ pr_cont("\n");
+
+ if (stat & 0x3fffffff)
+ nv_wr32(priv, 0x407020, 0x40000000);
+ nv_wr32(priv, 0x400108, 0x00000100);
+ trap &= ~0x00000100;
+ }
+
+ if (trap & 0x01000000) {
+ nv_error(priv, "GPC ch %d [0x%010llx %s]:\n",
+ chid, inst, nouveau_client_name(engctx));
+ nve0_graph_gpc_trap(priv);
+ trap &= ~0x01000000;
+ }
+
if (trap & 0x02000000) {
@@ -219,2 +441,4 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ priv->base.units = nvc0_graph_units;
+
if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) {
@@ -229,3 +453,4 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0,
+ &priv->unk4188b4);
if (ret)
@@ -233,3 +458,4 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0,
+ &priv->unk4188b8);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
index a523eaad47e3..d698e710ddd4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
@@ -96,2 +96,28 @@ nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd,
+static int
+nvc0_software_mthd_mp_control(struct nouveau_object *object, u32 mthd,
+ void *args, u32 size)
+{
+ struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
+ struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine;
+ u32 data = *(u32 *)args;
+
+ switch (mthd) {
+ case 0x600:
+ nv_wr32(priv, 0x419e00, data); /* MP.PM_UNK000 */
+ break;
+ case 0x644:
+ if (data & ~0x1ffffe)
+ return -EINVAL;
+ nv_wr32(priv, 0x419e44, data); /* MP.TRAP_WARP_ERROR_EN */
+ break;
+ case 0x6ac:
+ nv_wr32(priv, 0x419eac, data); /* MP.PM_UNK0AC */
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static struct nouveau_omthds
@@ -103,2 +129,5 @@ nvc0_software_omthds[] = {
{ 0x0500, 0x0500, nvc0_software_mthd_flip },
+ { 0x0600, 0x0600, nvc0_software_mthd_mp_control },
+ { 0x0644, 0x0644, nvc0_software_mthd_mp_control },
+ { 0x06ac, 0x06ac, nvc0_software_mthd_mp_control },
{}
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
index d351a4e5819c..05840f3eee98 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -8,3 +8,3 @@
enum nv_subdev_type {
- NVDEV_SUBDEV_DEVICE,
+ NVDEV_ENGINE_DEVICE,
NVDEV_SUBDEV_VBIOS,
@@ -59,3 +59,3 @@ enum nv_subdev_type {
struct nouveau_device {
- struct nouveau_subdev base;
+ struct nouveau_engine base;
struct list_head head;
@@ -101,3 +101,3 @@ nv_device(void *obj)
if (unlikely(!nv_iclass(device, NV_SUBDEV_CLASS) ||
- (nv_hclass(device) & 0xff) != NVDEV_SUBDEV_DEVICE)) {
+ (nv_hclass(device) & 0xff) != NVDEV_ENGINE_DEVICE)) {
nv_assert("BAD CAST -> NvDevice, 0x%08x 0x%08x",
diff --git a/drivers/gpu/drm/nouveau/core/include/core/parent.h b/drivers/gpu/drm/nouveau/core/include/core/parent.h
index 31cd852c96df..9f5ea900ff00 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/parent.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/parent.h
@@ -53,4 +53,4 @@ void nouveau_parent_destroy(struct nouveau_parent *);
void _nouveau_parent_dtor(struct nouveau_object *);
-#define _nouveau_parent_init _nouveau_object_init
-#define _nouveau_parent_fini _nouveau_object_fini
+#define _nouveau_parent_init nouveau_object_init
+#define _nouveau_parent_fini nouveau_object_fini
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/device.h b/drivers/gpu/drm/nouveau/core/include/engine/device.h
index c9e4c4afa50e..b3dd2c4c2f1e 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/device.h
@@ -20,3 +20,2 @@ int nve0_identify(struct nouveau_device *);
-extern struct nouveau_oclass nouveau_device_sclass[];
struct nouveau_device *nouveau_device_find(u64 name);
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
index b46c197709f3..633c2f806482 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
@@ -67,3 +67,4 @@ struct nouveau_fifo {
- struct nouveau_event *uevent;
+ struct nouveau_event *cevent; /* channel creation event */
+ struct nouveau_event *uevent; /* async user trigger */
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
index 6943b40d0817..5d392439f2ac 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
@@ -28,2 +28,6 @@ struct nouveau_graph {
struct nouveau_engine base;
+
+ /* Returns chipset-specific counts of units packed into an u64.
+ */
+ u64 (*units)(struct nouveau_graph *);
};
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
index f351f63bc654..a1985ed3d58d 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
@@ -6,4 +6,11 @@
+struct nouveau_mm_node;
+
struct nouveau_ltcg {
struct nouveau_subdev base;
+
+ int (*tags_alloc)(struct nouveau_ltcg *, u32 count,
+ struct nouveau_mm_node **);
+ void (*tags_free)(struct nouveau_ltcg *, struct nouveau_mm_node **);
+ void (*tags_clear)(struct nouveau_ltcg *, u32 first, u32 count);
};
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
index fded97cea500..d5502267c30f 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
@@ -23,14 +23,18 @@ nouveau_mc(void *obj)
#define nouveau_mc_create(p,e,o,d) \
- nouveau_subdev_create_((p), (e), (o), 0, "PMC", "master", \
- sizeof(**d), (void **)d)
-#define nouveau_mc_destroy(p) \
- nouveau_subdev_destroy(&(p)->base)
-#define nouveau_mc_init(p) \
- nouveau_subdev_init(&(p)->base)
-#define nouveau_mc_fini(p,s) \
- nouveau_subdev_fini(&(p)->base, (s))
-
-#define _nouveau_mc_dtor _nouveau_subdev_dtor
-#define _nouveau_mc_init _nouveau_subdev_init
-#define _nouveau_mc_fini _nouveau_subdev_fini
+ nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_destroy(p) ({ \
+ struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
+})
+#define nouveau_mc_init(p) ({ \
+ struct nouveau_mc *pmc = (p); _nouveau_mc_init(nv_object(pmc)); \
+})
+#define nouveau_mc_fini(p,s) ({ \
+ struct nouveau_mc *pmc = (p); _nouveau_mc_fini(nv_object(pmc), (s)); \
+})
+
+int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, int, void **);
+void _nouveau_mc_dtor(struct nouveau_object *);
+int _nouveau_mc_init(struct nouveau_object *);
+int _nouveau_mc_fini(struct nouveau_object *, bool);
@@ -42,4 +46,2 @@ extern struct nouveau_oclass nvc0_mc_oclass;
-void nouveau_mc_intr(struct nouveau_subdev *);
-
extern const struct nouveau_mc_intr nv04_mc_intr[];
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
index 0b20fc0d19c1..c075998d82e6 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
@@ -75,2 +75,3 @@ extern struct nouveau_oclass nv40_therm_oclass;
extern struct nouveau_oclass nv50_therm_oclass;
+extern struct nouveau_oclass nv84_therm_oclass;
extern struct nouveau_oclass nva3_therm_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h
index eb496033b55c..3bd9be2ab37f 100644
--- a/drivers/gpu/drm/nouveau/core/os.h
+++ b/drivers/gpu/drm/nouveau/core/os.h
@@ -19,2 +19,3 @@
#include <linux/reboot.h>
+#include <linux/interrupt.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
index c3acf5b70d9e..649f1ced1fe0 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
@@ -124,4 +124,4 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0, NVOBJ_FLAG_HEAP,
- &priv->mem);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x20000, 0,
+ NVOBJ_FLAG_HEAP, &priv->mem);
heap = nv_object(priv->mem);
@@ -130,4 +130,5 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, heap, (device->chipset == 0x50) ?
- 0x1400 : 0x0200, 0, 0, &priv->pad);
+ ret = nouveau_gpuobj_new(nv_object(priv), heap,
+ (device->chipset == 0x50) ? 0x1400 : 0x0200,
+ 0, 0, &priv->pad);
if (ret)
@@ -135,3 +136,4 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, heap, 0x4000, 0, 0, &priv->pgd);
+ ret = nouveau_gpuobj_new(nv_object(priv), heap, 0x4000, 0,
+ 0, &priv->pgd);
if (ret)
@@ -147,5 +149,5 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, heap, ((limit-- - start) >> 12) * 8,
- 0x1000, NVOBJ_FLAG_ZERO_ALLOC,
- &vm->pgt[0].obj[0]);
+ ret = nouveau_gpuobj_new(nv_object(priv), heap,
+ ((limit-- - start) >> 12) * 8, 0x1000,
+ NVOBJ_FLAG_ZERO_ALLOC, &vm->pgt[0].obj[0]);
vm->pgt[0].refcount[0] = 1;
@@ -159,3 +161,3 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, heap, 24, 16, 0, &priv->bar3);
+ ret = nouveau_gpuobj_new(nv_object(priv), heap, 24, 16, 0, &priv->bar3);
if (ret)
@@ -184,3 +186,3 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, heap, 24, 16, 0, &priv->bar1);
+ ret = nouveau_gpuobj_new(nv_object(priv), heap, 24, 16, 0, &priv->bar1);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
index 77a6fb725d3f..f8a44956dec1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
@@ -103,3 +103,4 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* BAR3 */
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[0].mem);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
+ &priv->bar[0].mem);
mem = priv->bar[0].mem;
@@ -108,3 +109,4 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[0].pgd);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0,
+ &priv->bar[0].pgd);
if (ret)
@@ -116,3 +118,3 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(pci_resource_len(pdev, 3) >> 12) * 8,
@@ -135,3 +137,4 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* BAR1 */
- ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0, 0, &priv->bar[1].mem);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
+ &priv->bar[1].mem);
mem = priv->bar[1].mem;
@@ -140,3 +143,4 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL, 0x8000, 0, 0, &priv->bar[1].pgd);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0,
+ &priv->bar[1].pgd);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index 9c41b58d57e2..c300b5e7b670 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -66,5 +66,7 @@ init_or(struct nvbios_init *init)
{
- if (init->outp)
- return ffs(init->outp->or) - 1;
- error("script needs OR!!\n");
+ if (init_exec(init)) {
+ if (init->outp)
+ return ffs(init->outp->or) - 1;
+ error("script needs OR!!\n");
+ }
return 0;
@@ -75,5 +77,7 @@ init_link(struct nvbios_init *init)
{
- if (init->outp)
- return !(init->outp->sorconf.link & 1);
- error("script needs OR link\n");
+ if (init_exec(init)) {
+ if (init->outp)
+ return !(init->outp->sorconf.link & 1);
+ error("script needs OR link\n");
+ }
return 0;
@@ -84,5 +88,7 @@ init_crtc(struct nvbios_init *init)
{
- if (init->crtc >= 0)
- return init->crtc;
- error("script needs crtc\n");
+ if (init_exec(init)) {
+ if (init->crtc >= 0)
+ return init->crtc;
+ error("script needs crtc\n");
+ }
return 0;
@@ -94,12 +100,17 @@ init_conn(struct nvbios_init *init)
struct nouveau_bios *bios = init->bios;
+ u8 ver, len;
+ u16 conn;
- if (init->outp) {
- u8 ver, len;
- u16 conn = dcb_conn(bios, init->outp->connector, &ver, &len);
- if (conn)
- return nv_ro08(bios, conn);
+ if (init_exec(init)) {
+ if (init->outp) {
+ conn = init->outp->connector;
+ conn = dcb_conn(bios, conn, &ver, &len);
+ if (conn)
+ return nv_ro08(bios, conn);
+ }
+
+ error("script needs connector type\n");
}
- error("script needs connector type\n");
- return 0x00;
+ return 0xff;
}
@@ -229,3 +240,4 @@ init_i2c(struct nvbios_init *init, int index)
if (!init->outp) {
- error("script needs output for i2c\n");
+ if (init_exec(init))
+ error("script needs output for i2c\n");
return NULL;
@@ -546,3 +558,4 @@ init_tmds_reg(struct nvbios_init *init, u8 tmds)
- error("tmds opcodes need dcb\n");
+ if (init_exec(init))
+ error("tmds opcodes need dcb\n");
} else {
@@ -794,3 +807,4 @@ init_dp_condition(struct nvbios_init *init)
- warn("script needs dp output table data\n");
+ if (init_exec(init))
+ warn("script needs dp output table data\n");
break;
@@ -818,3 +832,3 @@ init_io_mask_or(struct nvbios_init *init)
- trace("IO_MASK_OR\t0x03d4[0x%02x] &= ~(1 << 0x%02x)", index, or);
+ trace("IO_MASK_OR\t0x03d4[0x%02x] &= ~(1 << 0x%02x)\n", index, or);
init->offset += 2;
@@ -837,3 +851,3 @@ init_io_or(struct nvbios_init *init)
- trace("IO_OR\t0x03d4[0x%02x] |= (1 << 0x%02x)", index, or);
+ trace("IO_OR\t0x03d4[0x%02x] |= (1 << 0x%02x)\n", index, or);
init->offset += 2;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index 7606ed15b6fa..86ad59203c8b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -25,2 +25,3 @@
#include <subdev/fb.h>
+#include <subdev/ltcg.h>
#include <subdev/bios.h>
@@ -33,24 +34,4 @@ struct nvc0_fb_priv {
-/* 0 = unsupported
- * 1 = non-compressed
- * 3 = compressed
- */
-static const u8 types[256] = {
- 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
- 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
- 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
- 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
- 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
-};
+extern const u8 nvc0_pte_storage_type_map[256];
+
@@ -60,3 +41,3 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
u8 memtype = (tile_flags & 0x0000ff00) >> 8;
- return likely((types[memtype] == 1));
+ return likely((nvc0_pte_storage_type_map[memtype] != 0xff));
}
@@ -132,2 +113,3 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
int ret;
+ const bool comp = nvc0_pte_storage_type_map[type] != type;
@@ -144,3 +126,2 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
INIT_LIST_HEAD(&mem->regions);
- mem->memtype = type;
mem->size = size;
@@ -148,2 +129,15 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
mutex_lock(&pfb->base.mutex);
+ if (comp) {
+ struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb->base.base.parent);
+
+ /* compression only works with lpages */
+ if (align == (1 << (17 - 12))) {
+ int n = size >> 5;
+ ltcg->tags_alloc(ltcg, n, &mem->tag);
+ }
+ if (unlikely(!mem->tag))
+ type = nvc0_pte_storage_type_map[type];
+ }
+ mem->memtype = type;
+
do {
@@ -170,2 +164,13 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
+static void
+nvc0_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
+{
+ struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb->base.base.parent);
+
+ if ((*pmem)->tag)
+ ltcg->tags_free(ltcg, &(*pmem)->tag);
+
+ nv50_fb_vram_del(pfb, pmem);
+}
+
static int
@@ -180,3 +185,4 @@ nvc0_fb_init(struct nouveau_object *object)
- nv_wr32(priv, 0x100c10, priv->r100c10 >> 8);
+ if (priv->r100c10_page)
+ nv_wr32(priv, 0x100c10, priv->r100c10 >> 8);
return 0;
@@ -216,12 +222,12 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->base.ram.get = nvc0_fb_vram_new;
- priv->base.ram.put = nv50_fb_vram_del;
+ priv->base.ram.put = nvc0_fb_vram_del;
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (!priv->r100c10_page)
- return -ENOMEM;
-
- priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, 0,
- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(device->pdev, priv->r100c10))
- return -EFAULT;
+ if (priv->r100c10_page) {
+ priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page,
+ 0, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(device->pdev, priv->r100c10))
+ return -EFAULT;
+ }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index 2e98e8a3f1aa..8ae2625415e1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -142,8 +142,4 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
/* drop port's i2c subdev refcount, i2c handles this itself */
- if (ret == 0) {
+ if (ret == 0)
list_add_tail(&port->head, &i2c->ports);
- atomic_dec(&parent->refcount);
- atomic_dec(&engine->refcount);
- }
-
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
index f5bbd3834116..795393d7b2f5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
@@ -95,3 +95,2 @@ nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
struct nouveau_object *engine = nv_object(imem);
- struct nv04_instmem_priv *priv = (void *)(imem);
int ret;
@@ -103,10 +102,2 @@ nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
- /* INSTMEM itself creates objects to reserve (and preserve across
- * suspend/resume) various fixed data locations, each one of these
- * takes a reference on INSTMEM itself, causing it to never be
- * freed. We drop all the self-references here to avoid this.
- */
- if (unlikely(!priv->created))
- atomic_dec(&engine->refcount);
-
return 0;
@@ -136,3 +127,4 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* 0x00000-0x10000: reserve for probable vbios image */
- ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x10000, 0, 0,
+ &priv->vbios);
if (ret)
@@ -141,3 +133,3 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* 0x10000-0x18000: reserve for RAMHT */
- ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht);
+ ret = nouveau_ramht_new(nv_object(priv), NULL, 0x08000, 0, &priv->ramht);
if (ret)
@@ -146,3 +138,3 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* 0x18000-0x18800: reserve for RAMFC (enough for 32 nv30 channels) */
- ret = nouveau_gpuobj_new(parent, NULL, 0x00800, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x00800, 0,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc);
@@ -152,3 +144,4 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* 0x18800-0x18a00: reserve for RAMRO */
- ret = nouveau_gpuobj_new(parent, NULL, 0x00200, 0, 0, &priv->ramro);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x00200, 0, 0,
+ &priv->ramro);
if (ret)
@@ -156,3 +149,2 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- priv->created = true;
return 0;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
index 7983d8d9b358..b15b61310236 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
@@ -11,3 +11,2 @@ struct nv04_instmem_priv {
struct nouveau_instmem base;
- bool created;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
index da64253201ef..716bf41bc3c1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
@@ -84,3 +84,4 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* 0x00000-0x10000: reserve for probable vbios image */
- ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x10000, 0, 0,
+ &priv->vbios);
if (ret)
@@ -89,3 +90,4 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
/* 0x10000-0x18000: reserve for RAMHT */
- ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht);
+ ret = nouveau_ramht_new(nv_object(priv), NULL, 0x08000, 0,
+ &priv->ramht);
if (ret)
@@ -96,3 +98,4 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
*/
- ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, 0, &priv->ramro);
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x08000, 0, 0,
+ &priv->ramro);
if (ret)
@@ -103,3 +106,3 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
*/
- ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x20000, 0,
NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc);
@@ -108,3 +111,2 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- priv->created = true;
return 0;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
index 078a2b9d6bd6..e4940fb166e8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
@@ -25,2 +25,4 @@
#include <subdev/ltcg.h>
+#include <subdev/fb.h>
+#include <subdev/timer.h>
@@ -28,3 +30,8 @@ struct nvc0_ltcg_priv {
struct nouveau_ltcg base;
+ u32 part_nr;
+ u32 part_mask;
u32 subp_nr;
+ struct nouveau_mm tags;
+ u32 num_tags;
+ struct nouveau_mm_node *tag_ram;
};
@@ -64,2 +71,94 @@ nvc0_ltcg_intr(struct nouveau_subdev *subdev)
static int
+nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
+ struct nouveau_mm_node **pnode)
+{
+ struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ int ret;
+
+ ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
+ if (ret)
+ *pnode = NULL;
+
+ return ret;
+}
+
+static void
+nvc0_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
+{
+ struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+
+ nouveau_mm_free(&priv->tags, pnode);
+}
+
+static void
+nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+{
+ struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ u32 last = first + count - 1;
+ int p, i;
+
+ BUG_ON((first > last) || (last >= priv->num_tags));
+
+ nv_wr32(priv, 0x17e8cc, first);
+ nv_wr32(priv, 0x17e8d0, last);
+ nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
+
+ /* wait until it's finished with clearing */
+ for (p = 0; p < priv->part_nr; ++p) {
+ if (!(priv->part_mask & (1 << p)))
+ continue;
+ for (i = 0; i < priv->subp_nr; ++i)
+ nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
+ }
+}
+
+/* TODO: Figure out tag memory details and drop the over-cautious allocation.
+ */
+static int
+nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
+{
+ u32 tag_size, tag_margin, tag_align;
+ int ret;
+
+ nv_wr32(priv, 0x17e8d8, priv->part_nr);
+
+ /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
+ priv->num_tags = (pfb->ram.size >> 17) / 4;
+ if (priv->num_tags > (1 << 17))
+ priv->num_tags = 1 << 17; /* we have 17 bits in PTE */
+ priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */
+
+ tag_align = priv->part_nr * 0x800;
+ tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;
+
+ /* 4 part 4 sub: 0x2000 bytes for 56 tags */
+ /* 3 part 4 sub: 0x6000 bytes for 168 tags */
+ /*
+ * About 147 bytes per tag. Let's be safe and allocate x2, which makes
+ * 0x4980 bytes for 64 tags, and round up to 0x6000 bytes for 64 tags.
+ *
+ * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %.
+ */
+ tag_size = (priv->num_tags / 64) * 0x6000 + tag_margin;
+ tag_size += tag_align;
+ tag_size = (tag_size + 0xfff) >> 12; /* round up */
+
+ ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1,
+ &priv->tag_ram);
+ if (ret) {
+ priv->num_tags = 0;
+ } else {
+ u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin;
+
+ tag_base += tag_align - 1;
+ ret = do_div(tag_base, tag_align);
+
+ nv_wr32(priv, 0x17e8d4, tag_base);
+ }
+ ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
+
+ return ret;
+}
+
+static int
nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
@@ -69,2 +168,3 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_ltcg_priv *priv;
+ struct nouveau_fb *pfb = nouveau_fb(parent);
int ret;
@@ -76,5 +176,17 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 24;
+ priv->part_nr = nv_rd32(priv, 0x022438);
+ priv->part_mask = nv_rd32(priv, 0x022554);
+
+ priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
+
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+ ret = nvc0_ltcg_init_tag_ram(pfb, priv);
+ if (ret)
+ return ret;
+
+ priv->base.tags_alloc = nvc0_ltcg_tags_alloc;
+ priv->base.tags_free = nvc0_ltcg_tags_free;
+ priv->base.tags_clear = nvc0_ltcg_tags_clear;
+
nv_subdev(priv)->intr = nvc0_ltcg_intr;
@@ -83,2 +195,15 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+static void
+nvc0_ltcg_dtor(struct nouveau_object *object)
+{
+ struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+ struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+ struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
+
+ nouveau_mm_fini(&priv->tags);
+ nouveau_mm_free(&pfb->vram, &priv->tag_ram);
+
+ nouveau_ltcg_destroy(ltcg);
+}
+
struct nouveau_oclass
@@ -88,3 +213,3 @@ nvc0_ltcg_oclass = {
.ctor = nvc0_ltcg_ctor,
- .dtor = _nouveau_ltcg_dtor,
+ .dtor = nvc0_ltcg_dtor,
.init = _nouveau_ltcg_init,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
index 8379aafa6e1b..1c0330b8c9a4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
@@ -26,6 +26,6 @@
-void
-nouveau_mc_intr(struct nouveau_subdev *subdev)
+static irqreturn_t
+nouveau_mc_intr(int irq, void *arg)
{
- struct nouveau_mc *pmc = nouveau_mc(subdev);
+ struct nouveau_mc *pmc = arg;
const struct nouveau_mc_intr *map = pmc->intr_map;
@@ -37,3 +37,3 @@ nouveau_mc_intr(struct nouveau_subdev *subdev)
if (stat & map->stat) {
- unit = nouveau_subdev(subdev, map->unit);
+ unit = nouveau_subdev(pmc, map->unit);
if (unit && unit->intr)
@@ -48,2 +48,54 @@ nouveau_mc_intr(struct nouveau_subdev *subdev)
}
+
+ return stat ? IRQ_HANDLED : IRQ_NONE;
+}
+
+int
+_nouveau_mc_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nouveau_mc *pmc = (void *)object;
+ nv_wr32(pmc, 0x000140, 0x00000000);
+ return nouveau_subdev_fini(&pmc->base, suspend);
+}
+
+int
+_nouveau_mc_init(struct nouveau_object *object)
+{
+ struct nouveau_mc *pmc = (void *)object;
+ int ret = nouveau_subdev_init(&pmc->base);
+ if (ret)
+ return ret;
+ nv_wr32(pmc, 0x000140, 0x00000001);
+ return 0;
+}
+
+void
+_nouveau_mc_dtor(struct nouveau_object *object)
+{
+ struct nouveau_device *device = nv_device(object);
+ struct nouveau_mc *pmc = (void *)object;
+ free_irq(device->pdev->irq, pmc);
+ nouveau_subdev_destroy(&pmc->base);
+}
+
+int
+nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, int length, void **pobject)
+{
+ struct nouveau_device *device = nv_device(parent);
+ struct nouveau_mc *pmc;
+ int ret;
+
+ ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PMC",
+ "master", length, pobject);
+ pmc = *pobject;
+ if (ret)
+ return ret;
+
+ ret = request_irq(device->pdev->irq, nouveau_mc_intr,
+ IRQF_SHARED, "nouveau", pmc);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
index 89da8fa7ea0f..8c769715227b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
@@ -57,3 +57,2 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- nv_subdev(priv)->intr = nouveau_mc_intr;
priv->base.intr_map = nv04_mc_intr;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
index 397d868359ad..51919371810f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
@@ -43,3 +43,2 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- nv_subdev(priv)->intr = nouveau_mc_intr;
priv->base.intr_map = nv04_mc_intr;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
index 5965add6daee..d796924f9930 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
@@ -59,3 +59,2 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- nv_subdev(priv)->intr = nouveau_mc_intr;
priv->base.intr_map = nv50_mc_intr;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
index 3a80b29dce0f..e82fd21b5041 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
@@ -61,3 +61,2 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- nv_subdev(priv)->intr = nouveau_mc_intr;
priv->base.intr_map = nv98_mc_intr;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
index 42bbf72023a8..737bd4b682e1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
@@ -63,3 +63,2 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- nv_subdev(priv)->intr = nouveau_mc_intr;
priv->base.intr_map = nvc0_mc_intr;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
index a70d1b7e397b..002e51b3af93 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
@@ -167,3 +167,3 @@ nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
-static void
+void
nv40_therm_intr(struct nouveau_subdev *subdev)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index 86632cbd65ce..8cf7597a2182 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -120,141 +120,32 @@ nv50_fan_pwm_clock(struct nouveau_therm *therm)
-int
-nv50_temp_get(struct nouveau_therm *therm)
-{
- return nv_rd32(therm, 0x20400);
-}
-
-static void
-nv50_therm_program_alarms(struct nouveau_therm *therm)
-{
- struct nouveau_therm_priv *priv = (void *)therm;
- struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
-
- /* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */
- nv_wr32(therm, 0x20000, 0x000003ff);
-
- /* shutdown: The computer should be shutdown when reached */
- nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis);
- nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp);
-
- /* THRS_1 : fan boost*/
- nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp);
-
- /* THRS_2 : critical */
- nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp);
-
- /* THRS_4 : down clock */
- nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp);
- spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
-
- nv_info(therm,
- "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
- sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
- sensor->thrs_down_clock.temp,
- sensor->thrs_down_clock.hysteresis,
- sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
- sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
-
-}
-
-/* must be called with alarm_program_lock taken ! */
static void
-nv50_therm_threshold_hyst_emulation(struct nouveau_therm *therm,
- uint32_t thrs_reg, u8 status_bit,
- const struct nvbios_therm_threshold *thrs,
- enum nouveau_therm_thrs thrs_name)
+nv50_sensor_setup(struct nouveau_therm *therm)
{
- enum nouveau_therm_thrs_direction direction;
- enum nouveau_therm_thrs_state prev_state, new_state;
- int temp, cur;
-
- prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name);
- temp = nv_rd32(therm, thrs_reg);
-
- /* program the next threshold */
- if (temp == thrs->temp) {
- nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis);
- new_state = NOUVEAU_THERM_THRS_HIGHER;
- } else {
- nv_wr32(therm, thrs_reg, thrs->temp);
- new_state = NOUVEAU_THERM_THRS_LOWER;
- }
-
- /* fix the state (in case someone reprogrammed the alarms) */
- cur = therm->temp_get(therm);
- if (new_state == NOUVEAU_THERM_THRS_LOWER && cur > thrs->temp)
- new_state = NOUVEAU_THERM_THRS_HIGHER;
- else if (new_state == NOUVEAU_THERM_THRS_HIGHER &&
- cur < thrs->temp - thrs->hysteresis)
- new_state = NOUVEAU_THERM_THRS_LOWER;
- nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state);
-
- /* find the direction */
- if (prev_state < new_state)
- direction = NOUVEAU_THERM_THRS_RISING;
- else if (prev_state > new_state)
- direction = NOUVEAU_THERM_THRS_FALLING;
- else
- return;
-
- /* advertise a change in direction */
- nouveau_therm_sensor_event(therm, thrs_name, direction);
+ nv_mask(therm, 0x20010, 0x40000000, 0x0);
+ mdelay(20); /* wait for the temperature to stabilize */
}
-static void
-nv50_therm_intr(struct nouveau_subdev *subdev)
+static int
+nv50_temp_get(struct nouveau_therm *therm)
{
- struct nouveau_therm *therm = nouveau_therm(subdev);
struct nouveau_therm_priv *priv = (void *)therm;
struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
- unsigned long flags;
- uint32_t intr;
-
- spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
-
- intr = nv_rd32(therm, 0x20100);
-
- /* THRS_4: downclock */
- if (intr & 0x002) {
- nv50_therm_threshold_hyst_emulation(therm, 0x20414, 24,
- &sensor->thrs_down_clock,
- NOUVEAU_THERM_THRS_DOWNCLOCK);
- intr &= ~0x002;
- }
+ int core_temp;
- /* shutdown */
- if (intr & 0x004) {
- nv50_therm_threshold_hyst_emulation(therm, 0x20480, 20,
- &sensor->thrs_shutdown,
- NOUVEAU_THERM_THRS_SHUTDOWN);
- intr &= ~0x004;
- }
-
- /* THRS_1 : fan boost */
- if (intr & 0x008) {
- nv50_therm_threshold_hyst_emulation(therm, 0x204c4, 21,
- &sensor->thrs_fan_boost,
- NOUVEAU_THERM_THRS_FANBOOST);
- intr &= ~0x008;
- }
+ core_temp = nv_rd32(therm, 0x20014) & 0x3fff;
- /* THRS_2 : critical */
- if (intr & 0x010) {
- nv50_therm_threshold_hyst_emulation(therm, 0x204c0, 22,
- &sensor->thrs_critical,
- NOUVEAU_THERM_THRS_CRITICAL);
- intr &= ~0x010;
- }
+ /* if the slope or the offset is unset, do no use the sensor */
+ if (!sensor->slope_div || !sensor->slope_mult ||
+ !sensor->offset_num || !sensor->offset_den)
+ return -ENODEV;
- if (intr)
- nv_error(therm, "unhandled intr 0x%08x\n", intr);
+ core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
+ core_temp = core_temp + sensor->offset_num / sensor->offset_den;
+ core_temp = core_temp + sensor->offset_constant - 8;
- /* ACK everything */
- nv_wr32(therm, 0x20100, 0xffffffff);
- nv_wr32(therm, 0x1100, 0x10000); /* PBUS */
+ /* reserve negative temperatures for errors */
+ if (core_temp < 0)
+ core_temp = 0;
- spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
+ return core_temp;
}
@@ -280,18 +171,4 @@ nv50_therm_ctor(struct nouveau_object *parent,
priv->base.base.temp_get = nv50_temp_get;
- priv->base.sensor.program_alarms = nv50_therm_program_alarms;
- nv_subdev(priv)->intr = nv50_therm_intr;
-
- /* init the thresholds */
- nouveau_therm_sensor_set_threshold_state(&priv->base.base,
- NOUVEAU_THERM_THRS_SHUTDOWN,
- NOUVEAU_THERM_THRS_LOWER);
- nouveau_therm_sensor_set_threshold_state(&priv->base.base,
- NOUVEAU_THERM_THRS_FANBOOST,
- NOUVEAU_THERM_THRS_LOWER);
- nouveau_therm_sensor_set_threshold_state(&priv->base.base,
- NOUVEAU_THERM_THRS_CRITICAL,
- NOUVEAU_THERM_THRS_LOWER);
- nouveau_therm_sensor_set_threshold_state(&priv->base.base,
- NOUVEAU_THERM_THRS_DOWNCLOCK,
- NOUVEAU_THERM_THRS_LOWER);
+ priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling;
+ nv_subdev(priv)->intr = nv40_therm_intr;
@@ -300,2 +177,12 @@ nv50_therm_ctor(struct nouveau_object *parent,
+static int
+nv50_therm_init(struct nouveau_object *object)
+{
+ struct nouveau_therm *therm = (void *)object;
+
+ nv50_sensor_setup(therm);
+
+ return _nouveau_therm_init(object);
+}
+
struct nouveau_oclass
@@ -306,3 +193,3 @@ nv50_therm_oclass = {
.dtor = _nouveau_therm_dtor,
- .init = _nouveau_therm_init,
+ .init = nv50_therm_init,
.fini = _nouveau_therm_fini,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c
new file mode 100644
index 000000000000..42ba633ccff7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2012 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
+ * Martin Peres
+ */
+
+#include "priv.h"
+
+struct nv84_therm_priv {
+ struct nouveau_therm_priv base;
+};
+
+int
+nv84_temp_get(struct nouveau_therm *therm)
+{
+ return nv_rd32(therm, 0x20400);
+}
+
+static void
+nv84_therm_program_alarms(struct nouveau_therm *therm)
+{
+ struct nouveau_therm_priv *priv = (void *)therm;
+ struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
+
+ /* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */
+ nv_wr32(therm, 0x20000, 0x000003ff);
+
+ /* shutdown: The computer should be shutdown when reached */
+ nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis);
+ nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp);
+
+ /* THRS_1 : fan boost*/
+ nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp);
+
+ /* THRS_2 : critical */
+ nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp);
+
+ /* THRS_4 : down clock */
+ nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp);
+ spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
+
+ nv_debug(therm,
+ "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
+ sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
+ sensor->thrs_down_clock.temp,
+ sensor->thrs_down_clock.hysteresis,
+ sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
+ sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
+
+}
+
+/* must be called with alarm_program_lock taken ! */
+static void
+nv84_therm_threshold_hyst_emulation(struct nouveau_therm *therm,
+ uint32_t thrs_reg, u8 status_bit,
+ const struct nvbios_therm_threshold *thrs,
+ enum nouveau_therm_thrs thrs_name)
+{
+ enum nouveau_therm_thrs_direction direction;
+ enum nouveau_therm_thrs_state prev_state, new_state;
+ int temp, cur;
+
+ prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name);
+ temp = nv_rd32(therm, thrs_reg);
+
+ /* program the next threshold */
+ if (temp == thrs->temp) {
+ nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis);
+ new_state = NOUVEAU_THERM_THRS_HIGHER;
+ } else {
+ nv_wr32(therm, thrs_reg, thrs->temp);
+ new_state = NOUVEAU_THERM_THRS_LOWER;
+ }
+
+ /* fix the state (in case someone reprogrammed the alarms) */
+ cur = therm->temp_get(therm);
+ if (new_state == NOUVEAU_THERM_THRS_LOWER && cur > thrs->temp)
+ new_state = NOUVEAU_THERM_THRS_HIGHER;
+ else if (new_state == NOUVEAU_THERM_THRS_HIGHER &&
+ cur < thrs->temp - thrs->hysteresis)
+ new_state = NOUVEAU_THERM_THRS_LOWER;
+ nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state);
+
+ /* find the direction */
+ if (prev_state < new_state)
+ direction = NOUVEAU_THERM_THRS_RISING;
+ else if (prev_state > new_state)
+ direction = NOUVEAU_THERM_THRS_FALLING;
+ else
+ return;
+
+ /* advertise a change in direction */
+ nouveau_therm_sensor_event(therm, thrs_name, direction);
+}
+
+static void
+nv84_therm_intr(struct nouveau_subdev *subdev)
+{
+ struct nouveau_therm *therm = nouveau_therm(subdev);
+ struct nouveau_therm_priv *priv = (void *)therm;
+ struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+ unsigned long flags;
+ uint32_t intr;
+
+ spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
+
+ intr = nv_rd32(therm, 0x20100);
+
+ /* THRS_4: downclock */
+ if (intr & 0x002) {
+ nv84_therm_threshold_hyst_emulation(therm, 0x20414, 24,
+ &sensor->thrs_down_clock,
+ NOUVEAU_THERM_THRS_DOWNCLOCK);
+ intr &= ~0x002;
+ }
+
+ /* shutdown */
+ if (intr & 0x004) {
+ nv84_therm_threshold_hyst_emulation(therm, 0x20480, 20,
+ &sensor->thrs_shutdown,
+ NOUVEAU_THERM_THRS_SHUTDOWN);
+ intr &= ~0x004;
+ }
+
+ /* THRS_1 : fan boost */
+ if (intr & 0x008) {
+ nv84_therm_threshold_hyst_emulation(therm, 0x204c4, 21,
+ &sensor->thrs_fan_boost,
+ NOUVEAU_THERM_THRS_FANBOOST);
+ intr &= ~0x008;
+ }
+
+ /* THRS_2 : critical */
+ if (intr & 0x010) {
+ nv84_therm_threshold_hyst_emulation(therm, 0x204c0, 22,
+ &sensor->thrs_critical,
+ NOUVEAU_THERM_THRS_CRITICAL);
+ intr &= ~0x010;
+ }
+
+ if (intr)
+ nv_error(therm, "unhandled intr 0x%08x\n", intr);
+
+ /* ACK everything */
+ nv_wr32(therm, 0x20100, 0xffffffff);
+ nv_wr32(therm, 0x1100, 0x10000); /* PBUS */
+
+ spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
+}
+
+static int
+nv84_therm_ctor(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nv84_therm_priv *priv;
+ int ret;
+
+ ret = nouveau_therm_create(parent, engine, oclass, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl;
+ priv->base.base.pwm_get = nv50_fan_pwm_get;
+ priv->base.base.pwm_set = nv50_fan_pwm_set;
+ priv->base.base.pwm_clock = nv50_fan_pwm_clock;
+ priv->base.base.temp_get = nv84_temp_get;
+ priv->base.sensor.program_alarms = nv84_therm_program_alarms;
+ nv_subdev(priv)->intr = nv84_therm_intr;
+
+ /* init the thresholds */
+ nouveau_therm_sensor_set_threshold_state(&priv->base.base,
+ NOUVEAU_THERM_THRS_SHUTDOWN,
+ NOUVEAU_THERM_THRS_LOWER);
+ nouveau_therm_sensor_set_threshold_state(&priv->base.base,
+ NOUVEAU_THERM_THRS_FANBOOST,
+ NOUVEAU_THERM_THRS_LOWER);
+ nouveau_therm_sensor_set_threshold_state(&priv->base.base,
+ NOUVEAU_THERM_THRS_CRITICAL,
+ NOUVEAU_THERM_THRS_LOWER);
+ nouveau_therm_sensor_set_threshold_state(&priv->base.base,
+ NOUVEAU_THERM_THRS_DOWNCLOCK,
+ NOUVEAU_THERM_THRS_LOWER);
+
+ return nouveau_therm_preinit(&priv->base.base);
+}
+
+struct nouveau_oclass
+nv84_therm_oclass = {
+ .handle = NV_SUBDEV(THERM, 0x84),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nv84_therm_ctor,
+ .dtor = _nouveau_therm_dtor,
+ .init = _nouveau_therm_init,
+ .fini = _nouveau_therm_fini,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
index 2dcc5437116a..d11a7c400813 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
@@ -83,3 +83,3 @@ nva3_therm_ctor(struct nouveau_object *parent,
priv->base.base.pwm_clock = nv50_fan_pwm_clock;
- priv->base.base.temp_get = nv50_temp_get;
+ priv->base.base.temp_get = nv84_temp_get;
priv->base.base.fan_sense = nva3_therm_fan_sense;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index d7d30ee8332e..54c28bdc4204 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -137,3 +137,3 @@ nvd0_therm_ctor(struct nouveau_object *parent,
priv->base.base.pwm_clock = nvd0_fan_pwm_clock;
- priv->base.base.temp_get = nv50_temp_get;
+ priv->base.base.temp_get = nv84_temp_get;
priv->base.base.fan_sense = nva3_therm_fan_sense;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index 438d9824b774..15ca64e481f1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -136,2 +136,3 @@ void nouveau_therm_program_alarms_polling(struct nouveau_therm *therm);
+void nv40_therm_intr(struct nouveau_subdev *);
int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);
@@ -140,3 +141,3 @@ int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
int nv50_fan_pwm_clock(struct nouveau_therm *);
-int nv50_temp_get(struct nouveau_therm *therm);
+int nv84_temp_get(struct nouveau_therm *therm);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
index 470f6a47b656..dde746c78c8a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
@@ -207,9 +207,9 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm)
- nv_info(therm,
- "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
- sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
- sensor->thrs_down_clock.temp,
- sensor->thrs_down_clock.hysteresis,
- sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
- sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
+ nv_debug(therm,
+ "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
+ sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
+ sensor->thrs_down_clock.temp,
+ sensor->thrs_down_clock.hysteresis,
+ sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
+ sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
index 8e1bae4f12e8..9469b8275675 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
@@ -98,7 +98,12 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time,
spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(list, &priv->alarms, head) {
- if (list->timestamp > alarm->timestamp)
- break;
+ if (!time) {
+ if (!list_empty(&alarm->head))
+ list_del(&alarm->head);
+ } else {
+ list_for_each_entry(list, &priv->alarms, head) {
+ if (list->timestamp > alarm->timestamp)
+ break;
+ }
+ list_add_tail(&alarm->head, &list->head);
}
- list_add_tail(&alarm->head, &list->head);
spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
index 6adbbc9cc361..ed45437167f2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
@@ -112,3 +112,3 @@ nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 +
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
index 9474cfca6e4c..064c76262876 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
@@ -121,3 +121,3 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(NV41_GART_SIZE / NV41_GART_PAGE) * 4,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
index aa8131436e3d..fae1f67d5948 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
@@ -198,3 +198,3 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- ret = nouveau_gpuobj_new(parent, NULL,
+ ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(NV44_GART_SIZE / NV44_GART_PAGE) * 4,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
index 30c61e6c2017..4c3b0a23b9d6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
@@ -30,2 +30,3 @@
#include <subdev/vm.h>
+#include <subdev/ltcg.h>
@@ -36,2 +37,43 @@ struct nvc0_vmmgr_priv {
+
+/* Map from compressed to corresponding uncompressed storage type.
+ * The value 0xff represents an invalid storage type.
+ */
+const u8 nvc0_pte_storage_type_map[256] =
+{
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */
+ 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */
+ 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */
+ 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */
+ 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27,
+ 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */
+ 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */
+ 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */
+ 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
+ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3,
+ 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
+ 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe,
+ 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */
+ 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
+};
+
+
static void
@@ -70,3 +112,3 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
{
- u32 next = 1 << (vma->node->type - 8);
+ u64 next = 1 << (vma->node->type - 8);
@@ -74,2 +116,12 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
pte <<= 3;
+
+ if (mem->tag) {
+ struct nouveau_ltcg *ltcg =
+ nouveau_ltcg(vma->vm->vmm->base.base.parent);
+ u32 tag = mem->tag->offset + (delta >> 17);
+ phys |= (u64)tag << (32 + 12);
+ next |= (u64)1 << (32 + 12);
+ ltcg->tags_clear(ltcg, tag, cnt);
+ }
+
while (cnt--) {
@@ -87,2 +139,4 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5;
+ /* compressed storage types are invalid for system memory */
+ u32 memtype = nvc0_pte_storage_type_map[mem->memtype & 0xff];
@@ -90,3 +144,3 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
while (cnt--) {
- u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, target);
+ u64 phys = nvc0_vm_addr(vma, *list++, memtype, target);
nv_wo32(pgt, pte + 0, lower_32_bits(phys));
diff --git a/drivers/gpu/drm/nouveau/dispnv04/Makefile b/drivers/gpu/drm/nouveau/dispnv04/Makefile
new file mode 100644
index 000000000000..ea3f5b8a0f95
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv04/Makefile
@@ -0,0 +1,10 @@
+nouveau-y += dispnv04/arb.o
+nouveau-y += dispnv04/crtc.o
+nouveau-y += dispnv04/cursor.o
+nouveau-y += dispnv04/dac.o
+nouveau-y += dispnv04/dfp.o
+nouveau-y += dispnv04/disp.o
+nouveau-y += dispnv04/hw.o
+nouveau-y += dispnv04/tvmodesnv17.o
+nouveau-y += dispnv04/tvnv04.o
+nouveau-y += dispnv04/tvnv17.o
diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c
index 6da576445b3d..2e70462883e8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_calc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c
@@ -27,3 +27,3 @@
#include "nouveau_reg.h"
-#include "nouveau_hw.h"
+#include "hw.h"
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 6578cd28c556..0782bd2f1e04 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -35,6 +35,6 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
+#include "hw.h"
#include "nvreg.h"
#include "nouveau_fbcon.h"
-#include "nv04_display.h"
+#include "disp.h"
@@ -1072,2 +1072 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
}
-
diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
index fe86f0de348f..a810303169de 100644
--- a/drivers/gpu/drm/nouveau/nv04_cursor.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
@@ -5,3 +5,3 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
+#include "hw.h"
@@ -70,2 +70 @@ nv04_cursor_init(struct nouveau_crtc *crtc)
}
-
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c
index 64f7020fb605..434b920f6bd4 100644
--- a/drivers/gpu/drm/nouveau/nv04_dac.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c
@@ -33,3 +33,3 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
+#include "hw.h"
#include "nvreg.h"
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index 7e24cdf1cb39..93dd23ff0093 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -34,3 +34,3 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
+#include "hw.h"
#include "nvreg.h"
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index ad48444c385c..4908d3fd0486 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -32,3 +32,3 @@
#include "nouveau_reg.h"
-#include "nouveau_hw.h"
+#include "hw.h"
#include "nouveau_encoder.h"
diff --git a/drivers/gpu/drm/nouveau/nv04_display.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
index a0a031dad13f..a0a031dad13f 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
index 617a06ffdb46..973056b86207 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hw.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
@@ -26,3 +26,3 @@
#include "nouveau_drm.h"
-#include "nouveau_hw.h"
+#include "hw.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/dispnv04/hw.h
index 7dff1021fab4..eeb70d912d99 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hw.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.h
@@ -26,3 +26,4 @@
#include <drm/drmP.h>
-#include "nv04_display.h"
+#include "disp.h"
+#include "nvreg.h"
diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/dispnv04/nvreg.h
index bbfb1a68fb11..bbfb1a68fb11 100644
--- a/drivers/gpu/drm/nouveau/nvreg.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/nvreg.h
diff --git a/drivers/gpu/drm/nouveau/nv17_tv_modes.c b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
index 1cdfe2a5875d..08c6f5e50610 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv_modes.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
@@ -31,4 +31,4 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
-#include "nv17_tv.h"
+#include "hw.h"
+#include "tvnv17.h"
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
index 4a69ccdef9b4..bf13db4e8631 100644
--- a/drivers/gpu/drm/nouveau/nv04_tv.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
@@ -32,3 +32,3 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
+#include "hw.h"
#include <drm/drm_crtc_helper.h>
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 977e42be2050..acef48f4a4ea 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -33,4 +33,4 @@
#include "nouveau_crtc.h"
-#include "nouveau_hw.h"
-#include "nv17_tv.h"
+#include "hw.h"
+#include "tvnv17.h"
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
index 7b331543a41b..7b331543a41b 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 5eb3e0da7c6e..1c4c6c9161ac 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -32,2 +32,3 @@
#include <subdev/instmem.h>
+#include <engine/graph.h>
@@ -170,2 +171,3 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
struct nouveau_timer *ptimer = nouveau_timer(device);
+ struct nouveau_graph *graph = (void *)nouveau_engine(device, NVDEV_ENGINE_GR);
struct drm_nouveau_getparam *getparam = data;
@@ -210,10 +212,4 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
case NOUVEAU_GETPARAM_GRAPH_UNITS:
- /* NV40 and NV50 versions are quite different, but register
- * address is the same. User is supposed to know the card
- * family anyway... */
- if (device->chipset >= 0x40) {
- getparam->value = nv_rd32(device, 0x001540);
- break;
- }
- /* FALLTHRU */
+ getparam->value = graph->units ? graph->units(graph) : 0;
+ break;
default:
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 5d940302d2aa..2ffad2176b7f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -241,2 +241,5 @@ nouveau_backlight_init(struct drm_device *dev)
case NV_50:
+ case NV_C0:
+ case NV_D0:
+ case NV_E0:
return nv50_backlight_init(connector);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 50a6dd02f7c5..6aa2137e093a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -30,3 +30,3 @@
#include "nouveau_reg.h"
-#include "nouveau_hw.h"
+#include "dispnv04/hw.h"
#include "nouveau_encoder.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 7ccd28f11adf..0067586eb015 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -26,4 +26,2 @@
-#include "nvreg.h"
-
#define DCB_MAX_NUM_ENTRIES 16
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 4dd7ae2ac6c6..4da776f344d7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -34,3 +34,3 @@
#include "nouveau_drm.h"
-#include "nouveau_hw.h"
+#include "dispnv04/hw.h"
#include "nouveau_acpi.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 4610c3a29bbe..7bf22d4a3d96 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -30,3 +30,3 @@
#include "nouveau_fbcon.h"
-#include "nouveau_hw.h"
+#include "dispnv04/hw.h"
#include "nouveau_crtc.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index c95decf543e9..c33b13fb18db 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -33,9 +33,8 @@
-#include <subdev/device.h>
-#include <subdev/vm.h>
-
+#include <engine/device.h>
#include <engine/disp.h>
+#include <subdev/vm.h>
+
#include "nouveau_drm.h"
-#include "nouveau_irq.h"
#include "nouveau_dma.h"
@@ -367,6 +366,2 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
- ret = nouveau_irq_init(dev);
- if (ret)
- goto fail_irq;
-
ret = nouveau_display_create(dev);
@@ -390,4 +385,2 @@ fail_dispinit:
fail_dispctor:
- nouveau_irq_fini(dev);
-fail_irq:
nouveau_bios_takedown(dev);
@@ -417,3 +410,2 @@ nouveau_drm_unload(struct drm_device *dev)
- nouveau_irq_fini(dev);
nouveau_bios_takedown(dev);
@@ -535,3 +527,2 @@ nouveau_do_resume(struct drm_device *dev)
nouveau_run_vbios_init(dev);
- nouveau_irq_postinstall(dev);
nouveau_pm_resume(dev);
@@ -671,4 +662,3 @@ driver = {
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
- DRIVER_MODESET | DRIVER_PRIME,
+ DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME,
@@ -686,7 +676,2 @@ driver = {
- .irq_preinstall = nouveau_irq_preinstall,
- .irq_postinstall = nouveau_irq_postinstall,
- .irq_uninstall = nouveau_irq_uninstall,
- .irq_handler = nouveau_irq_handler,
-
.get_vblank_counter = drm_vblank_count,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 9c39bafbef2c..f2b30f89dee0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -12,3 +12,14 @@
#define DRIVER_MINOR 1
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_PATCHLEVEL 1
+
+/*
+ * 1.1.1:
+ * - added support for tiled system memory buffer objects
+ * - added support for NOUVEAU_GETPARAM_GRAPH_UNITS on [nvc0,nve0].
+ * - added support for compressed memory storage types on [nvc0,nve0].
+ * - added support for software methods 0x600,0x644,0x6ac on nvc0
+ * to control registers on the MPs to enable performance counters,
+ * and to control the warp error enable mask (OpenGL requires out of
+ * bounds access to local memory to be silently ignored / return 0).
+ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index e24341229d5e..24660c0f713d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -32,3 +32,3 @@
#include <drm/drm_encoder_slave.h>
-#include "nv04_display.h"
+#include "dispnv04/disp.h"
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
deleted file mode 100644
index 1303680affd3..000000000000
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012 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 <subdev/mc.h>
-
-#include "nouveau_drm.h"
-#include "nouveau_irq.h"
-#include "nv50_display.h"
-
-void
-nouveau_irq_preinstall(struct drm_device *dev)
-{
- nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000);
-}
-
-int
-nouveau_irq_postinstall(struct drm_device *dev)
-{
- nv_wr32(nouveau_dev(dev), 0x000140, 0x00000001);
- return 0;
-}
-
-void
-nouveau_irq_uninstall(struct drm_device *dev)
-{
- nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000);
-}
-
-irqreturn_t
-nouveau_irq_handler(DRM_IRQ_ARGS)
-{
- struct drm_device *dev = arg;
- struct nouveau_device *device = nouveau_dev(dev);
- struct nouveau_mc *pmc = nouveau_mc(device);
- u32 stat;
-
- stat = nv_rd32(device, 0x000100);
- if (stat == 0 || stat == ~0)
- return IRQ_NONE;
-
- nv_subdev(pmc)->intr(nv_subdev(pmc));
- return IRQ_HANDLED;
-}
-
-int
-nouveau_irq_init(struct drm_device *dev)
-{
- return drm_irq_install(dev);
-}
-
-void
-nouveau_irq_fini(struct drm_device *dev)
-{
- drm_irq_uninstall(dev);
-}
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.h b/drivers/gpu/drm/nouveau/nouveau_irq.h
deleted file mode 100644
index 06714ad857bb..000000000000
--- a/drivers/gpu/drm/nouveau/nouveau_irq.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __NOUVEAU_IRQ_H__
-#define __NOUVEAU_IRQ_H__
-
-extern int nouveau_irq_init(struct drm_device *);
-extern void nouveau_irq_fini(struct drm_device *);
-extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
-extern void nouveau_irq_preinstall(struct drm_device *);
-extern int nouveau_irq_postinstall(struct drm_device *);
-extern void nouveau_irq_uninstall(struct drm_device *);
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 9be9cb58e19b..f19a15a3bc03 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -37,3 +37,5 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
{
- /* nothing to do */
+ struct nouveau_drm *drm = nouveau_bdev(man->bdev);
+ struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ man->priv = pfb;
return 0;
@@ -44,3 +46,3 @@ nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
{
- /* nothing to do */
+ man->priv = NULL;
return 0;
@@ -106,3 +108,4 @@ nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix)
{
- struct nouveau_mm *mm = man->priv;
+ struct nouveau_fb *pfb = man->priv;
+ struct nouveau_mm *mm = &pfb->vram;
struct nouveau_mm_node *r;
@@ -163,2 +166,4 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
{
+ struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
+ struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_mem *node;
@@ -173,2 +178,16 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
+ switch (nv_device(drm->device)->card_type) {
+ case NV_50:
+ if (nv_device(drm->device)->chipset != 0x50)
+ node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
+ break;
+ case NV_C0:
+ case NV_D0:
+ case NV_E0:
+ node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
+ break;
+ default:
+ break;
+ }
+
mem->mm_node = node;
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c
index 2a0cc9d0614a..27afc0ea28b0 100644
--- a/drivers/gpu/drm/nouveau/nv04_pm.c
+++ b/drivers/gpu/drm/nouveau/nv04_pm.c
@@ -27,3 +27,3 @@
#include "nouveau_reg.h"
-#include "nouveau_hw.h"
+#include "dispnv04/hw.h"
#include "nouveau_pm.h"
diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c
index 3382064c7f33..3af5bcd0b203 100644
--- a/drivers/gpu/drm/nouveau/nv40_pm.c
+++ b/drivers/gpu/drm/nouveau/nv40_pm.c
@@ -28,3 +28,3 @@
#include "nouveau_pm.h"
-#include "nouveau_hw.h"
+#include "dispnv04/hw.h"
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index 8bd5d2781baf..69620e39c90c 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -27,3 +27,3 @@
#include "nouveau_bios.h"
-#include "nouveau_hw.h"
+#include "dispnv04/hw.h"
#include "nouveau_pm.h"