/** * drm_gem_cma_create - allocate an object with the given size * @drm: DRM device * @size: size of the object to allocate * * This function creates a CMA GEM object and allocates a contiguous chunk of * memory as backing store. The backing memory has the writecombine attribute * set. * * Returns: * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative * error code on failure. */ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, size_t size) { struct drm_gem_cma_object *cma_obj; int ret; size = round_up(size, PAGE_SIZE); cma_obj = __drm_gem_cma_create(drm, size); if (IS_ERR(cma_obj)) return cma_obj; cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size, &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN); if (!cma_obj->vaddr) { dev_err(drm->dev, "failed to allocate buffer with size %zu\n", size); ret = -ENOMEM; goto error; } return cma_obj; error: drm->driver->gem_free_object(&cma_obj->base); return ERR_PTR(ret); }
/* * drm_gem_cma_create - allocate an object with the given size * * returns a struct drm_gem_cma_object* on success or ERR_PTR values * on failure. */ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, unsigned int size) { struct drm_gem_cma_object *cma_obj; struct sg_table *sgt = NULL; int ret; size = round_up(size, PAGE_SIZE); cma_obj = __drm_gem_cma_create(drm, size); if (IS_ERR(cma_obj)) return cma_obj; cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size, &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN); if (!cma_obj->vaddr) { dev_err(drm->dev, "failed to allocate buffer with size %d\n", size); ret = -ENOMEM; goto error; } sgt = kzalloc(sizeof(*cma_obj->sgt), GFP_KERNEL); if (sgt == NULL) { ret = -ENOMEM; goto error; } ret = dma_get_sgtable(drm->dev, sgt, cma_obj->vaddr, cma_obj->paddr, size); if (ret < 0) goto error; cma_obj->sgt = sgt; return cma_obj; error: kfree(sgt); drm_gem_cma_free_object(&cma_obj->base); return ERR_PTR(ret); }
struct drm_gem_object * drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size, struct sg_table *sgt) { struct drm_gem_cma_object *cma_obj; if (sgt->nents != 1) return ERR_PTR(-EINVAL); /* Create a CMA GEM buffer. */ cma_obj = __drm_gem_cma_create(dev, size); if (IS_ERR(cma_obj)) return ERR_PTR(PTR_ERR(cma_obj)); cma_obj->paddr = sg_dma_address(sgt->sgl); cma_obj->sgt = sgt; DRM_DEBUG_PRIME("dma_addr = 0x%x, size = %zu\n", cma_obj->paddr, size); return &cma_obj->base; }
/** * drm_gem_cma_prime_import_sg_table - produce a CMA GEM object from another * driver's scatter/gather table of pinned pages * @dev: device to import into * @attach: DMA-BUF attachment * @sgt: scatter/gather table of pinned pages * * This function imports a scatter/gather table exported via DMA-BUF by * another driver. Imported buffers must be physically contiguous in memory * (i.e. the scatter/gather table must contain a single entry). Drivers that * use the CMA helpers should set this as their DRM driver's * ->gem_prime_import_sg_table() callback. * * Returns: * A pointer to a newly created GEM object or an ERR_PTR-encoded negative * error code on failure. */ struct drm_gem_object * drm_gem_cma_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt) { struct drm_gem_cma_object *cma_obj; if (sgt->nents != 1) return ERR_PTR(-EINVAL); /* Create a CMA GEM buffer. */ cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size); if (IS_ERR(cma_obj)) return ERR_CAST(cma_obj); cma_obj->paddr = sg_dma_address(sgt->sgl); cma_obj->sgt = sgt; DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, attach->dmabuf->size); return &cma_obj->base; }