mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
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:
parent
5c53592e3b
commit
5d4f401827
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user