Пример #1
0
drm_private int drm_tegra_bo_free(struct drm_tegra_bo *bo)
{
	struct drm_tegra *drm = bo->drm;
	struct drm_gem_close args;
	void *map_cached;
	int err;

	DBG_BO(bo, "\n");

#ifndef NDEBUG
	if (drm->debug_bo) {
		drm->debug_bos_allocated--;
		drm->debug_bos_total_size -= bo->debug_size;
	}
#endif
	drm_tegra_bo_unmap_guards(bo);

	if (bo->map) {
		if (RUNNING_ON_VALGRIND)
			VG_BO_UNMMAP(bo);
		else
			munmap(bo->map, bo->offset + bo->size);

	} else if (bo->map_cached) {
		map_cached = drm_tegra_bo_cache_map(bo);

		if (!RUNNING_ON_VALGRIND)
			munmap(map_cached, bo->offset + bo->size);
	} else {
		goto vg_free;
	}

#ifndef NDEBUG
	if (drm->debug_bo) {
		drm->debug_bos_mapped--;
		drm->debug_bos_total_pages -= bo->debug_size / 4096;
	}
#endif
vg_free:
	VG_BO_FREE(bo);

	if (bo->name)
		drmHashDelete(drm->name_table, bo->name);

	drmHashDelete(drm->handle_table, bo->handle);

	memset(&args, 0, sizeof(args));
	args.handle = bo->handle;

	err = drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args);
	if (err < 0)
		err = -errno;

	free(bo);

	DBG_BO_STATS(drm);

	return err;
}
Пример #2
0
/* Called under table_lock */
drm_private void bo_del(struct fd_bo *bo)
{
	VG_BO_FREE(bo);

	if (bo->map)
		drm_munmap(bo->map, bo->size);

	/* TODO probably bo's in bucket list get removed from
	 * handle table??
	 */

	if (bo->handle) {
		struct drm_gem_close req = {
				.handle = bo->handle,
		};
		drmHashDelete(bo->dev->handle_table, bo->handle);
		if (bo->name)
			drmHashDelete(bo->dev->name_table, bo->name);
		drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
	}

	bo->funcs->destroy(bo);
}

int fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
{
	if (!bo->name) {
		struct drm_gem_flink req = {
				.handle = bo->handle,
		};
		int ret;

		ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
		if (ret) {
			return ret;
		}

		pthread_mutex_lock(&table_lock);
		set_name(bo, req.name);
		pthread_mutex_unlock(&table_lock);
		bo->bo_reuse = FALSE;
	}

	*name = bo->name;

	return 0;
}

uint32_t fd_bo_handle(struct fd_bo *bo)
{
	return bo->handle;
}

int fd_bo_dmabuf(struct fd_bo *bo)
{
	int ret, prime_fd;

	ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC,
			&prime_fd);
	if (ret) {
		ERROR_MSG("failed to get dmabuf fd: %d", ret);
		return ret;
	}

	bo->bo_reuse = FALSE;

	return prime_fd;
}

uint32_t fd_bo_size(struct fd_bo *bo)
{
	return bo->size;
}

void * fd_bo_map(struct fd_bo *bo)
{
	if (!bo->map) {
		uint64_t offset;
		int ret;

		ret = bo->funcs->offset(bo, &offset);
		if (ret) {
			return NULL;
		}

		bo->map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
				bo->dev->fd, offset);
		if (bo->map == MAP_FAILED) {
			ERROR_MSG("mmap failed: %s", strerror(errno));
			bo->map = NULL;
		}
	}
	return bo->map;
}

/* a bit odd to take the pipe as an arg, but it's a, umm, quirk of kgsl.. */
int fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op)
{
	return bo->funcs->cpu_prep(bo, pipe, op);
}

void fd_bo_cpu_fini(struct fd_bo *bo)
{
	bo->funcs->cpu_fini(bo);
}