Commit 5728d064 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fb: handle sysmem flush page from common code



- also executes pre-DEVINIT, so early boot is able to DMA sysmem

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 0e44c217
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@ struct nvkm_fb {

	struct nvkm_blob vpr_scrubber;

	struct {
		struct page *flush_page;
		dma_addr_t flush_page_addr;
	} sysmem;

	struct nvkm_ram *ram;

	struct {
+41 −3
Original line number Diff line number Diff line
@@ -57,6 +57,15 @@ nvkm_fb_tile_prog(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile)
	}
}

static void
nvkm_fb_sysmem_flush_page_init(struct nvkm_device *device)
{
	struct nvkm_fb *fb = device->fb;

	if (fb->func->sysmem.flush_page_init)
		fb->func->sysmem.flush_page_init(fb);
}

int
nvkm_fb_bios_memtype(struct nvkm_bios *bios)
{
@@ -168,6 +177,8 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
	for (i = 0; i < fb->tile.regions; i++)
		fb->func->tile.prog(fb, i, &fb->tile.region[i]);

	nvkm_fb_sysmem_flush_page_init(subdev->device);

	if (fb->func->init)
		fb->func->init(fb);

@@ -193,6 +204,13 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
	return 0;
}

static int
nvkm_fb_preinit(struct nvkm_subdev *subdev)
{
	nvkm_fb_sysmem_flush_page_init(subdev->device);
	return 0;
}

static void *
nvkm_fb_dtor(struct nvkm_subdev *subdev)
{
@@ -212,20 +230,28 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)

	nvkm_blob_dtor(&fb->vpr_scrubber);

	if (fb->sysmem.flush_page) {
		dma_unmap_page(subdev->device->dev, fb->sysmem.flush_page_addr,
			       PAGE_SIZE, DMA_BIDIRECTIONAL);
		__free_page(fb->sysmem.flush_page);
	}

	if (fb->func->dtor)
		return fb->func->dtor(fb);

	return fb;
}

static const struct nvkm_subdev_func
nvkm_fb = {
	.dtor = nvkm_fb_dtor,
	.preinit = nvkm_fb_preinit,
	.oneinit = nvkm_fb_oneinit,
	.init = nvkm_fb_init,
	.intr = nvkm_fb_intr,
};

void
int
nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
	     enum nvkm_subdev_type type, int inst, struct nvkm_fb *fb)
{
@@ -234,6 +260,19 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
	fb->tile.regions = fb->func->tile.regions;
	fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", fb->func->default_bigpage);
	mutex_init(&fb->tags.mutex);

	if (func->sysmem.flush_page_init) {
		fb->sysmem.flush_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
		if (!fb->sysmem.flush_page)
			return -ENOMEM;

		fb->sysmem.flush_page_addr = dma_map_page(device->dev, fb->sysmem.flush_page,
							  0, PAGE_SIZE, DMA_BIDIRECTIONAL);
		if (dma_mapping_error(device->dev, fb->sysmem.flush_page_addr))
			return -EFAULT;
	}

	return 0;
}

int
@@ -242,6 +281,5 @@ nvkm_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device,
{
	if (!(*pfb = kzalloc(sizeof(**pfb), GFP_KERNEL)))
		return -ENOMEM;
	nvkm_fb_ctor(func, device, type, inst, *pfb);
	return 0;
	return nvkm_fb_ctor(func, device, type, inst, *pfb);
}
+2 −1
Original line number Diff line number Diff line
@@ -26,9 +26,10 @@ static const struct nvkm_fb_func
ga100_fb = {
	.dtor = gf100_fb_dtor,
	.oneinit = gf100_fb_oneinit,
	.init = gp100_fb_init,
	.init = gm200_fb_init,
	.init_page = gv100_fb_init_page,
	.init_unkn = gp100_fb_init_unkn,
	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
	.ram_new = gp100_ram_new,
	.default_bigpage = 16,
};
+2 −1
Original line number Diff line number Diff line
@@ -26,9 +26,10 @@ static const struct nvkm_fb_func
ga102_fb = {
	.dtor = gf100_fb_dtor,
	.oneinit = gf100_fb_oneinit,
	.init = gp100_fb_init,
	.init = gm200_fb_init,
	.init_page = gv100_fb_init_page,
	.init_unkn = gp100_fb_init_unkn,
	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
	.ram_new = ga102_ram_new,
	.default_bigpage = 16,
};
+7 −18
Original line number Diff line number Diff line
@@ -61,14 +61,6 @@ gf100_fb_oneinit(struct nvkm_fb *base)
	if (ret)
		return ret;

	fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
	if (fb->r100c10_page) {
		fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
					   PAGE_SIZE, DMA_BIDIRECTIONAL);
		if (dma_mapping_error(device->dev, fb->r100c10))
			return -EFAULT;
	}

	return 0;
}

@@ -85,15 +77,18 @@ gf100_fb_init_page(struct nvkm_fb *fb)
	return 0;
}

void
gf100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
{
	nvkm_wr32(fb->subdev.device, 0x100c10, fb->sysmem.flush_page_addr >> 8);
}

void
gf100_fb_init(struct nvkm_fb *base)
{
	struct gf100_fb *fb = gf100_fb(base);
	struct nvkm_device *device = fb->base.subdev.device;

	if (fb->r100c10_page)
		nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);

	if (base->func->clkgate_pack) {
		nvkm_therm_clkgate_init(device->therm,
					base->func->clkgate_pack);
@@ -104,13 +99,6 @@ void *
gf100_fb_dtor(struct nvkm_fb *base)
{
	struct gf100_fb *fb = gf100_fb(base);
	struct nvkm_device *device = fb->base.subdev.device;

	if (fb->r100c10_page) {
		dma_unmap_page(device->dev, fb->r100c10, PAGE_SIZE,
			       DMA_BIDIRECTIONAL);
		__free_page(fb->r100c10_page);
	}

	return fb;
}
@@ -136,6 +124,7 @@ gf100_fb = {
	.init = gf100_fb_init,
	.init_page = gf100_fb_init_page,
	.intr = gf100_fb_intr,
	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
	.ram_new = gf100_ram_new,
	.default_bigpage = 17,
};
Loading