diff --git a/drivers/gpu/host1x/fence.c b/drivers/gpu/host1x/fence.c index ac6e07c1..4374e249 100644 --- a/drivers/gpu/host1x/fence.c +++ b/drivers/gpu/host1x/fence.c @@ -72,7 +72,7 @@ const struct dma_fence_ops host1x_syncpt_fence_ops = { .enable_signaling = host1x_syncpt_fence_enable_signaling, }; -void host1x_fence_signal(struct host1x_syncpt_fence *f) +void host1x_fence_signal(struct host1x_syncpt_fence *f, ktime_t ts) { if (atomic_xchg(&f->signaling, 1)) { /* @@ -91,7 +91,7 @@ void host1x_fence_signal(struct host1x_syncpt_fence *f) dma_fence_put(&f->base); } - dma_fence_signal_locked(&f->base); + dma_fence_signal_timestamp_locked(&f->base, ts); dma_fence_put(&f->base); } diff --git a/drivers/gpu/host1x/fence.h b/drivers/gpu/host1x/fence.h index f3c644c7..0a2e6b3f 100644 --- a/drivers/gpu/host1x/fence.h +++ b/drivers/gpu/host1x/fence.h @@ -25,6 +25,6 @@ struct host1x_fence_list { struct list_head list; }; -void host1x_fence_signal(struct host1x_syncpt_fence *fence); +void host1x_fence_signal(struct host1x_syncpt_fence *fence, ktime_t ts); #endif diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index b915ef7d..d6cdc489 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "../intr.h" #include "../dev.h" @@ -18,6 +19,9 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) struct host1x *host = dev_id; unsigned long reg; unsigned int i, id; + ktime_t ts; + + ts = ktime_get(); for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) { reg = host1x_sync_readl(host, @@ -29,7 +33,7 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); for_each_set_bit(id, ®, 32) - host1x_intr_handle_interrupt(host, i * 32 + id); + host1x_intr_handle_interrupt(host, i * 32 + id, ts); } return IRQ_HANDLED; diff --git a/drivers/gpu/host1x/include/linux/host1x-next.h b/drivers/gpu/host1x/include/linux/host1x-next.h index 6fc0bb28..b9ab6475 100644 --- a/drivers/gpu/host1x/include/linux/host1x-next.h +++ b/drivers/gpu/host1x/include/linux/host1x-next.h @@ -10,6 +10,7 @@ #include #include #include +#include #include enum host1x_class { @@ -211,6 +212,8 @@ u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); u32 host1x_syncpt_read(struct host1x_syncpt *sp); int host1x_syncpt_incr(struct host1x_syncpt *sp); u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); +int host1x_syncpt_wait_ts(struct host1x_syncpt *sp, u32 thresh, long timeout, + u32 *value, ktime_t *ts); int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value); struct host1x_syncpt *host1x_syncpt_request(struct host1x_client *client, diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c index 995bfa98..6f4b1820 100644 --- a/drivers/gpu/host1x/intr.c +++ b/drivers/gpu/host1x/intr.c @@ -72,7 +72,7 @@ bool host1x_intr_remove_fence(struct host1x *host, struct host1x_syncpt_fence *f return true; } -void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id) +void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id, ktime_t ts) { struct host1x_syncpt *sp = &host->syncpt[id]; struct host1x_syncpt_fence *fence, *tmp; @@ -89,7 +89,7 @@ void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id) } list_del_init(&fence->list); - host1x_fence_signal(fence); + host1x_fence_signal(fence, ts); } /* Re-enable interrupt if necessary */ diff --git a/drivers/gpu/host1x/intr.h b/drivers/gpu/host1x/intr.h index 3b5610b5..e4f307ab 100644 --- a/drivers/gpu/host1x/intr.h +++ b/drivers/gpu/host1x/intr.h @@ -8,6 +8,8 @@ #ifndef __HOST1X_INTR_H #define __HOST1X_INTR_H +#include + struct host1x; struct host1x_syncpt_fence; @@ -23,7 +25,7 @@ void host1x_intr_start(struct host1x *host); /* Disable host1x sync point interrupt */ void host1x_intr_stop(struct host1x *host); -void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id); +void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id, ktime_t ts); void host1x_intr_add_fence_locked(struct host1x *host, struct host1x_syncpt_fence *fence); diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 2d200776..098ff002 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -211,14 +212,15 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp) EXPORT_SYMBOL(host1x_syncpt_incr); /** - * host1x_syncpt_wait() - wait for a syncpoint to reach a given value + * host1x_syncpt_wait_ts() - wait for a syncpoint to reach a given value * @sp: host1x syncpoint * @thresh: threshold * @timeout: maximum time to wait for the syncpoint to reach the given value * @value: return location for the syncpoint value + * @ts: return location for completion timestamp */ -int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, - u32 *value) +int host1x_syncpt_wait_ts(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value, + ktime_t *ts) { struct dma_fence *fence; long wait_err; @@ -227,6 +229,8 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, if (value) *value = host1x_syncpt_load(sp); + if (ts) + *ts = ktime_get(); if (host1x_syncpt_is_expired(sp, thresh)) return 0; @@ -243,10 +247,13 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, wait_err = dma_fence_wait_timeout(fence, true, timeout); if (wait_err == 0) host1x_fence_cancel(fence); - dma_fence_put(fence); if (value) *value = host1x_syncpt_load(sp); + if (ts) + *ts = fence->timestamp; + + dma_fence_put(fence); if (wait_err == 0) return -EAGAIN; @@ -255,6 +262,19 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, else return 0; } +EXPORT_SYMBOL(host1x_syncpt_wait_ts); + +/** + * host1x_syncpt_wait() - wait for a syncpoint to reach a given value + * @sp: host1x syncpoint + * @thresh: threshold + * @timeout: maximum time to wait for the syncpoint to reach the given value + * @value: return location for the syncpoint value + */ +int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value) +{ + return host1x_syncpt_wait_ts(sp, thresh, timeout, value, NULL); +} EXPORT_SYMBOL(host1x_syncpt_wait); /*