Home | History | Annotate | Line # | Download | only in nouveau
      1  1.2  riastrad /*	$NetBSD: nouveau_sgdma.c,v 1.3 2021/12/18 23:45:32 riastradh Exp $	*/
      2  1.2  riastrad 
      3  1.3  riastrad // SPDX-License-Identifier: MIT
      4  1.2  riastrad #include <sys/cdefs.h>
      5  1.2  riastrad __KERNEL_RCSID(0, "$NetBSD: nouveau_sgdma.c,v 1.3 2021/12/18 23:45:32 riastradh Exp $");
      6  1.2  riastrad 
      7  1.1  riastrad #include <linux/pagemap.h>
      8  1.1  riastrad #include <linux/slab.h>
      9  1.1  riastrad 
     10  1.3  riastrad #include "nouveau_drv.h"
     11  1.3  riastrad #include "nouveau_mem.h"
     12  1.1  riastrad #include "nouveau_ttm.h"
     13  1.1  riastrad 
     14  1.1  riastrad struct nouveau_sgdma_be {
     15  1.1  riastrad 	/* this has to be the first field so populate/unpopulated in
     16  1.1  riastrad 	 * nouve_bo.c works properly, otherwise have to move them here
     17  1.1  riastrad 	 */
     18  1.1  riastrad 	struct ttm_dma_tt ttm;
     19  1.3  riastrad 	struct nouveau_mem *mem;
     20  1.1  riastrad };
     21  1.1  riastrad 
     22  1.1  riastrad static void
     23  1.1  riastrad nouveau_sgdma_destroy(struct ttm_tt *ttm)
     24  1.1  riastrad {
     25  1.1  riastrad 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
     26  1.1  riastrad 
     27  1.1  riastrad 	if (ttm) {
     28  1.1  riastrad 		ttm_dma_tt_fini(&nvbe->ttm);
     29  1.1  riastrad 		kfree(nvbe);
     30  1.1  riastrad 	}
     31  1.1  riastrad }
     32  1.1  riastrad 
     33  1.1  riastrad static int
     34  1.3  riastrad nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg)
     35  1.1  riastrad {
     36  1.1  riastrad 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
     37  1.3  riastrad 	struct nouveau_mem *mem = nouveau_mem(reg);
     38  1.3  riastrad 	int ret;
     39  1.1  riastrad 
     40  1.3  riastrad 	ret = nouveau_mem_host(reg, &nvbe->ttm);
     41  1.3  riastrad 	if (ret)
     42  1.3  riastrad 		return ret;
     43  1.3  riastrad 
     44  1.3  riastrad 	ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]);
     45  1.3  riastrad 	if (ret) {
     46  1.3  riastrad 		nouveau_mem_fini(mem);
     47  1.3  riastrad 		return ret;
     48  1.1  riastrad 	}
     49  1.1  riastrad 
     50  1.3  riastrad 	nvbe->mem = mem;
     51  1.1  riastrad 	return 0;
     52  1.1  riastrad }
     53  1.1  riastrad 
     54  1.1  riastrad static int
     55  1.1  riastrad nv04_sgdma_unbind(struct ttm_tt *ttm)
     56  1.1  riastrad {
     57  1.1  riastrad 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
     58  1.3  riastrad 	nouveau_mem_fini(nvbe->mem);
     59  1.1  riastrad 	return 0;
     60  1.1  riastrad }
     61  1.1  riastrad 
     62  1.1  riastrad static struct ttm_backend_func nv04_sgdma_backend = {
     63  1.1  riastrad 	.bind			= nv04_sgdma_bind,
     64  1.1  riastrad 	.unbind			= nv04_sgdma_unbind,
     65  1.1  riastrad 	.destroy		= nouveau_sgdma_destroy
     66  1.1  riastrad };
     67  1.1  riastrad 
     68  1.1  riastrad static int
     69  1.3  riastrad nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg)
     70  1.1  riastrad {
     71  1.1  riastrad 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
     72  1.3  riastrad 	struct nouveau_mem *mem = nouveau_mem(reg);
     73  1.3  riastrad 	int ret;
     74  1.1  riastrad 
     75  1.3  riastrad 	ret = nouveau_mem_host(reg, &nvbe->ttm);
     76  1.3  riastrad 	if (ret)
     77  1.3  riastrad 		return ret;
     78  1.1  riastrad 
     79  1.3  riastrad 	nvbe->mem = mem;
     80  1.1  riastrad 	return 0;
     81  1.1  riastrad }
     82  1.1  riastrad 
     83  1.1  riastrad static struct ttm_backend_func nv50_sgdma_backend = {
     84  1.1  riastrad 	.bind			= nv50_sgdma_bind,
     85  1.3  riastrad 	.unbind			= nv04_sgdma_unbind,
     86  1.1  riastrad 	.destroy		= nouveau_sgdma_destroy
     87  1.1  riastrad };
     88  1.1  riastrad 
     89  1.1  riastrad struct ttm_tt *
     90  1.3  riastrad nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags)
     91  1.1  riastrad {
     92  1.3  riastrad 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
     93  1.1  riastrad 	struct nouveau_sgdma_be *nvbe;
     94  1.1  riastrad 
     95  1.1  riastrad 	nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
     96  1.1  riastrad 	if (!nvbe)
     97  1.1  riastrad 		return NULL;
     98  1.1  riastrad 
     99  1.3  riastrad 	if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA)
    100  1.1  riastrad 		nvbe->ttm.ttm.func = &nv04_sgdma_backend;
    101  1.1  riastrad 	else
    102  1.1  riastrad 		nvbe->ttm.ttm.func = &nv50_sgdma_backend;
    103  1.1  riastrad 
    104  1.3  riastrad 	if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags))
    105  1.2  riastrad 		/*
    106  1.2  riastrad 		 * A failing ttm_dma_tt_init() will call ttm_tt_destroy()
    107  1.2  riastrad 		 * and thus our nouveau_sgdma_destroy() hook, so we don't need
    108  1.2  riastrad 		 * to free nvbe here.
    109  1.2  riastrad 		 */
    110  1.1  riastrad 		return NULL;
    111  1.1  riastrad 	return &nvbe->ttm.ttm;
    112  1.1  riastrad }
    113