android_kernel_samsung_sm86.../qcom/opensource/graphics-kernel/adreno_a5xx_preempt.c

549 lines
16 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2014-2017,2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "adreno.h"
#include "adreno_a5xx.h"
#include "adreno_pm4types.h"
#include "adreno_trace.h"
#define PREEMPT_RECORD(_field) \
offsetof(struct a5xx_cp_preemption_record, _field)
#define PREEMPT_SMMU_RECORD(_field) \
offsetof(struct a5xx_cp_smmu_info, _field)
static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_ringbuffer *rb = adreno_dev->cur_rb;
unsigned int wptr;
unsigned long flags;
spin_lock_irqsave(&rb->preempt_lock, flags);
kgsl_regread(device, A5XX_CP_RB_WPTR, &wptr);
if (wptr != rb->wptr) {
kgsl_regwrite(device, A5XX_CP_RB_WPTR, rb->wptr);
/*
* In case something got submitted while preemption was on
* going, reset the timer.
*/
reset_timer = true;
}
if (reset_timer)
rb->dispatch_q.expires = jiffies +
msecs_to_jiffies(adreno_drawobj_timeout);
spin_unlock_irqrestore(&rb->preempt_lock, flags);
}
static void _a5xx_preemption_done(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
unsigned int status;
/*
* In the very unlikely case that the power is off, do nothing - the
* state will be reset on power up and everybody will be happy
*/
if (!kgsl_state_is_awake(device))
return;
kgsl_regread(device, A5XX_CP_CONTEXT_SWITCH_CNTL, &status);
if (status != 0) {
dev_err(device->dev,
"Preemption not complete: status=%X cur=%d R/W=%X/%X next=%d R/W=%X/%X\n",
status, adreno_dev->cur_rb->id,
adreno_get_rptr(adreno_dev->cur_rb),
adreno_dev->cur_rb->wptr,
adreno_dev->next_rb->id,
adreno_get_rptr(adreno_dev->next_rb),
adreno_dev->next_rb->wptr);
/* Set a fault and restart */
adreno_dispatcher_fault(adreno_dev, ADRENO_PREEMPT_FAULT);
return;
}
del_timer_sync(&adreno_dev->preempt.timer);
trace_adreno_preempt_done(adreno_dev->cur_rb->id, adreno_dev->next_rb->id, 0, 0);
/* Clean up all the bits */
adreno_dev->prev_rb = adreno_dev->cur_rb;
adreno_dev->cur_rb = adreno_dev->next_rb;
adreno_dev->next_rb = NULL;
/* Update the wptr for the new command queue */
_update_wptr(adreno_dev, true);
/* Update the dispatcher timer for the new command queue */
mod_timer(&adreno_dev->dispatcher.timer,
adreno_dev->cur_rb->dispatch_q.expires);
/* Clear the preempt state */
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
}
static void _a5xx_preemption_fault(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
unsigned int status;
/*
* If the power is on check the preemption status one more time - if it
* was successful then just transition to the complete state
*/
if (kgsl_state_is_awake(device)) {
kgsl_regread(device, A5XX_CP_CONTEXT_SWITCH_CNTL, &status);
if (status == 0) {
adreno_set_preempt_state(adreno_dev,
ADRENO_PREEMPT_COMPLETE);
adreno_dispatcher_schedule(device);
return;
}
}
dev_err(device->dev,
"Preemption timed out: cur=%d R/W=%X/%X, next=%d R/W=%X/%X\n",
adreno_dev->cur_rb->id,
adreno_get_rptr(adreno_dev->cur_rb),
adreno_dev->cur_rb->wptr,
adreno_dev->next_rb->id,
adreno_get_rptr(adreno_dev->next_rb),
adreno_dev->next_rb->wptr);
adreno_dispatcher_fault(adreno_dev, ADRENO_PREEMPT_FAULT);
}
static void _a5xx_preemption_worker(struct work_struct *work)
{
struct adreno_preemption *preempt = container_of(work,
struct adreno_preemption, work);
struct adreno_device *adreno_dev = container_of(preempt,
struct adreno_device, preempt);
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
/* Need to take the mutex to make sure that the power stays on */
mutex_lock(&device->mutex);
if (adreno_in_preempt_state(adreno_dev, ADRENO_PREEMPT_FAULTED))
_a5xx_preemption_fault(adreno_dev);
mutex_unlock(&device->mutex);
}
/* Find the highest priority active ringbuffer */
static struct adreno_ringbuffer *a5xx_next_ringbuffer(
struct adreno_device *adreno_dev)
{
struct adreno_ringbuffer *rb;
unsigned long flags;
unsigned int i;
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
bool empty;
spin_lock_irqsave(&rb->preempt_lock, flags);
empty = adreno_rb_empty(rb);
spin_unlock_irqrestore(&rb->preempt_lock, flags);
if (!empty)
return rb;
}
return NULL;
}
void a5xx_preemption_trigger(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_iommu *iommu = KGSL_IOMMU(device);
struct adreno_ringbuffer *next;
uint64_t ttbr0;
unsigned int contextidr;
unsigned long flags;
/* Put ourselves into a possible trigger state */
if (!adreno_move_preempt_state(adreno_dev,
ADRENO_PREEMPT_NONE, ADRENO_PREEMPT_START))
return;
/* Get the next ringbuffer to preempt in */
next = a5xx_next_ringbuffer(adreno_dev);
/*
* Nothing to do if every ringbuffer is empty or if the current
* ringbuffer is the only active one
*/
if (next == NULL || next == adreno_dev->cur_rb) {
/*
* Update any critical things that might have been skipped while
* we were looking for a new ringbuffer
*/
if (next != NULL) {
_update_wptr(adreno_dev, false);
mod_timer(&adreno_dev->dispatcher.timer,
adreno_dev->cur_rb->dispatch_q.expires);
}
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
return;
}
/* Turn off the dispatcher timer */
del_timer(&adreno_dev->dispatcher.timer);
/*
* This is the most critical section - we need to take care not to race
* until we have programmed the CP for the switch
*/
spin_lock_irqsave(&next->preempt_lock, flags);
msm: kgsl: Catchup from msm-5.10 Update KGSL code to msm-5.10 commit f3801b189e25 (Merge "msm: kgsl: Correct a6xx CP init sequence"). This includes the following changes from msm-5.10: 4aabff3db0cf (msm: kgsl: Add support to query process memory usage) dcf93c3a2f0b (msm: kgsl: Vote ddr perf mode for better performance) dc70d7f2961e (msm: kgsl: Enable preemption for gen7 GPU) 211d943edc87 (msm: kgsl: Provide a mechanism to unbind a range in VBO) 45d7e571a332 (msm: kgsl: Correctly validate devfreq_add_device return value) a07afc4e1477 (msm: kgsl: Reclaim gpu pages asynchronously) 8b5de66d4f1d (msm: kgsl: Fix uninitialized variable use in kgsl_iommu_print_fault()) 0bd2f8ba6a8f (msm: kgsl: Use kmalloc() for HFI message storage) 79f18623e7f1 (msm: kgsl: Make sure BR doesn't race ahead of BV) 48fc67d2bcfb (msm: kgsl: Get rid of per ringbuffer scratch memory) 96f7537ccfcd (msm: kgsl: Remove redundant SET_PSEUDO_REGISTER packets) ca1cbeedfcd6 (msm: kgsl: Fix return value due to devfreq_add_device() failure) 2092f3df2fae (msm: kgsl: Add enable_signaling for timeline fence) 6f24e5a5112e (msm: kgsl: Remove unneeded NULL check when submitting commands) 9d13d7a5ca6d (msm: kgsl: Pre-allocate page pool tracking structures) 7e5a0845ad64 (msm: kgsl: Add Gen7 support for RDPM frequency register writes) 682d0ea32d62 (msm: kgsl: Add RDPM update for GMU frequency changes) 2eddfeae4850 (msm: kgsl: Add support for the new bit in RESET_CONTEXT_STATE packet) 1141005a4787 (msm: kgsl: Add support for A662 GPU) fc04d956e44a (msm: kgsl: Fix gmu power counter reg address) 286d5d09faf1 (msm: kgsl: Remove invalid kgsl_process_private_put) 4b5e16dbec0d (msm: kgsl: Update the list of protected registers for A730) 3a107bfc062a (msm: kgsl: Bail out of allocation loops if a SIG_KILL is pending) ca22fde3705d (msm: kgsl: Fix out of bound write in adreno_profile_submit_time) 73d27010f02f (msm: kgsl: Avoid parsing IBs during atomic snapshot) 684032d39451 (msm: kgsl: Correct VMID flag for secure buffer validation) 8548ed02e179 (msm: kgsl: Expose memtype stats through sysfs) 52757e33639a (msm: kgsl: Enable Preemption on A662 GPU) a8edbf590967 (msm: kgsl: Add support for new GMU uncached VA range) ff25ecb13ad5 (msm: kgsl: Remove process debugfs and kobject without mutex) 397f7d63607e (msm: kgsl: Fix clockgating values for various blocks) 06f837b9da4f (msm: kgsl: Allow concurrent requests for oob_perfcntr) 73a66962fe20 (msm: kgsl: Make the Adreno trace instance enabled through Kconfig) 6d65fed34558 (msm: kgsl: Update range checking when building voltage tables) 698d612ba43d (msm: kgsl: Verify secure access before importing buffers) 1a278333d0c7 (msm: kgsl: Fix syncsource spinlock recursion) 82c89093b63b (msm: kgsl: Fix HWSCHED_MAX_DISPATCH_NUMIBS) e6d7e1d4bdc3 (msm: kgsl: Set max ACD levels to match max power levels) eb56597e5392 (msm: kgsl: Ensure global entry free stays in bounds) 8a8fbdf97a7a (msm: kgsl: Ensure local variables are set before use) 402bb87906b3 (msm: kgsl: Take snapshot if GPU isn't idle before slumber) 6341d395821b (msm: kgsl: Fix syncpoint timeout log for timeline fences) 0058b5eb2760 (msm: kgsl: Add inflight commands to tracepoint) 127ac415117e (msm: kgsl: Fix NULL pointer dereference) 4433948157f8 (msm: kgsl: Do not process HFI queues in F2H daemon during init sequence) 6a298b62c2d7 (msm: kgsl: Increase wait during kgsl_open) e5fd445b298e (msm: kgsl: Update register protection config) eff8f6e07da7 (msm: kgsl: Set min_pwrlevel based on configuration) e13459b66d4a (msm: kgsl: Log unprotected write address) c19ed67ffbcf (msm: kgsl: Free up iommu page tables on process close) d221f9dd6c44 (msm: kgsl: Update the IFPC power up reglist) 697143a7d17a (msm: kgsl: Update GPUCC Offsets for A662) 180c1d5e124a (msm: kgsl: Add support for C501 GPU) f583f456d0a2 (msm: kgsl: Correct a6xx CP init sequence) dde4355ea92d (msm: kgsl: Add GBIF L2 CGC control with A6x CGC) Change-Id: Ib679fb0b2cb47b79e7caed531de0c0aa7ef0558d Signed-off-by: Lynus Vaz <quic_lvaz@quicinc.com>
2021-11-12 11:57:59 +09:00
/* Get the pagetable from the pagetable info. */
kgsl_sharedmem_readq(device->scratch, &ttbr0,
SCRATCH_RB_OFFSET(next->id, ttbr0));
kgsl_sharedmem_readl(device->scratch, &contextidr,
SCRATCH_RB_OFFSET(next->id, contextidr));
kgsl_sharedmem_writel(next->preemption_desc,
PREEMPT_RECORD(wptr), next->wptr);
spin_unlock_irqrestore(&next->preempt_lock, flags);
/* And write it to the smmu info */
if (kgsl_mmu_is_perprocess(&device->mmu)) {
kgsl_sharedmem_writeq(iommu->smmu_info,
PREEMPT_SMMU_RECORD(ttbr0), ttbr0);
kgsl_sharedmem_writel(iommu->smmu_info,
PREEMPT_SMMU_RECORD(context_idr), contextidr);
}
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO,
lower_32_bits(next->preemption_desc->gpuaddr));
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_HI,
upper_32_bits(next->preemption_desc->gpuaddr));
adreno_dev->next_rb = next;
/* Start the timer to detect a stuck preemption */
mod_timer(&adreno_dev->preempt.timer,
jiffies + msecs_to_jiffies(ADRENO_PREEMPT_TIMEOUT));
trace_adreno_preempt_trigger(adreno_dev->cur_rb->id, adreno_dev->next_rb->id,
1, 0);
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_TRIGGERED);
/* Trigger the preemption */
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_CNTL, 1);
}
void a5xx_preempt_callback(struct adreno_device *adreno_dev, int bit)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
unsigned int status;
if (!adreno_move_preempt_state(adreno_dev,
ADRENO_PREEMPT_TRIGGERED, ADRENO_PREEMPT_PENDING))
return;
kgsl_regread(device, A5XX_CP_CONTEXT_SWITCH_CNTL, &status);
if (status != 0) {
dev_err(KGSL_DEVICE(adreno_dev)->dev,
"preempt interrupt with non-zero status: %X\n",
status);
/*
* Under the assumption that this is a race between the
* interrupt and the register, schedule the worker to clean up.
* If the status still hasn't resolved itself by the time we get
* there then we have to assume something bad happened
*/
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_COMPLETE);
adreno_dispatcher_schedule(device);
return;
}
del_timer(&adreno_dev->preempt.timer);
trace_adreno_preempt_done(adreno_dev->cur_rb->id, adreno_dev->next_rb->id, 0, 0);
adreno_dev->prev_rb = adreno_dev->cur_rb;
adreno_dev->cur_rb = adreno_dev->next_rb;
adreno_dev->next_rb = NULL;
/* Update the wptr if it changed while preemption was ongoing */
_update_wptr(adreno_dev, true);
/* Update the dispatcher timer for the new command queue */
mod_timer(&adreno_dev->dispatcher.timer,
adreno_dev->cur_rb->dispatch_q.expires);
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
a5xx_preemption_trigger(adreno_dev);
}
void a5xx_preemption_schedule(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
if (!adreno_is_preemption_enabled(adreno_dev))
return;
mutex_lock(&device->mutex);
if (adreno_in_preempt_state(adreno_dev, ADRENO_PREEMPT_COMPLETE))
_a5xx_preemption_done(adreno_dev);
a5xx_preemption_trigger(adreno_dev);
mutex_unlock(&device->mutex);
}
u32 a5xx_preemption_pre_ibsubmit(struct adreno_device *adreno_dev,
struct adreno_ringbuffer *rb,
struct adreno_context *drawctxt, u32 *cmds)
{
unsigned int *cmds_orig = cmds;
uint64_t gpuaddr = rb->preemption_desc->gpuaddr;
unsigned int preempt_style = 0;
if (!adreno_is_preemption_enabled(adreno_dev))
return 0;
if (drawctxt) {
/*
* Preemption from secure to unsecure needs Zap shader to be
* run to clear all secure content. CP does not know during
* preemption if it is switching between secure and unsecure
* contexts so restrict Secure contexts to be preempted at
* ringbuffer level.
*/
if (drawctxt->base.flags & KGSL_CONTEXT_SECURE)
preempt_style = KGSL_CONTEXT_PREEMPT_STYLE_RINGBUFFER;
else
preempt_style = FIELD_GET(KGSL_CONTEXT_PREEMPT_STYLE_MASK,
drawctxt->base.flags);
}
/*
* CP_PREEMPT_ENABLE_GLOBAL(global preemption) can only be set by KMD
* in ringbuffer.
* 1) set global preemption to 0x0 to disable global preemption.
* Only RB level preemption is allowed in this mode
* 2) Set global preemption to defer(0x2) for finegrain preemption.
* when global preemption is set to defer(0x2),
* CP_PREEMPT_ENABLE_LOCAL(local preemption) determines the
* preemption point. Local preemption
* can be enabled by both UMD(within IB) and KMD.
*/
*cmds++ = cp_type7_packet(CP_PREEMPT_ENABLE_GLOBAL, 1);
*cmds++ = ((preempt_style == KGSL_CONTEXT_PREEMPT_STYLE_FINEGRAIN)
? 2 : 0);
/* Turn CP protection OFF */
cmds += cp_protected_mode(adreno_dev, cmds, 0);
/*
* CP during context switch will save context switch info to
* a5xx_cp_preemption_record pointed by CONTEXT_SWITCH_SAVE_ADDR
*/
*cmds++ = cp_type4_packet(A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO, 1);
*cmds++ = lower_32_bits(gpuaddr);
*cmds++ = cp_type4_packet(A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_HI, 1);
*cmds++ = upper_32_bits(gpuaddr);
/* Turn CP protection ON */
cmds += cp_protected_mode(adreno_dev, cmds, 1);
/*
* Enable local preemption for finegrain preemption in case of
* a misbehaving IB
*/
if (preempt_style == KGSL_CONTEXT_PREEMPT_STYLE_FINEGRAIN) {
*cmds++ = cp_type7_packet(CP_PREEMPT_ENABLE_LOCAL, 1);
*cmds++ = 1;
} else {
*cmds++ = cp_type7_packet(CP_PREEMPT_ENABLE_LOCAL, 1);
*cmds++ = 0;
}
/* Enable CP_CONTEXT_SWITCH_YIELD packets in the IB2s */
*cmds++ = cp_type7_packet(CP_YIELD_ENABLE, 1);
*cmds++ = 2;
return (unsigned int) (cmds - cmds_orig);
}
unsigned int a5xx_preemption_post_ibsubmit(struct adreno_device *adreno_dev,
unsigned int *cmds)
{
int dwords = 0;
if (!adreno_is_preemption_enabled(adreno_dev))
return 0;
cmds[dwords++] = cp_type7_packet(CP_CONTEXT_SWITCH_YIELD, 4);
/* Write NULL to the address to skip the data write */
dwords += cp_gpuaddr(adreno_dev, &cmds[dwords], 0x0);
cmds[dwords++] = 1;
/* generate interrupt on preemption completion */
cmds[dwords++] = 1;
return dwords;
}
void a5xx_preemption_start(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_iommu *iommu = KGSL_IOMMU(device);
struct adreno_ringbuffer *rb;
unsigned int i;
if (!adreno_is_preemption_enabled(adreno_dev))
return;
/* Force the state to be clear */
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
/* Only set up smmu info when per-process pagetables are enabled */
if (kgsl_mmu_is_perprocess(&device->mmu)) {
/* smmu_info is allocated and mapped in a5xx_preemption_iommu_init */
kgsl_sharedmem_writel(iommu->smmu_info,
PREEMPT_SMMU_RECORD(magic), A5XX_CP_SMMU_INFO_MAGIC_REF);
kgsl_sharedmem_writeq(iommu->smmu_info,
PREEMPT_SMMU_RECORD(ttbr0), MMU_DEFAULT_TTBR0(device));
/* The CP doesn't use the asid record, so poison it */
kgsl_sharedmem_writel(iommu->smmu_info,
PREEMPT_SMMU_RECORD(asid), 0xDECAFBAD);
kgsl_sharedmem_writel(iommu->smmu_info,
PREEMPT_SMMU_RECORD(context_idr), 0);
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_LO,
lower_32_bits(iommu->smmu_info->gpuaddr));
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_HI,
upper_32_bits(iommu->smmu_info->gpuaddr));
}
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
/*
* preemption_desc is allocated and mapped at init time,
* so no need to check sharedmem_writel return value
*/
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(rptr), 0);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(wptr), 0);
msm: kgsl: Catchup from msm-5.10 Update KGSL code to msm-5.10 commit f3801b189e25 (Merge "msm: kgsl: Correct a6xx CP init sequence"). This includes the following changes from msm-5.10: 4aabff3db0cf (msm: kgsl: Add support to query process memory usage) dcf93c3a2f0b (msm: kgsl: Vote ddr perf mode for better performance) dc70d7f2961e (msm: kgsl: Enable preemption for gen7 GPU) 211d943edc87 (msm: kgsl: Provide a mechanism to unbind a range in VBO) 45d7e571a332 (msm: kgsl: Correctly validate devfreq_add_device return value) a07afc4e1477 (msm: kgsl: Reclaim gpu pages asynchronously) 8b5de66d4f1d (msm: kgsl: Fix uninitialized variable use in kgsl_iommu_print_fault()) 0bd2f8ba6a8f (msm: kgsl: Use kmalloc() for HFI message storage) 79f18623e7f1 (msm: kgsl: Make sure BR doesn't race ahead of BV) 48fc67d2bcfb (msm: kgsl: Get rid of per ringbuffer scratch memory) 96f7537ccfcd (msm: kgsl: Remove redundant SET_PSEUDO_REGISTER packets) ca1cbeedfcd6 (msm: kgsl: Fix return value due to devfreq_add_device() failure) 2092f3df2fae (msm: kgsl: Add enable_signaling for timeline fence) 6f24e5a5112e (msm: kgsl: Remove unneeded NULL check when submitting commands) 9d13d7a5ca6d (msm: kgsl: Pre-allocate page pool tracking structures) 7e5a0845ad64 (msm: kgsl: Add Gen7 support for RDPM frequency register writes) 682d0ea32d62 (msm: kgsl: Add RDPM update for GMU frequency changes) 2eddfeae4850 (msm: kgsl: Add support for the new bit in RESET_CONTEXT_STATE packet) 1141005a4787 (msm: kgsl: Add support for A662 GPU) fc04d956e44a (msm: kgsl: Fix gmu power counter reg address) 286d5d09faf1 (msm: kgsl: Remove invalid kgsl_process_private_put) 4b5e16dbec0d (msm: kgsl: Update the list of protected registers for A730) 3a107bfc062a (msm: kgsl: Bail out of allocation loops if a SIG_KILL is pending) ca22fde3705d (msm: kgsl: Fix out of bound write in adreno_profile_submit_time) 73d27010f02f (msm: kgsl: Avoid parsing IBs during atomic snapshot) 684032d39451 (msm: kgsl: Correct VMID flag for secure buffer validation) 8548ed02e179 (msm: kgsl: Expose memtype stats through sysfs) 52757e33639a (msm: kgsl: Enable Preemption on A662 GPU) a8edbf590967 (msm: kgsl: Add support for new GMU uncached VA range) ff25ecb13ad5 (msm: kgsl: Remove process debugfs and kobject without mutex) 397f7d63607e (msm: kgsl: Fix clockgating values for various blocks) 06f837b9da4f (msm: kgsl: Allow concurrent requests for oob_perfcntr) 73a66962fe20 (msm: kgsl: Make the Adreno trace instance enabled through Kconfig) 6d65fed34558 (msm: kgsl: Update range checking when building voltage tables) 698d612ba43d (msm: kgsl: Verify secure access before importing buffers) 1a278333d0c7 (msm: kgsl: Fix syncsource spinlock recursion) 82c89093b63b (msm: kgsl: Fix HWSCHED_MAX_DISPATCH_NUMIBS) e6d7e1d4bdc3 (msm: kgsl: Set max ACD levels to match max power levels) eb56597e5392 (msm: kgsl: Ensure global entry free stays in bounds) 8a8fbdf97a7a (msm: kgsl: Ensure local variables are set before use) 402bb87906b3 (msm: kgsl: Take snapshot if GPU isn't idle before slumber) 6341d395821b (msm: kgsl: Fix syncpoint timeout log for timeline fences) 0058b5eb2760 (msm: kgsl: Add inflight commands to tracepoint) 127ac415117e (msm: kgsl: Fix NULL pointer dereference) 4433948157f8 (msm: kgsl: Do not process HFI queues in F2H daemon during init sequence) 6a298b62c2d7 (msm: kgsl: Increase wait during kgsl_open) e5fd445b298e (msm: kgsl: Update register protection config) eff8f6e07da7 (msm: kgsl: Set min_pwrlevel based on configuration) e13459b66d4a (msm: kgsl: Log unprotected write address) c19ed67ffbcf (msm: kgsl: Free up iommu page tables on process close) d221f9dd6c44 (msm: kgsl: Update the IFPC power up reglist) 697143a7d17a (msm: kgsl: Update GPUCC Offsets for A662) 180c1d5e124a (msm: kgsl: Add support for C501 GPU) f583f456d0a2 (msm: kgsl: Correct a6xx CP init sequence) dde4355ea92d (msm: kgsl: Add GBIF L2 CGC control with A6x CGC) Change-Id: Ib679fb0b2cb47b79e7caed531de0c0aa7ef0558d Signed-off-by: Lynus Vaz <quic_lvaz@quicinc.com>
2021-11-12 11:57:59 +09:00
adreno_ringbuffer_set_pagetable(device, rb,
device->mmu.defaultpagetable);
}
}
static int a5xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev,
struct adreno_ringbuffer *rb, uint64_t counteraddr)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
if (IS_ERR_OR_NULL(rb->preemption_desc))
rb->preemption_desc = kgsl_allocate_global(device,
A5XX_CP_CTXRECORD_SIZE_IN_BYTES, SZ_16K, 0,
KGSL_MEMDESC_PRIVILEGED, "preemption_desc");
if (IS_ERR(rb->preemption_desc))
return PTR_ERR(rb->preemption_desc);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(magic), A5XX_CP_CTXRECORD_MAGIC_REF);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(info), 0);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(data), 0);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(cntl), A5XX_CP_RB_CNTL_DEFAULT);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(rptr), 0);
kgsl_sharedmem_writel(rb->preemption_desc,
PREEMPT_RECORD(wptr), 0);
kgsl_sharedmem_writeq(rb->preemption_desc,
msm: kgsl: Catchup from msm-5.10 Update KGSL code to msm-5.10 commit f3801b189e25 (Merge "msm: kgsl: Correct a6xx CP init sequence"). This includes the following changes from msm-5.10: 4aabff3db0cf (msm: kgsl: Add support to query process memory usage) dcf93c3a2f0b (msm: kgsl: Vote ddr perf mode for better performance) dc70d7f2961e (msm: kgsl: Enable preemption for gen7 GPU) 211d943edc87 (msm: kgsl: Provide a mechanism to unbind a range in VBO) 45d7e571a332 (msm: kgsl: Correctly validate devfreq_add_device return value) a07afc4e1477 (msm: kgsl: Reclaim gpu pages asynchronously) 8b5de66d4f1d (msm: kgsl: Fix uninitialized variable use in kgsl_iommu_print_fault()) 0bd2f8ba6a8f (msm: kgsl: Use kmalloc() for HFI message storage) 79f18623e7f1 (msm: kgsl: Make sure BR doesn't race ahead of BV) 48fc67d2bcfb (msm: kgsl: Get rid of per ringbuffer scratch memory) 96f7537ccfcd (msm: kgsl: Remove redundant SET_PSEUDO_REGISTER packets) ca1cbeedfcd6 (msm: kgsl: Fix return value due to devfreq_add_device() failure) 2092f3df2fae (msm: kgsl: Add enable_signaling for timeline fence) 6f24e5a5112e (msm: kgsl: Remove unneeded NULL check when submitting commands) 9d13d7a5ca6d (msm: kgsl: Pre-allocate page pool tracking structures) 7e5a0845ad64 (msm: kgsl: Add Gen7 support for RDPM frequency register writes) 682d0ea32d62 (msm: kgsl: Add RDPM update for GMU frequency changes) 2eddfeae4850 (msm: kgsl: Add support for the new bit in RESET_CONTEXT_STATE packet) 1141005a4787 (msm: kgsl: Add support for A662 GPU) fc04d956e44a (msm: kgsl: Fix gmu power counter reg address) 286d5d09faf1 (msm: kgsl: Remove invalid kgsl_process_private_put) 4b5e16dbec0d (msm: kgsl: Update the list of protected registers for A730) 3a107bfc062a (msm: kgsl: Bail out of allocation loops if a SIG_KILL is pending) ca22fde3705d (msm: kgsl: Fix out of bound write in adreno_profile_submit_time) 73d27010f02f (msm: kgsl: Avoid parsing IBs during atomic snapshot) 684032d39451 (msm: kgsl: Correct VMID flag for secure buffer validation) 8548ed02e179 (msm: kgsl: Expose memtype stats through sysfs) 52757e33639a (msm: kgsl: Enable Preemption on A662 GPU) a8edbf590967 (msm: kgsl: Add support for new GMU uncached VA range) ff25ecb13ad5 (msm: kgsl: Remove process debugfs and kobject without mutex) 397f7d63607e (msm: kgsl: Fix clockgating values for various blocks) 06f837b9da4f (msm: kgsl: Allow concurrent requests for oob_perfcntr) 73a66962fe20 (msm: kgsl: Make the Adreno trace instance enabled through Kconfig) 6d65fed34558 (msm: kgsl: Update range checking when building voltage tables) 698d612ba43d (msm: kgsl: Verify secure access before importing buffers) 1a278333d0c7 (msm: kgsl: Fix syncsource spinlock recursion) 82c89093b63b (msm: kgsl: Fix HWSCHED_MAX_DISPATCH_NUMIBS) e6d7e1d4bdc3 (msm: kgsl: Set max ACD levels to match max power levels) eb56597e5392 (msm: kgsl: Ensure global entry free stays in bounds) 8a8fbdf97a7a (msm: kgsl: Ensure local variables are set before use) 402bb87906b3 (msm: kgsl: Take snapshot if GPU isn't idle before slumber) 6341d395821b (msm: kgsl: Fix syncpoint timeout log for timeline fences) 0058b5eb2760 (msm: kgsl: Add inflight commands to tracepoint) 127ac415117e (msm: kgsl: Fix NULL pointer dereference) 4433948157f8 (msm: kgsl: Do not process HFI queues in F2H daemon during init sequence) 6a298b62c2d7 (msm: kgsl: Increase wait during kgsl_open) e5fd445b298e (msm: kgsl: Update register protection config) eff8f6e07da7 (msm: kgsl: Set min_pwrlevel based on configuration) e13459b66d4a (msm: kgsl: Log unprotected write address) c19ed67ffbcf (msm: kgsl: Free up iommu page tables on process close) d221f9dd6c44 (msm: kgsl: Update the IFPC power up reglist) 697143a7d17a (msm: kgsl: Update GPUCC Offsets for A662) 180c1d5e124a (msm: kgsl: Add support for C501 GPU) f583f456d0a2 (msm: kgsl: Correct a6xx CP init sequence) dde4355ea92d (msm: kgsl: Add GBIF L2 CGC control with A6x CGC) Change-Id: Ib679fb0b2cb47b79e7caed531de0c0aa7ef0558d Signed-off-by: Lynus Vaz <quic_lvaz@quicinc.com>
2021-11-12 11:57:59 +09:00
PREEMPT_RECORD(rptr_addr), SCRATCH_RB_GPU_ADDR(device,
rb->id, rptr));
kgsl_sharedmem_writeq(rb->preemption_desc,
PREEMPT_RECORD(rbase), rb->buffer_desc->gpuaddr);
kgsl_sharedmem_writeq(rb->preemption_desc,
PREEMPT_RECORD(counter), counteraddr);
return 0;
}
int a5xx_preemption_init(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_iommu *iommu = KGSL_IOMMU(device);
struct adreno_preemption *preempt = &adreno_dev->preempt;
struct adreno_ringbuffer *rb;
int ret;
unsigned int i;
uint64_t addr;
/* We are dependent on IOMMU to make preemption go on the CP side */
if (kgsl_mmu_get_mmutype(device) != KGSL_MMU_TYPE_IOMMU)
return -ENODEV;
INIT_WORK(&preempt->work, _a5xx_preemption_worker);
/* Allocate mem for storing preemption counters */
if (IS_ERR_OR_NULL(preempt->scratch))
preempt->scratch = kgsl_allocate_global(device,
adreno_dev->num_ringbuffers *
A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0, 0,
"preemption_counters");
ret = PTR_ERR_OR_ZERO(preempt->scratch);
if (ret)
return ret;
addr = preempt->scratch->gpuaddr;
/* Allocate mem for storing preemption switch record */
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
ret = a5xx_preemption_ringbuffer_init(adreno_dev, rb, addr);
if (ret)
return ret;
addr += A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE;
}
/* Allocate mem for storing preemption smmu record */
if (kgsl_mmu_is_perprocess(&device->mmu) && IS_ERR_OR_NULL(iommu->smmu_info))
iommu->smmu_info = kgsl_allocate_global(device, PAGE_SIZE, 0,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED,
"smmu_info");
if (IS_ERR(iommu->smmu_info))
return PTR_ERR(iommu->smmu_info);
set_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
return 0;
}