aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_drm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c149
1 files changed, 56 insertions, 93 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 051e7104106d..309be93de597 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -30,18 +30,10 @@
30#include "drmP.h" 30#include "drmP.h"
31#include "drm_crtc_helper.h" 31#include "drm_crtc_helper.h"
32#include <core/device.h> 32#include <core/device.h>
33#include <core/client.h>
34#include <core/gpuobj.h> 33#include <core/gpuobj.h>
35#include <core/class.h> 34#include <core/class.h>
36#include <core/option.h> 35#include <core/option.h>
37 36
38#include <engine/device.h>
39#include <engine/disp.h>
40#include <engine/fifo.h>
41#include <engine/software.h>
42
43#include <subdev/vm.h>
44
45#include "nouveau_drm.h" 37#include "nouveau_drm.h"
46#include "nouveau_dma.h" 38#include "nouveau_dma.h"
47#include "nouveau_ttm.h" 39#include "nouveau_ttm.h"
@@ -109,40 +101,34 @@ static int
109nouveau_cli_create(u64 name, const char *sname, 101nouveau_cli_create(u64 name, const char *sname,
110 int size, void **pcli) 102 int size, void **pcli)
111{ 103{
112 struct nouveau_cli *cli; 104 struct nouveau_cli *cli = *pcli = kzalloc(size, GFP_KERNEL);
113 int ret; 105 if (cli) {
114 106 int ret = nvif_client_init(NULL, NULL, sname, name,
115 *pcli = NULL; 107 nouveau_config, nouveau_debug,
116 ret = nouveau_client_create_(sname, name, nouveau_config, 108 &cli->base);
117 nouveau_debug, size, pcli); 109 if (ret == 0)
118 cli = *pcli; 110 mutex_init(&cli->mutex);
119 if (ret) {
120 if (cli)
121 nouveau_client_destroy(&cli->base);
122 *pcli = NULL;
123 return ret; 111 return ret;
124 } 112 }
125 113 return -ENOMEM;
126 mutex_init(&cli->mutex);
127 return 0;
128} 114}
129 115
130static void 116static void
131nouveau_cli_destroy(struct nouveau_cli *cli) 117nouveau_cli_destroy(struct nouveau_cli *cli)
132{ 118{
133 struct nouveau_object *client = nv_object(cli); 119 nouveau_vm_ref(NULL, &nvkm_client(&cli->base)->vm, NULL);
134 nouveau_vm_ref(NULL, &cli->base.vm, NULL); 120 nvif_client_fini(&cli->base);
135 nouveau_client_fini(&cli->base, false);
136 atomic_set(&client->refcount, 1);
137 nouveau_object_ref(NULL, &client);
138} 121}
139 122
140static void 123static void
141nouveau_accel_fini(struct nouveau_drm *drm) 124nouveau_accel_fini(struct nouveau_drm *drm)
142{ 125{
143 nouveau_gpuobj_ref(NULL, &drm->notify);
144 nouveau_channel_del(&drm->channel); 126 nouveau_channel_del(&drm->channel);
127 nvif_object_fini(&drm->ntfy);
128 nouveau_gpuobj_ref(NULL, &drm->notify);
129 nvif_object_fini(&drm->nvsw);
145 nouveau_channel_del(&drm->cechan); 130 nouveau_channel_del(&drm->cechan);
131 nvif_object_fini(&drm->ttm.copy);
146 if (drm->fence) 132 if (drm->fence)
147 nouveau_fence(drm)->dtor(drm); 133 nouveau_fence(drm)->dtor(drm);
148} 134}
@@ -151,7 +137,6 @@ static void
151nouveau_accel_init(struct nouveau_drm *drm) 137nouveau_accel_init(struct nouveau_drm *drm)
152{ 138{
153 struct nvif_device *device = &drm->device; 139 struct nvif_device *device = &drm->device;
154 struct nouveau_object *object;
155 u32 arg0, arg1; 140 u32 arg0, arg1;
156 u32 sclass[16]; 141 u32 sclass[16];
157 int ret, i; 142 int ret, i;
@@ -163,8 +148,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
163 /*XXX: this is crap, but the fence/channel stuff is a little 148 /*XXX: this is crap, but the fence/channel stuff is a little
164 * backwards in some places. this will be fixed. 149 * backwards in some places. this will be fixed.
165 */ 150 */
166 ret = nouveau_parent_lclass(nvkm_object(device), sclass, 151 ret = nvif_object_sclass(&device->base, sclass, ARRAY_SIZE(sclass));
167 ARRAY_SIZE(sclass));
168 if (ret < 0) 152 if (ret < 0)
169 return; 153 return;
170 154
@@ -202,8 +186,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
202 } 186 }
203 187
204 if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { 188 if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
205 ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, 189 ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
206 NVDRM_CHAN + 1,
207 NVE0_CHANNEL_IND_ENGINE_CE0 | 190 NVE0_CHANNEL_IND_ENGINE_CE0 |
208 NVE0_CHANNEL_IND_ENGINE_CE1, 0, 191 NVE0_CHANNEL_IND_ENGINE_CE1, 0,
209 &drm->cechan); 192 &drm->cechan);
@@ -216,9 +199,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
216 if (device->info.chipset >= 0xa3 && 199 if (device->info.chipset >= 0xa3 &&
217 device->info.chipset != 0xaa && 200 device->info.chipset != 0xaa &&
218 device->info.chipset != 0xac) { 201 device->info.chipset != 0xac) {
219 ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, 202 ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
220 NVDRM_CHAN + 1, NvDmaFB, NvDmaTT, 203 NvDmaFB, NvDmaTT, &drm->cechan);
221 &drm->cechan);
222 if (ret) 204 if (ret)
223 NV_ERROR(drm, "failed to create ce channel, %d\n", ret); 205 NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
224 206
@@ -229,18 +211,18 @@ nouveau_accel_init(struct nouveau_drm *drm)
229 arg1 = NvDmaTT; 211 arg1 = NvDmaTT;
230 } 212 }
231 213
232 ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, 214 ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1,
233 arg0, arg1, &drm->channel); 215 &drm->channel);
234 if (ret) { 216 if (ret) {
235 NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); 217 NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
236 nouveau_accel_fini(drm); 218 nouveau_accel_fini(drm);
237 return; 219 return;
238 } 220 }
239 221
240 ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW, 222 ret = nvif_object_init(drm->channel->object, NULL, NVDRM_NVSW,
241 nouveau_abi16_swclass(drm), NULL, 0, &object); 223 nouveau_abi16_swclass(drm), NULL, 0, &drm->nvsw);
242 if (ret == 0) { 224 if (ret == 0) {
243 struct nouveau_software_chan *swch = (void *)object->parent; 225 struct nouveau_software_chan *swch;
244 ret = RING_SPACE(drm->channel, 2); 226 ret = RING_SPACE(drm->channel, 2);
245 if (ret == 0) { 227 if (ret == 0) {
246 if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { 228 if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
@@ -252,7 +234,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
252 OUT_RING (drm->channel, 0x001f0000); 234 OUT_RING (drm->channel, 0x001f0000);
253 } 235 }
254 } 236 }
255 swch = (void *)object->parent; 237 swch = (void *)nvkm_object(&drm->nvsw)->parent;
256 swch->flip = nouveau_flip_complete; 238 swch->flip = nouveau_flip_complete;
257 swch->flip_data = drm->channel; 239 swch->flip_data = drm->channel;
258 } 240 }
@@ -272,15 +254,15 @@ nouveau_accel_init(struct nouveau_drm *drm)
272 return; 254 return;
273 } 255 }
274 256
275 ret = nouveau_object_new(nv_object(drm), 257 ret = nvif_object_init(drm->channel->object, NULL, NvNotify0,
276 drm->channel->handle, NvNotify0, 258 NV_DMA_IN_MEMORY_CLASS,
277 0x003d, &(struct nv_dma_class) { 259 &(struct nv_dma_class) {
278 .flags = NV_DMA_TARGET_VRAM | 260 .flags = NV_DMA_TARGET_VRAM |
279 NV_DMA_ACCESS_RDWR, 261 NV_DMA_ACCESS_RDWR,
280 .start = drm->notify->addr, 262 .start = drm->notify->addr,
281 .limit = drm->notify->addr + 31 263 .limit = drm->notify->addr + 31
282 }, sizeof(struct nv_dma_class), 264 }, sizeof(struct nv_dma_class),
283 &object); 265 &drm->ntfy);
284 if (ret) { 266 if (ret) {
285 nouveau_accel_fini(drm); 267 nouveau_accel_fini(drm);
286 return; 268 return;
@@ -373,27 +355,6 @@ nouveau_get_hdmi_dev(struct nouveau_drm *drm)
373 } 355 }
374} 356}
375 357
376void
377nouveau_drm_hack_device(struct nouveau_drm *drm, struct nvif_device *device)
378{
379 drm->device.info.chipset = nvkm_device(&drm->device)->chipset;
380 switch (nvkm_device(&drm->device)->card_type) {
381 case NV_04: device->info.family = NV_DEVICE_INFO_V0_TNT; break;
382 case NV_10: device->info.family = NV_DEVICE_INFO_V0_CELSIUS; break;
383 case NV_11: device->info.family = NV_DEVICE_INFO_V0_CELSIUS; break;
384 case NV_20: device->info.family = NV_DEVICE_INFO_V0_KELVIN; break;
385 case NV_30: device->info.family = NV_DEVICE_INFO_V0_RANKINE; break;
386 case NV_40: device->info.family = NV_DEVICE_INFO_V0_CURIE; break;
387 case NV_50: device->info.family = NV_DEVICE_INFO_V0_TESLA; break;
388 case NV_C0: device->info.family = NV_DEVICE_INFO_V0_FERMI; break;
389 case NV_E0: device->info.family = NV_DEVICE_INFO_V0_KEPLER; break;
390 case GM100: device->info.family = NV_DEVICE_INFO_V0_MAXWELL; break;
391 default:
392 BUG_ON(1);
393 break;
394 }
395}
396
397static int 358static int
398nouveau_drm_load(struct drm_device *dev, unsigned long flags) 359nouveau_drm_load(struct drm_device *dev, unsigned long flags)
399{ 360{
@@ -408,7 +369,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
408 369
409 dev->dev_private = drm; 370 dev->dev_private = drm;
410 drm->dev = dev; 371 drm->dev = dev;
411 nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM"); 372 nvkm_client(&drm->client.base)->debug =
373 nouveau_dbgopt(nouveau_debug, "DRM");
412 374
413 INIT_LIST_HEAD(&drm->clients); 375 INIT_LIST_HEAD(&drm->clients);
414 spin_lock_init(&drm->tile.lock); 376 spin_lock_init(&drm->tile.lock);
@@ -422,39 +384,34 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
422 /* dummy device object, doesn't init anything, but allows 384 /* dummy device object, doesn't init anything, but allows
423 * agp code access to registers 385 * agp code access to registers
424 */ 386 */
425 ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, 387 ret = nvif_device_init(&drm->client.base.base, NULL,
426 NVDRM_DEVICE, 0x0080, 388 NVDRM_DEVICE, NV_DEVICE_CLASS,
427 &(struct nv_device_class) { 389 &(struct nv_device_class) {
428 .device = ~0, 390 .device = ~0,
429 .disable = 391 .disable =
430 ~(NV_DEVICE_DISABLE_MMIO | 392 ~(NV_DEVICE_DISABLE_MMIO |
431 NV_DEVICE_DISABLE_IDENTIFY), 393 NV_DEVICE_DISABLE_IDENTIFY),
432 .debug0 = ~0, 394 .debug0 = ~0,
433 }, sizeof(struct nv_device_class), 395 }, sizeof(struct nv_device_class),
434 (struct nouveau_object **) 396 &drm->device);
435 &drm->device.object);
436 if (ret) 397 if (ret)
437 goto fail_device; 398 goto fail_device;
438 399
439 nouveau_drm_hack_device(drm, &drm->device);
440
441 nouveau_agp_reset(drm); 400 nouveau_agp_reset(drm);
442 nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE); 401 nvif_device_fini(&drm->device);
443 } 402 }
444 403
445 ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE, 404 ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE,
446 0x0080, &(struct nv_device_class) { 405 NV_DEVICE_CLASS,
406 &(struct nv_device_class) {
447 .device = ~0, 407 .device = ~0,
448 .disable = 0, 408 .disable = 0,
449 .debug0 = 0, 409 .debug0 = 0,
450 }, sizeof(struct nv_device_class), 410 }, sizeof(struct nv_device_class),
451 (struct nouveau_object **) 411 &drm->device);
452 &drm->device.object);
453 if (ret) 412 if (ret)
454 goto fail_device; 413 goto fail_device;
455 414
456 nouveau_drm_hack_device(drm, &drm->device);
457
458 dev->irq_enabled = true; 415 dev->irq_enabled = true;
459 416
460 /* workaround an odd issue on nvc1 by disabling the device's 417 /* workaround an odd issue on nvc1 by disabling the device's
@@ -473,7 +430,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
473 if (ret) 430 if (ret)
474 goto fail_device; 431 goto fail_device;
475 432
476 drm->client.base.vm = drm->client.vm; 433 nvkm_client(&drm->client.base)->vm = drm->client.vm;
477 } 434 }
478 435
479 ret = nouveau_ttm_init(drm); 436 ret = nouveau_ttm_init(drm);
@@ -519,6 +476,7 @@ fail_ttm:
519 nouveau_agp_fini(drm); 476 nouveau_agp_fini(drm);
520 nouveau_vga_fini(drm); 477 nouveau_vga_fini(drm);
521fail_device: 478fail_device:
479 nvif_device_fini(&drm->device);
522 nouveau_cli_destroy(&drm->client); 480 nouveau_cli_destroy(&drm->client);
523 return ret; 481 return ret;
524} 482}
@@ -544,6 +502,7 @@ nouveau_drm_unload(struct drm_device *dev)
544 nouveau_agp_fini(drm); 502 nouveau_agp_fini(drm);
545 nouveau_vga_fini(drm); 503 nouveau_vga_fini(drm);
546 504
505 nvif_device_fini(&drm->device);
547 if (drm->hdmi_device) 506 if (drm->hdmi_device)
548 pci_dev_put(drm->hdmi_device); 507 pci_dev_put(drm->hdmi_device);
549 nouveau_cli_destroy(&drm->client); 508 nouveau_cli_destroy(&drm->client);
@@ -554,10 +513,12 @@ void
554nouveau_drm_device_remove(struct drm_device *dev) 513nouveau_drm_device_remove(struct drm_device *dev)
555{ 514{
556 struct nouveau_drm *drm = nouveau_drm(dev); 515 struct nouveau_drm *drm = nouveau_drm(dev);
516 struct nouveau_client *client;
557 struct nouveau_object *device; 517 struct nouveau_object *device;
558 518
559 dev->irq_enabled = false; 519 dev->irq_enabled = false;
560 device = drm->client.base.device; 520 client = nvkm_client(&drm->client.base);
521 device = client->device;
561 drm_put_dev(dev); 522 drm_put_dev(dev);
562 523
563 nouveau_object_ref(NULL, &device); 524 nouveau_object_ref(NULL, &device);
@@ -612,13 +573,13 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
612 } 573 }
613 574
614 list_for_each_entry(cli, &drm->clients, head) { 575 list_for_each_entry(cli, &drm->clients, head) {
615 ret = nouveau_client_fini(&cli->base, true); 576 ret = nvif_client_suspend(&cli->base);
616 if (ret) 577 if (ret)
617 goto fail_client; 578 goto fail_client;
618 } 579 }
619 580
620 NV_INFO(drm, "suspending kernel object tree...\n"); 581 NV_INFO(drm, "suspending kernel object tree...\n");
621 ret = nouveau_client_fini(&drm->client.base, true); 582 ret = nvif_client_suspend(&drm->client.base);
622 if (ret) 583 if (ret)
623 goto fail_client; 584 goto fail_client;
624 585
@@ -627,7 +588,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
627 588
628fail_client: 589fail_client:
629 list_for_each_entry_continue_reverse(cli, &drm->clients, head) { 590 list_for_each_entry_continue_reverse(cli, &drm->clients, head) {
630 nouveau_client_init(&cli->base); 591 nvif_client_resume(&cli->base);
631 } 592 }
632 593
633 if (drm->fence && nouveau_fence(drm)->resume) 594 if (drm->fence && nouveau_fence(drm)->resume)
@@ -675,7 +636,7 @@ nouveau_do_resume(struct drm_device *dev)
675 nouveau_agp_reset(drm); 636 nouveau_agp_reset(drm);
676 637
677 NV_INFO(drm, "resuming kernel object tree...\n"); 638 NV_INFO(drm, "resuming kernel object tree...\n");
678 nouveau_client_init(&drm->client.base); 639 nvif_client_resume(&drm->client.base);
679 nouveau_agp_init(drm); 640 nouveau_agp_init(drm);
680 641
681 NV_INFO(drm, "resuming client object trees...\n"); 642 NV_INFO(drm, "resuming client object trees...\n");
@@ -683,7 +644,7 @@ nouveau_do_resume(struct drm_device *dev)
683 nouveau_fence(drm)->resume(drm); 644 nouveau_fence(drm)->resume(drm);
684 645
685 list_for_each_entry(cli, &drm->clients, head) { 646 list_for_each_entry(cli, &drm->clients, head) {
686 nouveau_client_init(&cli->base); 647 nvif_client_resume(&cli->base);
687 } 648 }
688 649
689 nouveau_run_vbios_init(dev); 650 nouveau_run_vbios_init(dev);
@@ -779,6 +740,8 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
779 if (ret) 740 if (ret)
780 goto out_suspend; 741 goto out_suspend;
781 742
743 cli->base.super = false;
744
782 if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { 745 if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
783 ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40), 746 ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),
784 0x1000, &cli->vm); 747 0x1000, &cli->vm);
@@ -787,7 +750,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
787 goto out_suspend; 750 goto out_suspend;
788 } 751 }
789 752
790 cli->base.vm = cli->vm; 753 nvkm_client(&cli->base)->vm = cli->vm;
791 } 754 }
792 755
793 fpriv->driver_priv = cli; 756 fpriv->driver_priv = cli;