Skip to content

Commit e0c0891

Browse files
jlawrynokwachows
authored andcommitted
accel/ivpu: Rework bind/unbind of imported buffers
Ensure that imported buffers are properly mapped and unmapped in the same way as regular buffers to properly handle buffers during device's bind and unbind operations to prevent resource leaks and inconsistent buffer states. Imported buffers are now dma_mapped before submission and dma_unmapped in ivpu_bo_unbind(), guaranteeing they are unmapped when the device is unbound. Add also imported buffers to vdev->bo_list for consistent unmapping on device unbind. The bo->ctx_id is set in open() so imported buffers have a valid context ID. Debug logs have been updated to match the new code structure. The function ivpu_bo_pin() has been renamed to ivpu_bo_bind() to better reflect its purpose, and unbind tests have been refactored for improved coverage and clarity. Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> Signed-off-by: Maciej Falkowski <maciej.falkowski@linux.intel.com> Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com> Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com> Link: https://lore.kernel.org/r/20250925145059.1446243-1-maciej.falkowski@linux.intel.com
1 parent 87a23fe commit e0c0891

3 files changed

Lines changed: 60 additions & 34 deletions

File tree

drivers/accel/ivpu/ivpu_gem.c

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ static const struct drm_gem_object_funcs ivpu_gem_funcs;
2828
static inline void ivpu_dbg_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, const char *action)
2929
{
3030
ivpu_dbg(vdev, BO,
31-
"%6s: bo %8p vpu_addr %9llx size %8zu ctx %d has_pages %d dma_mapped %d mmu_mapped %d wc %d imported %d\n",
32-
action, bo, bo->vpu_addr, ivpu_bo_size(bo), bo->ctx_id,
31+
"%6s: bo %8p size %9zu ctx %d vpu_addr %9llx pages %d sgt %d mmu_mapped %d wc %d imported %d\n",
32+
action, bo, ivpu_bo_size(bo), bo->ctx_id, bo->vpu_addr,
3333
(bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc,
3434
(bool)drm_gem_is_imported(&bo->base.base));
3535
}
@@ -44,22 +44,46 @@ static inline void ivpu_bo_unlock(struct ivpu_bo *bo)
4444
dma_resv_unlock(bo->base.base.resv);
4545
}
4646

