These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nouveau_drm.c
index cd6dae0..1d3ee51 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/console.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
 #include "drmP.h"
 #include "drm_crtc_helper.h"
 
-#include <core/device.h>
 #include <core/gpuobj.h>
 #include <core/option.h>
+#include <core/pci.h>
+#include <core/tegra.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_ttm.h"
 #include "nouveau_gem.h"
-#include "nouveau_agp.h"
 #include "nouveau_vga.h"
 #include "nouveau_sysfs.h"
 #include "nouveau_hwmon.h"
@@ -104,14 +105,18 @@ nouveau_name(struct drm_device *dev)
 }
 
 static int
-nouveau_cli_create(u64 name, const char *sname,
+nouveau_cli_create(struct drm_device *dev, const char *sname,
                   int size, void **pcli)
 {
        struct nouveau_cli *cli = *pcli = kzalloc(size, GFP_KERNEL);
+       int ret;
        if (cli) {
-               int ret = nvif_client_init(NULL, NULL, sname, name,
-                                          nouveau_config, nouveau_debug,
-                                         &cli->base);
+               snprintf(cli->name, sizeof(cli->name), "%s", sname);
+               cli->dev = dev;
+
+               ret = nvif_client_init(NULL, cli->name, nouveau_name(dev),
+                                      nouveau_config, nouveau_debug,
+                                      &cli->base);
                if (ret == 0) {
                        mutex_init(&cli->mutex);
                        usif_client_init(cli);
@@ -127,17 +132,23 @@ nouveau_cli_destroy(struct nouveau_cli *cli)
        nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL);
        nvif_client_fini(&cli->base);
        usif_client_fini(cli);
+       kfree(cli);
 }
 
 static void
 nouveau_accel_fini(struct nouveau_drm *drm)
 {
-       nouveau_channel_del(&drm->channel);
+       nouveau_channel_idle(drm->channel);
        nvif_object_fini(&drm->ntfy);
-       nvkm_gpuobj_ref(NULL, &drm->notify);
+       nvkm_gpuobj_del(&drm->notify);
+       nvif_notify_fini(&drm->flip);
        nvif_object_fini(&drm->nvsw);
-       nouveau_channel_del(&drm->cechan);
+       nouveau_channel_del(&drm->channel);
+
+       nouveau_channel_idle(drm->cechan);
        nvif_object_fini(&drm->ttm.copy);
+       nouveau_channel_del(&drm->cechan);
+
        if (drm->fence)
                nouveau_fence(drm)->dtor(drm);
 }
@@ -146,9 +157,9 @@ static void
 nouveau_accel_init(struct nouveau_drm *drm)
 {
        struct nvif_device *device = &drm->device;
+       struct nvif_sclass *sclass;
        u32 arg0, arg1;
-       u32 sclass[16];
-       int ret, i;
+       int ret, i, n;
 
        if (nouveau_noaccel)
                return;
@@ -157,12 +168,12 @@ nouveau_accel_init(struct nouveau_drm *drm)
        /*XXX: this is crap, but the fence/channel stuff is a little
         *     backwards in some places.  this will be fixed.
         */
-       ret = nvif_object_sclass(&device->base, sclass, ARRAY_SIZE(sclass));
+       ret = n = nvif_object_sclass_get(&device->object, &sclass);
        if (ret < 0)
                return;
 
-       for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) {
-               switch (sclass[i]) {
+       for (ret = -ENOSYS, i = 0; i < n; i++) {
+               switch (sclass[i].oclass) {
                case NV03_CHANNEL_DMA:
                        ret = nv04_fence_create(drm);
                        break;
@@ -189,6 +200,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
                }
        }
 
+       nvif_object_sclass_put(&sclass);
        if (ret) {
                NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret);
                nouveau_accel_fini(drm);
@@ -196,7 +208,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
        }
 
        if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
-               ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+               ret = nouveau_channel_new(drm, &drm->device,
                                          KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
                                          KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
                                          0, &drm->cechan);
@@ -209,7 +221,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
        if (device->info.chipset >= 0xa3 &&
            device->info.chipset != 0xaa &&
            device->info.chipset != 0xac) {
-               ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+               ret = nouveau_channel_new(drm, &drm->device,
                                          NvDmaFB, NvDmaTT, &drm->cechan);
                if (ret)
                        NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
@@ -221,18 +233,16 @@ nouveau_accel_init(struct nouveau_drm *drm)
                arg1 = NvDmaTT;
        }
 
-       ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1,
-                                &drm->channel);
+       ret = nouveau_channel_new(drm, &drm->device, arg0, arg1, &drm->channel);
        if (ret) {
                NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
                nouveau_accel_fini(drm);
                return;
        }
 
-       ret = nvif_object_init(drm->channel->object, NULL, NVDRM_NVSW,
+       ret = nvif_object_init(&drm->channel->user, NVDRM_NVSW,
                               nouveau_abi16_swclass(drm), NULL, 0, &drm->nvsw);
        if (ret == 0) {
-               struct nvkm_sw_chan *swch;
                ret = RING_SPACE(drm->channel, 2);
                if (ret == 0) {
                        if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
@@ -244,9 +254,16 @@ nouveau_accel_init(struct nouveau_drm *drm)
                                OUT_RING  (drm->channel, 0x001f0000);
                        }
                }
-               swch = (void *)nvxx_object(&drm->nvsw)->parent;
-               swch->flip = nouveau_flip_complete;
-               swch->flip_data = drm->channel;
+
+               ret = nvif_notify_init(&drm->nvsw, nouveau_flip_complete,
+                                      false, NVSW_NTFY_UEVENT, NULL, 0, 0,
+                                      &drm->flip);
+               if (ret == 0)
+                       ret = nvif_notify_get(&drm->flip);
+               if (ret) {
+                       nouveau_accel_fini(drm);
+                       return;
+               }
        }
 
        if (ret) {
@@ -256,15 +273,15 @@ nouveau_accel_init(struct nouveau_drm *drm)
        }
 
        if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
-               ret = nvkm_gpuobj_new(nvxx_object(&drm->device), NULL, 32,
-                                     0, 0, &drm->notify);
+               ret = nvkm_gpuobj_new(nvxx_device(&drm->device), 32, 0, false,
+                                     NULL, &drm->notify);
                if (ret) {
                        NV_ERROR(drm, "failed to allocate notifier, %d\n", ret);
                        nouveau_accel_fini(drm);
                        return;
                }
 
-               ret = nvif_object_init(drm->channel->object, NULL, NvNotify0,
+               ret = nvif_object_init(&drm->channel->user, NvNotify0,
                                       NV_DMA_IN_MEMORY,
                                       &(struct nv_dma_v0) {
                                                .target = NV_DMA_V0_TARGET_VRAM,
@@ -319,9 +336,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
                remove_conflicting_framebuffers(aper, "nouveaufb", boot);
        kfree(aper);
 
-       ret = nvkm_device_create(pdev, NVKM_BUS_PCI,
-                                nouveau_pci_name(pdev), pci_name(pdev),
-                                nouveau_config, nouveau_debug, &device);
+       ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
+                                 true, true, ~0ULL, &device);
        if (ret)
                return ret;
 
@@ -329,7 +345,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
 
        ret = drm_get_pci_dev(pdev, pent, &driver_pci);
        if (ret) {
-               nvkm_object_ref(NULL, (struct nvkm_object **)&device);
+               nvkm_device_del(&device);
                return ret;
        }
 
@@ -369,12 +385,10 @@ nouveau_get_hdmi_dev(struct nouveau_drm *drm)
 static int
 nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 {
-       struct pci_dev *pdev = dev->pdev;
        struct nouveau_drm *drm;
        int ret;
 
-       ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),
-                                (void **)&drm);
+       ret = nouveau_cli_create(dev, "DRM", sizeof(*drm), (void **)&drm);
        if (ret)
                return ret;
 
@@ -388,36 +402,9 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 
        nouveau_get_hdmi_dev(drm);
 
-       /* make sure AGP controller is in a consistent state before we
-        * (possibly) execute vbios init tables (see nouveau_agp.h)
-        */
-       if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
-               const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY |
-                                   NV_DEVICE_V0_DISABLE_MMIO;
-               /* dummy device object, doesn't init anything, but allows
-                * agp code access to registers
-                */
-               ret = nvif_device_init(&drm->client.base.base, NULL,
-                                      NVDRM_DEVICE, NV_DEVICE,
-                                      &(struct nv_device_v0) {
-                                               .device = ~0,
-                                               .disable = ~enables,
-                                               .debug0 = ~0,
-                                      }, sizeof(struct nv_device_v0),
-                                      &drm->device);
-               if (ret)
-                       goto fail_device;
-
-               nouveau_agp_reset(drm);
-               nvif_device_fini(&drm->device);
-       }
-
-       ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE,
-                              NV_DEVICE,
+       ret = nvif_device_init(&drm->client.base.object, 0, NV_DEVICE,
                               &(struct nv_device_v0) {
                                        .device = ~0,
-                                       .disable = 0,
-                                       .debug0 = 0,
                               }, sizeof(struct nv_device_v0),
                               &drm->device);
        if (ret)
@@ -430,14 +417,13 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
         * better fix is found - assuming there is one...
         */
        if (drm->device.info.chipset == 0xc1)
-               nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000);
+               nvif_mask(&drm->device.object, 0x00088080, 0x00000800, 0x00000000);
 
        nouveau_vga_init(drm);
-       nouveau_agp_init(drm);
 
        if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
                ret = nvkm_vm_new(nvxx_device(&drm->device), 0, (1ULL << 40),
-                                 0x1000, &drm->client.vm);
+                                 0x1000, NULL, &drm->client.vm);
                if (ret)
                        goto fail_device;
 
