diff options
105 files changed, 1316 insertions, 644 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 90f9140eeef..52930a20d8f 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -53,15 +53,6 @@ nouveau-y += core/subdev/clock/nva3.o nouveau-y += core/subdev/clock/nvc0.o 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 nouveau-y += core/subdev/devinit/nv04.o nouveau-y += core/subdev/devinit/nv05.o @@ -126,6 +117,7 @@ nouveau-y += core/subdev/therm/ic.o nouveau-y += core/subdev/therm/temp.o 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 nouveau-y += core/subdev/therm/nvd0.o nouveau-y += core/subdev/timer/base.o @@ -150,6 +142,15 @@ nouveau-y += core/engine/copy/nvc0.o nouveau-y += core/engine/copy/nve0.o 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 nouveau-y += core/engine/disp/nv04.o nouveau-y += core/engine/disp/nv50.o @@ -212,7 +213,7 @@ nouveau-y += core/engine/vp/nve0.o # drm/core 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 nouveau-y += nouveau_prime.o nouveau_abi16.o nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o @@ -224,9 +225,7 @@ nouveau-y += nouveau_connector.o nouveau_dp.o 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 # drm/kms/nv50- nouveau-y += nv50_display.o diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index 295c22165ea..9079c0ac58e 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c @@ -27,7 +27,7 @@ #include <core/handle.h> #include <core/option.h> -#include <subdev/device.h> +#include <engine/device.h> static void nouveau_client_dtor(struct nouveau_object *object) @@ -58,8 +58,9 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg, return -ENODEV; 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; if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c index 09b3bd502fd..c8bed4a2683 100644 --- a/drivers/gpu/drm/nouveau/core/core/engine.c +++ b/drivers/gpu/drm/nouveau/core/core/engine.c @@ -33,7 +33,6 @@ nouveau_engine_create_(struct nouveau_object *parent, const char *iname, const char *fname, int length, void **pobject) { - struct nouveau_device *device = nv_device(parent); struct nouveau_engine *engine; int ret; @@ -43,7 +42,8 @@ nouveau_engine_create_(struct nouveau_object *parent, if (ret) return ret; - if (!nouveau_boolopt(device->cfgopt, iname, enable)) { + if ( parent && + !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) { if (!enable) nv_warn(engine, "disabled, %s=1 to enable\n", iname); return -ENODEV; diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c index 6d01e0f0fc8..7eb81c1b6fa 100644 --- a/drivers/gpu/drm/nouveau/core/core/event.c +++ b/drivers/gpu/drm/nouveau/core/core/event.c @@ -27,8 +27,10 @@ static void nouveau_event_put_locked(struct nouveau_event *event, int index, struct nouveau_eventh *handler) { - 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); } @@ -53,8 +55,10 @@ nouveau_event_get(struct nouveau_event *event, int index, spin_lock_irqsave(&event->lock, flags); if (index < event->index_nr) { 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); + } } spin_unlock_irqrestore(&event->lock, flags); } diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c index 3b2e7b6304d..7f48e288215 100644 --- a/drivers/gpu/drm/nouveau/core/core/object.c +++ b/drivers/gpu/drm/nouveau/core/core/object.c @@ -136,26 +136,30 @@ nouveau_object_ctor(struct nouveau_object *parent, struct nouveau_object **pobject) { 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) { if (ret != -ENODEV) { nv_error(parent, "failed to create 0x%08x, %d\n", oclass->handle, ret); } - if (*pobject) { - ofuncs->dtor(*pobject); + if (object) { + ofuncs->dtor(object); *pobject = NULL; } return ret; } - nv_debug(*pobject, "created\n"); + if (ret == 0) { + nv_debug(object, "created\n"); + atomic_set(&object->refcount, 1); + } + return 0; } @@ -327,6 +331,7 @@ nouveau_object_inc(struct nouveau_object *object) } ret = nv_ofuncs(object)->init(object); + atomic_set(&object->usecount, 1); if (ret) { nv_error(object, "init failed, %d\n", ret); goto fail_self; @@ -357,6 +362,7 @@ nouveau_object_decf(struct nouveau_object *object) nv_trace(object, "stopping...\n"); ret = nv_ofuncs(object)->fini(object, false); + atomic_set(&object->usecount, 0); if (ret) nv_warn(object, "failed fini, %d\n", ret); @@ -381,6 +387,7 @@ nouveau_object_decs(struct nouveau_object *object) nv_trace(object, "suspending...\n"); ret = nv_ofuncs(object)->fini(object, true); + atomic_set(&object->usecount, 0); if (ret) { nv_error(object, "failed suspend, %d\n", ret); return ret; diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c index db7c5494310..313380ce632 100644 --- a/drivers/gpu/drm/nouveau/core/core/parent.c +++ b/drivers/gpu/drm/nouveau/core/core/parent.c @@ -24,6 +24,7 @@ #include <core/object.h> #include <core/parent.h> +#include <core/client.h> int nouveau_parent_sclass(struct nouveau_object *parent, u16 handle, @@ -50,7 +51,12 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle, while (mask) { int i = ffsll(mask) - 1; - 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; while (oclass->ofuncs) { if ((oclass->handle & 0xffff) == handle) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index 3937ced5c75..86d24904e9d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -29,7 +29,7 @@ #include <core/class.h> -#include <subdev/device.h> +#include <engine/device.h> static DEFINE_MUTEX(nv_devices_mutex); static LIST_HEAD(nv_devices); @@ -55,7 +55,6 @@ nouveau_device_find(u64 name) struct nouveau_devobj { struct nouveau_parent base; struct nouveau_object *subdev[NVDEV_SUBDEV_NR]; - bool created; }; static const u64 disable_map[] = { @@ -238,26 +237,24 @@ 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))) continue; - 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 * due to not knowing exactly what the vbios init tables will * mess with. devinit also can't be run until all of its @@ -273,6 +270,10 @@ nouveau_devobj_ctor(struct nouveau_object *parent, ret = nouveau_object_inc(subdev); if (ret) return ret; + atomic_dec(&nv_object(device)->usecount); + } else + if (subdev) { + nouveau_subdev_reset(subdev); } } } @@ -292,74 +293,6 @@ nouveau_devobj_dtor(struct nouveau_object *object) nouveau_parent_destroy(&devobj->base); } -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 nouveau_devobj_rd08(struct nouveau_object *object, u64 addr) { @@ -400,8 +333,8 @@ static struct nouveau_ofuncs nouveau_devobj_ofuncs = { .ctor = nouveau_devobj_ctor, .dtor = nouveau_devobj_dtor, - .init = nouveau_devobj_init, - .fini = nouveau_devobj_fini, + .init = _nouveau_parent_init, + .fini = _nouveau_parent_fini, .rd08 = nouveau_devobj_rd08, .rd16 = nouveau_devobj_rd16, .rd32 = nouveau_devobj_rd32, @@ -413,12 +346,76 @@ nouveau_devobj_ofuncs = { /****************************************************************************** * nouveau_device: engine functions *****************************************************************************/ -struct nouveau_oclass +static struct nouveau_oclass nouveau_device_sclass[] = { { 0x0080, &nouveau_devobj_ofuncs }, {} }; +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 nouveau_device_dtor(struct nouveau_object *object) { @@ -428,17 +425,19 @@ nouveau_device_dtor(struct nouveau_object *object) list_del(&device->head); mutex_unlock(&nv_devices_mutex); - 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); } 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, }, }; @@ -456,13 +455,12 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname, goto done; } - ret = nouveau_subdev_create_(NULL, NULL, &nouveau_device_oclass, 0, + ret = nouveau_engine_create_(NULL, NULL, &nouveau_device_oclass, true, "DEVICE", "device", length, pobject); device = *pobject; if (ret) goto done; - atomic_set(&nv_object(device)->usecount, 2); device->pdev = pdev; device->handle = name; device->cfgopt = cfg; @@ -470,6 +468,7 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname, device->name = sname; nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE"); + nv_engine(device)->sclass = nouveau_device_sclass; list_add(&device->head, &nv_devices); done: mutex_unlock(&nv_devices_mutex); diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c index 473c5c03d3c..a0284cf09c0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/i2c.h> @@ -34,6 +33,7 @@ #include <subdev/instmem.h> #include <subdev/vm.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c index d0774f5bebe..1b7809a095c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/gpio.h> @@ -35,6 +34,7 @@ #include <subdev/instmem.h> #include <subdev/vm.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c index ab920e0dc45..12a4005fa61 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/gpio.h> @@ -36,6 +35,7 @@ #include <subdev/instmem.h> #include <subdev/vm.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c index 5f2110261b0..cef0f1ea4c2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/gpio.h> @@ -35,6 +34,7 @@ #include <subdev/instmem.h> #include <subdev/vm.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c index f3d55efe9ac..1719cb0ee59 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/vm.h> @@ -37,6 +36,7 @@ #include <subdev/instmem.h> #include <subdev/vm.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c index 5ed2fa51ddc..5e8c3de7559 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/gpio.h> @@ -38,6 +37,7 @@ #include <subdev/vm.h> #include <subdev/bar.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> @@ -83,7 +83,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -109,7 +109,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -135,7 +135,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -161,7 +161,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -187,7 +187,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; @@ -213,7 +213,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -239,7 +239,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -265,7 +265,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; @@ -291,7 +291,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 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; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c index 4393eb4d656..955af122c3a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/gpio.h> @@ -40,6 +39,7 @@ #include <subdev/vm.h> #include <subdev/bar.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> @@ -285,6 +285,34 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass; device->oclass[NVDEV_ENGINE_DISP ] = &nvd0_disp_oclass; 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: nv_fatal(device, "unknown Fermi chipset\n"); return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index 5c12391619f..e6a77944f43 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include <subdev/device.h> #include <subdev/bios.h> #include <subdev/bus.h> #include <subdev/gpio.h> @@ -40,6 +39,7 @@ #include <subdev/vm.h> #include <subdev/bar.h> +#include <engine/device.h> #include <engine/dmaobj.h> #include <engine/fifo.h> #include <engine/software.h> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c index fa27b02ff82..31cc8fe8e7f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c @@ -191,7 +191,7 @@ dp_link_train_cr(struct dp_state *dp) static int 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; dp_set_training_pattern(dp, 2); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 02e369f8044..6a38402fa56 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -572,7 +572,8 @@ nv50_disp_base_ctor(struct nouveau_object *parent, priv->base.vblank->priv = priv; priv->base.vblank->enable = nv50_disp_base_vblank_enable; 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); } static void @@ -719,7 +720,7 @@ nv50_disp_data_ctor(struct nouveau_object *parent, if (nv_mclass(parent) != NV_DEVICE_CLASS) { atomic_inc(&parent->refcount); *pobject = parent; - return 0; + return 1; } /* allocate display hardware to client */ diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 788dd34ccb5..019eacd8a68 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -473,7 +473,8 @@ nvd0_disp_base_ctor(struct nouveau_object *parent, priv->base.vblank->enable = nvd0_disp_base_vblank_enable; priv->base.vblank->disable = nvd0_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); } static void diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index 7341ebe131f..d3ec436d9cb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -91,6 +91,8 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent, if (!chan->user) return -EFAULT; + nouveau_event_trigger(priv->cevent, 0); + chan->size = size; return 0; } @@ -167,6 +169,7 @@ nouveau_fifo_destroy(struct nouveau_fifo *priv) { kfree(priv->channel); nouveau_event_destroy(&priv->uevent); + nouveau_event_destroy(&priv->cevent); nouveau_engine_destroy(&priv->base); } @@ -191,6 +194,10 @@ nouveau_fifo_create_(struct nouveau_object *parent, if (!priv->channel) return -ENOMEM; + ret = nouveau_event_create(1, &priv->cevent); + if (ret) + return ret; + ret = nouveau_event_create(1, &priv->uevent); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 840af617278..ddaeb557290 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -210,7 +210,8 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent, nv_parent(chan)->object_attach = nv50_fifo_object_attach; nv_parent(chan)->object_detach = nv50_fifo_object_detach; - 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) return ret; @@ -263,7 +264,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, nv_parent(chan)->object_attach = nv50_fifo_object_attach; nv_parent(chan)->object_detach = nv50_fifo_object_detach; - 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) return ret; @@ -373,17 +375,17 @@ nv50_fifo_context_ctor(struct nouveau_object *parent, if (ret) return ret; - 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) return ret; - 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); if (ret) return ret; - 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); if (ret) return ret; @@ -437,12 +439,12 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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]); if (ret) return ret; - 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]); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 094000e8787..35b94bd1880 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -180,7 +180,8 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent, if (ret) return ret; - 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) return ret; @@ -242,7 +243,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, if (ret) return ret; - 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) return ret; @@ -336,12 +338,12 @@ nv84_fifo_context_ctor(struct nouveau_object *parent, if (ret) return ret; - 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); if (ret) return ret; - 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); if (ret) return ret; @@ -350,13 +352,13 @@ nv84_fifo_context_ctor(struct nouveau_object *parent, if (ret) return ret; - 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) return ret; - 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) return ret; @@ -407,12 +409,12 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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]); if (ret) return ret; - 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]); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 4f226afb559..4d4a6b90537 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -292,7 +292,8 @@ nvc0_fifo_context_ctor(struct nouveau_object *parent, if (ret) return ret; - 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) return ret; @@ -623,17 +624,17 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, &priv->playlist[0]); if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x1000, 0, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, &priv->playlist[1]); if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 4419e40d88e..9151919fb83 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -96,7 +96,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine) cur = engn->playlist[engn->cur_playlist]; 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); if (ret) { nv_error(priv, "playlist alloc failed\n"); @@ -333,7 +333,8 @@ nve0_fifo_context_ctor(struct nouveau_object *parent, if (ret) return ret; - 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) return ret; @@ -595,7 +596,7 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index 0b7951a8594..4cc6269d407 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -36,7 +36,6 @@ int 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; u32 size = (0x80000 + priv->size + 4095) & ~4095; int ret, i; @@ -44,7 +43,7 @@ nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) /* allocate memory to for a "channel", which we'll use to generate * the default context values */ - ret = nouveau_gpuobj_new(parent, NULL, size, 0x1000, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &info->chan); chan = info->chan; if (ret) { @@ -1399,7 +1398,7 @@ nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv) { int i; - 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); nv_mthd(priv, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); @@ -1415,7 +1414,7 @@ nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv) nv_mthd(priv, 0x90c0, 0x27ac, 0x00000000); nv_mthd(priv, 0x90c0, 0x27cc, 0x00000000); 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); nv_mthd(priv, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); @@ -1615,7 +1614,7 @@ static void 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); nv_wr32(priv, 0x405830, 0x02180218); nv_wr32(priv, 0x405834, 0x08000000); @@ -1658,10 +1657,10 @@ nvc0_grctx_generate_unk64xx(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x4064ac, 0x00003fff); nv_wr32(priv, 0x4064b4, 0x00000000); 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); nv_wr32(priv, 0x4064c4, 0x0086ffff); } @@ -1701,7 +1700,7 @@ nvc0_grctx_generate_rop(struct nvc0_graph_priv *priv) /* ROPC_BROADCAST */ nv_wr32(priv, 0x408800, 0x02802a3c); nv_wr32(priv, 0x408804, 0x00000040); - if (chipset == 0xd9) { + if (chipset >= 0xd0) { nv_wr32(priv, 0x408808, 0x1043e005); nv_wr32(priv, 0x408900, 0x3080b801); nv_wr32(priv, 0x408904, 0x1043e005); @@ -1735,7 +1734,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418408, 0x00000000); nv_wr32(priv, 0x41840c, 0x00001008); 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); nv_wr32(priv, 0x418454, 0x00000000); nv_wr32(priv, 0x418458, 0x00000000); @@ -1750,14 +1749,14 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418700, 0x00000002); nv_wr32(priv, 0x418704, 0x00000080); 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); nv_wr32(priv, 0x41880c, 0x00000000); nv_wr32(priv, 0x418810, 0x00000000); nv_wr32(priv, 0x418828, 0x00008442); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x418830, 0x10000001); else nv_wr32(priv, 0x418830, 0x00000001); @@ -1768,7 +1767,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x4188f0, 0x00000000); nv_wr32(priv, 0x4188f4, 0x00000000); nv_wr32(priv, 0x4188f8, 0x00000000); - if (chipset == 0xd9) + if (chipset >= 0xd0) nv_wr32(priv, 0x4188fc, 0x20100008); else if (chipset == 0xc1) nv_wr32(priv, 0x4188fc, 0x00100018); @@ -1787,7 +1786,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418a14 + (i * 0x20), 0x00000000); nv_wr32(priv, 0x418a18 + (i * 0x20), 0x00000000); } - nv_wr32(priv, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); + nv_wr32(priv, 0x418b00, chipset < 0xd0 ? 0x00000000 : 0x00000006); nv_wr32(priv, 0x418b08, 0x0a418820); nv_wr32(priv, 0x418b0c, 0x062080e6); nv_wr32(priv, 0x418b10, 0x020398a4); @@ -1804,7 +1803,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418c24, 0x00000000); nv_wr32(priv, 0x418c28, 0x00000000); nv_wr32(priv, 0x418c2c, 0x00000000); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x418c6c, 0x00000001); nv_wr32(priv, 0x418c80, 0x20200004); nv_wr32(priv, 0x418c8c, 0x00000001); @@ -1823,7 +1822,7 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x419818, 0x00000000); nv_wr32(priv, 0x41983c, 0x00038bc7); nv_wr32(priv, 0x419848, 0x00000000); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419864, 0x00000129); else nv_wr32(priv, 0x419864, 0x0000012a); @@ -1836,7 +1835,7 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x419a14, 0x00000200); nv_wr32(priv, 0x419a1c, 0x00000000); nv_wr32(priv, 0x419a20, 0x00000800); - if (chipset == 0xd9) + if (chipset >= 0xd0) nv_wr32(priv, 0x00419ac4, 0x0017f440); else if (chipset != 0xc0 && chipset != 0xc8) nv_wr32(priv, 0x00419ac4, 0x0007f440); @@ -1847,16 +1846,16 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x419b10, 0x0a418820); nv_wr32(priv, 0x419b14, 0x000000e6); nv_wr32(priv, 0x419bd0, 0x00900103); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419be0, 0x00400001); else nv_wr32(priv, 0x419be0, 0x00000001); 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); nv_wr32(priv, 0x419c08, 0x00000002); nv_wr32(priv, 0x419c20, 0x00000000); - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { nv_wr32(priv, 0x419c24, 0x00084210); nv_wr32(priv, 0x419c28, 0x3cf3cf3c); nv_wr32(priv, 0x419cb0, 0x00020048); @@ -1868,12 +1867,12 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) } nv_wr32(priv, 0x419ce8, 0x00000000); nv_wr32(priv, 0x419cf4, 0x00000183); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419d20, 0x12180000); else nv_wr32(priv, 0x419d20, 0x02180000); nv_wr32(priv, 0x419d24, 0x00001fff); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419d44, 0x02180218); nv_wr32(priv, 0x419e04, 0x00000000); nv_wr32(priv, 0x419e08, 0x00000000); @@ -2210,7 +2209,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x00000215, 0x00000040); nv_icmd(priv, 0x00000216, 0x00000040); nv_icmd(priv, 0x00000217, 0x00000040); - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { for (i = 0x0400; i <= 0x0417; i++) nv_icmd(priv, i, 0x00000040); } @@ -2222,7 +2221,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x0000021d, 0x0000c080); nv_icmd(priv, 0x0000021e, 0x0000c080); nv_icmd(priv, 0x0000021f, 0x0000c080); - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { for (i = 0x0440; i <= 0x0457; i++) nv_icmd(priv, i, 0x0000c080); } @@ -2789,7 +2788,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x00000585, 0x0000003f); nv_icmd(priv, 0x00000576, 0x00000003); if (nv_device(priv)->chipset == 0xc1 || - nv_device(priv)->chipset == 0xd9) + nv_device(priv)->chipset >= 0xd0) nv_icmd(priv, 0x0000057b, 0x00000059); nv_icmd(priv, 0x00000586, 0x00000040); nv_icmd(priv, 0x00000582, 0x00000080); @@ -2891,7 +2890,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x00000957, 0x00000003); nv_icmd(priv, 0x0000095e, 0x20164010); nv_icmd(priv, 0x0000095f, 0x00000020); - if (nv_device(priv)->chipset == 0xd9) + if (nv_device(priv)->chipset >= 0xd0) nv_icmd(priv, 0x0000097d, 0x00000020); nv_icmd(priv, 0x00000683, 0x00000006); nv_icmd(priv, 0x00000685, 0x003fffff); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c index 6d8c63931ee..ae27dae3fe3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -2772,10 +2772,15 @@ nve0_grctx_generate(struct nvc0_graph_priv *priv) for (i = 0; i < 8; i++) nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); - 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); nve0_grctx_generate_icmd(priv); nve0_grctx_generate_a097(priv); 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 b86cc60dcd5..f7055af0f2a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc @@ -87,6 +87,11 @@ chipsets: .b16 #nvd9_gpc_mmio_tail .b16 #nvd9_tpc_mmio_head .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 // GPC mmio lists 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 0bcfa4d447e..7fbdebb2baf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc @@ -62,6 +62,9 @@ chipsets: .b8 0xd9 0 0 0 .b16 #nvd9_hub_mmio_head .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 nvc0_hub_mmio_head: diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 0607b980174..b2455931590 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -254,7 +254,7 @@ nv20_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c index b2b650dd8b2..7a80d005a97 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c @@ -142,7 +142,7 @@ nv25_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c index 700462fa0ae..3e1f32ee43d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c @@ -109,7 +109,7 @@ nv2a_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c index cedadaa92d3..e451db32e92 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c @@ -143,7 +143,7 @@ nv30_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c index 273f6320027..9385ac7b44a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c @@ -143,7 +143,7 @@ nv34_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c index f40ee2116ee..9ce84b73f86 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c @@ -141,7 +141,7 @@ nv35_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 17049d5c723..193a5de1b48 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -46,6 +46,14 @@ struct nv40_graph_chan { struct nouveau_graph_chan base; }; +static u64 +nv40_graph_units(struct nouveau_graph *graph) +{ + struct nv40_graph_priv *priv = (void *)graph; + + return nv_rd32(priv, 0x1540); +} + /******************************************************************************* * Graphics object classes ******************************************************************************/ @@ -359,6 +367,8 @@ nv40_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, else nv_engine(priv)->sclass = nv40_graph_sclass; 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 f2b1a7a124f..1ac36110ca1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -48,6 +48,14 @@ struct nv50_graph_chan { struct nouveau_graph_chan base; }; +static u64 +nv50_graph_units(struct nouveau_graph *graph) +{ + struct nv50_graph_priv *priv = (void *)graph; + + return nv_rd32(priv, 0x1540); +} + /******************************************************************************* * Graphics object classes ******************************************************************************/ @@ -819,6 +827,8 @@ nv50_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_subdev(priv)->intr = nv50_graph_intr; nv_engine(priv)->cclass = &nv50_graph_cclass; + priv->base.units = nv50_graph_units; + switch (nv_device(priv)->chipset) { case 0x50: nv_engine(priv)->sclass = nv50_graph_sclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 0de0dd724af..f9b9d82c287 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -60,6 +60,19 @@ 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; +} + /******************************************************************************* * PGRAPH context ******************************************************************************/ @@ -89,7 +102,8 @@ nvc0_graph_context_ctor(struct nouveau_object *parent, * fuc to modify some per-context register settings on first load * of the context. */ - 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) return ret; @@ -101,8 +115,8 @@ nvc0_graph_context_ctor(struct nouveau_object *parent, /* allocate buffers referenced by mmio list */ 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) return ret; @@ -518,9 +532,10 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, { struct nouveau_device *device = nv_device(parent); 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); if (ret) return ret; @@ -529,6 +544,8 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_subdev(priv)->intr = nvc0_graph_intr; nv_engine(priv)->cclass = &nvc0_graph_cclass; + priv->base.units = nvc0_graph_units; + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { nv_info(priv, "using external firmware\n"); if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || @@ -551,11 +568,13 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, break; } - 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) return ret; - 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) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index a1e78de4645..c870dad0f67 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -118,6 +118,7 @@ nvc0_graph_class(void *obj) return 0x9197; case 0xc8: case 0xd9: + case 0xd7: return 0x9297; case 0xe4: case 0xe7: @@ -169,4 +170,6 @@ int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *, struct nouveau_object **); 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 4857f913efd..678c16f6305 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -77,11 +77,207 @@ nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x409c20, ustat); } +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 nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, struct nouveau_object *engctx) { u32 trap = nv_rd32(priv, 0x400108); + int i; int rop; if (trap & 0x00000001) { @@ -102,6 +298,32 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, trap &= ~0x00000010; } + 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) { for (rop = 0; rop < priv->rop_nr; rop++) { u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); @@ -217,6 +439,8 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nve0_graph_cclass; nv_engine(priv)->sclass = nve0_graph_sclass; + priv->base.units = nvc0_graph_units; + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { nv_info(priv, "using external firmware\n"); if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || @@ -227,11 +451,13 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->firmware = true; } - 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) return ret; - 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) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c index a523eaad47e..d698e710ddd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -94,6 +94,32 @@ nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd, return -EINVAL; } +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 nvc0_software_omthds[] = { { 0x0400, 0x0400, nvc0_software_mthd_vblsem_offset }, @@ -101,6 +127,9 @@ nvc0_software_omthds[] = { { 0x0408, 0x0408, nvc0_software_mthd_vblsem_value }, { 0x040c, 0x040c, nvc0_software_mthd_vblsem_release }, { 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 d351a4e5819..05840f3eee9 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -6,7 +6,7 @@ #include <core/engine.h> enum nv_subdev_type { - NVDEV_SUBDEV_DEVICE, + NVDEV_ENGINE_DEVICE, NVDEV_SUBDEV_VBIOS, /* All subdevs from DEVINIT to DEVINIT_LAST will be created before @@ -57,7 +57,7 @@ enum nv_subdev_type { }; struct nouveau_device { - struct nouveau_subdev base; + struct nouveau_engine base; struct list_head head; struct pci_dev *pdev; @@ -99,7 +99,7 @@ nv_device(void *obj) #if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA 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", nv_hclass(object), nv_hclass(device)); } diff --git a/drivers/gpu/drm/nouveau/core/include/core/parent.h b/drivers/gpu/drm/nouveau/core/include/core/parent.h index 31cd852c96d..9f5ea900ff0 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/parent.h +++ b/drivers/gpu/drm/nouveau/core/include/core/parent.h @@ -51,8 +51,8 @@ int nouveau_parent_create_(struct nouveau_object *, struct nouveau_object *, 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 int nouveau_parent_sclass(struct nouveau_object *, u16 handle, struct nouveau_object **pengine, diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/device.h b/drivers/gpu/drm/nouveau/core/include/engine/device.h index c9e4c4afa50..b3dd2c4c2f1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/device.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/device.h @@ -18,7 +18,6 @@ int nv50_identify(struct nouveau_device *); int nvc0_identify(struct nouveau_device *); int nve0_identify(struct nouveau_device *); -extern struct nouveau_oclass nouveau_device_sclass[]; struct nouveau_device *nouveau_device_find(u64 name); #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index b46c197709f..633c2f80648 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -65,7 +65,8 @@ struct nouveau_fifo_base { struct nouveau_fifo { struct nouveau_engine base; - struct nouveau_event *uevent; + struct nouveau_event *cevent; /* channel creation event */ + struct nouveau_event *uevent; /* async user trigger */ struct nouveau_object **channel; spinlock_t lock; diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h index 6943b40d081..5d392439f2a 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h @@ -26,6 +26,10 @@ struct nouveau_graph_chan { struct nouveau_graph { struct nouveau_engine base; + + /* Returns chipset-specific counts of units packed into an u64. + */ + u64 (*units)(struct nouveau_graph *); }; static inline 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 f351f63bc65..a1985ed3d58 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h @@ -4,8 +4,15 @@ #include <core/subdev.h> #include <core/device.h> +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); }; static inline struct nouveau_ltcg * diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index fded97cea50..d5502267c30 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h @@ -21,18 +21,22 @@ 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); extern struct nouveau_oclass nv04_mc_oclass; extern struct nouveau_oclass nv44_mc_oclass; @@ -40,8 +44,6 @@ extern struct nouveau_oclass nv50_mc_oclass; extern struct nouveau_oclass nv98_mc_oclass; extern struct nouveau_oclass nvc0_mc_oclass; -void nouveau_mc_intr(struct nouveau_subdev *); - extern const struct nouveau_mc_intr nv04_mc_intr[]; int nv04_mc_init(struct nouveau_object *); int nv50_mc_init(struct nouveau_object *); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h index 0b20fc0d19c..c075998d82e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h @@ -73,6 +73,7 @@ int _nouveau_therm_fini(struct nouveau_object *, bool); 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; extern struct nouveau_oclass nvd0_therm_oclass; diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index eb496033b55..3bd9be2ab37 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -17,6 +17,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/reboot.h> +#include <linux/interrupt.h> #include <asm/unaligned.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c index c3acf5b70d9..649f1ced1fe 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c @@ -122,18 +122,20 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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); if (ret) return ret; - 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) return ret; - 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) return ret; @@ -145,9 +147,9 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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; if (ret) return ret; @@ -157,7 +159,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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) return ret; @@ -182,7 +184,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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) return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c index 77a6fb725d3..f8a44956dec 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -101,12 +101,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 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; if (ret) return ret; - 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) return ret; @@ -114,7 +116,7 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, (pci_resource_len(pdev, 3) >> 12) * 8, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &vm->pgt[0].obj[0]); @@ -133,12 +135,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1)); /* 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; if (ret) return ret; - 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) return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 9c41b58d57e..c300b5e7b67 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -64,27 +64,33 @@ init_exec_force(struct nvbios_init *init, bool exec) static inline int 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; } static inline int 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; } static inline int 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; } @@ -92,16 +98,21 @@ static u8 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; } static inline u32 @@ -227,7 +238,8 @@ init_i2c(struct nvbios_init *init, int index) } else if (index < 0) { if (!init->outp) { - error("script needs output for i2c\n"); + if (init_exec(init)) + error("script needs output for i2c\n"); return NULL; } @@ -544,7 +556,8 @@ init_tmds_reg(struct nvbios_init *init, u8 tmds) return 0x6808b0 + dacoffset; } - error("tmds opcodes need dcb\n"); + if (init_exec(init)) + error("tmds opcodes need dcb\n"); } else { if (tmds < ARRAY_SIZE(pramdac_table)) return pramdac_table[tmds]; @@ -792,7 +805,8 @@ init_dp_condition(struct nvbios_init *init) break; } - warn("script needs dp output table data\n"); + if (init_exec(init)) + warn("script needs dp output table data\n"); break; case 5: if (!(init_rdauxr(init, 0x0d) & 1)) @@ -816,7 +830,7 @@ init_io_mask_or(struct nvbios_init *init) u8 or = init_or(init); u8 data; - 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; data = init_rdvgai(init, 0x03d4, index); @@ -835,7 +849,7 @@ init_io_or(struct nvbios_init *init) u8 or = init_or(init); u8 data; - 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; data = init_rdvgai(init, 0x03d4, index); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 7606ed15b6f..86ad59203c8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -23,6 +23,7 @@ */ #include <subdev/fb.h> +#include <subdev/ltcg.h> #include <subdev/bios.h> struct nvc0_fb_priv { @@ -31,34 +32,14 @@ struct nvc0_fb_priv { dma_addr_t r100c10; }; -/* 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]; + static bool 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)); } static int @@ -130,6 +111,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, int type = (memtype & 0x0ff); int back = (memtype & 0x800); int ret; + const bool comp = nvc0_pte_storage_type_map[type] != type; size >>= 12; align >>= 12; @@ -142,10 +124,22 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, return -ENOMEM; INIT_LIST_HEAD(&mem->regions); - mem->memtype = type; mem->size = size; 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 { if (back) ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); @@ -168,6 +162,17 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, return 0; } +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 nvc0_fb_init(struct nouveau_object *object) { @@ -178,7 +183,8 @@ nvc0_fb_init(struct nouveau_object *object) if (ret) return ret; - nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); + if (priv->r100c10_page) + nv_wr32(priv, 0x100c10, priv->r100c10 >> 8); return 0; } @@ -214,16 +220,16 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.memtype_valid = nvc0_fb_memtype_valid; priv->base.ram.init = nvc0_fb_vram_init; 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; + } return nouveau_fb_preinit(&priv->base); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 2e98e8a3f1a..8ae2625415e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -140,12 +140,8 @@ 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 f5bbd383411..795393d7b2f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -93,7 +93,6 @@ nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, u32 size, u32 align, struct nouveau_object **pobject) { struct nouveau_object *engine = nv_object(imem); - struct nv04_instmem_priv *priv = (void *)(imem); int ret; ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass, @@ -101,14 +100,6 @@ nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, if (ret) return ret; - /* 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; } @@ -134,27 +125,28 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 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) return ret; /* 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) return ret; /* 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); if (ret) return ret; /* 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) return ret; - 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 7983d8d9b35..b15b6131023 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -9,7 +9,6 @@ struct nv04_instmem_priv { struct nouveau_instmem base; - bool created; void __iomem *iomem; struct nouveau_mm heap; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index da64253201e..716bf41bc3c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -82,31 +82,33 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; /* 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) return ret; /* 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) return ret; /* 0x18000-0x18200: reserve for RAMRO * 0x18200-0x20000: padding */ - 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) return ret; /* 0x20000-0x21000: reserve for RAMFC * 0x21000-0x40000: padding and some unknown crap */ - ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x20000, 0, NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc); if (ret) return ret; - 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 078a2b9d6bd..e4940fb166e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -23,10 +23,17 @@ */ #include <subdev/ltcg.h> +#include <subdev/fb.h> +#include <subdev/timer.h> 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; }; static void @@ -62,11 +69,104 @@ 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, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nvc0_ltcg_priv *priv; + struct nouveau_fb *pfb = nouveau_fb(parent); int ret; ret = nouveau_ltcg_create(parent, engine, oclass, &priv); @@ -74,19 +174,44 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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; return 0; } +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 nvc0_ltcg_oclass = { .handle = NV_SUBDEV(LTCG, 0xc0), .ofuncs = &(struct nouveau_ofuncs) { .ctor = nvc0_ltcg_ctor, - .dtor = _nouveau_ltcg_dtor, + .dtor = nvc0_ltcg_dtor, .init = _nouveau_ltcg_init, .fini = _nouveau_ltcg_fini, }, diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 8379aafa6e1..1c0330b8c9a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c @@ -24,10 +24,10 @@ #include <subdev/mc.h> -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; struct nouveau_subdev *unit; u32 stat, intr; @@ -35,7 +35,7 @@ nouveau_mc_intr(struct nouveau_subdev *subdev) intr = stat = nv_rd32(pmc, 0x000100); while (stat && map->stat) { if (stat & map->stat) { - unit = nouveau_subdev(subdev, map->unit); + unit = nouveau_subdev(pmc, map->unit); if (unit && unit->intr) unit->intr(unit); intr &= ~map->stat; @@ -46,4 +46,56 @@ nouveau_mc_intr(struct nouveau_subdev *subdev) if (intr) { nv_error(pmc, "unknown intr 0x%08x\n", stat); } + + 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 89da8fa7ea0..8c769715227 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c @@ -55,7 +55,6 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - nv_subdev(priv)->intr = nouveau_mc_intr; priv->base.intr_map = nv04_mc_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index 397d868359a..51919371810 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c @@ -41,7 +41,6 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - nv_subdev(priv)->intr = nouveau_mc_intr; priv->base.intr_map = nv04_mc_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index 5965add6dae..d796924f993 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c @@ -57,7 +57,6 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - nv_subdev(priv)->intr = nouveau_mc_intr; priv->base.intr_map = nv50_mc_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index 3a80b29dce0..e82fd21b504 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c @@ -59,7 +59,6 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - nv_subdev(priv)->intr = nouveau_mc_intr; priv->base.intr_map = nv98_mc_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 42bbf72023a..737bd4b682e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -61,7 +61,6 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - nv_subdev(priv)->intr = nouveau_mc_intr; priv->base.intr_map = nvc0_mc_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c index a70d1b7e397..002e51b3af9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c @@ -165,7 +165,7 @@ nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) return 0; } -static void +void nv40_therm_intr(struct nouveau_subdev *subdev) { struct nouveau_therm *therm = nouveau_therm(subdev); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index 86632cbd65c..8cf7597a218 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -118,145 +118,36 @@ nv50_fan_pwm_clock(struct nouveau_therm *therm) return pwm_clock; } -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; } static int @@ -278,33 +169,29 @@ nv50_therm_ctor(struct nouveau_object *parent, priv->base.base.pwm_set = nv50_fan_pwm_set; priv->base.base.pwm_clock = nv50_fan_pwm_clock; 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; return nouveau_therm_preinit(&priv->base.base); } +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 nv50_therm_oclass = { .handle = NV_SUBDEV(THERM, 0x50), .ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_therm_ctor, .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 00000000000..42ba633ccff --- /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 2dcc5437116..d11a7c40081 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c @@ -81,7 +81,7 @@ nva3_therm_ctor(struct nouveau_object *parent, 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 = nv50_temp_get; + priv->base.base.temp_get = nv84_temp_get; priv->base.base.fan_sense = nva3_therm_fan_sense; priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; return nouveau_therm_preinit(&priv->base.base); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c index d7d30ee8332..54c28bdc420 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c @@ -135,7 +135,7 @@ nvd0_therm_ctor(struct nouveau_object *parent, priv->base.base.pwm_get = nvd0_fan_pwm_get; priv->base.base.pwm_set = nvd0_fan_pwm_set; 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; priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; return nouveau_therm_preinit(&priv->base.base); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index 438d9824b77..15ca64e481f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -134,11 +134,12 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, enum nouveau_therm_thrs_direction dir); 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); int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *); 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); int nva3_therm_fan_sense(struct nouveau_therm *); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index 470f6a47b65..dde746c78c8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c @@ -205,13 +205,13 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) struct nouveau_therm_priv *priv = (void *)therm; struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - 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); alarm_timer_callback(&priv->sensor.therm_poll_alarm); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 8e1bae4f12e..9469b827567 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -96,11 +96,16 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time, /* append new alarm to list, in soonest-alarm-first order */ 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); /* process pending alarms */ diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c index 6adbbc9cc36..ed45437167f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c @@ -110,7 +110,7 @@ nv04_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, (NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + 8, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->vm->pgt[0].obj[0]); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 9474cfca6e4..064c7626287 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -119,7 +119,7 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->vm->pgt[0].obj[0]); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index aa8131436e3..fae1f67d594 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -196,7 +196,7 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, (NV44_GART_SIZE / NV44_GART_PAGE) * 4, 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC, &priv->vm->pgt[0].obj[0]); diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index 30c61e6c201..4c3b0a23b9d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c @@ -28,12 +28,54 @@ #include <subdev/timer.h> #include <subdev/fb.h> #include <subdev/vm.h> +#include <subdev/ltcg.h> struct nvc0_vmmgr_priv { struct nouveau_vmmgr base; spinlock_t lock; }; + +/* 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 nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, struct nouveau_gpuobj *pgt[2]) @@ -68,10 +110,20 @@ static void nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) { - u32 next = 1 << (vma->node->type - 8); + u64 next = 1 << (vma->node->type - 8); phys = nvc0_vm_addr(vma, phys, mem->memtype, 0); 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--) { nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); @@ -85,10 +137,12 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) { 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]; pte <<= 3; 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)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; diff --git a/drivers/gpu/drm/nouveau/dispnv04/Makefile b/drivers/gpu/drm/nouveau/dispnv04/Makefile new file mode 100644 index 00000000000..ea3f5b8a0f9 --- /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 6da576445b3..2e70462883e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_calc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c @@ -25,7 +25,7 @@ #include "nouveau_drm.h" #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 6578cd28c55..0782bd2f1e0 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -33,10 +33,10 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #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" #include <subdev/bios/pll.h> #include <subdev/clock.h> @@ -1070,4 +1070,3 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) return 0; } - diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/dispnv04/cursor.c index fe86f0de348..a810303169d 100644 --- a/drivers/gpu/drm/nouveau/nv04_cursor.c +++ b/drivers/gpu/drm/nouveau/dispnv04/cursor.c @@ -3,7 +3,7 @@ #include "nouveau_drm.h" #include "nouveau_reg.h" #include "nouveau_crtc.h" -#include "nouveau_hw.h" +#include "hw.h" static void nv04_cursor_show(struct nouveau_crtc *nv_crtc, bool update) @@ -68,4 +68,3 @@ nv04_cursor_init(struct nouveau_crtc *crtc) crtc->cursor.show = nv04_cursor_show; return 0; } - diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c index 64f7020fb60..434b920f6bd 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -31,7 +31,7 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include "nouveau_hw.h" +#include "hw.h" #include "nvreg.h" #include <subdev/bios/gpio.h> diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 7e24cdf1cb3..93dd23ff009 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -32,7 +32,7 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include "nouveau_hw.h" +#include "hw.h" #include "nvreg.h" #include <drm/i2c/sil164.h> diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index ad48444c385..4908d3fd048 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -30,7 +30,7 @@ #include "nouveau_drm.h" #include "nouveau_reg.h" -#include "nouveau_hw.h" +#include "hw.h" #include "nouveau_encoder.h" #include "nouveau_connector.h" diff --git a/drivers/gpu/drm/nouveau/nv04_display.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index a0a031dad13..a0a031dad13 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 617a06ffdb4..973056b8620 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c @@ -24,7 +24,7 @@ #include <drm/drmP.h> #include "nouveau_drm.h" -#include "nouveau_hw.h" +#include "hw.h" #include <subdev/bios/pll.h> #include <subdev/clock.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/dispnv04/hw.h index 7dff1021fab..eeb70d912d9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/dispnv04/hw.h @@ -24,7 +24,8 @@ #define __NOUVEAU_HW_H__ #include <drm/drmP.h> -#include "nv04_display.h" +#include "disp.h" +#include "nvreg.h" #include <subdev/bios/pll.h> diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/dispnv04/nvreg.h index bbfb1a68fb1..bbfb1a68fb1 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 1cdfe2a5875..08c6f5e5061 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv_modes.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c @@ -29,8 +29,8 @@ #include "nouveau_drm.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include "nouveau_hw.h" -#include "nv17_tv.h" +#include "hw.h" +#include "tvnv17.h" char *nv17_tv_norm_names[NUM_TV_NORMS] = { [TV_NORM_PAL] = "PAL", diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index 4a69ccdef9b..bf13db4e863 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -30,7 +30,7 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include "nouveau_hw.h" +#include "hw.h" #include <drm/drm_crtc_helper.h> #include <drm/i2c/ch7006.h> diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 977e42be205..acef48f4a4e 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -31,8 +31,8 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include "nouveau_hw.h" -#include "nv17_tv.h" +#include "hw.h" +#include "tvnv17.h" #include <core/device.h> diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h index 7b331543a41..7b331543a41 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 5eb3e0da7c6..1c4c6c9161a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -30,6 +30,7 @@ #include <subdev/fb.h> #include <subdev/timer.h> #include <subdev/instmem.h> +#include <engine/graph.h> #include "nouveau_drm.h" #include "nouveau_dma.h" @@ -168,6 +169,7 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_device *device = nv_device(drm->device); struct nouveau_timer *ptimer = nouveau_timer(device); + struct nouveau_graph *graph = (void *)nouveau_engine(device, NVDEV_ENGINE_GR); struct drm_nouveau_getparam *getparam = data; switch (getparam->param) { @@ -208,14 +210,8 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = 1; break; 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: nv_debug(device, "unknown parameter %lld\n", getparam->param); return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 5d940302d2a..2ffad2176b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -239,6 +239,9 @@ nouveau_backlight_init(struct drm_device *dev) case NV_40: return nv40_backlight_init(connector); case NV_50: + case NV_C0: + case NV_D0: + case NV_E0: return nv50_backlight_init(connector); default: break; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 50a6dd02f7c..6aa2137e093 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -28,7 +28,7 @@ #include "nouveau_drm.h" #include "nouveau_reg.h" -#include "nouveau_hw.h" +#include "dispnv04/hw.h" #include "nouveau_encoder.h" #include <linux/io-mapping.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 7ccd28f11ad..0067586eb01 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -24,8 +24,6 @@ #ifndef __NOUVEAU_DISPBIOS_H__ #define __NOUVEAU_DISPBIOS_H__ -#include "nvreg.h" - #define DCB_MAX_NUM_ENTRIES 16 #define DCB_MAX_NUM_I2C_ENTRIES 16 #define DCB_MAX_NUM_GPIO_ENTRIES 32 diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 4dd7ae2ac6c..4da776f344d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -32,7 +32,7 @@ #include "nouveau_reg.h" #include "nouveau_drm.h" -#include "nouveau_hw.h" +#include "dispnv04/hw.h" #include "nouveau_acpi.h" #include "nouveau_display.h" diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 4610c3a29bb..7bf22d4a3d9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -28,7 +28,7 @@ #include <drm/drm_crtc_helper.h> #include "nouveau_fbcon.h" -#include "nouveau_hw.h" +#include "dispnv04/hw.h" #include "nouveau_crtc.h" #include "nouveau_dma.h" #include "nouveau_gem.h" diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index c95decf543e..c33b13fb18d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -31,13 +31,12 @@ #include <core/gpuobj.h> #include <core/class.h> -#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" #include "nouveau_ttm.h" #include "nouveau_gem.h" @@ -365,10 +364,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_bios; - ret = nouveau_irq_init(dev); - if (ret) - goto fail_irq; - ret = nouveau_display_create(dev); if (ret) goto fail_dispctor; @@ -388,8 +383,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) fail_dispinit: nouveau_display_destroy(dev); fail_dispctor: - nouveau_irq_fini(dev); -fail_irq: nouveau_bios_takedown(dev); fail_bios: nouveau_ttm_fini(drm); @@ -415,7 +408,6 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_display_fini(dev); nouveau_display_destroy(dev); - nouveau_irq_fini(dev); nouveau_bios_takedown(dev); nouveau_ttm_fini(drm); @@ -533,7 +525,6 @@ nouveau_do_resume(struct drm_device *dev) nouveau_fence(drm)->resume(drm); nouveau_run_vbios_init(dev); - nouveau_irq_postinstall(dev); nouveau_pm_resume(dev); if (dev->mode_config.num_crtc) { @@ -669,8 +660,7 @@ static struct drm_driver driver = { .driver_features = 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, .load = nouveau_drm_load, .unload = nouveau_drm_unload, @@ -684,11 +674,6 @@ driver = { .debugfs_cleanup = nouveau_debugfs_takedown, #endif - .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, .enable_vblank = nouveau_drm_vblank_enable, .disable_vblank = nouveau_drm_vblank_disable, diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 9c39bafbef2..f2b30f89dee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -10,7 +10,18 @@ #define DRIVER_MAJOR 1 #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). + */ #include <core/client.h> #include <core/event.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index e24341229d5..24660c0f713 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -30,7 +30,7 @@ #include <subdev/bios/dcb.h> #include <drm/drm_encoder_slave.h> -#include "nv04_display.h" +#include "dispnv04/disp.h" #define NV_DPMS_CLEARED 0x80 diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c deleted file mode 100644 index 1303680affd..00000000000 --- 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 06714ad857b..00000000000 --- 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 9be9cb58e19..f19a15a3bc0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -35,14 +35,16 @@ static int 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; } static int nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) { - /* nothing to do */ + man->priv = NULL; return 0; } @@ -104,7 +106,8 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, static void 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; u32 total = 0, free = 0; @@ -161,6 +164,8 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, struct ttm_placement *placement, struct ttm_mem_reg *mem) { + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_mem *node; if (unlikely((mem->num_pages << PAGE_SHIFT) >= 512 * 1024 * 1024)) @@ -171,6 +176,20 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, return -ENOMEM; node->page_shift = 12; + 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; mem->start = 0; return 0; diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 2a0cc9d0614..27afc0ea28b 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c @@ -25,7 +25,7 @@ #include <drm/drmP.h> #include "nouveau_drm.h" #include "nouveau_reg.h" -#include "nouveau_hw.h" +#include "dispnv04/hw.h" #include "nouveau_pm.h" #include <subdev/bios/pll.h> diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 3382064c7f3..3af5bcd0b20 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -26,7 +26,7 @@ #include "nouveau_drm.h" #include "nouveau_bios.h" #include "nouveau_pm.h" -#include "nouveau_hw.h" +#include "dispnv04/hw.h" #include <subdev/bios/pll.h> #include <subdev/clock.h> diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 8bd5d2781ba..69620e39c90 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -25,7 +25,7 @@ #include <drm/drmP.h> #include "nouveau_drm.h" #include "nouveau_bios.h" -#include "nouveau_hw.h" +#include "dispnv04/hw.h" #include "nouveau_pm.h" #include "nouveau_hwsq.h" |