OSDN Git Service

make RAM device optional
authorAlexandre Courbot <acourbot@nvidia.com>
Fri, 20 Feb 2015 09:22:59 +0000 (18:22 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 14 Apr 2015 07:00:42 +0000 (17:00 +1000)
Having a RAM device does not make sense for chips like GK20A which have
no dedicated video memory. The dummy RAM device that we used so far
works as a temporary band-aid, but in the longer term it is desirable
for the driver to be able to work without any kind of VRAM.

This patch adds a few conditionals in places where a RAM device was
assumed to be present and allows some more objects to be allocated from
the TT domain, allowing Nouveau to handle GPUs for which
pfb->ram == NULL.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/nouveau/nv84_fence.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c

index 860b0e2..8670d90 100644 (file)
@@ -869,13 +869,20 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
                            struct drm_mode_create_dumb *args)
 {
        struct nouveau_bo *bo;
+       uint32_t domain;
        int ret;
 
        args->pitch = roundup(args->width * (args->bpp / 8), 256);
        args->size = args->pitch * args->height;
        args->size = roundup(args->size, PAGE_SIZE);
 
-       ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);
+       /* Use VRAM if there is any ; otherwise fallback to system memory */
+       if (nouveau_drm(dev)->device.info.ram_size != 0)
+               domain = NOUVEAU_GEM_DOMAIN_VRAM;
+       else
+               domain = NOUVEAU_GEM_DOMAIN_GART;
+
+       ret = nouveau_gem_new(dev, args->size, 0, domain, 0, 0, &bo);
        if (ret)
                return ret;
 
index 273e501..18f4497 100644 (file)
@@ -82,6 +82,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
        u32 size_nc = 0;
        int ret;
 
+       if (drm->device.info.ram_size == 0)
+               return -ENOMEM;
+
        if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
                size_nc = 1 << nvbo->page_shift;
 
index bf429ca..a03db43 100644 (file)
@@ -215,6 +215,7 @@ nv84_fence_create(struct nouveau_drm *drm)
 {
        struct nvkm_fifo *pfifo = nvxx_fifo(&drm->device);
        struct nv84_fence_priv *priv;
+       u32 domain;
        int ret;
 
        priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -231,10 +232,17 @@ nv84_fence_create(struct nouveau_drm *drm)
        priv->base.context_base = fence_context_alloc(priv->base.contexts);
        priv->base.uevent = true;
 
-       ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
-                            TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo);
+       /* Use VRAM if there is any ; otherwise fallback to system memory */
+       domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
+                        /*
+                         * fences created in sysmem must be non-cached or we
+                         * will lose CPU/GPU coherency!
+                         */
+                        TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED;
+       ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, domain, 0,
+                            0, NULL, NULL, &priv->bo);
        if (ret == 0) {
-               ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false);
+               ret = nouveau_bo_pin(priv->bo, domain, false);
                if (ret == 0) {
                        ret = nouveau_bo_map(priv->bo);
                        if (ret)
index 6efa8f3..63d8e52 100644 (file)
@@ -139,9 +139,13 @@ nvkm_devobj_info(struct nvkm_object *object, void *data, u32 size)
 
        args->v0.chipset  = device->chipset;
        args->v0.revision = device->chiprev;
-       if (pfb)  args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
-       else      args->v0.ram_size = args->v0.ram_user = 0;
-       if (imem) args->v0.ram_user = args->v0.ram_user - imem->reserved;
+       if (pfb && pfb->ram)
+               args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
+       else
+               args->v0.ram_size = args->v0.ram_user = 0;
+       if (imem && args->v0.ram_size > 0)
+               args->v0.ram_user = args->v0.ram_user - imem->reserved;
+
        return 0;
 }
 
index b24a9cc..39a83d8 100644 (file)
@@ -184,7 +184,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
        nv_debug(clk, "setting performance state %d\n", pstatei);
        clk->pstate = pstatei;
 
-       if (pfb->ram->calc) {
+       if (pfb->ram && pfb->ram->calc) {
                int khz = pstate->base.domain[nv_clk_src_mem];
                do {
                        ret = pfb->ram->calc(pfb, khz);
index 16589fa..61fde43 100644 (file)
@@ -55,9 +55,11 @@ _nvkm_fb_fini(struct nvkm_object *object, bool suspend)
        struct nvkm_fb *pfb = (void *)object;
        int ret;
 
-       ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend);
-       if (ret && suspend)
-               return ret;
+       if (pfb->ram) {
+               ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend);
+               if (ret && suspend)
+                       return ret;
+       }
 
        return nvkm_subdev_fini(&pfb->base, suspend);
 }
@@ -72,9 +74,11 @@ _nvkm_fb_init(struct nvkm_object *object)
        if (ret)
                return ret;
 
-       ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram));
-       if (ret)
-               return ret;
+       if (pfb->ram) {
+               ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram));
+               if (ret)
+                       return ret;
+       }
 
        for (i = 0; i < pfb->tile.regions; i++)
                pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
@@ -91,9 +95,12 @@ _nvkm_fb_dtor(struct nvkm_object *object)
        for (i = 0; i < pfb->tile.regions; i++)
                pfb->tile.fini(pfb, i, &pfb->tile.region[i]);
        nvkm_mm_fini(&pfb->tags);
-       nvkm_mm_fini(&pfb->vram);
 
-       nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram);
+       if (pfb->ram) {
+               nvkm_mm_fini(&pfb->vram);
+               nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram);
+       }
+
        nvkm_subdev_destroy(&pfb->base);
 }
 
@@ -127,6 +134,9 @@ nvkm_fb_create_(struct nvkm_object *parent, struct nvkm_object *engine,
 
        pfb->memtype_valid = impl->memtype;
 
+       if (!impl->ram)
+               return 0;
+
        ret = nvkm_object_ctor(nv_object(pfb), NULL, impl->ram, NULL, 0, &ram);
        if (ret) {
                nv_fatal(pfb, "error detecting memory configuration!!\n");
index 8e7cc62..7fb5ea0 100644 (file)
@@ -136,7 +136,8 @@ gf100_ltc_dtor(struct nvkm_object *object)
        struct nvkm_ltc_priv *priv = (void *)object;
 
        nvkm_mm_fini(&priv->tags);
-       nvkm_mm_free(&pfb->vram, &priv->tag_ram);
+       if (pfb->ram)
+               nvkm_mm_free(&pfb->vram, &priv->tag_ram);
 
        nvkm_ltc_destroy(priv);
 }
@@ -149,6 +150,12 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv)
        u32 tag_size, tag_margin, tag_align;
        int ret;
 
+       /* No VRAM, no tags for now. */
+       if (!pfb->ram) {
+               priv->num_tags = 0;
+               goto mm_init;
+       }
+
        /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
        priv->num_tags = (pfb->ram->size >> 17) / 4;
        if (priv->num_tags > (1 << 17))
@@ -183,6 +190,7 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv)
                priv->tag_base = tag_base;
        }
 
+mm_init:
        ret = nvkm_mm_init(&priv->tags, 0, priv->num_tags, 1);
        return ret;
 }