drivers/accel/ivpu/ivpu_gem.c

Source file repositories/reference/linux-study-clean/drivers/accel/ivpu/ivpu_gem.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/ivpu/ivpu_gem.c
Extension
.c
Size
14265 bytes
Lines
580
Domain
Driver Families
Bucket
drivers/accel
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret) {
			ivpu_err(vdev, "Failed to map BO in MMU: %d\n", ret);
			goto unlock;
		}
		bo->mmu_mapped = true;
	}

unlock:
	ivpu_bo_unlock(bo);

	return ret;
}

static int
ivpu_bo_alloc_vpu_addr(struct ivpu_bo *bo, struct ivpu_mmu_context *ctx,
		       const struct ivpu_addr_range *range)
{
	struct ivpu_device *vdev = ivpu_bo_to_vdev(bo);
	int idx, ret;

	if (!drm_dev_enter(&vdev->drm, &idx))
		return -ENODEV;

	ivpu_bo_lock(bo);

	ret = ivpu_mmu_context_insert_node(ctx, range, ivpu_bo_size(bo), &bo->mm_node);
	if (!ret) {
		bo->ctx = ctx;
		bo->ctx_id = ctx->id;
		bo->vpu_addr = bo->mm_node.start;
		ivpu_dbg_bo(vdev, bo, "vaddr");
	}

	ivpu_bo_unlock(bo);

	drm_dev_exit(idx);

	return ret;
}

static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
{
	struct ivpu_device *vdev = ivpu_bo_to_vdev(bo);

	dma_resv_assert_held(bo->base.base.resv);

	if (bo->mmu_mapped) {
		drm_WARN_ON(&vdev->drm, !bo->ctx);
		drm_WARN_ON(&vdev->drm, !bo->vpu_addr);
		drm_WARN_ON(&vdev->drm, !bo->base.sgt);
		ivpu_mmu_context_unmap_sgt(vdev, bo->ctx, bo->vpu_addr, bo->base.sgt);
		bo->mmu_mapped = false;
	}

	if (bo->ctx) {
		ivpu_mmu_context_remove_node(bo->ctx, &bo->mm_node);
		bo->ctx = NULL;
	}

	if (bo->base.sgt) {
		if (drm_gem_is_imported(&bo->base.base)) {
			dma_buf_unmap_attachment(bo->base.base.import_attach,
						 bo->base.sgt, DMA_BIDIRECTIONAL);
		} else {
			dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
			sg_free_table(bo->base.sgt);
			kfree(bo->base.sgt);
		}
		bo->base.sgt = NULL;
	}
}

void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx)
{
	struct ivpu_bo *bo;

	if (drm_WARN_ON(&vdev->drm, !ctx))
		return;

	mutex_lock(&vdev->bo_list_lock);
	list_for_each_entry(bo, &vdev->bo_list, bo_list_node) {
		ivpu_bo_lock(bo);
		if (bo->ctx == ctx) {
			ivpu_dbg_bo(vdev, bo, "unbind");
			ivpu_bo_unbind_locked(bo);
		}
		ivpu_bo_unlock(bo);
	}
	mutex_unlock(&vdev->bo_list_lock);
}

Annotation

Implementation Notes