msm: kgsl: Handle sync object with software fence correctly

It is possible that even with hardware fences enabled, kgsl
will create a software only fence if the corresponding timestamp
has been retired by the GPU. Now, assume kgsl receives an input
fence array which has this (signaled) software only fence as one
of its children and say has another child fence which is a hardware
fence. Currently, kgsl will not send this sync object to GMU
because one of its children is a software fence. Whereas it would
be more appropriate to ignore the software fence (if it is signaled)
and send the rest of the hardware fences to GMU.

Change-Id: I3d22d689ff84308ec4026beedc2f7b0c75b01d16
Signed-off-by: Harshdeep Dhatt <quic_hdhatt@quicinc.com>
This commit is contained in:
Harshdeep Dhatt 2023-05-02 11:08:29 -06:00
parent fa27422a49
commit 1682238c74
3 changed files with 36 additions and 15 deletions

View File

@ -2860,8 +2860,8 @@ static void populate_kgsl_fence(struct hfi_syncobj *obj,
obj->flags |= BIT(GMU_SYNCOBJ_FLAG_KGSL_FENCE_BIT);
spin_lock_irqsave(&ktimeline->lock, flags);
/* This means that the context is going away. Mark the fence as triggered */
if (!ktimeline->context) {
/* If the context is going away or the dma fence is signaled, mark the fence as triggered */
if (!ktimeline->context || dma_fence_is_signaled_locked(fence)) {
obj->flags |= BIT(GMU_SYNCOBJ_FLAG_SIGNALED_BIT);
spin_unlock_irqrestore(&ktimeline->lock, flags);
return;
@ -2917,6 +2917,17 @@ static int _submit_hw_fence(struct adreno_device *adreno_dev,
for (j = 0; j < num_fences; j++) {
/*
* If this sync object has a software only fence, make sure that it is
* already signaled so that we can skip sending this fence to the GMU.
*/
if (!test_bit(MSM_HW_FENCE_FLAG_ENABLED_BIT, &fences[j]->flags)) {
if (WARN(!dma_fence_is_signaled(fences[j]),
"sync object has unsignaled software fence"))
return -EINVAL;
continue;
}
if (is_kgsl_fence(fences[j])) {
populate_kgsl_fence(obj, fences[j]);
} else {
@ -3307,8 +3318,10 @@ void gen7_hwsched_create_hw_fence(struct adreno_device *adreno_dev,
* guaranteed to be retired. This way, we don't need the device mutex to check the device
* state explicitly.
*/
if (timestamp_cmp(retired, kfence->timestamp) >= 0)
if (timestamp_cmp(retired, kfence->timestamp) >= 0) {
kgsl_sync_timeline_signal(ktimeline, kfence->timestamp);
goto done;
}
/*
* If timestamp is not retired then GMU must already be powered up. This is because SLUMBER

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2019, 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/file.h>
@ -12,9 +12,6 @@
#include "kgsl_device.h"
#include "kgsl_sync.h"
static void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *timeline,
unsigned int timestamp);
static const struct dma_fence_ops kgsl_sync_fence_ops;
static struct kgsl_sync_fence *kgsl_sync_fence_create(
@ -357,7 +354,7 @@ int kgsl_sync_timeline_create(struct kgsl_context *context)
return 0;
}
static void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *ktimeline,
void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *ktimeline,
unsigned int timestamp)
{
unsigned long flags;
@ -439,17 +436,19 @@ bool is_kgsl_fence(struct dma_fence *f)
static void kgsl_count_hw_fences(struct kgsl_drawobj_sync_event *event, struct dma_fence *fence)
{
/*
* Even one sw-only fence in this sync object means we can't send this
* sync object to the hardware
* Even one unsignaled sw-only fence in this sync object means we can't send this sync
* object to the hardware
*/
if (event->syncobj->flags & KGSL_SYNCOBJ_SW)
return;
if (!test_bit(MSM_HW_FENCE_FLAG_ENABLED_BIT, &fence->flags))
event->syncobj->flags |= KGSL_SYNCOBJ_SW;
else
if (!test_bit(MSM_HW_FENCE_FLAG_ENABLED_BIT, &fence->flags)) {
/* Ignore software fences that are already signaled */
if (!dma_fence_is_signaled(fence))
event->syncobj->flags |= KGSL_SYNCOBJ_SW;
} else {
event->syncobj->num_hw_fence++;
}
}
static void kgsl_get_fence_info(struct dma_fence *fence,

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2012-2014,2018-2019, 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __KGSL_SYNC_H
#define __KGSL_SYNC_H
@ -112,6 +112,9 @@ void kgsl_syncsource_process_release_syncsources(
bool is_kgsl_fence(struct dma_fence *f);
void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *ktimeline,
u32 timestamp);
#else
static inline int kgsl_add_fence_event(struct kgsl_device *device,
u32 context_id, u32 timestamp, void __user *data, int len,
@ -191,6 +194,12 @@ bool is_kgsl_fence(struct dma_fence *f)
}
void kgsl_sync_timeline_signal(struct kgsl_sync_timeline *ktimeline,
u32 timestamp)
{
}
#endif /* CONFIG_SYNC_FILE */
#endif /* __KGSL_SYNC_H */