@@ -484,7 +470,6 @@ fail_dispctor:
 fail_bios:
        nouveau_ttm_fini(drm);
 fail_ttm:
-       nouveau_agp_fini(drm);
        nouveau_vga_fini(drm);
 fail_device:
        nvif_device_fini(&drm->device);
@@ -510,7 +495,6 @@ nouveau_drm_unload(struct drm_device *dev)
        nouveau_bios_takedown(dev);
 
        nouveau_ttm_fini(drm);
-       nouveau_agp_fini(drm);
        nouveau_vga_fini(drm);
 
        nvif_device_fini(&drm->device);
@@ -525,15 +509,14 @@ nouveau_drm_device_remove(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nvkm_client *client;
-       struct nvkm_object *device;
+       struct nvkm_device *device;
 
        dev->irq_enabled = false;
        client = nvxx_client(&drm->client.base);
-       device = client->device;
+       device = nvkm_device_find(client->device);
        drm_put_dev(dev);
 
-       nvkm_object_ref(NULL, &device);
-       nvkm_object_debug();
+       nvkm_device_del(&device);
 }
 
 static void
@@ -595,7 +578,6 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
        if (ret)
                goto fail_client;
 
-       nouveau_agp_fini(drm);
        return 0;
 
 fail_client:
@@ -620,13 +602,8 @@ nouveau_do_resume(struct drm_device *dev, bool runtime)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_cli *cli;
 
