summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-11 10:41:07 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-13 08:17:18 +0300
commite09b41010ba33a20a87472ee821fa407a5b8da36 (patch)
treed10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/gpu/drm/nouveau/nouveau_drm.c
parentf93b97fd65072de626c074dbe099a1fff05ce060 (diff)
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page. During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/gpu/drm/nouveau/nouveau_drm.c')
-rw-r--r--kernel/drivers/gpu/drm/nouveau/nouveau_drm.c184
1 files changed, 79 insertions, 105 deletions
diff --git a/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c b/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c
index cd6dae081..1d3ee5179 100644
--- a/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/kernel/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -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>
@@ -31,15 +32,15 @@
#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);
}