gpu: host1x: Annotate intentional syncpoint wrap-around

Host1x syncpoints are 32-bit counters that roll over by design.
To make that explicit in the code, use wrapping_* functions whenever
arithmetic is done on syncpoint values.

Atomic operations cannot be updated but a comment is added.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patch.msgid.link/20260609-b4-host1x-small-fixes-a-v1-6-7c1131c0b3ad@nvidia.com
This commit is contained in:
Mikko Perttunen 2026-06-09 17:09:22 +09:00 committed by Thierry Reding
parent 5c53592e3b
commit 5d4f401827
5 changed files with 20 additions and 8 deletions

View File

@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/kfifo.h>
#include <linux/overflow.h>
#include <linux/slab.h>
#include <trace/events/host1x.h>
@ -419,7 +420,7 @@ void host1x_cdma_update_sync_queue(struct host1x_cdma *cdma,
/* won't need a timeout when replayed */
job->timeout = 0;
syncpt_incrs = job->syncpt_end - syncpt_val;
syncpt_incrs = wrapping_sub(u32, job->syncpt_end, syncpt_val);
dev_dbg(dev, "%s: CPU incr (%d)\n", __func__, syncpt_incrs);
host1x_job_dump(dev, job);

View File

@ -7,6 +7,7 @@
#include <linux/host1x.h>
#include <linux/iommu.h>
#include <linux/overflow.h>
#include <linux/slab.h>
#include <trace/events/host1x.h>
@ -120,7 +121,8 @@ static void submit_gathers(struct host1x_job *job, struct host1x_job_cmd *cmds,
if (cmd->is_wait) {
if (cmd->wait.relative)
threshold = job_syncpt_base + cmd->wait.threshold;
threshold = wrapping_add(u32, job_syncpt_base,
cmd->wait.threshold);
else
threshold = cmd->wait.threshold;
@ -259,7 +261,8 @@ static void channel_program_cdma(struct host1x_job *job)
/* Submit work. */
job->syncpt_end = host1x_syncpt_incr_max(sp, job->syncpt_incrs);
submit_gathers(job, job->cmds + i, job->num_cmds - i, job->syncpt_end - job->syncpt_incrs);
submit_gathers(job, job->cmds + i, job->num_cmds - i,
wrapping_sub(u32, job->syncpt_end, job->syncpt_incrs));
/* Before releasing MLOCK, ensure engine is idle again. */
fence = host1x_syncpt_incr_max(sp, 1);
@ -297,7 +300,8 @@ static void channel_program_cdma(struct host1x_job *job)
job->syncpt_end = host1x_syncpt_incr_max(sp, job->syncpt_incrs);
submit_gathers(job, job->cmds, job->num_cmds, job->syncpt_end - job->syncpt_incrs);
submit_gathers(job, job->cmds, job->num_cmds,
wrapping_sub(u32, job->syncpt_end, job->syncpt_incrs));
#endif
}

View File

@ -7,6 +7,7 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/overflow.h>
#include "dev.h"
#include "fence.h"
#include "intr.h"
@ -17,7 +18,7 @@ static void host1x_intr_add_fence_to_list(struct host1x_fence_list *list,
struct host1x_syncpt_fence *fence_in_list;
list_for_each_entry_reverse(fence_in_list, &list->list, list) {
if ((s32)(fence_in_list->threshold - fence->threshold) <= 0) {
if ((s32)wrapping_sub(u32, fence_in_list->threshold, fence->threshold) <= 0) {
/* Fence in list is before us, we can insert here */
list_add(&fence->list, &fence_in_list->list);
return;
@ -83,7 +84,7 @@ void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id)
spin_lock(&sp->fences.lock);
list_for_each_entry_safe(fence, tmp, &sp->fences.list, list) {
if (((value - fence->threshold) & 0x80000000U) != 0U) {
if ((wrapping_sub(u32, value, fence->threshold) & 0x80000000U) != 0U) {
/* Fence is not yet expired, we are done */
break;
}

View File

@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/dma-fence.h>
#include <linux/overflow.h>
#include <linux/slab.h>
#include <trace/events/host1x.h>
@ -126,6 +127,10 @@ EXPORT_SYMBOL(host1x_syncpt_id);
*/
u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs)
{
/*
* Syncpoint values are intended to be modulo 2^32, so overflow
* here is intended.
*/
return (u32)atomic_add_return(incrs, &sp->max_val);
}
EXPORT_SYMBOL(host1x_syncpt_incr_max);
@ -279,7 +284,7 @@ bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh)
current_val = (u32)atomic_read(&sp->min_val);
return ((current_val - thresh) & 0x80000000U) == 0U;
return (wrapping_sub(u32, current_val, thresh) & 0x80000000U) == 0U;
}
int host1x_syncpt_init(struct host1x *host)

View File

@ -12,6 +12,7 @@
#include <linux/host1x.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/overflow.h>
#include <linux/sched.h>
#include "fence.h"
@ -77,7 +78,7 @@ static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
if (sp->client_managed)
return true;
max = host1x_syncpt_read_max(sp);
return (s32)(max - real) >= 0;
return (s32)wrapping_sub(u32, max, real) >= 0;
}
/* Return true if sync point is client managed. */