-       NV_INFO(drm, "re-enabling device...\n");
-
-       nouveau_agp_reset(drm);
-
        NV_INFO(drm, "resuming kernel object tree...\n");
        nvif_client_resume(&drm->client.base);
-       nouveau_agp_init(drm);
 
        NV_INFO(drm, "resuming client object trees...\n");
        if (drm->fence && nouveau_fence(drm)->resume)
@@ -666,6 +643,7 @@ nouveau_pmops_suspend(struct device *dev)
        pci_save_state(pdev);
        pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
+       udelay(200);
        return 0;
 }
 
@@ -725,7 +703,6 @@ nouveau_pmops_runtime_suspend(struct device *dev)
                return -EBUSY;
        }
 
-       nv_debug_level(SILENT);
        drm_kms_helper_poll_disable(drm_dev);
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
        nouveau_switcheroo_optimus_dsm();
@@ -759,10 +736,9 @@ nouveau_pmops_runtime_resume(struct device *dev)
        ret = nouveau_do_resume(drm_dev, true);
        drm_kms_helper_poll_enable(drm_dev);
        /* do magic */
-       nvif_mask(device, 0x88488, (1 << 25), (1 << 25));
+       nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
        drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
-       nv_debug_level(NORMAL);
        return ret;
 }
 
@@ -823,8 +799,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
        get_task_comm(tmpname, current);
        snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
 
-       ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli),
-                       (void **)&cli);
+       ret = nouveau_cli_create(dev, name, sizeof(*cli), (void **)&cli);
 
        if (ret)
                goto out_suspend;
@@ -833,7 +808,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
 
        if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
                ret = nvkm_vm_new(nvxx_device(&drm->device), 0, (1ULL << 40),
-                                 0x1000, &cli->vm);
+                                 0x1000, NULL, &cli->vm);
                if (ret) {
                        nouveau_cli_destroy(cli);
                        goto out_suspend;
@@ -885,18 +860,18 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
 
 static const struct drm_ioctl_desc
 nouveau_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW),
 };
 
 long
@@ -942,8 +917,8 @@ nouveau_driver_fops = {
 static struct drm_driver
 driver_stub = {
        .driver_features =
-               DRIVER_USE_AGP |
-               DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER,
+               DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER |
+               DRIVER_KMS_LEGACY_CONTEXT,
 
        .load = nouveau_drm_load,
        .unload = nouveau_drm_unload,
@@ -957,7 +932,7 @@ driver_stub = {
        .debugfs_cleanup = nouveau_debugfs_takedown,
 #endif
 
-       .get_vblank_counter = drm_vblank_count,
+       .get_vblank_counter = drm_vblank_no_hw_counter,
        .enable_vblank = nouveau_display_vblank_enable,
        .disable_vblank = nouveau_display_vblank_disable,
        .get_scanout_position = nouveau_display_scanoutpos,
@@ -1053,18 +1028,17 @@ nouveau_drm_pci_driver = {
 };
 
 struct drm_device *
-nouveau_platform_device_create_(struct platform_device *pdev, int size,
-                               void **pobject)
+nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
+                              struct platform_device *pdev,
+                              struct nvkm_device **pdevice)
 {
        struct drm_device *drm;
        int err;
 
-       err = nvkm_device_create_(pdev, NVKM_BUS_PLATFORM,
-                                 nouveau_platform_name(pdev),
-                                 dev_name(&pdev->dev), nouveau_config,
-                                 nouveau_debug, size, pobject);
+       err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug,
+                                   true, true, ~0ULL, pdevice);
        if (err)
-               return ERR_PTR(err);
+               goto err_free;
 
        drm = drm_dev_alloc(&driver_platform, &pdev->dev);
        if (!drm) {
@@ -1082,7 +1056,7 @@ nouveau_platform_device_create_(struct platform_device *pdev, int size,
        return drm;
 
 err_free:
-       nvkm_object_ref(NULL, (struct nvkm_object **)pobject);
+       nvkm_device_del(pdevice);
 
        return ERR_PTR(err);
 }