diff options
author | 2020-01-08 10:26:26 -0800 | |
---|---|---|
committer | 2020-01-08 10:26:29 -0800 | |
commit | 40a9012a3b24334796403491b317a83935719809 (patch) | |
tree | 66d96124571e0bf70253b57e74bfb5885804e645 /drivers/gpu/drm/i915/i915_request.c | |
parent | Merge tag 'renesas-drivers-for-v5.6-tag1' of git://git.kernel.org/pub/scm/lin... (diff) | |
parent | arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916 (diff) | |
download | linux-40a9012a3b24334796403491b317a83935719809.tar.gz linux-40a9012a3b24334796403491b317a83935719809.tar.bz2 linux-40a9012a3b24334796403491b317a83935719809.zip |
Merge tag 'cpuidle_psci-v5.5-rc4' of git://git.linaro.org/people/ulf.hansson/linux-pm into arm/drivers
Initial support for hierarchical CPU arrangement, managed by PSCI and its
corresponding cpuidle driver. This support is based upon using the generic
PM domain, which already supports devices belonging to CPUs.
Finally, these is a DTS patch that enables the hierarchical topology to be
used for the Qcom 410c Dragonboard, which supports the PSCI OS-initiated
mode.
* tag 'cpuidle_psci-v5.5-rc4' of git://git.linaro.org/people/ulf.hansson/linux-pm: (611 commits)
arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
cpuidle: psci: Add support for PM domains by using genpd
PM / Domains: Introduce a genpd OF helper that removes a subdomain
cpuidle: psci: Support CPU hotplug for the hierarchical model
cpuidle: psci: Manage runtime PM in the idle path
cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
cpuidle: psci: Attach CPU devices to their PM domains
cpuidle: psci: Add a helper to attach a CPU to its PM domain
cpuidle: psci: Support hierarchical CPU idle states
cpuidle: psci: Simplify OF parsing of CPU idle state nodes
cpuidle: dt: Support hierarchical CPU idle states
of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
firmware: psci: Export functions to manage the OSI mode
dt: psci: Update DT bindings to support hierarchical PSCI states
cpuidle: psci: Align psci_power_state count with idle state count
Linux 5.5-rc4
locks: print unsigned ino in /proc/locks
riscv: export flush_icache_all to modules
riscv: reject invalid syscalls below -1
riscv: fix compile failure with EXPORT_SYMBOL() & !MMU
...
Link: https://lore.kernel.org/r/20200102160820.3572-1-ulf.hansson@linaro.org
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_request.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_request.c | 114 |
1 files changed, 89 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index bbd71af00a91..765bec89fc0d 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -300,11 +300,11 @@ void i915_request_retire_upto(struct i915_request *rq) } static int -__i915_request_await_execution(struct i915_request *rq, - struct i915_request *signal, - void (*hook)(struct i915_request *rq, - struct dma_fence *signal), - gfp_t gfp) +__await_execution(struct i915_request *rq, + struct i915_request *signal, + void (*hook)(struct i915_request *rq, + struct dma_fence *signal), + gfp_t gfp) { struct execute_cb *cb; @@ -341,6 +341,8 @@ __i915_request_await_execution(struct i915_request *rq, } spin_unlock_irq(&signal->lock); + /* Copy across semaphore status as we need the same behaviour */ + rq->sched.flags |= signal->sched.flags; return 0; } @@ -811,31 +813,21 @@ already_busywaiting(struct i915_request *rq) } static int -emit_semaphore_wait(struct i915_request *to, - struct i915_request *from, - gfp_t gfp) +__emit_semaphore_wait(struct i915_request *to, + struct i915_request *from, + u32 seqno) { const int has_token = INTEL_GEN(to->i915) >= 12; u32 hwsp_offset; - int len; + int len, err; u32 *cs; GEM_BUG_ON(INTEL_GEN(to->i915) < 8); - /* Just emit the first semaphore we see as request space is limited. */ - if (already_busywaiting(to) & from->engine->mask) - goto await_fence; - - if (i915_request_await_start(to, from) < 0) - goto await_fence; - - /* Only submit our spinner after the signaler is running! */ - if (__i915_request_await_execution(to, from, NULL, gfp)) - goto await_fence; - /* We need to pin the signaler's HWSP until we are finished reading. */ - if (intel_timeline_read_hwsp(from, to, &hwsp_offset)) - goto await_fence; + err = intel_timeline_read_hwsp(from, to, &hwsp_offset); + if (err) + return err; len = 4; if (has_token) @@ -858,7 +850,7 @@ emit_semaphore_wait(struct i915_request *to, MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_GTE_SDD) + has_token; - *cs++ = from->fence.seqno; + *cs++ = seqno; *cs++ = hwsp_offset; *cs++ = 0; if (has_token) { @@ -867,6 +859,28 @@ emit_semaphore_wait(struct i915_request *to, } intel_ring_advance(to, cs); + return 0; +} + +static int +emit_semaphore_wait(struct i915_request *to, + struct i915_request *from, + gfp_t gfp) +{ + /* Just emit the first semaphore we see as request space is limited. */ + if (already_busywaiting(to) & from->engine->mask) + goto await_fence; + + if (i915_request_await_start(to, from) < 0) + goto await_fence; + + /* Only submit our spinner after the signaler is running! */ + if (__await_execution(to, from, NULL, gfp)) + goto await_fence; + + if (__emit_semaphore_wait(to, from, from->fence.seqno)) + goto await_fence; + to->sched.semaphores |= from->engine->mask; to->sched.flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN; return 0; @@ -980,6 +994,57 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence) return 0; } +static bool intel_timeline_sync_has_start(struct intel_timeline *tl, + struct dma_fence *fence) +{ + return __intel_timeline_sync_is_later(tl, + fence->context, + fence->seqno - 1); +} + +static int intel_timeline_sync_set_start(struct intel_timeline *tl, + const struct dma_fence *fence) +{ + return __intel_timeline_sync_set(tl, fence->context, fence->seqno - 1); +} + +static int +__i915_request_await_execution(struct i915_request *to, + struct i915_request *from, + void (*hook)(struct i915_request *rq, + struct dma_fence *signal)) +{ + int err; + + /* Submit both requests at the same time */ + err = __await_execution(to, from, hook, I915_FENCE_GFP); + if (err) + return err; + + /* Squash repeated depenendices to the same timelines */ + if (intel_timeline_sync_has_start(i915_request_timeline(to), + &from->fence)) + return 0; + + /* Ensure both start together [after all semaphores in signal] */ + if (intel_engine_has_semaphores(to->engine)) + err = __emit_semaphore_wait(to, from, from->fence.seqno - 1); + else + err = i915_request_await_start(to, from); + if (err < 0) + return err; + + /* Couple the dependency tree for PI on this exposed to->fence */ + if (to->engine->schedule) { + err = i915_sched_node_add_dependency(&to->sched, &from->sched); + if (err < 0) + return err; + } + + return intel_timeline_sync_set_start(i915_request_timeline(to), + &from->fence); +} + int i915_request_await_execution(struct i915_request *rq, struct dma_fence *fence, @@ -1013,8 +1078,7 @@ i915_request_await_execution(struct i915_request *rq, if (dma_fence_is_i915(fence)) ret = __i915_request_await_execution(rq, to_request(fence), - hook, - I915_FENCE_GFP); + hook); else ret = i915_sw_fence_await_dma_fence(&rq->submit, fence, I915_FENCE_TIMEOUT, |