/* the dumb interface doesn't work with the GEM straight MMAP interface, it expects to do MMAP on the drm fd, like normal */ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset) { struct udl_gem_object *gobj; struct drm_gem_object *obj; int ret = 0; mutex_lock(&dev->struct_mutex); obj = drm_gem_object_lookup(file, handle); if (obj == NULL) { ret = -ENOENT; goto unlock; } gobj = to_udl_bo(obj); ret = udl_gem_get_pages(gobj); if (ret) goto out; ret = drm_gem_create_mmap_offset(obj); if (ret) goto out; *offset = drm_vma_node_offset_addr(&gobj->base.vma_node); out: drm_gem_object_unreference(&gobj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; }
/* the dumb interface doesn't work with the GEM straight MMAP interface, it expects to do MMAP on the drm fd, like normal */ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset) { struct udl_gem_object *gobj; struct drm_gem_object *obj; int ret = 0; mutex_lock(&dev->struct_mutex); obj = drm_gem_object_lookup(dev, file, handle); if (obj == NULL) { ret = -ENOENT; goto unlock; } gobj = to_udl_bo(obj); ret = udl_gem_get_pages(gobj, GFP_KERNEL); if (ret) goto out; if (!gobj->base.map_list.map) { ret = drm_gem_create_mmap_offset(obj); if (ret) goto out; } *offset = (u64)gobj->base.map_list.hash.key << PAGE_SHIFT; out: drm_gem_object_unreference(&gobj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; }
int udl_gem_vmap(struct udl_gem_object *obj) { int page_count = obj->base.size / PAGE_SIZE; int ret; if (obj->base.import_attach) { ret = dma_buf_begin_cpu_access(obj->base.import_attach->dmabuf, 0, obj->base.size, DMA_BIDIRECTIONAL); if (ret) return -EINVAL; obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf); if (!obj->vmapping) return -ENOMEM; return 0; } ret = udl_gem_get_pages(obj, GFP_KERNEL); if (ret) return ret; obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL); if (!obj->vmapping) return -ENOMEM; return 0; }
int udl_gem_vmap(struct udl_gem_object *obj) { int page_count = obj->base.size / PAGE_SIZE; int ret; ret = udl_gem_get_pages(obj, GFP_KERNEL); if (ret) return ret; obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL); if (!obj->vmapping) return -ENOMEM; return 0; }
int udl_gem_vmap(struct udl_gem_object *obj) { int page_count = obj->base.size / PAGE_SIZE; int ret; if (obj->base.import_attach) { obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf); if (!obj->vmapping) return -ENOMEM; return 0; } ret = udl_gem_get_pages(obj); if (ret) return ret; obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL); if (!obj->vmapping) return -ENOMEM; return 0; }
static struct sg_table *udl_map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction dir) { struct udl_drm_dmabuf_attachment *udl_attach = attach->priv; struct udl_gem_object *obj = to_udl_bo(attach->dmabuf->priv); struct drm_device *dev = obj->base.dev; struct scatterlist *rd, *wr; struct sg_table *sgt = NULL; unsigned int i; int page_count; int nents, ret; DRM_DEBUG_PRIME("[DEV:%s] size:%zd dir=%d\n", dev_name(attach->dev), attach->dmabuf->size, dir); /* just return current sgt if already requested. */ if (udl_attach->dir == dir && udl_attach->is_mapped) return &udl_attach->sgt; if (!obj->pages) { ret = udl_gem_get_pages(obj); if (ret) { DRM_ERROR("failed to map pages.\n"); return ERR_PTR(ret); } } page_count = obj->base.size / PAGE_SIZE; obj->sg = drm_prime_pages_to_sg(obj->pages, page_count); if (IS_ERR(obj->sg)) { DRM_ERROR("failed to allocate sgt.\n"); return ERR_CAST(obj->sg); } sgt = &udl_attach->sgt; ret = sg_alloc_table(sgt, obj->sg->orig_nents, GFP_KERNEL); if (ret) { DRM_ERROR("failed to alloc sgt.\n"); return ERR_PTR(-ENOMEM); } mutex_lock(&dev->struct_mutex); rd = obj->sg->sgl; wr = sgt->sgl; for (i = 0; i < sgt->orig_nents; ++i) { sg_set_page(wr, sg_page(rd), rd->length, rd->offset); rd = sg_next(rd); wr = sg_next(wr); } if (dir != DMA_NONE) { nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); if (!nents) { DRM_ERROR("failed to map sgl with iommu.\n"); sg_free_table(sgt); sgt = ERR_PTR(-EIO); goto err_unlock; } } udl_attach->is_mapped = true; udl_attach->dir = dir; attach->priv = udl_attach; err_unlock: mutex_unlock(&dev->struct_mutex); return sgt; }