aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 4cea35c57d15..3a047ec1ead3 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 155ebdcbf06f..30b9e89a3a2a 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 31e34ae16dae..6b43cb02dce0 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 f7b806f26f2f..4fb05b6c6985 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 fa81b9017b35..a1a25ea7cc7e 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 2e06b55cfdc1..16ffc4cceebf 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 6c2694490741..1f58b0d62796 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 4918f4e60bab..75b809a51748 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}