Skip to content

Commit 4defc08

Browse files
mairacanalpelwell
authored andcommitted
drm/v3d: Replace a global spinlock with a per-queue spinlock
Each V3D queue works independently and all the dependencies between the jobs are handled through the DRM scheduler. Therefore, there is no need to use one single lock for all queues. Using it, creates unnecessary contention between different queues that can operate independently. Replace the global spinlock with per-queue locks to improve parallelism and reduce contention between different V3D queues (BIN, RENDER, TFU, CSD). This allows independent queues to operate concurrently while maintaining proper synchronization within each queue. Signed-off-by: Maíra Canal <[email protected]>
1 parent d22faf7 commit 4defc08

File tree

5 files changed

+20
-21
lines changed

5 files changed

+20
-21
lines changed

drivers/gpu/drm/v3d/v3d_drv.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct v3d_queue_state {
6161

6262
/* Currently active job for this queue */
6363
struct v3d_job *active_job;
64+
spinlock_t queue_lock;
6465
};
6566

6667
/* Performance monitor object. The perform lifetime is controlled by userspace
@@ -170,11 +171,6 @@ struct v3d_dev {
170171

171172
struct v3d_queue_state queue[V3D_MAX_QUEUES];
172173

173-
/* Spinlock used to synchronize the overflow memory
174-
* management against bin job submission.
175-
*/
176-
spinlock_t job_lock;
177-
178174
/* Used to track the active perfmon if any. */
179175
struct v3d_perfmon *active_perfmon;
180176

@@ -563,7 +559,7 @@ void v3d_get_stats(const struct v3d_stats *stats, u64 timestamp,
563559

564560
/* v3d_fence.c */
565561
extern const struct dma_fence_ops v3d_fence_ops;
566-
struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue queue);
562+
struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q);
567563

568564
/* v3d_gem.c */
569565
int v3d_gem_init(struct drm_device *dev);

drivers/gpu/drm/v3d/v3d_fence.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33

44
#include "v3d_drv.h"
55

6-
struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue queue)
6+
struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q)
77
{
8+
struct v3d_queue_state *queue = &v3d->queue[q];
89
struct v3d_fence *fence;
910

1011
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
1112
if (!fence)
1213
return ERR_PTR(-ENOMEM);
1314

1415
fence->dev = &v3d->drm;
15-
fence->queue = queue;
16-
fence->seqno = ++v3d->queue[queue].emit_seqno;
17-
dma_fence_init(&fence->base, &v3d_fence_ops, &v3d->job_lock,
18-
v3d->queue[queue].fence_context, fence->seqno);
16+
fence->queue = q;
17+
fence->seqno = ++queue->emit_seqno;
18+
dma_fence_init(&fence->base, &v3d_fence_ops, &queue->queue_lock,
19+
queue->fence_context, fence->seqno);
1920

2021
return &fence->base;
2122
}

drivers/gpu/drm/v3d/v3d_gem.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,11 @@ v3d_gem_init(struct drm_device *dev)
272272
queue->fence_context = dma_fence_context_alloc(1);
273273
memset(&queue->stats, 0, sizeof(queue->stats));
274274
seqcount_init(&queue->stats.lock);
275+
276+
spin_lock_init(&queue->queue_lock);
275277
}
276278

277279
spin_lock_init(&v3d->mm_lock);
278-
spin_lock_init(&v3d->job_lock);
279280
ret = drmm_mutex_init(dev, &v3d->bo_lock);
280281
if (ret)
281282
return ret;

drivers/gpu/drm/v3d/v3d_irq.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,17 @@ v3d_overflow_mem_work(struct work_struct *work)
6262
* bin job got scheduled, that's fine. We'll just give them
6363
* some binner pool anyway.
6464
*/
65-
spin_lock_irqsave(&v3d->job_lock, irqflags);
65+
spin_lock_irqsave(&queue->queue_lock, irqflags);
6666
bin_job = (struct v3d_bin_job *)queue->active_job;
6767

6868
if (!bin_job) {
69-
spin_unlock_irqrestore(&v3d->job_lock, irqflags);
69+
spin_unlock_irqrestore(&queue->queue_lock, irqflags);
7070
goto out;
7171
}
7272

7373
drm_gem_object_get(obj);
7474
list_add_tail(&bo->unref_head, &bin_job->render->unref_list);
75-
spin_unlock_irqrestore(&v3d->job_lock, irqflags);
75+
spin_unlock_irqrestore(&queue->queue_lock, irqflags);
7676

7777
v3d_mmu_flush_all(v3d);
7878

drivers/gpu/drm/v3d/v3d_sched.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,27 +226,28 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
226226
{
227227
struct v3d_bin_job *job = to_bin_job(sched_job);
228228
struct v3d_dev *v3d = job->base.v3d;
229+
struct v3d_queue_state *queue = &v3d->queue[V3D_BIN];
229230
struct drm_device *dev = &v3d->drm;
230231
struct dma_fence *fence;
231232
unsigned long irqflags;
232233

233234
if (unlikely(job->base.base.s_fence->finished.error)) {
234-
spin_lock_irqsave(&v3d->job_lock, irqflags);
235-
v3d->queue[V3D_BIN].active_job = NULL;
236-
spin_unlock_irqrestore(&v3d->job_lock, irqflags);
235+
spin_lock_irqsave(&queue->queue_lock, irqflags);
236+
queue->active_job = NULL;
237+
spin_unlock_irqrestore(&queue->queue_lock, irqflags);
237238
return NULL;
238239
}
239240

240241
/* Lock required around bin_job update vs
241242
* v3d_overflow_mem_work().
242243
*/
243-
spin_lock_irqsave(&v3d->job_lock, irqflags);
244-
v3d->queue[V3D_BIN].active_job = &job->base;
244+
spin_lock_irqsave(&queue->queue_lock, irqflags);
245+
queue->active_job = &job->base;
245246
/* Clear out the overflow allocation, so we don't
246247
* reuse the overflow attached to a previous job.
247248
*/
248249
V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
249-
spin_unlock_irqrestore(&v3d->job_lock, irqflags);
250+
spin_unlock_irqrestore(&queue->queue_lock, irqflags);
250251

251252
v3d_invalidate_caches(v3d);
252253

0 commit comments

Comments
 (0)