aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2009-12-15 23:28:55 -0500
committerBen Skeggs <bskeggs@redhat.com>2009-12-16 02:05:57 -0500
commit0735f62e116fae1e4f36237a97de28e8a56b4c2c (patch)
tree3c43ff86368448a041fecd5c8841de3e8230a003 /drivers/gpu
parent3c8868d3dbba5110bd43b49879f12d1a6b2a28ca (diff)
drm/nouveau: prevent all channel creation if accel not available
Previously, if there was no firmware available, the DRM would just disable channel creation from userspace, but still use a single channel for its own purposes. With a bit of care it should actually be possible to do this, due to the DRM's very limited use of the engine. It currently doesn't work correctly however, resulting in corrupted fbcon and hangs on a number of cards. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c20
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c84
3 files changed, 64 insertions, 48 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index e9f01906c52..2f5d4702110 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -461,11 +461,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait,
461 int ret; 461 int ret;
462 462
463 chan = nvbo->channel; 463 chan = nvbo->channel;
464 if (!chan || nvbo->tile_flags || nvbo->no_vm) { 464 if (!chan || nvbo->tile_flags || nvbo->no_vm)
465 chan = dev_priv->channel; 465 chan = dev_priv->channel;
466 if (!chan)
467 return -EINVAL;
468 }
469 466
470 src_offset = old_mem->mm_node->start << PAGE_SHIFT; 467 src_offset = old_mem->mm_node->start << PAGE_SHIFT;
471 dst_offset = new_mem->mm_node->start << PAGE_SHIFT; 468 dst_offset = new_mem->mm_node->start << PAGE_SHIFT;
@@ -631,7 +628,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
631 return ret; 628 return ret;
632 } 629 }
633 630
634 if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE) 631 if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
632 !dev_priv->channel)
635 return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); 633 return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
636 634
637 if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { 635 if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 489d4926811..84af25c238b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -58,7 +58,7 @@ nouveau_fbcon_sync(struct fb_info *info)
58 struct nouveau_channel *chan = dev_priv->channel; 58 struct nouveau_channel *chan = dev_priv->channel;
59 int ret, i; 59 int ret, i;
60 60
61 if (!chan->accel_done || 61 if (!chan || !chan->accel_done ||
62 info->state != FBINFO_STATE_RUNNING || 62 info->state != FBINFO_STATE_RUNNING ||
63 info->flags & FBINFO_HWACCEL_DISABLED) 63 info->flags & FBINFO_HWACCEL_DISABLED)
64 return 0; 64 return 0;
@@ -318,14 +318,16 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
318 par->nouveau_fb = nouveau_fb; 318 par->nouveau_fb = nouveau_fb;
319 par->dev = dev; 319 par->dev = dev;
320 320
321 switch (dev_priv->card_type) { 321 if (dev_priv->channel) {
322 case NV_50: 322 switch (dev_priv->card_type) {
323 nv50_fbcon_accel_init(info); 323 case NV_50:
324 break; 324 nv50_fbcon_accel_init(info);
325 default: 325 break;
326 nv04_fbcon_accel_init(info); 326 default:
327 break; 327 nv04_fbcon_accel_init(info);
328 }; 328 break;
329 };
330 }
329 331
330 nouveau_fbcon_zfill(dev); 332 nouveau_fbcon_zfill(dev);
331 333
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 9fc582432da..e76ec2d207a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state)
299 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 299 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
300} 300}
301 301
302static int
303nouveau_card_init_channel(struct drm_device *dev)
304{
305 struct drm_nouveau_private *dev_priv = dev->dev_private;
306 struct nouveau_gpuobj *gpuobj;
307 int ret;
308
309 ret = nouveau_channel_alloc(dev, &dev_priv->channel,
310 (struct drm_file *)-2,
311 NvDmaFB, NvDmaTT);
312 if (ret)
313 return ret;
314
315 gpuobj = NULL;
316 ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
317 0, nouveau_mem_fb_amount(dev),
318 NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
319 &gpuobj);
320 if (ret)
321 goto out_err;
322
323 ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
324 gpuobj, NULL);
325 if (ret)
326 goto out_err;
327
328 gpuobj = NULL;
329 ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
330 dev_priv->gart_info.aper_size,
331 NV_DMA_ACCESS_RW, &gpuobj, NULL);
332 if (ret)
333 goto out_err;
334
335 ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
336 gpuobj, NULL);
337 if (ret)
338 goto out_err;
339
340 return 0;
341out_err:
342 nouveau_gpuobj_del(dev, &gpuobj);
343 nouveau_channel_free(dev_priv->channel);
344 dev_priv->channel = NULL;
345 return ret;
346}
347
302int 348int
303nouveau_card_init(struct drm_device *dev) 349nouveau_card_init(struct drm_device *dev)
304{ 350{
305 struct drm_nouveau_private *dev_priv = dev->dev_private; 351 struct drm_nouveau_private *dev_priv = dev->dev_private;
306 struct nouveau_engine *engine; 352 struct nouveau_engine *engine;
307 struct nouveau_gpuobj *gpuobj;
308 int ret; 353 int ret;
309 354
310 NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); 355 NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
@@ -387,39 +432,10 @@ nouveau_card_init(struct drm_device *dev)
387 432
388 /* what about PVIDEO/PCRTC/PRAMDAC etc? */ 433 /* what about PVIDEO/PCRTC/PRAMDAC etc? */
389 434
390 ret = nouveau_channel_alloc(dev, &dev_priv->channel, 435 if (!engine->graph.accel_blocked) {
391 (struct drm_file *)-2, 436 ret = nouveau_card_init_channel(dev);
392 NvDmaFB, NvDmaTT); 437 if (ret)
393 if (ret) 438 goto out_irq;
394 goto out_irq;
395
396 gpuobj = NULL;
397 ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
398 0, nouveau_mem_fb_amount(dev),
399 NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
400 &gpuobj);
401 if (ret)
402 goto out_irq;
403
404 ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
405 gpuobj, NULL);
406 if (ret) {
407 nouveau_gpuobj_del(dev, &gpuobj);
408 goto out_irq;
409 }
410
411 gpuobj = NULL;
412 ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
413 dev_priv->gart_info.aper_size,
414 NV_DMA_ACCESS_RW, &gpuobj, NULL);
415 if (ret)
416 goto out_irq;
417
418 ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
419 gpuobj, NULL);
420 if (ret) {
421 nouveau_gpuobj_del(dev, &gpuobj);
422 goto out_irq;
423 } 439 }
424 440
425 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 441 if (drm_core_check_feature(dev, DRIVER_MODESET)) {