diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_object.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 81 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_vm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_vm.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_crypt.c | 122 |
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 | ||
297 | struct 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 | |||
301 | struct nouveau_instmem_engine { | 308 | struct 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 | ||
504 | struct 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 | |||
515 | struct nouveau_vram_engine { | 511 | struct 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, | |||
881 | extern void nouveau_channel_idle(struct nouveau_channel *chan); | 877 | extern 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 *); | |||
1209 | extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16); | 1215 | extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16); |
1210 | 1216 | ||
1211 | /* nv84_crypt.c */ | 1217 | /* nv84_crypt.c */ |
1212 | extern int nv84_crypt_init(struct drm_device *dev); | 1218 | extern int nv84_crypt_create(struct drm_device *); |
1213 | extern void nv84_crypt_fini(struct drm_device *dev); | ||
1214 | extern int nv84_crypt_create_context(struct nouveau_channel *); | ||
1215 | extern void nv84_crypt_destroy_context(struct nouveau_channel *); | ||
1216 | extern void nv84_crypt_tlb_flush(struct drm_device *dev); | ||
1217 | extern int nv84_crypt_object_new(struct nouveau_channel *, u32, u16); | ||
1218 | 1219 | ||
1219 | /* nv04_instmem.c */ | 1220 | /* nv04_instmem.c */ |
1220 | extern int nv04_instmem_init(struct drm_device *); | 1221 | extern 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 | ||
1586 | static inline void * | ||
1587 | nv_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 | ||
665 | static int | 662 | static 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: | |||
723 | out_fifo: | 706 | out_fifo: |
724 | if (!nouveau_noaccel) | 707 | if (!nouveau_noaccel) |
725 | engine->fifo.takedown(dev); | 708 | engine->fifo.takedown(dev); |
726 | out_crypt: | ||
727 | if (!nouveau_noaccel) | ||
728 | engine->crypt.takedown(dev); | ||
729 | out_graph: | 709 | out_graph: |
730 | if (!nouveau_noaccel) | 710 | if (!nouveau_noaccel) |
731 | engine->graph.takedown(dev); | 711 | engine->graph.takedown(dev); |
732 | out_fb: | 712 | out_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); |
734 | out_timer: | 721 | out_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 | ||
173 | void | 175 | void |
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 | ||
31 | static void nv84_crypt_isr(struct drm_device *); | 31 | struct nv84_crypt_engine { |
32 | struct nouveau_exec_engine base; | ||
33 | }; | ||
32 | 34 | ||
33 | int | 35 | static int |
34 | nv84_crypt_create_context(struct nouveau_channel *chan) | 36 | nv84_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 | ||
61 | void | 64 | static void |
62 | nv84_crypt_destroy_context(struct nouveau_channel *chan) | 65 | nv84_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 | ||
88 | int | 91 | static int |
89 | nv84_crypt_object_new(struct nouveau_channel *chan, u32 handle, u16 class) | 92 | nv84_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 | ||
110 | void | 114 | static void |
111 | nv84_crypt_tlb_flush(struct drm_device *dev) | 115 | nv84_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 | ||
116 | int | 120 | static void |
117 | nv84_crypt_init(struct drm_device *dev) | 121 | nv84_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 | |||
140 | static int | ||
141 | nv84_crypt_fini(struct drm_device *dev, int engine) | ||
142 | { | ||
143 | nv_wr32(dev, 0x102140, 0x00000000); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int | ||
148 | nv84_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 | ||
138 | void | 160 | static void |
139 | nv84_crypt_fini(struct drm_device *dev) | 161 | nv84_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 | ||
145 | static void | 171 | int |
146 | nv84_crypt_isr(struct drm_device *dev) | 172 | nv84_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 | } |