mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
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>
This commit is contained in:
parent
3c8868d3db
commit
0735f62e11
3 changed files with 64 additions and 48 deletions
|
@ -461,11 +461,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait,
|
|||
int ret;
|
||||
|
||||
chan = nvbo->channel;
|
||||
if (!chan || nvbo->tile_flags || nvbo->no_vm) {
|
||||
if (!chan || nvbo->tile_flags || nvbo->no_vm)
|
||||
chan = dev_priv->channel;
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
src_offset = old_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,
|
|||
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);
|
||||
|
||||
if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
|
||||
|
|
|
@ -58,7 +58,7 @@ nouveau_fbcon_sync(struct fb_info *info)
|
|||
struct nouveau_channel *chan = dev_priv->channel;
|
||||
int ret, i;
|
||||
|
||||
if (!chan->accel_done ||
|
||||
if (!chan || !chan->accel_done ||
|
||||
info->state != FBINFO_STATE_RUNNING ||
|
||||
info->flags & FBINFO_HWACCEL_DISABLED)
|
||||
return 0;
|
||||
|
@ -318,14 +318,16 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
|
|||
par->nouveau_fb = nouveau_fb;
|
||||
par->dev = dev;
|
||||
|
||||
switch (dev_priv->card_type) {
|
||||
case NV_50:
|
||||
nv50_fbcon_accel_init(info);
|
||||
break;
|
||||
default:
|
||||
nv04_fbcon_accel_init(info);
|
||||
break;
|
||||
};
|
||||
if (dev_priv->channel) {
|
||||
switch (dev_priv->card_type) {
|
||||
case NV_50:
|
||||
nv50_fbcon_accel_init(info);
|
||||
break;
|
||||
default:
|
||||
nv04_fbcon_accel_init(info);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
nouveau_fbcon_zfill(dev);
|
||||
|
||||
|
|
|
@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state)
|
|||
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
|
||||
nouveau_card_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine *engine;
|
||||
struct nouveau_gpuobj *gpuobj;
|
||||
int ret;
|
||||
|
||||
NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
|
||||
|
@ -387,39 +432,10 @@ nouveau_card_init(struct drm_device *dev)
|
|||
|
||||
/* what about PVIDEO/PCRTC/PRAMDAC etc? */
|
||||
|
||||
ret = nouveau_channel_alloc(dev, &dev_priv->channel,
|
||||
(struct drm_file *)-2,
|
||||
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)
|
||||
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 (!engine->graph.accel_blocked) {
|
||||
ret = nouveau_card_init_channel(dev);
|
||||
if (ret)
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
|
|
Loading…
Reference in a new issue