47+
static struct sg_table *ivpu_bo_map_attachment(struct ivpu_device *vdev, struct ivpu_bo *bo)
48+
{
49+
struct sg_table *sgt = bo->base.sgt;
50+
51+
drm_WARN_ON(&vdev->drm, !bo->base.base.import_attach);
52+
53+
ivpu_bo_lock(bo);
54+
55+
if (!sgt) {
56+
sgt = dma_buf_map_attachment(bo->base.base.import_attach, DMA_BIDIRECTIONAL);
57+
if (IS_ERR(sgt))
58+
ivpu_err(vdev, "Failed to map BO in IOMMU: %ld\n", PTR_ERR(sgt));
59+
else
60+
bo->base.sgt = sgt;
61+
}
62+
63+
ivpu_bo_unlock(bo);
64+
65+
return sgt;
66+
}
67+
4768
/*
48-
* ivpu_bo_pin() - pin the backing physical pages and map them to VPU.
69+
* ivpu_bo_bind() - pin the backing physical pages and map them to VPU.
4970
*
5071
* This function pins physical memory pages, then maps the physical pages
5172
* to IOMMU address space and finally updates the VPU MMU page tables
5273
* to allow the VPU to translate VPU address to IOMMU address.
5374
*/
54-
int __must_check ivpu_bo_pin(struct ivpu_bo *bo)
75+
int __must_check ivpu_bo_bind(struct ivpu_bo *bo)
5576
{
5677
struct ivpu_device *vdev = ivpu_bo_to_vdev(bo);
5778
struct sg_table *sgt;
5879
int ret = 0;
5980

60-
ivpu_dbg_bo(vdev, bo, "pin");
81+
ivpu_dbg_bo(vdev, bo, "bind");
6182

62-
sgt = drm_gem_shmem_get_pages_sgt(&bo->base);
83+
if (bo->base.base.import_attach)
84+
sgt = ivpu_bo_map_attachment(vdev, bo);
85+
else
86+
sgt = drm_gem_shmem_get_pages_sgt(&bo->base);
6387
if (IS_ERR(sgt)) {
6488
ret = PTR_ERR(sgt);
6589
ivpu_err(vdev, "Failed to map BO in IOMMU: %d\n", ret);
@@ -100,7 +124,9 @@ ivpu_bo_alloc_vpu_addr(struct ivpu_bo *bo, struct ivpu_mmu_context *ctx,
100124
ret = ivpu_mmu_context_insert_node(ctx, range, ivpu_bo_size(bo), &bo->mm_node);
101125
if (!ret) {
102126
bo->ctx = ctx;
127+
bo->ctx_id = ctx->id;
103128
bo->vpu_addr = bo->mm_node.start;
129+
ivpu_dbg_bo(vdev, bo, "vaddr");
104130
} else {
105131
ivpu_err(vdev, "Failed to add BO to context %u: %d\n", ctx->id, ret);
106132
}
@@ -116,7 +142,7 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
116142
{
117143
struct ivpu_device *vdev = ivpu_bo_to_vdev(bo);
118144

119-
lockdep_assert(dma_resv_held(bo->base.base.resv) || !kref_read(&bo->base.base.refcount));
145+
dma_resv_assert_held(bo->base.base.resv);
120146

121147
if (bo->mmu_mapped) {
122148
drm_WARN_ON(&vdev->drm, !bo->ctx);
@@ -135,9 +161,14 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
135161
return;
136162

137163
if (bo->base.sgt) {
138-
dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
139-
sg_free_table(bo->base.sgt);
140-
kfree(bo->base.sgt);
164+
if (bo->base.base.import_attach) {
165+
dma_buf_unmap_attachment(bo->base.base.import_attach,
166+
bo->base.sgt, DMA_BIDIRECTIONAL);
167+
} else {
168+
dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
169+
sg_free_table(bo->base.sgt);
170+
kfree(bo->base.sgt);
171+
}
141172
bo->base.sgt = NULL;
142173
}
143174
}
@@ -163,6 +194,7 @@ void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_m
163194

164195
struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t size)
165196
{
197+
struct ivpu_device *vdev = to_ivpu_device(dev);
166198
struct ivpu_bo *bo;
167199

168200
if (size == 0 || !PAGE_ALIGNED(size))
@@ -177,6 +209,11 @@ struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t siz
177209

178210
INIT_LIST_HEAD(&bo->bo_list_node);
179211

212+
mutex_lock(&vdev->bo_list_lock);
213+
list_add_tail(&bo->bo_list_node, &vdev->bo_list);
214+
mutex_unlock(&vdev->bo_list_lock);
215+
216+
ivpu_dbg(vdev, BO, " alloc: bo %8p size %9zu\n", bo, size);
180217
return &bo->base.base;
181218
}
182219

@@ -185,7 +222,6 @@ struct drm_gem_object *ivpu_gem_prime_import(struct drm_device *dev,
185222
{
186223
struct device *attach_dev = dev->dev;
187224
struct dma_buf_attachment *attach;
188-
struct sg_table *sgt;
189225
struct drm_gem_object *obj;
190226
int ret;
191227

@@ -195,33 +231,25 @@ struct drm_gem_object *ivpu_gem_prime_import(struct drm_device *dev,
195231

196232
get_dma_buf(dma_buf);
197233

198-
sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
199-
if (IS_ERR(sgt)) {
200-
ret = PTR_ERR(sgt);
201-
goto fail_detach;
202-
}
203-
204-
obj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt);
234+
obj = drm_gem_shmem_prime_import_sg_table(dev, attach, NULL);
205235
if (IS_ERR(obj)) {
206236
ret = PTR_ERR(obj);
207-
goto fail_unmap;
237+
goto fail_detach;
208238
}
209239

210240
obj->import_attach = attach;
211241
obj->resv = dma_buf->resv;
212242

213243
return obj;
214244

215-
fail_unmap:
216-
dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
217245
fail_detach:
218246
dma_buf_detach(dma_buf, attach);
219247
dma_buf_put(dma_buf);
220248

221249
return ERR_PTR(ret);
222250
}
223251

224-
static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 flags, u32 ctx_id)
252+
static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 flags)
225253
{
226254
struct drm_gem_shmem_object *shmem;
227255
struct ivpu_bo *bo;
@@ -239,16 +267,9 @@ static struct ivpu_bo *ivpu_bo_alloc(struct ivpu_device *vdev, u64 size, u32 fla
239267
return ERR_CAST(shmem);
240268

241269
bo = to_ivpu_bo(&shmem->base);
242-
bo->ctx_id = ctx_id;
243270
bo->base.map_wc = flags & DRM_IVPU_BO_WC;
244271
bo->flags = flags;
245272

246-
mutex_lock(&vdev->bo_list_lock);
247-
list_add_tail(&bo->bo_list_node, &vdev->bo_list);
248-
mutex_unlock(&vdev->bo_list_lock);
249-
250-
ivpu_dbg_bo(vdev, bo, "alloc");
251-
252273
return bo;
253274
}
254275

@@ -282,6 +303,8 @@ static void ivpu_gem_bo_free(struct drm_gem_object *obj)
282303

283304
ivpu_dbg_bo(vdev, bo, "free");
284305

306+
drm_WARN_ON(&vdev->drm, list_empty(&bo->bo_list_node));
307+
285308
mutex_lock(&vdev->bo_list_lock);
286309
list_del(&bo->bo_list_node);
287310
mutex_unlock(&vdev->bo_list_lock);
@@ -291,7 +314,10 @@ static void ivpu_gem_bo_free(struct drm_gem_object *obj)
291314
drm_WARN_ON(&vdev->drm, ivpu_bo_size(bo) == 0);
292315
drm_WARN_ON(&vdev->drm, bo->base.vaddr);
293316

317+
ivpu_bo_lock(bo);
294318
ivpu_bo_unbind_locked(bo);
319+
ivpu_bo_unlock(bo);
320+
295321
drm_WARN_ON(&vdev->drm, bo->mmu_mapped);
296322
drm_WARN_ON(&vdev->drm, bo->ctx);
297323

@@ -327,7 +353,7 @@ int ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
327353
if (size == 0)
328354
return -EINVAL;
329355

330-
bo = ivpu_bo_alloc(vdev, size, args->flags, file_priv->ctx.id);
356+
bo = ivpu_bo_alloc(vdev, size, args->flags);
331357
if (IS_ERR(bo)) {
332358
ivpu_err(vdev, "Failed to allocate BO: %pe (ctx %u size %llu flags 0x%x)",
333359
bo, file_priv->ctx.id, args->size, args->flags);
@@ -361,7 +387,7 @@ ivpu_bo_create(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
361387
drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(range->end));
362388
drm_WARN_ON(&vdev->drm, !PAGE_ALIGNED(size));
363389

364-
bo = ivpu_bo_alloc(vdev, size, flags, IVPU_GLOBAL_CONTEXT_MMU_SSID);
390+
bo = ivpu_bo_alloc(vdev, size, flags);
365391
if (IS_ERR(bo)) {
366392
ivpu_err(vdev, "Failed to allocate BO: %pe (vpu_addr 0x%llx size %llu flags 0x%x)",
367393
bo, range->start, size, flags);
@@ -372,7 +398,7 @@ ivpu_bo_create(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
372398
if (ret)
373399
goto err_put;
374400

375-
ret = ivpu_bo_pin(bo);
401+
ret = ivpu_bo_bind(bo);
376402
if (ret)
377403
goto err_put;
378404

drivers/accel/ivpu/ivpu_gem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct ivpu_bo {
2424
bool mmu_mapped;
2525
};
2626

27-
int ivpu_bo_pin(struct ivpu_bo *bo);
27+
int ivpu_bo_bind(struct ivpu_bo *bo);
2828
void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx);
2929

3030
struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t size);

drivers/accel/ivpu/ivpu_job.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct ivpu_job *job, u32
751751

752752
job->bos[i] = to_ivpu_bo(obj);
753753

754-
ret = ivpu_bo_pin(job->bos[i]);
754+
ret = ivpu_bo_bind(job->bos[i]);
755755
if (ret)
756756
return ret;
757757
}

0 commit comments

Comments
 (0)