aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-03-31 01:40:43 -0400
committerBen Skeggs <bskeggs@redhat.com>2011-05-15 20:48:01 -0400
commit6dfdd7a61e8fc25552d9de1cb25272324dfc4c13 (patch)
treed158037ace54303d33323a14bafc8a2ef27a85b5 /drivers
parent2d7b919c9b0ca3df1da2498bb0cede25ddd97e00 (diff)
drm/nouveau: working towards a common way to represent engines
There's lots of more-or-less independant engines present on NVIDIA GPUs these days, and we generally want to perform the same operations on them. Implementing new ones requires hooking into lots of different places, the aim of this work is to make this simpler and cleaner. NV84:NV98 PCRYPT moved over as a test. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h60
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c15
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c81
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vm.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv84_crypt.c122
8 files changed, 174 insertions, 133 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 4cea35c57d1..3a047ec1ead 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -269,8 +269,8 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
269 struct drm_nouveau_private *dev_priv = dev->dev_private; 269 struct drm_nouveau_private *dev_priv = dev->dev_private;
270 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 270 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
271 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 271 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
272 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
273 unsigned long flags; 272 unsigned long flags;
273 int i;
274 274
275 /* decrement the refcount, and we're done if there's still refs */ 275 /* decrement the refcount, and we're done if there's still refs */
276 if (likely(!atomic_dec_and_test(&chan->users))) { 276 if (likely(!atomic_dec_and_test(&chan->users))) {
@@ -305,8 +305,10 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
305 /* destroy the engine specific contexts */ 305 /* destroy the engine specific contexts */
306 pfifo->destroy_context(chan); 306 pfifo->destroy_context(chan);
307 pgraph->destroy_context(chan); 307 pgraph->destroy_context(chan);
308 if (pcrypt->destroy_context) 308 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
309 pcrypt->destroy_context(chan); 309 if (chan->engctx[i])
310 dev_priv->eng[i]->context_del(chan, i);
311 }
310 312
311 pfifo->reassign(dev, true); 313 pfifo->reassign(dev, true);
312 314
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 155ebdcbf06..30b9e89a3a2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -208,6 +208,12 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
208 208
209 pgraph->fifo_access(dev, false); 209 pgraph->fifo_access(dev, false);
210 nouveau_wait_for_idle(dev); 210 nouveau_wait_for_idle(dev);
211
212 for (i = NVOBJ_ENGINE_NR - 1; i >= 0; i--) {
213 if (dev_priv->eng[i])
214 dev_priv->eng[i]->fini(dev, i);
215 }
216
211 pfifo->reassign(dev, false); 217 pfifo->reassign(dev, false);
212 pfifo->disable(dev); 218 pfifo->disable(dev);
213 pfifo->unload_context(dev); 219 pfifo->unload_context(dev);
@@ -299,8 +305,11 @@ nouveau_pci_resume(struct pci_dev *pdev)
299 engine->mc.init(dev); 305 engine->mc.init(dev);
300 engine->timer.init(dev); 306 engine->timer.init(dev);
301 engine->fb.init(dev); 307 engine->fb.init(dev);
308 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
309 if (dev_priv->eng[i])
310 dev_priv->eng[i]->init(dev, i);
311 }
302 engine->graph.init(dev); 312 engine->graph.init(dev);
303 engine->crypt.init(dev);
304 engine->fifo.init(dev); 313 engine->fifo.init(dev);
305 314
306 nouveau_irq_postinstall(dev); 315 nouveau_irq_postinstall(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 31e34ae16da..6b43cb02dce 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -150,13 +150,9 @@ enum nouveau_flags {
150 150
151#define NVOBJ_ENGINE_SW 0 151#define NVOBJ_ENGINE_SW 0
152#define NVOBJ_ENGINE_GR 1 152#define NVOBJ_ENGINE_GR 1
153#define NVOBJ_ENGINE_PPP 2 153#define NVOBJ_ENGINE_CRYPT 2
154#define NVOBJ_ENGINE_COPY 3 154#define NVOBJ_ENGINE_DISPLAY 15
155#define NVOBJ_ENGINE_VP 4 155#define NVOBJ_ENGINE_NR 16
156#define NVOBJ_ENGINE_CRYPT 5
157#define NVOBJ_ENGINE_BSP 6
158#define NVOBJ_ENGINE_DISPLAY 0xcafe0001
159#define NVOBJ_ENGINE_INT 0xdeadbeef
160 156
161#define NVOBJ_FLAG_DONT_MAP (1 << 0) 157#define NVOBJ_FLAG_DONT_MAP (1 << 0)
162#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) 158#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1)
@@ -248,8 +244,8 @@ struct nouveau_channel {
248 /* PGRAPH context */ 244 /* PGRAPH context */
249 /* XXX may be merge 2 pointers as private data ??? */ 245 /* XXX may be merge 2 pointers as private data ??? */
250 struct nouveau_gpuobj *ramin_grctx; 246 struct nouveau_gpuobj *ramin_grctx;
251 struct nouveau_gpuobj *crypt_ctx;
252 void *pgraph_ctx; 247 void *pgraph_ctx;
248 void *engctx[NVOBJ_ENGINE_NR];
253 249
254 /* NV50 VM */ 250 /* NV50 VM */
255 struct nouveau_vm *vm; 251 struct nouveau_vm *vm;
@@ -298,6 +294,17 @@ struct nouveau_channel {
298 } debugfs; 294 } debugfs;
299}; 295};
300 296
297struct nouveau_exec_engine {
298 void (*destroy)(struct drm_device *, int engine);
299 int (*init)(struct drm_device *, int engine);
300 int (*fini)(struct drm_device *, int engine);
301 int (*context_new)(struct nouveau_channel *, int engine);
302 void (*context_del)(struct nouveau_channel *, int engine);
303 int (*object_new)(struct nouveau_channel *, int engine,
304 u32 handle, u16 class);
305 void (*tlb_flush)(struct drm_device *, int engine);
306};
307
301struct nouveau_instmem_engine { 308struct nouveau_instmem_engine {
302 void *priv; 309 void *priv;
303 310
@@ -501,17 +508,6 @@ struct nouveau_pm_engine {
501 int (*temp_get)(struct drm_device *); 508 int (*temp_get)(struct drm_device *);
502}; 509};
503 510
504struct nouveau_crypt_engine {
505 bool registered;
506
507 int (*init)(struct drm_device *);
508 void (*takedown)(struct drm_device *);
509 int (*create_context)(struct nouveau_channel *);
510 void (*destroy_context)(struct nouveau_channel *);
511 int (*object_new)(struct nouveau_channel *, u32 handle, u16 class);
512 void (*tlb_flush)(struct drm_device *dev);
513};
514
515struct nouveau_vram_engine { 511struct nouveau_vram_engine {
516 int (*init)(struct drm_device *); 512 int (*init)(struct drm_device *);
517 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, 513 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
@@ -531,7 +527,6 @@ struct nouveau_engine {
531 struct nouveau_display_engine display; 527 struct nouveau_display_engine display;
532 struct nouveau_gpio_engine gpio; 528 struct nouveau_gpio_engine gpio;
533 struct nouveau_pm_engine pm; 529 struct nouveau_pm_engine pm;
534 struct nouveau_crypt_engine crypt;
535 struct nouveau_vram_engine vram; 530 struct nouveau_vram_engine vram;
536}; 531};
537 532
@@ -651,6 +646,7 @@ struct drm_nouveau_private {
651 u32 ramin_base; 646 u32 ramin_base;
652 bool ramin_available; 647 bool ramin_available;
653 struct drm_mm ramin_heap; 648 struct drm_mm ramin_heap;
649 struct nouveau_exec_engine *eng[NVOBJ_ENGINE_NR];
654 struct list_head gpuobj_list; 650 struct list_head gpuobj_list;
655 struct list_head classes; 651 struct list_head classes;
656 652
@@ -881,6 +877,16 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan,
881extern void nouveau_channel_idle(struct nouveau_channel *chan); 877extern void nouveau_channel_idle(struct nouveau_channel *chan);
882 878
883/* nouveau_object.c */ 879/* nouveau_object.c */
880#define NVOBJ_ENGINE_ADD(d, e, p) do { \
881 struct drm_nouveau_private *dev_priv = (d)->dev_private; \
882 dev_priv->eng[NVOBJ_ENGINE_##e] = (p); \
883} while (0)
884
885#define NVOBJ_ENGINE_DEL(d, e) do { \
886 struct drm_nouveau_private *dev_priv = (d)->dev_private; \
887 dev_priv->eng[NVOBJ_ENGINE_##e] = NULL; \
888} while (0)
889
884#define NVOBJ_CLASS(d, c, e) do { \ 890#define NVOBJ_CLASS(d, c, e) do { \
885 int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ 891 int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \
886 if (ret) \ 892 if (ret) \
@@ -1209,12 +1215,7 @@ extern int nvc0_graph_unload_context(struct drm_device *);
1209extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16); 1215extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16);
1210 1216
1211/* nv84_crypt.c */ 1217/* nv84_crypt.c */
1212extern int nv84_crypt_init(struct drm_device *dev); 1218extern int nv84_crypt_create(struct drm_device *);
1213extern void nv84_crypt_fini(struct drm_device *dev);
1214extern int nv84_crypt_create_context(struct nouveau_channel *);
1215extern void nv84_crypt_destroy_context(struct nouveau_channel *);
1216extern void nv84_crypt_tlb_flush(struct drm_device *dev);
1217extern int nv84_crypt_object_new(struct nouveau_channel *, u32, u16);
1218 1219
1219/* nv04_instmem.c */ 1220/* nv04_instmem.c */
1220extern int nv04_instmem_init(struct drm_device *); 1221extern int nv04_instmem_init(struct drm_device *);
@@ -1582,6 +1583,13 @@ nv_match_device(struct drm_device *dev, unsigned device,
1582 dev->pdev->subsystem_device == sub_device; 1583 dev->pdev->subsystem_device == sub_device;
1583} 1584}
1584 1585
1586static inline void *
1587nv_engine(struct drm_device *dev, int engine)
1588{
1589 struct drm_nouveau_private *dev_priv = dev->dev_private;
1590 return (void *)dev_priv->eng[engine];
1591}
1592
1585/* returns 1 if device is one of the nv4x using the 0x4497 object class, 1593/* returns 1 if device is one of the nv4x using the 0x4497 object class,
1586 * helpful to determine a number of other hardware features 1594 * helpful to determine a number of other hardware features
1587 */ 1595 */
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index f7b806f26f2..4fb05b6c698 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -621,7 +621,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
621{ 621{
622 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 622 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
623 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 623 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
624 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
625 struct drm_device *dev = chan->dev; 624 struct drm_device *dev = chan->dev;
626 struct nouveau_gpuobj_class *oc; 625 struct nouveau_gpuobj_class *oc;
627 int ret; 626 int ret;
@@ -649,17 +648,15 @@ found:
649 } 648 }
650 649
651 return pgraph->object_new(chan, handle, class); 650 return pgraph->object_new(chan, handle, class);
652 case NVOBJ_ENGINE_CRYPT: 651 }
653 if (!chan->crypt_ctx) {
654 ret = pcrypt->create_context(chan);
655 if (ret)
656 return ret;
657 }
658 652
659 return pcrypt->object_new(chan, handle, class); 653 if (!chan->engctx[oc->engine]) {
654 ret = dev_priv->eng[oc->engine]->context_new(chan, oc->engine);
655 if (ret)
656 return ret;
660 } 657 }
661 658
662 BUG_ON(1); 659 return dev_priv->eng[oc->engine]->object_new(chan, oc->engine, handle, class);
663} 660}
664 661
665static int 662static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index fa81b9017b3..a1a25ea7cc7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -99,8 +99,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
99 engine->pm.clock_get = nv04_pm_clock_get; 99 engine->pm.clock_get = nv04_pm_clock_get;
100 engine->pm.clock_pre = nv04_pm_clock_pre; 100 engine->pm.clock_pre = nv04_pm_clock_pre;
101 engine->pm.clock_set = nv04_pm_clock_set; 101 engine->pm.clock_set = nv04_pm_clock_set;
102 engine->crypt.init = nouveau_stub_init;
103 engine->crypt.takedown = nouveau_stub_takedown;
104 engine->vram.init = nouveau_mem_detect; 102 engine->vram.init = nouveau_mem_detect;
105 engine->vram.flags_valid = nouveau_mem_flags_valid; 103 engine->vram.flags_valid = nouveau_mem_flags_valid;
106 break; 104 break;
@@ -159,8 +157,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
159 engine->pm.clock_get = nv04_pm_clock_get; 157 engine->pm.clock_get = nv04_pm_clock_get;
160 engine->pm.clock_pre = nv04_pm_clock_pre; 158 engine->pm.clock_pre = nv04_pm_clock_pre;
161 engine->pm.clock_set = nv04_pm_clock_set; 159 engine->pm.clock_set = nv04_pm_clock_set;
162 engine->crypt.init = nouveau_stub_init;
163 engine->crypt.takedown = nouveau_stub_takedown;
164 engine->vram.init = nouveau_mem_detect; 160 engine->vram.init = nouveau_mem_detect;
165 engine->vram.flags_valid = nouveau_mem_flags_valid; 161 engine->vram.flags_valid = nouveau_mem_flags_valid;
166 break; 162 break;
@@ -219,8 +215,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
219 engine->pm.clock_get = nv04_pm_clock_get; 215 engine->pm.clock_get = nv04_pm_clock_get;
220 engine->pm.clock_pre = nv04_pm_clock_pre; 216 engine->pm.clock_pre = nv04_pm_clock_pre;
221 engine->pm.clock_set = nv04_pm_clock_set; 217 engine->pm.clock_set = nv04_pm_clock_set;
222 engine->crypt.init = nouveau_stub_init;
223 engine->crypt.takedown = nouveau_stub_takedown;
224 engine->vram.init = nouveau_mem_detect; 218 engine->vram.init = nouveau_mem_detect;
225 engine->vram.flags_valid = nouveau_mem_flags_valid; 219 engine->vram.flags_valid = nouveau_mem_flags_valid;
226 break; 220 break;
@@ -281,8 +275,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
281 engine->pm.clock_set = nv04_pm_clock_set; 275 engine->pm.clock_set = nv04_pm_clock_set;
282 engine->pm.voltage_get = nouveau_voltage_gpio_get; 276 engine->pm.voltage_get = nouveau_voltage_gpio_get;
283 engine->pm.voltage_set = nouveau_voltage_gpio_set; 277 engine->pm.voltage_set = nouveau_voltage_gpio_set;
284 engine->crypt.init = nouveau_stub_init;
285 engine->crypt.takedown = nouveau_stub_takedown;
286 engine->vram.init = nouveau_mem_detect; 278 engine->vram.init = nouveau_mem_detect;
287 engine->vram.flags_valid = nouveau_mem_flags_valid; 279 engine->vram.flags_valid = nouveau_mem_flags_valid;
288 break; 280 break;
@@ -345,8 +337,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
345 engine->pm.voltage_get = nouveau_voltage_gpio_get; 337 engine->pm.voltage_get = nouveau_voltage_gpio_get;
346 engine->pm.voltage_set = nouveau_voltage_gpio_set; 338 engine->pm.voltage_set = nouveau_voltage_gpio_set;
347 engine->pm.temp_get = nv40_temp_get; 339 engine->pm.temp_get = nv40_temp_get;
348 engine->crypt.init = nouveau_stub_init;
349 engine->crypt.takedown = nouveau_stub_takedown;
350 engine->vram.init = nouveau_mem_detect; 340 engine->vram.init = nouveau_mem_detect;
351 engine->vram.flags_valid = nouveau_mem_flags_valid; 341 engine->vram.flags_valid = nouveau_mem_flags_valid;
352 break; 342 break;
@@ -438,25 +428,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
438 engine->pm.temp_get = nv84_temp_get; 428 engine->pm.temp_get = nv84_temp_get;
439 else 429 else
440 engine->pm.temp_get = nv40_temp_get; 430 engine->pm.temp_get = nv40_temp_get;
441 switch (dev_priv->chipset) {
442 case 0x84:
443 case 0x86:
444 case 0x92:
445 case 0x94:
446 case 0x96:
447 case 0xa0:
448 engine->crypt.init = nv84_crypt_init;
449 engine->crypt.takedown = nv84_crypt_fini;
450 engine->crypt.create_context = nv84_crypt_create_context;
451 engine->crypt.destroy_context = nv84_crypt_destroy_context;
452 engine->crypt.object_new = nv84_crypt_object_new;
453 engine->crypt.tlb_flush = nv84_crypt_tlb_flush;
454 break;
455 default:
456 engine->crypt.init = nouveau_stub_init;
457 engine->crypt.takedown = nouveau_stub_takedown;
458 break;
459 }
460 engine->vram.init = nv50_vram_init; 431 engine->vram.init = nv50_vram_init;
461 engine->vram.get = nv50_vram_new; 432 engine->vram.get = nv50_vram_new;
462 engine->vram.put = nv50_vram_del; 433 engine->vram.put = nv50_vram_del;
@@ -511,8 +482,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
511 engine->gpio.irq_register = nv50_gpio_irq_register; 482 engine->gpio.irq_register = nv50_gpio_irq_register;
512 engine->gpio.irq_unregister = nv50_gpio_irq_unregister; 483 engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
513 engine->gpio.irq_enable = nv50_gpio_irq_enable; 484 engine->gpio.irq_enable = nv50_gpio_irq_enable;
514 engine->crypt.init = nouveau_stub_init;
515 engine->crypt.takedown = nouveau_stub_takedown;
516 engine->vram.init = nvc0_vram_init; 485 engine->vram.init = nvc0_vram_init;
517 engine->vram.get = nvc0_vram_new; 486 engine->vram.get = nvc0_vram_new;
518 engine->vram.put = nv50_vram_del; 487 engine->vram.put = nv50_vram_del;
@@ -601,7 +570,7 @@ nouveau_card_init(struct drm_device *dev)
601{ 570{
602 struct drm_nouveau_private *dev_priv = dev->dev_private; 571 struct drm_nouveau_private *dev_priv = dev->dev_private;
603 struct nouveau_engine *engine; 572 struct nouveau_engine *engine;
604 int ret; 573 int ret, e;
605 574
606 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); 575 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
607 vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, 576 vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
@@ -666,23 +635,37 @@ nouveau_card_init(struct drm_device *dev)
666 if (ret) 635 if (ret)
667 goto out_timer; 636 goto out_timer;
668 637
638 switch (dev_priv->chipset) {
639 case 0x84:
640 case 0x86:
641 case 0x92:
642 case 0x94:
643 case 0x96:
644 case 0xa0:
645 nv84_crypt_create(dev);
646 break;
647 }
648
669 if (nouveau_noaccel) 649 if (nouveau_noaccel)
670 engine->graph.accel_blocked = true; 650 engine->graph.accel_blocked = true;
671 else { 651 else {
652 for (e = 0; e < NVOBJ_ENGINE_NR; e++) {
653 if (dev_priv->eng[e]) {
654 ret = dev_priv->eng[e]->init(dev, e);
655 if (ret)
656 goto out_engine;
657 }
658 }
659
672 /* PGRAPH */ 660 /* PGRAPH */
673 ret = engine->graph.init(dev); 661 ret = engine->graph.init(dev);
674 if (ret) 662 if (ret)
675 goto out_fb; 663 goto out_engine;
676
677 /* PCRYPT */
678 ret = engine->crypt.init(dev);
679 if (ret)
680 goto out_graph;
681 664
682 /* PFIFO */ 665 /* PFIFO */
683 ret = engine->fifo.init(dev); 666 ret = engine->fifo.init(dev);
684 if (ret) 667 if (ret)
685 goto out_crypt; 668 goto out_graph;
686 } 669 }
687 670
688 ret = engine->display.create(dev); 671 ret = engine->display.create(dev);
@@ -723,13 +706,17 @@ out_vblank:
723out_fifo: 706out_fifo:
724 if (!nouveau_noaccel) 707 if (!nouveau_noaccel)
725 engine->fifo.takedown(dev); 708 engine->fifo.takedown(dev);
726out_crypt:
727 if (!nouveau_noaccel)
728 engine->crypt.takedown(dev);
729out_graph: 709out_graph:
730 if (!nouveau_noaccel) 710 if (!nouveau_noaccel)
731 engine->graph.takedown(dev); 711 engine->graph.takedown(dev);
732out_fb: 712out_engine:
713 if (!nouveau_noaccel) {
714 for (e = e - 1; e >= 0; e--) {
715 dev_priv->eng[e]->fini(dev, e);
716 dev_priv->eng[e]->destroy(dev, e);
717 }
718 }
719
733 engine->fb.takedown(dev); 720 engine->fb.takedown(dev);
734out_timer: 721out_timer:
735 engine->timer.takedown(dev); 722 engine->timer.takedown(dev);
@@ -759,6 +746,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
759{ 746{
760 struct drm_nouveau_private *dev_priv = dev->dev_private; 747 struct drm_nouveau_private *dev_priv = dev->dev_private;
761 struct nouveau_engine *engine = &dev_priv->engine; 748 struct nouveau_engine *engine = &dev_priv->engine;
749 int e;
762 750
763 if (!engine->graph.accel_blocked) { 751 if (!engine->graph.accel_blocked) {
764 nouveau_fence_fini(dev); 752 nouveau_fence_fini(dev);
@@ -767,8 +755,13 @@ static void nouveau_card_takedown(struct drm_device *dev)
767 755
768 if (!nouveau_noaccel) { 756 if (!nouveau_noaccel) {
769 engine->fifo.takedown(dev); 757 engine->fifo.takedown(dev);
770 engine->crypt.takedown(dev);
771 engine->graph.takedown(dev); 758 engine->graph.takedown(dev);
759 for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
760 if (dev_priv->eng[e]) {
761 dev_priv->eng[e]->fini(dev, e);
762 dev_priv->eng[e]->destroy(dev,e );
763 }
764 }
772 } 765 }
773 engine->fb.takedown(dev); 766 engine->fb.takedown(dev);
774 engine->timer.takedown(dev); 767 engine->timer.takedown(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index 2e06b55cfdc..16ffc4cceeb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -54,7 +54,7 @@ struct nouveau_vm {
54 54
55 struct list_head pgd_list; 55 struct list_head pgd_list;
56 atomic_t pgraph_refs; 56 atomic_t pgraph_refs;
57 atomic_t pcrypt_refs; 57 atomic_t engref[16];
58 58
59 struct nouveau_vm_pgt *pgt; 59 struct nouveau_vm_pgt *pgt;
60 u32 fpde; 60 u32 fpde;
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
index 6c269449074..1f58b0d6279 100644
--- a/drivers/gpu/drm/nouveau/nv50_vm.c
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -152,7 +152,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
152 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; 152 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
153 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 153 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
154 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 154 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
155 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; 155 int i;
156 156
157 pinstmem->flush(vm->dev); 157 pinstmem->flush(vm->dev);
158 158
@@ -166,8 +166,10 @@ nv50_vm_flush(struct nouveau_vm *vm)
166 166
167 if (atomic_read(&vm->pgraph_refs)) 167 if (atomic_read(&vm->pgraph_refs))
168 pgraph->tlb_flush(vm->dev); 168 pgraph->tlb_flush(vm->dev);
169 if (atomic_read(&vm->pcrypt_refs)) 169 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
170 pcrypt->tlb_flush(vm->dev); 170 if (atomic_read(&vm->engref[i]))
171 dev_priv->eng[i]->tlb_flush(vm->dev, i);
172 }
171} 173}
172 174
173void 175void
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
index 4918f4e60ba..75b809a5174 100644
--- a/drivers/gpu/drm/nouveau/nv84_crypt.c
+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
@@ -28,45 +28,46 @@
28#include "nouveau_vm.h" 28#include "nouveau_vm.h"
29#include "nouveau_ramht.h" 29#include "nouveau_ramht.h"
30 30
31static void nv84_crypt_isr(struct drm_device *); 31struct nv84_crypt_engine {
32 struct nouveau_exec_engine base;
33};
32 34
33int 35static int
34nv84_crypt_create_context(struct nouveau_channel *chan) 36nv84_crypt_context_new(struct nouveau_channel *chan, int engine)
35{ 37{
36 struct drm_device *dev = chan->dev; 38 struct drm_device *dev = chan->dev;
37 struct drm_nouveau_private *dev_priv = dev->dev_private; 39 struct drm_nouveau_private *dev_priv = dev->dev_private;
38 struct nouveau_gpuobj *ramin = chan->ramin; 40 struct nouveau_gpuobj *ramin = chan->ramin;
41 struct nouveau_gpuobj *ctx;
39 int ret; 42 int ret;
40 43
41 NV_DEBUG(dev, "ch%d\n", chan->id); 44 NV_DEBUG(dev, "ch%d\n", chan->id);
42 45
43 ret = nouveau_gpuobj_new(dev, chan, 256, 0, 46 ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC |
44 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, 47 NVOBJ_FLAG_ZERO_FREE, &ctx);
45 &chan->crypt_ctx);
46 if (ret) 48 if (ret)
47 return ret; 49 return ret;
48 50
49 nv_wo32(ramin, 0xa0, 0x00190000); 51 nv_wo32(ramin, 0xa0, 0x00190000);
50 nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff); 52 nv_wo32(ramin, 0xa4, ctx->vinst + ctx->size - 1);
51 nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst); 53 nv_wo32(ramin, 0xa8, ctx->vinst);
52 nv_wo32(ramin, 0xac, 0); 54 nv_wo32(ramin, 0xac, 0);
53 nv_wo32(ramin, 0xb0, 0); 55 nv_wo32(ramin, 0xb0, 0);
54 nv_wo32(ramin, 0xb4, 0); 56 nv_wo32(ramin, 0xb4, 0);
55
56 dev_priv->engine.instmem.flush(dev); 57 dev_priv->engine.instmem.flush(dev);
57 atomic_inc(&chan->vm->pcrypt_refs); 58
59 atomic_inc(&chan->vm->engref[engine]);
60 chan->engctx[engine] = ctx;
58 return 0; 61 return 0;
59} 62}
60 63
61void 64static void
62nv84_crypt_destroy_context(struct nouveau_channel *chan) 65nv84_crypt_context_del(struct nouveau_channel *chan, int engine)
63{ 66{
67 struct nouveau_gpuobj *ctx = chan->engctx[engine];
64 struct drm_device *dev = chan->dev; 68 struct drm_device *dev = chan->dev;
65 u32 inst; 69 u32 inst;
66 70
67 if (!chan->crypt_ctx)
68 return;
69
70 inst = (chan->ramin->vinst >> 12); 71 inst = (chan->ramin->vinst >> 12);
71 inst |= 0x80000000; 72 inst |= 0x80000000;
72 73
@@ -81,12 +82,15 @@ nv84_crypt_destroy_context(struct nouveau_channel *chan)
81 nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); 82 nv_mask(dev, 0x10218c, 0x80000000, 0x00000000);
82 nv_wr32(dev, 0x10200c, 0x00000010); 83 nv_wr32(dev, 0x10200c, 0x00000010);
83 84
84 nouveau_gpuobj_ref(NULL, &chan->crypt_ctx); 85 nouveau_gpuobj_ref(NULL, &ctx);
85 atomic_dec(&chan->vm->pcrypt_refs); 86
87 atomic_dec(&chan->vm->engref[engine]);
88 chan->engctx[engine] = NULL;
86} 89}
87 90
88int 91static int
89nv84_crypt_object_new(struct nouveau_channel *chan, u32 handle, u16 class) 92nv84_crypt_object_new(struct nouveau_channel *chan, int engine,
93 u32 handle, u16 class)
90{ 94{
91 struct drm_device *dev = chan->dev; 95 struct drm_device *dev = chan->dev;
92 struct drm_nouveau_private *dev_priv = dev->dev_private; 96 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -107,27 +111,45 @@ nv84_crypt_object_new(struct nouveau_channel *chan, u32 handle, u16 class)
107 return ret; 111 return ret;
108} 112}
109 113
110void 114static void
111nv84_crypt_tlb_flush(struct drm_device *dev) 115nv84_crypt_tlb_flush(struct drm_device *dev, int engine)
112{ 116{
113 nv50_vm_flush_engine(dev, 0x0a); 117 nv50_vm_flush_engine(dev, 0x0a);
114} 118}
115 119
116int 120static void
117nv84_crypt_init(struct drm_device *dev) 121nv84_crypt_isr(struct drm_device *dev)
118{ 122{
119 struct drm_nouveau_private *dev_priv = dev->dev_private; 123 u32 stat = nv_rd32(dev, 0x102130);
120 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; 124 u32 mthd = nv_rd32(dev, 0x102190);
125 u32 data = nv_rd32(dev, 0x102194);
126 u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff;
127 int show = nouveau_ratelimit();
121 128
122 if (!pcrypt->registered) { 129 if (show) {
123 NVOBJ_CLASS(dev, 0x74c1, CRYPT); 130 NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n",
124 pcrypt->registered = true; 131 stat, mthd, data, inst);
125 } 132 }
126 133
134 nv_wr32(dev, 0x102130, stat);
135 nv_wr32(dev, 0x10200c, 0x10);
136
137 nv50_fb_vm_trap(dev, show);
138}
139
140static int
141nv84_crypt_fini(struct drm_device *dev, int engine)
142{
143 nv_wr32(dev, 0x102140, 0x00000000);
144 return 0;
145}
146
147static int
148nv84_crypt_init(struct drm_device *dev, int engine)
149{
127 nv_mask(dev, 0x000200, 0x00004000, 0x00000000); 150 nv_mask(dev, 0x000200, 0x00004000, 0x00000000);
128 nv_mask(dev, 0x000200, 0x00004000, 0x00004000); 151 nv_mask(dev, 0x000200, 0x00004000, 0x00004000);
129 152
130 nouveau_irq_register(dev, 14, nv84_crypt_isr);
131 nv_wr32(dev, 0x102130, 0xffffffff); 153 nv_wr32(dev, 0x102130, 0xffffffff);
132 nv_wr32(dev, 0x102140, 0xffffffbf); 154 nv_wr32(dev, 0x102140, 0xffffffbf);
133 155
@@ -135,29 +157,37 @@ nv84_crypt_init(struct drm_device *dev)
135 return 0; 157 return 0;
136} 158}
137 159
138void 160static void
139nv84_crypt_fini(struct drm_device *dev) 161nv84_crypt_destroy(struct drm_device *dev, int engine)
140{ 162{
141 nv_wr32(dev, 0x102140, 0x00000000); 163 struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine);
164
165 NVOBJ_ENGINE_DEL(dev, CRYPT);
166
142 nouveau_irq_unregister(dev, 14); 167 nouveau_irq_unregister(dev, 14);
168 kfree(pcrypt);
143} 169}
144 170
145static void 171int
146nv84_crypt_isr(struct drm_device *dev) 172nv84_crypt_create(struct drm_device *dev)
147{ 173{
148 u32 stat = nv_rd32(dev, 0x102130); 174 struct nv84_crypt_engine *pcrypt;
149 u32 mthd = nv_rd32(dev, 0x102190);
150 u32 data = nv_rd32(dev, 0x102194);
151 u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff;
152 int show = nouveau_ratelimit();
153 175
154 if (show) { 176 pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL);
155 NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n", 177 if (!pcrypt)
156 stat, mthd, data, inst); 178 return -ENOMEM;
157 }
158 179
159 nv_wr32(dev, 0x102130, stat); 180 pcrypt->base.destroy = nv84_crypt_destroy;
160 nv_wr32(dev, 0x10200c, 0x10); 181 pcrypt->base.init = nv84_crypt_init;
182 pcrypt->base.fini = nv84_crypt_fini;
183 pcrypt->base.context_new = nv84_crypt_context_new;
184 pcrypt->base.context_del = nv84_crypt_context_del;
185 pcrypt->base.object_new = nv84_crypt_object_new;
186 pcrypt->base.tlb_flush = nv84_crypt_tlb_flush;
161 187
162 nv50_fb_vm_trap(dev, show); 188 nouveau_irq_register(dev, 14, nv84_crypt_isr);
189
190 NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base);
191 NVOBJ_CLASS (dev, 0x74c1, CRYPT);
192 return 0;
163} 193}