drm/nouveau/fb/gf100-: allow selection of an alternate big page size
authorBen Skeggs <bskeggs@redhat.com>
Sat, 9 Jul 2016 00:41:01 +0000 (10:41 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 14 Jul 2016 01:53:25 +0000 (11:53 +1000)
GFxxx/GM1xx support the selection of 64/128KiB big pages globally.

GM2xx supports the same, as well as another mode where the page size
can be selected per-instance.

We default to 128KiB pages (With per-instance for GM200, but the current
code selects 128KiB there already) as the MMU code isn't currently able
to handle otherwise.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h

index 0a734fd06acf347aeee52368ee159c62d99a4e75..c2c002d18f55972cff4eddc7ccf2981cc26348f0 100644 (file)
@@ -56,6 +56,8 @@ struct nvkm_fb {
                int regions;
        } tile;
 
+       u8 page;
+
        struct nvkm_memory *mmu_rd;
        struct nvkm_memory *mmu_wr;
 };
index ce90242b8cceeca8718b2daa7c1c6e8553d77db5..4742e5ee37ac501e1c434c00454b134d3112265f 100644 (file)
@@ -25,6 +25,7 @@
 #include "ram.h"
 
 #include <core/memory.h>
+#include <core/option.h>
 #include <subdev/bios.h>
 #include <subdev/bios/M0203.h>
 #include <engine/gr.h>
@@ -134,6 +135,8 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
 
        if (fb->func->init)
                fb->func->init(fb);
+       if (fb->func->init_page)
+               fb->func->init_page(fb);
        return 0;
 }
 
@@ -171,6 +174,7 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
        nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev);
        fb->func = func;
        fb->tile.regions = fb->func->tile.regions;
+       fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", 0);
 }
 
 int
index e649ead5ccfc74c7416e78f4294d7d1bcdbbf9b3..76433cc66fff2f1d96d1b4f81c5ab4a09b34e6e8 100644 (file)
@@ -71,6 +71,22 @@ gf100_fb_oneinit(struct nvkm_fb *fb)
        return 0;
 }
 
+void
+gf100_fb_init_page(struct nvkm_fb *fb)
+{
+       struct nvkm_device *device = fb->subdev.device;
+       switch (fb->page) {
+       case 16:
+               nvkm_mask(device, 0x100c80, 0x00000001, 0x00000001);
+               break;
+       case 17:
+       default:
+               nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000);
+               fb->page = 17;
+               break;
+       }
+}
+
 void
 gf100_fb_init(struct nvkm_fb *base)
 {
@@ -79,8 +95,6 @@ gf100_fb_init(struct nvkm_fb *base)
 
        if (fb->r100c10_page)
                nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);
-
-       nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
 }
 
 void *
@@ -125,6 +139,7 @@ gf100_fb = {
        .dtor = gf100_fb_dtor,
        .oneinit = gf100_fb_oneinit,
        .init = gf100_fb_init,
+       .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
        .ram_new = gf100_ram_new,
        .memtype_valid = gf100_fb_memtype_valid,
index b41f0f70038cb4c8a9d2d0ee464ed7a6fc768392..4245e2e6e604501fa9ead8ad0ed3582f9afee6cc 100644 (file)
@@ -29,6 +29,7 @@ gk104_fb = {
        .dtor = gf100_fb_dtor,
        .oneinit = gf100_fb_oneinit,
        .init = gf100_fb_init,
+       .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
        .ram_new = gk104_ram_new,
        .memtype_valid = gf100_fb_memtype_valid,
index 7306f7dfc3b93f4455942e9c2cb8387c51320669..f815fe2bbf08892dd52654552600c33843392f0b 100644 (file)
@@ -27,7 +27,6 @@ static void
 gk20a_fb_init(struct nvkm_fb *fb)
 {
        struct nvkm_device *device = fb->subdev.device;
-       nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
        nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->mmu_wr) >> 8);
        nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->mmu_rd) >> 8);
 }
@@ -36,6 +35,7 @@ static const struct nvkm_fb_func
 gk20a_fb = {
        .oneinit = gf100_fb_oneinit,
        .init = gk20a_fb_init,
+       .init_page = gf100_fb_init_page,
        .memtype_valid = gf100_fb_memtype_valid,
 };
 
index 4869fdb753c971f7cc35a880cd3bad06c3efa031..db699025f5464711c8b02972c32ea32ee5076a59 100644 (file)
@@ -29,6 +29,7 @@ gm107_fb = {
        .dtor = gf100_fb_dtor,
        .oneinit = gf100_fb_oneinit,
        .init = gf100_fb_init,
+       .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
        .ram_new = gm107_ram_new,
        .memtype_valid = gf100_fb_memtype_valid,
index 44f5716f64d88dfff577250b6a8be0b46350019c..6af3b724f07ba8d6d2b4aec2ec0b427b107a5470 100644 (file)
 
 #include <core/memory.h>
 
+static void
+gm200_fb_init_page(struct nvkm_fb *fb)
+{
+       struct nvkm_device *device = fb->subdev.device;
+       switch (fb->page) {
+       case 16:
+               nvkm_mask(device, 0x100c80, 0x00000801, 0x00000001);
+               break;
+       case 17:
+               nvkm_mask(device, 0x100c80, 0x00000801, 0x00000000);
+               break;
+       default:
+               nvkm_mask(device, 0x100c80, 0x00000800, 0x00000800);
+               fb->page = 0;
+               break;
+       }
+}
+
 static void
 gm200_fb_init(struct nvkm_fb *base)
 {
@@ -48,6 +66,7 @@ gm200_fb = {
        .dtor = gf100_fb_dtor,
        .oneinit = gf100_fb_oneinit,
        .init = gm200_fb_init,
+       .init_page = gm200_fb_init_page,
        .intr = gf100_fb_intr,
        .ram_new = gm107_ram_new,
        .memtype_valid = gf100_fb_memtype_valid,
index d97d640e60a0a32e5e92af83c116128ca8559dce..c93926c573103281a9ca79c8ed19e40897ff4ede 100644 (file)
@@ -8,6 +8,7 @@ struct nvkm_fb_func {
        void *(*dtor)(struct nvkm_fb *);
        int (*oneinit)(struct nvkm_fb *);
        void (*init)(struct nvkm_fb *);
+       void (*init_page)(struct nvkm_fb *);
        void (*intr)(struct nvkm_fb *);
 
        struct {
@@ -60,5 +61,6 @@ void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size,
                       u32 pitch, u32 flags, struct nvkm_fb_tile *);
 
 int gf100_fb_oneinit(struct nvkm_fb *);
+void gf100_fb_init_page(struct nvkm_fb *);
 bool gf100_fb_memtype_valid(struct nvkm_fb *, u32);
 #endif