Merge tag 'LA.UM.10.3.c25-02100-sdm845.0' of https://git.codelinaro.org/clo/la/kernel/msm-4.9 into android13-4.9-sdm845
"LA.UM.10.3.c25-02100-sdm845.0" * tag 'LA.UM.10.3.c25-02100-sdm845.0' of https://git.codelinaro.org/clo/la/kernel/msm-4.9: soc: qcom: smem: Add boundary checks for partitions msm: kgsl: Update the protect register list msm: kgsl: Do not release dma and anon buffers if unmap fails msm: kgsl: Do not free sharedmem if it cannot be unmapped msm: ADSPRPC: Restrict untrusted applications from attaching to GuestOS msm: kgsl: Use dma_buf_get() to get dma_buf structure pinctrl: qcom: Using readl_relaxed/writel_relaxed APIs msm: adsprpc: Handle UAF in fastrpc internal munmap iommu: Fix missing return check of arm_lpae_init_pte bus: mhi: misc: Add check for dev_rp if it is iommu range or not net: ipc_router: Add bounds check on tx path msm: kgsl: Remove 'fd' dependency to get dma_buf handle msm: kgsl: Keep postamble packets in a privileged buffer msm: kgsl: Make sure that pool pages don't have any extra references msm: kgsl: Prevent wrap around during user address mapping Conflicts: drivers/char/adsprpc.c drivers/gpu/msm/kgsl.c drivers/gpu/msm/kgsl_iommu.c drivers/gpu/msm/kgsl_mmu.c drivers/pinctrl/qcom/pinctrl-msm.c Change-Id: I431924199616b135e180fd3a6421bb5037bcf164
This commit is contained in:
commit
262ef91bdf
9 changed files with 178 additions and 181 deletions
|
|
@ -759,6 +759,12 @@ int mhi_send_cmd(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
|||
enum MHI_CMD cmd);
|
||||
int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
static inline bool is_valid_ring_ptr(struct mhi_ring *ring, dma_addr_t addr)
|
||||
{
|
||||
return ((addr >= ring->iommu_base &&
|
||||
addr < ring->iommu_base + ring->len) && (addr % 16 == 0));
|
||||
}
|
||||
|
||||
/* queue transfer buffer */
|
||||
int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
void *buf, void *cb, size_t buf_len, enum MHI_FLAGS flags);
|
||||
|
|
|
|||
|
|
@ -1337,6 +1337,13 @@ int mhi_process_tsync_event_ring(struct mhi_controller *mhi_cntrl,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (!is_valid_ring_ptr(ev_ring, er_ctxt->rp)) {
|
||||
MHI_ERR(
|
||||
"Event ring rp points outside of the event ring or unalign rp %llx\n",
|
||||
er_ctxt->rp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp);
|
||||
local_rp = ev_ring->rp;
|
||||
|
||||
|
|
@ -1425,6 +1432,14 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
|
|||
}
|
||||
|
||||
spin_lock_bh(&mhi_event->lock);
|
||||
if (!is_valid_ring_ptr(ev_ring, er_ctxt->rp)) {
|
||||
MHI_ERR(
|
||||
"Event ring rp points outside of the event ring or unalign rp %llx\n",
|
||||
er_ctxt->rp);
|
||||
spin_unlock_bh(&mhi_event->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp);
|
||||
|
||||
if (ev_ring->rp == dev_rp) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2002,2007-2018,2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -2015,17 +2015,6 @@ static int _adreno_start(struct adreno_device *adreno_dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (kgsl_gmu_isenabled(device) && adreno_dev->perfctr_ifpc_lo == 0) {
|
||||
ret = adreno_perfcounter_get(adreno_dev,
|
||||
KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 4,
|
||||
&adreno_dev->perfctr_ifpc_lo, NULL,
|
||||
PERFCOUNTER_FLAG_KERNEL);
|
||||
if (ret) {
|
||||
WARN_ONCE(1, "Unable to get perf counter for IFPC\n");
|
||||
adreno_dev->perfctr_ifpc_lo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the busy_data stats - we're starting over from scratch */
|
||||
adreno_dev->busy_data.gpu_busy = 0;
|
||||
adreno_dev->busy_data.bif_ram_cycles = 0;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (c) 2017-2018,2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -244,42 +245,6 @@ static const struct {
|
|||
{adreno_is_a616, a615_hwcg_regs, ARRAY_SIZE(a615_hwcg_regs)},
|
||||
};
|
||||
|
||||
static struct a6xx_protected_regs {
|
||||
unsigned int base;
|
||||
unsigned int count;
|
||||
int read_protect;
|
||||
} a6xx_protected_regs_group[] = {
|
||||
{ 0x600, 0x51, 0 },
|
||||
{ 0xAE50, 0x2, 1 },
|
||||
{ 0x9624, 0x13, 1 },
|
||||
{ 0x8630, 0x8, 1 },
|
||||
{ 0x9E70, 0x1, 1 },
|
||||
{ 0x9E78, 0x187, 1 },
|
||||
{ 0xF000, 0x810, 1 },
|
||||
{ 0xFC00, 0x3, 0 },
|
||||
{ 0x50E, 0x0, 1 },
|
||||
{ 0x50F, 0x0, 0 },
|
||||
{ 0x510, 0x0, 1 },
|
||||
{ 0x0, 0x4F9, 0 },
|
||||
{ 0x501, 0xA, 0 },
|
||||
{ 0x511, 0x44, 0 },
|
||||
{ 0xE00, 0x1, 1 },
|
||||
{ 0xE03, 0xB, 1 },
|
||||
{ 0x8E00, 0x0, 1 },
|
||||
{ 0x8E50, 0xF, 1 },
|
||||
{ 0xBE02, 0x0, 1 },
|
||||
{ 0xBE20, 0x11F3, 1 },
|
||||
{ 0x800, 0x82, 1 },
|
||||
{ 0x8A0, 0x8, 1 },
|
||||
{ 0x8AB, 0x19, 1 },
|
||||
{ 0x900, 0x4D, 1 },
|
||||
{ 0x98D, 0x76, 1 },
|
||||
{ 0x8D0, 0x23, 0 },
|
||||
{ 0x980, 0x4, 0 },
|
||||
{ 0xA630, 0x0, 1 },
|
||||
{ 0x1b400, 0x1fff, 1 },
|
||||
};
|
||||
|
||||
/* IFPC & Preemption static powerup restore list */
|
||||
static struct reg_list_pair {
|
||||
uint32_t offset;
|
||||
|
|
@ -360,6 +325,61 @@ static struct reg_list_pair a615_pwrup_reglist[] = {
|
|||
{ A6XX_UCHE_GBIF_GX_CONFIG, 0x0 },
|
||||
};
|
||||
|
||||
/**
|
||||
* struct a6xx_protected_regs - container for a protect register span
|
||||
*/
|
||||
static const struct a6xx_protected_regs {
|
||||
/** @reg: Physical protected mode register to write to */
|
||||
u32 reg;
|
||||
/** @start: Dword offset of the starting register in the range */
|
||||
u32 start;
|
||||
/**
|
||||
* @end: Dword offset of the ending register in the range
|
||||
* (inclusive)
|
||||
*/
|
||||
u32 end;
|
||||
/**
|
||||
* @noaccess: 1 if the register should not be accessible from
|
||||
* userspace, 0 if it can be read (but not written)
|
||||
*/
|
||||
u32 noaccess;
|
||||
}
|
||||
a630_protected_regs[] = {
|
||||
{ A6XX_CP_PROTECT_REG + 0, 0x00000, 0x004ff, 0 },
|
||||
{ A6XX_CP_PROTECT_REG + 1, 0x00501, 0x00506, 0 },
|
||||
{ A6XX_CP_PROTECT_REG + 2, 0x0050b, 0x007ff, 0 },
|
||||
{ A6XX_CP_PROTECT_REG + 3, 0x0050e, 0x0050e, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 4, 0x00510, 0x00510, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 5, 0x00534, 0x00534, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 6, 0x00800, 0x00882, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 7, 0x008a0, 0x008a8, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 8, 0x008ab, 0x008cf, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 9, 0x008d0, 0x0098c, 0 },
|
||||
{A6XX_CP_PROTECT_REG + 10, 0x00900, 0x0094d, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 11, 0x0098d, 0x00bff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 12, 0x00e00, 0x00e01, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 13, 0x00e03, 0x00e0f, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 14, 0x03c00, 0x03cc3, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 15, 0x03cc4, 0x05cc3, 0 },
|
||||
{ A6XX_CP_PROTECT_REG + 16, 0x08630, 0x087ff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 17, 0x08e00, 0x08e00, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 18, 0x08e08, 0x08e08, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 19, 0x08e50, 0x08e6f, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 20, 0x09624, 0x097ff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 21, 0x09e70, 0x09e71, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 22, 0x09e78, 0x09fff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 23, 0x0a630, 0x0a7ff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 24, 0x0ae02, 0x0ae02, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 25, 0x0ae50, 0x0b17f, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 26, 0x0b604, 0x0b604, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 27, 0x0be02, 0x0be03, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 28, 0x0be20, 0x0d5ff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 29, 0x0f000, 0x0fbff, 1 },
|
||||
{ A6XX_CP_PROTECT_REG + 30, 0x0fc00, 0x11bff, 0 },
|
||||
{ A6XX_CP_PROTECT_REG + 31, 0x11c00, 0x11c00, 1 },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void _update_always_on_regs(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
||||
|
|
@ -424,49 +444,31 @@ static void a6xx_init(struct adreno_device *adreno_dev)
|
|||
static void a6xx_protect_init(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct kgsl_protected_registers *mmu_prot =
|
||||
kgsl_mmu_get_prot_regs(&device->mmu);
|
||||
int i, num_sets;
|
||||
int req_sets = ARRAY_SIZE(a6xx_protected_regs_group);
|
||||
int max_sets = adreno_dev->gpucore->num_protected_regs;
|
||||
unsigned int mmu_base = 0, mmu_range = 0, cur_range;
|
||||
const struct a6xx_protected_regs *regs = a630_protected_regs;
|
||||
int i;
|
||||
|
||||
/* enable access protection to privileged registers */
|
||||
kgsl_regwrite(device, A6XX_CP_PROTECT_CNTL, 0x00000003);
|
||||
/*
|
||||
* Enable access protection to privileged registers, fault on an access
|
||||
* protect violation and select the last span to protect from the start
|
||||
* address all the way to the end of the register address space
|
||||
*/
|
||||
kgsl_regwrite(device, A6XX_CP_PROTECT_CNTL,
|
||||
(1 << 0) | (1 << 1) | (1 << 3));
|
||||
|
||||
if (mmu_prot) {
|
||||
mmu_base = mmu_prot->base;
|
||||
mmu_range = mmu_prot->range;
|
||||
req_sets += DIV_ROUND_UP(mmu_range, 0x2000);
|
||||
}
|
||||
/* Program each register defined by the core definition */
|
||||
for (i = 0; regs[i].reg; i++) {
|
||||
u32 count;
|
||||
|
||||
if (req_sets > max_sets)
|
||||
WARN(1, "Size exceeds the num of protection regs available\n");
|
||||
/*
|
||||
* This is the offset of the end register as counted from the
|
||||
* start, i.e. # of registers in the range - 1
|
||||
*/
|
||||
count = regs[i].end - regs[i].start;
|
||||
|
||||
/* Protect GPU registers */
|
||||
num_sets = min_t(unsigned int,
|
||||
ARRAY_SIZE(a6xx_protected_regs_group), max_sets);
|
||||
for (i = 0; i < num_sets; i++) {
|
||||
struct a6xx_protected_regs *regs =
|
||||
&a6xx_protected_regs_group[i];
|
||||
|
||||
kgsl_regwrite(device, A6XX_CP_PROTECT_REG + i,
|
||||
regs->base | (regs->count << 18) |
|
||||
(regs->read_protect << 31));
|
||||
}
|
||||
|
||||
/* Protect MMU registers */
|
||||
if (mmu_prot) {
|
||||
while ((i < max_sets) && (mmu_range > 0)) {
|
||||
cur_range = min_t(unsigned int, mmu_range,
|
||||
0x2000);
|
||||
kgsl_regwrite(device, A6XX_CP_PROTECT_REG + i,
|
||||
mmu_base | ((cur_range - 1) << 18) | (1 << 31));
|
||||
|
||||
mmu_base += cur_range;
|
||||
mmu_range -= cur_range;
|
||||
i++;
|
||||
}
|
||||
kgsl_regwrite(device, regs[i].reg,
|
||||
(regs[i].start & 0x3ffff) |
|
||||
((count & 0x1fff) << 18) |
|
||||
(regs[i].noaccess << 31));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -721,6 +723,11 @@ static void a6xx_start(struct adreno_device *adreno_dev)
|
|||
/* Turn on performance counters */
|
||||
kgsl_regwrite(device, A6XX_RBBM_PERFCTR_CNTL, 0x1);
|
||||
|
||||
/* Turn on the IFPC counter (countable 4 on XOCLK4) */
|
||||
if (kgsl_gmu_isenabled(device))
|
||||
kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_1,
|
||||
0xff, 0x4);
|
||||
|
||||
if (of_property_read_u32(device->pdev->dev.of_node,
|
||||
"qcom,highest-bank-bit", &bit))
|
||||
bit = MIN_HBB;
|
||||
|
|
@ -782,6 +789,13 @@ static void a6xx_start(struct adreno_device *adreno_dev)
|
|||
if (adreno_is_preemption_enabled(adreno_dev))
|
||||
kgsl_regwrite(device, A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE,
|
||||
0x1);
|
||||
/*
|
||||
* Enable GMU power counter 0 to count GPU busy. This is applicable to
|
||||
* all a6xx targets
|
||||
*/
|
||||
kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000);
|
||||
kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20);
|
||||
kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1);
|
||||
|
||||
a6xx_protect_init(adreno_dev);
|
||||
|
||||
|
|
@ -3455,50 +3469,11 @@ static struct adreno_perfcount_register a6xx_perfcounters_gbif_pwr[] = {
|
|||
A6XX_GBIF_PWR_CNT_HIGH2, -1, A6XX_GBIF_PERF_PWR_CNT_EN },
|
||||
};
|
||||
|
||||
static struct adreno_perfcount_register a6xx_perfcounters_pwr[] = {
|
||||
{ KGSL_PERFCOUNTER_BROKEN, 0, 0, 0, 0, -1, 0 },
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H, -1, 0 },
|
||||
};
|
||||
|
||||
static struct adreno_perfcount_register a6xx_perfcounters_alwayson[] = {
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0, A6XX_CP_ALWAYS_ON_COUNTER_LO,
|
||||
A6XX_CP_ALWAYS_ON_COUNTER_HI, -1 },
|
||||
};
|
||||
|
||||
static struct adreno_perfcount_register a6xx_pwrcounters_gpmu[] = {
|
||||
/*
|
||||
* A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0 is used for the GPU
|
||||
* busy count (see the PWR group above). Mark it as broken
|
||||
* so it's not re-used.
|
||||
*/
|
||||
{ KGSL_PERFCOUNTER_BROKEN, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H, -1,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, },
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_1_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_1_H, -1,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, },
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_2_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_2_H, -1,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, },
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_3_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_3_H, -1,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, },
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_H, -1,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_1, },
|
||||
{ KGSL_PERFCOUNTER_NOT_USED, 0, 0,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_5_L,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_5_H, -1,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_1, },
|
||||
};
|
||||
|
||||
/*
|
||||
* ADRENO_PERFCOUNTER_GROUP_RESTORE flag is enabled by default
|
||||
* because most of the perfcounter groups need to be restored
|
||||
|
|
@ -3537,11 +3512,8 @@ static struct adreno_perfcount_group a6xx_perfcounter_groups
|
|||
A6XX_PERFCOUNTER_GROUP_FLAGS(VBIF, vbif, 0),
|
||||
A6XX_PERFCOUNTER_GROUP_FLAGS(VBIF_PWR, vbif_pwr,
|
||||
ADRENO_PERFCOUNTER_GROUP_FIXED),
|
||||
A6XX_PERFCOUNTER_GROUP_FLAGS(PWR, pwr,
|
||||
ADRENO_PERFCOUNTER_GROUP_FIXED),
|
||||
A6XX_PERFCOUNTER_GROUP_FLAGS(ALWAYSON, alwayson,
|
||||
ADRENO_PERFCOUNTER_GROUP_FIXED),
|
||||
A6XX_POWER_COUNTER_GROUP(GPMU, gpmu),
|
||||
};
|
||||
|
||||
static struct adreno_perfcounters a6xx_perfcounters = {
|
||||
|
|
@ -3549,30 +3521,6 @@ static struct adreno_perfcounters a6xx_perfcounters = {
|
|||
ARRAY_SIZE(a6xx_perfcounter_groups),
|
||||
};
|
||||
|
||||
/* Program the GMU power counter to count GPU busy cycles */
|
||||
static int a6xx_enable_pwr_counters(struct adreno_device *adreno_dev,
|
||||
unsigned int counter)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
|
||||
/*
|
||||
* We have a limited number of power counters. Since we're not using
|
||||
* total GPU cycle count, return error if requested.
|
||||
*/
|
||||
if (counter == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!device->gmu.pdev)
|
||||
return -ENODEV;
|
||||
|
||||
kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xFF000000);
|
||||
kgsl_regrmw(device,
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xFF, 0x20);
|
||||
kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void a6xx_efuse_speed_bin(struct adreno_device *adreno_dev)
|
||||
{
|
||||
unsigned int val;
|
||||
|
|
@ -3637,6 +3585,13 @@ static void a6xx_platform_setup(struct adreno_device *adreno_dev)
|
|||
gpudev->vbif_xin_halt_ctrl0_mask =
|
||||
A6XX_VBIF_XIN_HALT_CTRL0_MASK;
|
||||
|
||||
/* Set the counter for IFPC */
|
||||
if (ADRENO_FEATURE(adreno_dev, ADRENO_IFPC))
|
||||
adreno_dev->perfctr_ifpc_lo =
|
||||
A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L;
|
||||
/* Set the GPU busy counter for frequency scaling */
|
||||
adreno_dev->perfctr_pwr_lo = A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L;
|
||||
|
||||
/* Check efuse bits for various capabilties */
|
||||
a6xx_check_features(adreno_dev);
|
||||
}
|
||||
|
|
@ -3876,7 +3831,6 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
|
|||
.regulator_enable = a6xx_sptprac_enable,
|
||||
.regulator_disable = a6xx_sptprac_disable,
|
||||
.perfcounters = &a6xx_perfcounters,
|
||||
.enable_pwr_counters = a6xx_enable_pwr_counters,
|
||||
.count_throttles = a6xx_count_throttles,
|
||||
.microcode_read = a6xx_microcode_read,
|
||||
.enable_64bit = a6xx_enable_64bit,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include "adreno_trace.h"
|
||||
|
||||
#include "a3xx_reg.h"
|
||||
#include "a6xx_reg.h"
|
||||
#include "adreno_a5xx.h"
|
||||
|
||||
#define RB_HOSTPTR(_rb, _pos) \
|
||||
|
|
@ -877,6 +878,8 @@ static inline int _get_alwayson_counter(struct adreno_device *adreno_dev,
|
|||
ADRENO_GPUREV(adreno_dev) <= ADRENO_REV_A530)
|
||||
*p++ = adreno_getreg(adreno_dev,
|
||||
ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO);
|
||||
else if (adreno_is_a6xx(adreno_dev))
|
||||
*p++ = A6XX_CP_ALWAYS_ON_COUNTER_LO | (1 << 30) | (2 << 18);
|
||||
else
|
||||
*p++ = adreno_getreg(adreno_dev,
|
||||
ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO) |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -276,6 +276,9 @@ static void kgsl_destroy_ion(struct kgsl_memdesc *memdesc)
|
|||
struct kgsl_mem_entry, memdesc);
|
||||
struct kgsl_dma_buf_meta *meta = entry->priv_data;
|
||||
|
||||
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
|
||||
return;
|
||||
|
||||
if (meta != NULL) {
|
||||
dma_buf_unmap_attachment(meta->attach, meta->table,
|
||||
DMA_FROM_DEVICE);
|
||||
|
|
@ -303,6 +306,9 @@ static void kgsl_destroy_anon(struct kgsl_memdesc *memdesc)
|
|||
struct scatterlist *sg;
|
||||
struct page *page;
|
||||
|
||||
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
|
||||
return;
|
||||
|
||||
for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) {
|
||||
page = sg_page(sg);
|
||||
for (j = 0; j < (sg->length >> PAGE_SHIFT); j++) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2002,2007-2017,2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -505,6 +505,8 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
|
|||
size = kgsl_memdesc_footprint(memdesc);
|
||||
|
||||
ret = pagetable->pt_ops->mmu_unmap(pagetable, memdesc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
atomic_dec(&pagetable->stats.entries);
|
||||
atomic_long_sub(size, &pagetable->stats.mapped);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -479,6 +480,9 @@ done:
|
|||
|
||||
static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
|
||||
return;
|
||||
|
||||
kgsl_page_alloc_unmap_kernel(memdesc);
|
||||
/* we certainly do not expect the hostptr to still be mapped */
|
||||
BUG_ON(memdesc->hostptr);
|
||||
|
|
@ -582,6 +586,9 @@ static void kgsl_cma_coherent_free(struct kgsl_memdesc *memdesc)
|
|||
{
|
||||
unsigned long attrs = 0;
|
||||
|
||||
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
|
||||
return;
|
||||
|
||||
if (memdesc->hostptr) {
|
||||
if (memdesc->priv & KGSL_MEMDESC_SECURE) {
|
||||
atomic_long_sub(memdesc->size,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Sony Mobile Communications AB.
|
||||
* Copyright (c) 2012-2013, 2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -85,6 +86,17 @@
|
|||
/* Max number of processors/hosts in a system */
|
||||
#define SMEM_HOST_COUNT 9
|
||||
|
||||
/* Entry range check
|
||||
* ptr >= start : Checks if ptr is greater than the start of access region
|
||||
* ptr + size >= ptr: Check for integer overflow (On 32bit system where ptr
|
||||
* and size are 32bits, ptr + size can wrap around to be a small integer)
|
||||
* ptr + size <= end: Checks if ptr+size is less than the end of access region
|
||||
*/
|
||||
#define IN_PARTITION_RANGE(ptr, size, start, end) \
|
||||
(((void *)(ptr) >= (void *)(start)) && \
|
||||
(((void *)(ptr) + (size)) >= (void *)(ptr)) && \
|
||||
(((void *)(ptr) + (size)) <= (void *)(end)))
|
||||
|
||||
/**
|
||||
* struct smem_proc_comm - proc_comm communication struct (legacy)
|
||||
* @command: current command to be executed
|
||||
|
|
@ -313,7 +325,8 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
|
|||
end = phdr_to_last_private_entry(phdr);
|
||||
cached = phdr_to_first_cached_entry(phdr);
|
||||
|
||||
if (WARN_ON((void *)end > p_end || (void *)cached > p_end))
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(end, 0, phdr, cached) ||
|
||||
cached > p_end))
|
||||
return -EINVAL;
|
||||
|
||||
while (hdr < end) {
|
||||
|
|
@ -482,8 +495,9 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
|
|||
unsigned item,
|
||||
size_t *size)
|
||||
{
|
||||
|
||||
struct smem_partition_header *phdr;
|
||||
struct smem_private_entry *e, *end;
|
||||
struct smem_private_entry *e, *uncached_end, *cached_end;
|
||||
void *item_ptr, *p_end;
|
||||
u32 partition_size;
|
||||
u32 padding_data;
|
||||
|
|
@ -494,35 +508,36 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
|
|||
p_end = (void *)phdr + partition_size;
|
||||
|
||||
e = phdr_to_first_private_entry(phdr);
|
||||
end = phdr_to_last_private_entry(phdr);
|
||||
uncached_end = phdr_to_last_private_entry(phdr);
|
||||
cached_end = phdr_to_first_cached_entry(phdr);
|
||||
|
||||
if (WARN_ON((void *)end > p_end))
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(uncached_end, 0, phdr, uncached_end)
|
||||
|| (void *)cached_end > p_end))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
while (e < end) {
|
||||
if (e->canary != SMEM_PRIVATE_CANARY) {
|
||||
dev_err(smem->dev,
|
||||
"Found invalid canary in host %d:%d partition\n",
|
||||
phdr->host0, phdr->host1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
while ((e < uncached_end) && ((e + 1) < uncached_end)) {
|
||||
if (e->canary != SMEM_PRIVATE_CANARY)
|
||||
goto invalid_canary;
|
||||
|
||||
if (le16_to_cpu(e->item) == item) {
|
||||
if (size != NULL) {
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
|
||||
if (e_size < partition_size
|
||||
&& padding_data < e_size)
|
||||
*size = e_size - padding_data;
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
item_ptr = entry_to_item(e);
|
||||
if (WARN_ON(item_ptr > p_end))
|
||||
if (e_size < partition_size && padding_data < e_size)
|
||||
entry_size = e_size - padding_data;
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
item_ptr = entry_to_item(e);
|
||||
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, e,
|
||||
uncached_end)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (size != NULL)
|
||||
*size = entry_size;
|
||||
|
||||
return item_ptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue