Commit 0735f62e authored by Ben Skeggs's avatar Ben Skeggs

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 3c8868d3
...@@ -461,11 +461,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait, ...@@ -461,11 +461,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait,
int ret; int ret;
chan = nvbo->channel; chan = nvbo->channel;
if (!chan || nvbo->tile_flags || nvbo->no_vm) { if (!chan || nvbo->tile_flags || nvbo->no_vm)
chan = dev_priv->channel; chan = dev_priv->channel;
if (!chan)
return -EINVAL;
}
src_offset = old_mem->mm_node->start << PAGE_SHIFT; src_offset = old_mem->mm_node->start << PAGE_SHIFT;
dst_offset = new_mem->mm_node->start << PAGE_SHIFT; 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,7 +628,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
return ret; return ret;
} }
if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE) if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
!dev_priv->channel)
return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
......
...@@ -58,7 +58,7 @@ nouveau_fbcon_sync(struct fb_info *info) ...@@ -58,7 +58,7 @@ nouveau_fbcon_sync(struct fb_info *info)
struct nouveau_channel *chan = dev_priv->channel; struct nouveau_channel *chan = dev_priv->channel;
int ret, i; int ret, i;
if (!chan->accel_done || if (!chan || !chan->accel_done ||
info->state != FBINFO_STATE_RUNNING || info->state != FBINFO_STATE_RUNNING ||
info->flags & FBINFO_HWACCEL_DISABLED) info->flags & FBINFO_HWACCEL_DISABLED)
return 0; return 0;
...@@ -318,6 +318,7 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, ...@@ -318,6 +318,7 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
par->nouveau_fb = nouveau_fb; par->nouveau_fb = nouveau_fb;
par->dev = dev; par->dev = dev;
if (dev_priv->channel) {
switch (dev_priv->card_type) { switch (dev_priv->card_type) {
case NV_50: case NV_50:
nv50_fbcon_accel_init(info); nv50_fbcon_accel_init(info);
...@@ -326,6 +327,7 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, ...@@ -326,6 +327,7 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
nv04_fbcon_accel_init(info); nv04_fbcon_accel_init(info);
break; break;
}; };
}
nouveau_fbcon_zfill(dev); nouveau_fbcon_zfill(dev);
......
...@@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state) ...@@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state)
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
} }
static int
nouveau_card_init_channel(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *gpuobj;
int ret;
ret = nouveau_channel_alloc(dev, &dev_priv->channel,
(struct drm_file *)-2,
NvDmaFB, NvDmaTT);
if (ret)
return ret;
gpuobj = NULL;
ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
0, nouveau_mem_fb_amount(dev),
NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
&gpuobj);
if (ret)
goto out_err;
ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
gpuobj, NULL);
if (ret)
goto out_err;
gpuobj = NULL;
ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
dev_priv->gart_info.aper_size,
NV_DMA_ACCESS_RW, &gpuobj, NULL);
if (ret)
goto out_err;
ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
gpuobj, NULL);
if (ret)
goto out_err;
return 0;
out_err:
nouveau_gpuobj_del(dev, &gpuobj);
nouveau_channel_free(dev_priv->channel);
dev_priv->channel = NULL;
return ret;
}
int int
nouveau_card_init(struct drm_device *dev) nouveau_card_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_engine *engine; struct nouveau_engine *engine;
struct nouveau_gpuobj *gpuobj;
int ret; int ret;
NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
...@@ -387,39 +432,10 @@ nouveau_card_init(struct drm_device *dev) ...@@ -387,39 +432,10 @@ nouveau_card_init(struct drm_device *dev)
/* what about PVIDEO/PCRTC/PRAMDAC etc? */ /* what about PVIDEO/PCRTC/PRAMDAC etc? */
ret = nouveau_channel_alloc(dev, &dev_priv->channel, if (!engine->graph.accel_blocked) {
(struct drm_file *)-2, ret = nouveau_card_init_channel(dev);
NvDmaFB, NvDmaTT);
if (ret)
goto out_irq;
gpuobj = NULL;
ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
0, nouveau_mem_fb_amount(dev),
NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
&gpuobj);
if (ret)
goto out_irq;
ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
gpuobj, NULL);
if (ret) {
nouveau_gpuobj_del(dev, &gpuobj);
goto out_irq;
}
gpuobj = NULL;
ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
dev_priv->gart_info.aper_size,
NV_DMA_ACCESS_RW, &gpuobj, NULL);
if (ret) if (ret)
goto out_irq; goto out_irq;
ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
gpuobj, NULL);
if (ret) {
nouveau_gpuobj_del(dev, &gpuobj);
goto out_irq;
} }
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment