From 19d2ff4fcddc6ce54549ef6ef7428f59e307e0c0 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Mon, 12 Jul 2021 19:56:00 +0530 Subject: [PATCH 01/21] msm: kgsl: Add support for A643 GPU Add A643 GPUID and initial settings to support graphics functionality. Change-Id: I494eae913b7fd4554a353789d79e52f96d0609f8 Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/adreno-gpulist.h | 33 ++++++++++++++++++++++++++++++++ drivers/gpu/msm/adreno.h | 8 +++++--- drivers/gpu/msm/adreno_a6xx.c | 11 ++++++++--- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 99ac323dd2fc..a63e3c43f60a 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -1746,6 +1746,38 @@ static const struct adreno_a6xx_core adreno_gpu_core_a642l = { .ctxt_record_size = 2496 * 1024, }; +static const struct adreno_a6xx_core adreno_gpu_core_a643 = { + .base = { + DEFINE_ADRENO_REV(ADRENO_REV_A643, ANY_ID, ANY_ID, ANY_ID, ANY_ID), + .compatible = "qcom,adreno-gpu-a643", + .features = ADRENO_RPMH | ADRENO_GPMU | ADRENO_APRIV | + ADRENO_IOCOHERENT | ADRENO_CONTENT_PROTECTION | + ADRENO_PREEMPTION | ADRENO_IFPC | ADRENO_BCL, + .gpudev = &adreno_a6xx_gmu_gpudev, + .perfcounters = &adreno_a6xx_perfcounters, + .gmem_size = SZ_512K, + .bus_width = 32, + .snapshot_size = SZ_2M, + }, + .prim_fifo_threshold = 0x00200000, + .gmu_major = 2, + .gmu_minor = 0, + .sqefw_name = "a660_sqe.fw", + .gmufw_name = "a660_gmu.bin", + .zap_name = "a660_zap", + .hwcg = a660_hwcg_regs, + .hwcg_count = ARRAY_SIZE(a660_hwcg_regs), + .vbif = a650_gbif_regs, + .vbif_count = ARRAY_SIZE(a650_gbif_regs), + .hang_detect_cycles = 0x3ffff, + .veto_fal10 = true, + .protected_regs = a660_protected_regs, + .disable_tseskip = true, + .highest_bank_bit = 15, + .pdc_in_aop = true, + .ctxt_record_size = 2496 * 1024, +}; + static const struct adreno_reglist a702_hwcg_regs[] = { {A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222}, {A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, @@ -1863,5 +1895,6 @@ static const struct adreno_gpu_core *adreno_gpulist[] = { &adreno_gpu_core_a610.base, &adreno_gpu_core_a642.base, &adreno_gpu_core_a642l.base, + &adreno_gpu_core_a643.base, &adreno_gpu_core_a702.base, }; diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 96285930c208..833ff5211925 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -202,6 +202,7 @@ enum adreno_gpurev { ADRENO_REV_A630 = 630, ADRENO_REV_A640 = 640, ADRENO_REV_A642 = 642, + ADRENO_REV_A643 = 643, ADRENO_REV_A650 = 650, ADRENO_REV_A660 = 660, ADRENO_REV_A680 = 680, @@ -1074,17 +1075,18 @@ ADRENO_TARGET(a619, ADRENO_REV_A619) ADRENO_TARGET(a620, ADRENO_REV_A620) ADRENO_TARGET(a630, ADRENO_REV_A630) ADRENO_TARGET(a640, ADRENO_REV_A640) +ADRENO_TARGET(a643, ADRENO_REV_A643) ADRENO_TARGET(a650, ADRENO_REV_A650) ADRENO_TARGET(a680, ADRENO_REV_A680) ADRENO_TARGET(a702, ADRENO_REV_A702) -/* A642 and A642L are derived from A660 and shares same logic */ +/* A642, A642L and A643 are derived from A660 and shares same logic */ static inline int adreno_is_a660(struct adreno_device *adreno_dev) { unsigned int rev = ADRENO_GPUREV(adreno_dev); return (rev == ADRENO_REV_A660 || adreno_is_a642(adreno_dev) || - adreno_is_a642l(adreno_dev)); + adreno_is_a642l(adreno_dev) || adreno_is_a643(adreno_dev)); } /* @@ -1123,7 +1125,7 @@ static inline int adreno_is_a650_family(struct adreno_device *adreno_dev) return (rev == ADRENO_REV_A650 || rev == ADRENO_REV_A620 || rev == ADRENO_REV_A660 || adreno_is_a642(adreno_dev) || - adreno_is_a642l(adreno_dev)); + adreno_is_a642l(adreno_dev) || rev == ADRENO_REV_A643); } static inline int adreno_is_a619_holi(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 2e61ace9b9ae..0c833132b6c8 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -175,7 +175,8 @@ int a6xx_init(struct adreno_device *adreno_dev) /* If the memory type is DDR 4, override the existing configuration */ if (of_fdt_get_ddrtype() == 0x7) { if (adreno_is_a642(adreno_dev) || - adreno_is_a642l(adreno_dev)) + adreno_is_a642l(adreno_dev) || + adreno_is_a643(adreno_dev)) adreno_dev->highest_bank_bit = 14; else if ((adreno_is_a650(adreno_dev) || adreno_is_a660(adreno_dev))) @@ -819,8 +820,12 @@ void a6xx_start(struct adreno_device *adreno_dev) kgsl_regwrite(device, A6XX_CP_CHICKEN_DBG, 0x1); kgsl_regwrite(device, A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x0); - /* Set dualQ + disable afull for A660, A642 GPU but not for A642L */ - if (!adreno_is_a642l(adreno_dev)) + /* + * Set dualQ + disable afull for A660, A642 GPU but + * not for A642L and A643 + */ + if (!adreno_is_a642l(adreno_dev) || + !adreno_is_a643(adreno_dev)) kgsl_regwrite(device, A6XX_UCHE_CMDQ_CONFIG, 0x66906); } From 35c00d33043b33f73c34b0d8020888af6a34ee25 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Mon, 11 Oct 2021 20:14:14 +0530 Subject: [PATCH 02/21] msm: kgsl: Update register protection config Update the register protection configurations as per the latest recommendation. Change-Id: I70365268e8e4c7ee4ff28538f22e970822e4edf0 Signed-off-by: Akhil P Oommen --- drivers/gpu/msm/adreno-gpulist.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index f548c4e83e5a..590326f4aa33 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -1078,9 +1078,10 @@ static const struct a6xx_protected_regs a620_protected_regs[] = { { A6XX_CP_PROTECT_REG + 32, 0x0fc00, 0x11bff, 0 }, { A6XX_CP_PROTECT_REG + 33, 0x18400, 0x1a3ff, 1 }, { A6XX_CP_PROTECT_REG + 34, 0x1a800, 0x1c7ff, 1 }, - { A6XX_CP_PROTECT_REG + 35, 0x1f400, 0x1f843, 1 }, - { A6XX_CP_PROTECT_REG + 36, 0x1f844, 0x1f8bf, 0 }, - { A6XX_CP_PROTECT_REG + 37, 0x1f887, 0x1f8a2, 1 }, + { A6XX_CP_PROTECT_REG + 35, 0x1c800, 0x1e7ff, 1 }, + { A6XX_CP_PROTECT_REG + 36, 0x1f400, 0x1f843, 1 }, + { A6XX_CP_PROTECT_REG + 37, 0x1f844, 0x1f8bf, 0 }, + { A6XX_CP_PROTECT_REG + 38, 0x1f887, 0x1f8a2, 1 }, { A6XX_CP_PROTECT_REG + 47, 0x1f8c0, 0x1f8c0, 1 }, { 0 }, }; @@ -1609,10 +1610,11 @@ static const struct a6xx_protected_regs a660_protected_regs[] = { { A6XX_CP_PROTECT_REG + 33, 0x0fc00, 0x11bff, 0 }, { A6XX_CP_PROTECT_REG + 34, 0x18400, 0x1a3ff, 1 }, { A6XX_CP_PROTECT_REG + 35, 0x1a400, 0x1c3ff, 1 }, - { A6XX_CP_PROTECT_REG + 36, 0x1f400, 0x1f843, 1 }, - { A6XX_CP_PROTECT_REG + 37, 0x1f844, 0x1f8bf, 0 }, - { A6XX_CP_PROTECT_REG + 38, 0x1f860, 0x1f860, 1 }, - { A6XX_CP_PROTECT_REG + 39, 0x1f887, 0x1f8a2, 1 }, + { A6XX_CP_PROTECT_REG + 36, 0x1c400, 0x1e3ff, 1 }, + { A6XX_CP_PROTECT_REG + 37, 0x1f400, 0x1f843, 1 }, + { A6XX_CP_PROTECT_REG + 38, 0x1f844, 0x1f8bf, 0 }, + { A6XX_CP_PROTECT_REG + 39, 0x1f860, 0x1f860, 1 }, + { A6XX_CP_PROTECT_REG + 40, 0x1f887, 0x1f8a2, 1 }, { A6XX_CP_PROTECT_REG + 47, 0x1f8c0, 0x1f8c0, 1 }, { 0 }, }; From c67b1d209348046abae688744cdaa6626848231f Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Wed, 13 Oct 2021 18:53:54 +0530 Subject: [PATCH 03/21] msm: kgsl: Update the IFPC power up reglist Update the IFPC power up reglist to include all the CP Protect registers. Change-Id: I1b43420c466b8a228892afac8ecf05b11b5a80e6 Signed-off-by: Akhil P Oommen --- drivers/gpu/msm/adreno_a6xx.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index f3495c023029..048e33de599c 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -92,7 +92,27 @@ static u32 a6xx_ifpc_pwrup_reglist[] = { A6XX_CP_AHB_CNTL, }; -/* Applicable to a620, a642l, a650 and a660 */ +/* Applicable to a620, a642, a642l, a650 and a660 */ +static u32 a650_ifpc_pwrup_reglist[] = { + A6XX_CP_PROTECT_REG+32, + A6XX_CP_PROTECT_REG+33, + A6XX_CP_PROTECT_REG+34, + A6XX_CP_PROTECT_REG+35, + A6XX_CP_PROTECT_REG+36, + A6XX_CP_PROTECT_REG+37, + A6XX_CP_PROTECT_REG+38, + A6XX_CP_PROTECT_REG+39, + A6XX_CP_PROTECT_REG+40, + A6XX_CP_PROTECT_REG+41, + A6XX_CP_PROTECT_REG+42, + A6XX_CP_PROTECT_REG+43, + A6XX_CP_PROTECT_REG+44, + A6XX_CP_PROTECT_REG+45, + A6XX_CP_PROTECT_REG+46, + A6XX_CP_PROTECT_REG+47, +}; + +/* Applicable to a620, a635, a650 and a660 */ static u32 a650_pwrup_reglist[] = { A6XX_CP_PROTECT_REG + 47, /* Programmed for infinite span */ A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, @@ -460,14 +480,21 @@ struct a6xx_reglist_list { static void a6xx_patch_pwrup_reglist(struct adreno_device *adreno_dev) { - struct a6xx_reglist_list reglist[3]; + struct a6xx_reglist_list reglist[4]; void *ptr = adreno_dev->pwrup_reglist->hostptr; struct cpu_gpu_lock *lock = ptr; int items = 0, i, j; u32 *dest = ptr + sizeof(*lock); + u16 list_offset = 0; /* Static IFPC-only registers */ - reglist[items++] = REGLIST(a6xx_ifpc_pwrup_reglist); + reglist[items] = REGLIST(a6xx_ifpc_pwrup_reglist); + list_offset += reglist[items++].count * 2; + + if (adreno_is_a650_family(adreno_dev)) { + reglist[items] = REGLIST(a650_ifpc_pwrup_reglist); + list_offset += reglist[items++].count * 2; + } /* Static IFPC + preemption registers */ reglist[items++] = REGLIST(a6xx_pwrup_reglist); @@ -520,7 +547,7 @@ static void a6xx_patch_pwrup_reglist(struct adreno_device *adreno_dev) * all the lists and list_offset should be specified as the size in * dwords of the first entry in the list. */ - lock->list_offset = reglist[0].count * 2; + lock->list_offset = list_offset; } From 7ec3d0ce36fed138330c4233a14d4da7cb804a48 Mon Sep 17 00:00:00 2001 From: Mohammed Mirza Mandayappurath Manzoor Date: Tue, 18 Jan 2022 16:06:24 -0800 Subject: [PATCH 04/21] msm: kgsl: Zap performance counters across context switches Performance counter values need not be retained across contexts unless specifically requested for debug. Zap the counters by initialising perfcounter SRAM with 0's using GPU_RBBM_PERFCTR_SRAM_INIT_CMD. Add pm4 packets during context switches and add a KMD postamble packet to clear the counters during preemption. Do not enable perfcounter save and restore unless requested. Change-Id: I371779ce659c07a1cc664327f5ecdcf0374201d8 Signed-off-by: Mohammed Mirza Mandayappurath Manzoor Signed-off-by: Harshitha Sai Neelati --- drivers/gpu/msm/a6xx_reg.h | 3 ++ drivers/gpu/msm/adreno.h | 8 +++++ drivers/gpu/msm/adreno_a6xx_preempt.c | 44 ++++++++++++++++++++++++--- drivers/gpu/msm/adreno_iommu.c | 18 +++++++++++ drivers/gpu/msm/adreno_perfcounter.c | 7 +++-- drivers/gpu/msm/adreno_pm4types.h | 7 +++++ drivers/gpu/msm/adreno_ringbuffer.c | 3 +- 7 files changed, 83 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h index 9d16d09cb3d2..df52db8ac6d1 100644 --- a/drivers/gpu/msm/a6xx_reg.h +++ b/drivers/gpu/msm/a6xx_reg.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _A6XX_REG_H @@ -406,6 +407,8 @@ #define A6XX_RBBM_PERFCTR_RBBM_SEL_2 0x509 #define A6XX_RBBM_PERFCTR_RBBM_SEL_3 0x50A #define A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED 0x50B +#define A6XX_RBBM_PERFCTR_SRAM_INIT_CMD 0x50e +#define A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS 0x50f #define A6XX_RBBM_ISDB_CNT 0x533 #define A6XX_RBBM_NC_MODE_CNTL 0X534 diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 833ff5211925..d71ef7338450 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -15,6 +15,9 @@ #include "adreno_ringbuffer.h" #include "kgsl_sharedmem.h" +/* Index to preemption scratch buffer to store KMD postamble */ +#define KMD_POSTAMBLE_IDX 100 + /* ADRENO_DEVICE - Given a kgsl_device return the adreno device struct */ #define ADRENO_DEVICE(device) \ container_of(device, struct adreno_device, dev) @@ -231,6 +234,9 @@ struct adreno_gpudev; /* Time to allow preemption to complete (in ms) */ #define ADRENO_PREEMPT_TIMEOUT 10000 +#define PREEMPT_SCRATCH_ADDR(dev, id) \ + ((dev)->preempt.scratch->gpuaddr + (id * sizeof(u64))) + /** * enum adreno_preempt_states * ADRENO_PREEMPT_NONE: No preemption is scheduled @@ -260,6 +266,7 @@ enum adreno_preempt_states { * skipsaverestore: To skip saverestore during L1 preemption (for 6XX) * usesgmem: enable GMEM save/restore across preemption (for 6XX) * count: Track the number of preemptions triggered + * @postamble_len: Number of dwords in KMD postamble pm4 packet */ struct adreno_preemption { atomic_t state; @@ -270,6 +277,7 @@ struct adreno_preemption { bool skipsaverestore; bool usesgmem; unsigned int count; + u32 postamble_len; }; struct adreno_busy_data { diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 49b082dd0e7c..f0c5cf5a4869 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "adreno.h" @@ -543,13 +544,24 @@ unsigned int a6xx_preemption_pre_ibsubmit( if (context) { struct adreno_context *drawctxt = ADRENO_CONTEXT(context); struct adreno_ringbuffer *rb = drawctxt->rb; - uint64_t dest = adreno_dev->preempt.scratch->gpuaddr - + (rb->id * sizeof(u64)); + uint64_t dest = PREEMPT_SCRATCH_ADDR(adreno_dev, rb->id); *cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2); cmds += cp_gpuaddr(adreno_dev, cmds, dest); *cmds++ = lower_32_bits(gpuaddr); *cmds++ = upper_32_bits(gpuaddr); + + /* Add a KMD post amble to clear the perf counters during preemption */ + if (!adreno_dev->perfcounter) { + u64 kmd_postamble_addr = + PREEMPT_SCRATCH_ADDR(adreno_dev, KMD_POSTAMBLE_IDX); + + *cmds++ = cp_type7_packet(CP_SET_AMBLE, 3); + *cmds++ = lower_32_bits(kmd_postamble_addr); + *cmds++ = upper_32_bits(kmd_postamble_addr); + *cmds++ = FIELD_PREP(GENMASK(22, 20), CP_KMD_AMBLE_TYPE) + | (FIELD_PREP(GENMASK(19, 0), adreno_dev->preempt.postamble_len)); + } } return (unsigned int) (cmds - cmds_orig); @@ -562,8 +574,7 @@ unsigned int a6xx_preemption_post_ibsubmit(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb = adreno_dev->cur_rb; if (rb) { - uint64_t dest = adreno_dev->preempt.scratch->gpuaddr - + (rb->id * sizeof(u64)); + uint64_t dest = PREEMPT_SCRATCH_ADDR(adreno_dev, adreno_dev->cur_rb->id); *cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2); cmds += cp_gpuaddr(adreno_dev, cmds, dest); @@ -721,6 +732,31 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) if (ret) return ret; + /* + * First 8 dwords of the preemption scratch buffer is used to store the address for CP + * to save/restore VPC data. Reserve 11 dwords in the preemption scratch buffer from + * index KMD_POSTAMBLE_IDX for KMD postamble pm4 packets + */ + if (!adreno_dev->perfcounter) { + u32 *postamble = preempt->scratch->hostptr + (KMD_POSTAMBLE_IDX * sizeof(u64)); + u32 count = 0; + + postamble[count++] = cp_type7_packet(CP_REG_RMW, 3); + postamble[count++] = A6XX_RBBM_PERFCTR_SRAM_INIT_CMD; + postamble[count++] = 0x0; + postamble[count++] = 0x1; + + postamble[count++] = cp_type7_packet(CP_WAIT_REG_MEM, 6); + postamble[count++] = 0x3; + postamble[count++] = A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS; + postamble[count++] = 0x0; + postamble[count++] = 0x1; + postamble[count++] = 0x1; + postamble[count++] = 0x0; + + preempt->postamble_len = count; + } + set_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv); return 0; } diff --git a/drivers/gpu/msm/adreno_iommu.c b/drivers/gpu/msm/adreno_iommu.c index 73e6016bf1d9..be88bafb12da 100644 --- a/drivers/gpu/msm/adreno_iommu.c +++ b/drivers/gpu/msm/adreno_iommu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -217,6 +218,12 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device, struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *cmds = cmds_orig; + /* Clear performance counters during contect switches */ + if (!adreno_dev->perfcounter) { + *cmds++ = cp_type4_packet(A6XX_RBBM_PERFCTR_SRAM_INIT_CMD, 1); + *cmds++ = 0x1; + } + /* CP switches the pagetable and flushes the Caches */ *cmds++ = cp_packet(adreno_dev, CP_SMMU_TABLE_UPDATE, 4); *cmds++ = lower_32_bits(ttbr0); @@ -245,6 +252,17 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device, *cmds++ = 0; } + /* Wait for performance counter clear to finish */ + if (!adreno_dev->perfcounter) { + *cmds++ = cp_type7_packet(CP_WAIT_REG_MEM, 6); + *cmds++ = 0x3; + *cmds++ = A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS; + *cmds++ = 0x0; + *cmds++ = 0x1; + *cmds++ = 0x1; + *cmds++ = 0x0; + } + return cmds - cmds_orig; } diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c index d0b0bd3a2846..49ff0356a065 100644 --- a/drivers/gpu/msm/adreno_perfcounter.c +++ b/drivers/gpu/msm/adreno_perfcounter.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -72,7 +73,8 @@ void adreno_perfcounter_restore(struct adreno_device *adreno_dev) const struct adreno_perfcount_group *group; unsigned int counter, groupid; - if (counters == NULL) + /* Do not save/restore if not requested */ + if (counters == NULL || !adreno_dev->perfcounter) return; for (groupid = 0; groupid < counters->group_count; groupid++) { @@ -106,7 +108,8 @@ inline void adreno_perfcounter_save(struct adreno_device *adreno_dev) const struct adreno_perfcount_group *group; unsigned int counter, groupid; - if (counters == NULL) + /* Do not save/restore if not requested */ + if (counters == NULL || !adreno_dev->perfcounter) return; for (groupid = 0; groupid < counters->group_count; groupid++) { diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h index b64492044400..deb54dcc6ccc 100644 --- a/drivers/gpu/msm/adreno_pm4types.h +++ b/drivers/gpu/msm/adreno_pm4types.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __ADRENO_PM4TYPES_H #define __ADRENO_PM4TYPES_H @@ -47,6 +48,9 @@ /* switches SMMU pagetable, used on a5xx only */ #define CP_SMMU_TABLE_UPDATE 0x53 +/* Designate command streams to be executed before/after CP does state restore during preemption */ +#define CP_SET_AMBLE 0x55 + /* Set internal CP registers, used to indicate context save data addresses */ #define CP_SET_PSEUDO_REGISTER 0x56 @@ -157,6 +161,9 @@ #define CP_LOADSTATE_STATETYPE_SHIFT 0x00000000 #define CP_LOADSTATE_EXTSRCADDR_SHIFT 0x00000002 +/* Used to define amble type in SET_AMBLE packet to execute during preemption */ +#define CP_KMD_AMBLE_TYPE 3 + static inline uint pm4_calc_odd_parity_bit(uint val) { return (0x9669 >> (0xf & ((val) ^ diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index 33e67cd0390a..0e25e7bfcf81 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -482,7 +483,7 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, if (gpudev->preemption_pre_ibsubmit && adreno_is_preemption_enabled(adreno_dev)) - total_sizedwords += 27; + total_sizedwords += 31; if (gpudev->preemption_post_ibsubmit && adreno_is_preemption_enabled(adreno_dev)) From c75f815cbec3ef5f5409b4be1b96f09cc1198c72 Mon Sep 17 00:00:00 2001 From: ravnar Date: Wed, 20 Apr 2022 19:51:19 +0530 Subject: [PATCH 05/21] msm: kgsl: Remove 'fd' dependency to get dma_buf handle Get the dma_buf handle directly from 'vm_file' after doing necessary checks on the file. Change-Id: Id5eec16588d64e4e28483b32bb52d4d3d9b86b99 Signed-off-by: ravnar Signed-off-by: Sanjay Yadav --- drivers/gpu/msm/kgsl.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index f7cafa94a50e..7044d7f1520a 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2583,15 +2583,6 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, } #ifdef CONFIG_DMA_SHARED_BUFFER -static int match_file(const void *p, struct file *file, unsigned int fd) -{ - /* - * We must return fd + 1 because iterate_fd stops searching on - * non-zero return, but 0 is a valid fd. - */ - return (p == file) ? (fd + 1) : 0; -} - static void _setup_cache_mode(struct kgsl_mem_entry *entry, struct vm_area_struct *vma) { @@ -2628,8 +2619,6 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, vma = find_vma(current->mm, hostptr); if (vma && vma->vm_file) { - int fd; - ret = check_vma_flags(vma, entry->memdesc.flags); if (ret) { up_read(¤t->mm->mmap_sem); @@ -2645,15 +2634,10 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, return -EFAULT; } - /* Look for the fd that matches this the vma file */ - fd = iterate_fd(current->files, 0, match_file, vma->vm_file); - if (fd != 0) { - dmabuf = dma_buf_get(fd - 1); - if (IS_ERR(dmabuf)) { - up_read(¤t->mm->mmap_sem); - return PTR_ERR(dmabuf); - } - } + /* Take a refcount because dma_buf_put() decrements the refcount */ + get_file(vma->vm_file); + + dmabuf = vma->vm_file->private_data; } if (!dmabuf) { From eebc5d781be903bd963ac6d28d2fe0a3b021be62 Mon Sep 17 00:00:00 2001 From: Rohan Sethi Date: Mon, 22 Nov 2021 14:23:30 +0530 Subject: [PATCH 06/21] msm: kgsl: Fix gpuaddr_in_range() to check upper bound Currently gpuaddr_in_range() accepts only the gpuaddr & returns true if it lies in valid range. But this does not mean that the entire buffer is within range. Modify the function to accept size as a parameter and check that both starting & ending points of buffer lie within mmu range. Change-Id: I1d722295b9a27e746bfdb6d3bf409ffe722193cb Signed-off-by: Rohan Sethi Signed-off-by: Debadutta Muni --- drivers/gpu/msm/adreno_dispatch.c | 4 ++-- drivers/gpu/msm/adreno_hwsched.c | 3 ++- drivers/gpu/msm/kgsl.c | 4 ++-- drivers/gpu/msm/kgsl_iommu.c | 8 ++++---- drivers/gpu/msm/kgsl_mmu.c | 6 +++--- drivers/gpu/msm/kgsl_mmu.h | 7 ++++--- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 5177e74acc10..823a382b56b4 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1125,8 +1125,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is in range and dword aligned */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr) || - !IS_ALIGNED(ib->gpuaddr, 4)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size) || !IS_ALIGNED(ib->gpuaddr, 4)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 6eb466919833..085c003e0bcd 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -657,7 +657,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is mapped */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 7044d7f1520a..196b6ed7fd92 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1302,9 +1302,9 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr) if (!private) return NULL; - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr) && + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr, 0) && !kgsl_mmu_gpuaddr_in_range( - private->pagetable->mmu->securepagetable, gpuaddr)) + private->pagetable->mmu->securepagetable, gpuaddr, 0)) return NULL; spin_lock(&private->mem_lock); diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 0a16898be6e2..fc75683dd210 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -2287,20 +2287,20 @@ static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable, } static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { struct kgsl_iommu_pt *pt = pagetable->priv; if (gpuaddr == 0) return false; - if (gpuaddr >= pt->va_start && gpuaddr < pt->va_end) + if (gpuaddr >= pt->va_start && (gpuaddr + size) < pt->va_end) return true; - if (gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end) + if (gpuaddr >= pt->compat_va_start && (gpuaddr + size) < pt->compat_va_end) return true; - if (gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end) + if (gpuaddr >= pt->svm_start && (gpuaddr + size) < pt->svm_end) return true; return false; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 090a028b3c6f..2633b72f18f7 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -529,10 +529,10 @@ enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device) } bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { if (PT_OP_VALID(pagetable, addr_in_range)) - return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr); + return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr, size); return false; } @@ -544,7 +544,7 @@ bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, */ static bool nommu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { return (gpuaddr != 0) ? true : false; } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index c1bcba4c666f..49d16d7e5491 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_MMU_H #define __KGSL_MMU_H @@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops { int (*svm_range)(struct kgsl_pagetable *pt, uint64_t *lo, uint64_t *hi, uint64_t memflags); bool (*addr_in_range)(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr); + uint64_t gpuaddr, uint64_t size); }; enum kgsl_mmu_feature { @@ -174,7 +174,8 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc); unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, u64 ttbr0, uint64_t addr); -bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr); +bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr, + uint64_t size); int kgsl_mmu_get_region(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size); From 084159c65181925b442eabd0595b14858b957d10 Mon Sep 17 00:00:00 2001 From: Mohammed Siddiq Date: Fri, 12 Nov 2021 10:57:00 +0530 Subject: [PATCH 07/21] cnss2: Add code to fallback to non-contiguous FW mem allocation Add code to fallback to non-contiguous FW mem allocation on failure to allocate contiguous memory. Change-Id: Idbc7ff7f9ea4d2157e3b549dde8ee090a0f0b412 Signed-off-by: Mohammed Siddiq --- drivers/net/wireless/cnss2/pci.c | 43 +++++++++++++++++++++++--------- drivers/net/wireless/cnss2/qmi.c | 7 ++++-- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index a9ab9735561d..35e060bca951 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ #include #include @@ -3982,15 +3984,27 @@ int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv) for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { if (!fw_mem[i].va && fw_mem[i].size) { +retry: fw_mem[i].va = dma_alloc_attrs(dev, fw_mem[i].size, &fw_mem[i].pa, GFP_KERNEL, fw_mem[i].attrs); if (!fw_mem[i].va) { + if ((fw_mem[i].attrs & + DMA_ATTR_FORCE_CONTIGUOUS)) { + fw_mem[i].attrs &= + ~DMA_ATTR_FORCE_CONTIGUOUS; + + cnss_pr_dbg("Fallback to non-contiguous memory for FW, Mem type: %u\n", + fw_mem[i].type); + goto retry; + } + cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx, type: %u\n", fw_mem[i].size, fw_mem[i].type); - BUG(); + CNSS_ASSERT(0); + return -ENOMEM; } } } @@ -5081,17 +5095,21 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic) mhi_dump_sfr(pci_priv->mhi_ctrl); - cnss_pr_dbg("Collect remote heap dump segment\n"); - for (i = 0, j = 0; i < plat_priv->fw_mem_seg_len; i++) { if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) { - cnss_pci_add_dump_seg(pci_priv, dump_seg, - CNSS_FW_REMOTE_HEAP, j, - fw_mem[i].va, fw_mem[i].pa, - fw_mem[i].size); - dump_seg++; - dump_data->nentries++; - j++; + if (fw_mem[i].attrs & DMA_ATTR_FORCE_CONTIGUOUS) { + cnss_pr_dbg("Collect remote heap dump segment\n"); + cnss_pci_add_dump_seg(pci_priv, dump_seg, + CNSS_FW_REMOTE_HEAP, j, + fw_mem[i].va, + fw_mem[i].pa, + fw_mem[i].size); + dump_seg++; + dump_data->nentries++; + j++; + } else { + cnss_pr_dbg("Skip remote heap dumps as it is non-contiguous\n"); + } } } @@ -5136,7 +5154,8 @@ void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv) } for (i = 0, j = 0; i < plat_priv->fw_mem_seg_len; i++) { - if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) { + if (fw_mem[i].type == CNSS_MEM_TYPE_DDR && + (fw_mem[i].attrs & DMA_ATTR_FORCE_CONTIGUOUS)) { cnss_pci_remove_dump_seg(pci_priv, dump_seg, CNSS_FW_REMOTE_HEAP, j, fw_mem[i].va, fw_mem[i].pa, diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index d0f85455de8e..157c90506d30 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ #include #include @@ -2206,7 +2208,8 @@ static void cnss_wlfw_request_mem_ind_cb(struct qmi_handle *qmi_wlfw, ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type); plat_priv->fw_mem[i].type = ind_msg->mem_seg[i].type; plat_priv->fw_mem[i].size = ind_msg->mem_seg[i].size; - if (plat_priv->fw_mem[i].type == CNSS_MEM_TYPE_DDR) + if (!plat_priv->fw_mem[i].va && + plat_priv->fw_mem[i].type == CNSS_MEM_TYPE_DDR) plat_priv->fw_mem[i].attrs |= DMA_ATTR_FORCE_CONTIGUOUS; } From b0164d0e71ff17ea727010eadab0172c80f94052 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Sep 2022 21:56:15 +0200 Subject: [PATCH 08/21] wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans() In the copy code of the elements, we do the following calculation to reach the end of the MBSSID element: /* copy the IEs after MBSSID */ cpy_len = mbssid[1] + 2; This looks fine, however, cpy_len is a u8, the same as mbssid[1], so the addition of two can overflow. In this case the subsequent memcpy() will overflow the allocated buffer, since it copies 256 bytes too much due to the way the allocation and memcpy() sizes are calculated. Fix this by using size_t for the cpy_len variable. This fixes CVE-2022-41674. Reported-by: Soenke Huster Tested-by: Soenke Huster Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") Link: https://lore.kernel.org/lkml/20221013175147.067414219@linuxfoundation.org/ Reviewed-by: Kees Cook Signed-off-by: Johannes Berg Git-commit: aebe9f4639b13a1f4e9a6b42cdd2e38c617b442d Git-repo: https://android.googlesource.com/kernel/common Change-Id: If6ed330dc65fdf387ee8584b5a69840242edf5cf Signed-off-by: Vulupala Shashank Reddy --- net/wireless/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 86c6066c42e5..81e7469c65b5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1717,7 +1717,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, size_t new_ie_len; struct cfg80211_bss_ies *new_ies; const struct cfg80211_bss_ies *old; - u8 cpy_len; + size_t cpy_len; lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock); From db38f844be32c08a46f847d4f5113937dc3621fb Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Wed, 2 Nov 2022 20:33:04 +0530 Subject: [PATCH 09/21] wifi: cfg80211: avoid nontransmitted BSS list corruption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a non-transmitted BSS shares enough information (both SSID and BSSID!) with another non-transmitted BSS of a different AP, then we can find and update it, and then try to add it to the non-transmitted BSS list. We do a search for it on the transmitted BSS, but if it's not there (but belongs to another transmitted BSS), the list gets corrupted. Since this is an erroneous situation, simply fail the list insertion in this case and free the non-transmitted BSS. This fixes CVE-2022-42721. Reported-by: Sönke Huster Tested-by: Sönke Huster Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") Link: https://lore.kernel.org/all/20221013175145.382242160@linuxfoundation.org/ Signed-off-by: Johannes Berg Git-commit: bcca852027e5878aec911a347407ecc88d6fff7f Git-repo: https://android.googlesource.com/kernel/common Change-Id: Icb2106b5ac5ff5e3ecb50bd09440bce5560fbb05 Signed-off-by: Srikanth Marepalli --- net/wireless/scan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 86c6066c42e5..2bdf93d28d3d 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -390,6 +390,14 @@ cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss, rcu_read_unlock(); + /* This is a bit weird - it's not on the list, but already on another + * one! The only way that could happen is if there's some BSSID/SSID + * shared by multiple APs in their multi-BSSID profiles, potentially + * with hidden SSID mixed in ... ignore it. + */ + if (!list_empty(&nontrans_bss->nontrans_list)) + return -EINVAL; + /* add to the list */ list_add_tail(&nontrans_bss->nontrans_list, &trans_bss->nontrans_list); return 0; From f3ed4ea6798d76e0d35ef3f4e5fe2dbe6c3547c0 Mon Sep 17 00:00:00 2001 From: Balaji Pothunoori Date: Wed, 2 Nov 2022 19:36:09 +0530 Subject: [PATCH 10/21] wifi: cfg80211: fix BSS refcounting bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are multiple refcounting bugs related to multi-BSSID: - In bss_ref_get(), if the BSS has a hidden_beacon_bss, then the bss pointer is overwritten before checking for the transmitted BSS, which is clearly wrong. Fix this by using the bss_from_pub() macro. - In cfg80211_bss_update() we copy the transmitted_bss pointer from tmp into new, but then if we release new, we'll unref it erroneously. We already set the pointer and ref it, but need to NULL it since it was copied from the tmp data. - In cfg80211_inform_single_bss_data(), if adding to the non- transmitted list fails, we unlink the BSS and yet still we return it, but this results in returning an entry without a reference. We shouldn't return it anyway if it was broken enough to not get added there. This fixes CVE-2022-42720. Reported-by: Sönke Huster Tested-by: Sönke Huster Fixes: a3584f56de1c ("cfg80211: Properly track transmitting and non-transmitting BSS") Link: https://lore.kernel.org/lkml/20221013175147.168042993@linuxfoundation.org/ Signed-off-by: Johannes Berg Change-Id: If6ed330dc65fdf387ee8584b5a69840242edf5cc Signed-off-by: Balaji Pothunoori --- net/wireless/scan.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 86c6066c42e5..df9c5778c424 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -104,18 +104,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev, lockdep_assert_held(&rdev->bss_lock); bss->refcount++; - if (bss->pub.hidden_beacon_bss) { - bss = container_of(bss->pub.hidden_beacon_bss, - struct cfg80211_internal_bss, - pub); - bss->refcount++; - } - if (bss->pub.transmitted_bss) { - bss = container_of(bss->pub.transmitted_bss, - struct cfg80211_internal_bss, - pub); - bss->refcount++; - } + + if (bss->pub.hidden_beacon_bss) + bss_from_pub(bss->pub.hidden_beacon_bss)->refcount++; + + if (bss->pub.transmitted_bss) + bss_from_pub(bss->pub.transmitted_bss)->refcount++; } static inline void bss_ref_put(struct cfg80211_registered_device *rdev, @@ -1231,6 +1225,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, new->refcount = 1; INIT_LIST_HEAD(&new->hidden_list); INIT_LIST_HEAD(&new->pub.nontrans_list); + /* we'll set this later if it was non-NULL */ + new->pub.transmitted_bss = NULL; if (rcu_access_pointer(tmp->pub.proberesp_ies)) { hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN); @@ -1460,10 +1456,15 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, spin_lock_bh(&rdev->bss_lock); if (cfg80211_add_nontrans_list(non_tx_data->tx_bss, &res->pub)) { - if (__cfg80211_unlink_bss(rdev, res)) + if (__cfg80211_unlink_bss(rdev, res)) { rdev->bss_generation++; + res = NULL; + } } spin_unlock_bh(&rdev->bss_lock); + + if (!res) + return NULL; } trace_cfg80211_return_bss(&res->pub); From 65f9ecf12fcf762a4d81c98997e86bb132465f38 Mon Sep 17 00:00:00 2001 From: Amit Kushwaha Date: Thu, 24 Nov 2022 17:30:18 +0530 Subject: [PATCH 11/21] msm: kgsl: Remove protected GPUCC registers from snapshot This change is to prevent data abort when HLOS accessing protected registers used in SoftSKU. Change-Id: Ia7facc5cf78453f75f829ae7b6626a7f182c8f91 Signed-off-by: Amit Kushwaha --- drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c b/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c index cc7ad875a598..5b19a616ee3e 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c @@ -43,7 +43,7 @@ static const unsigned int a6xx_gmu_registers[] = { 0x24000, 0x24012, 0x24040, 0x24052, 0x24400, 0x24404, 0x24407, 0x2440B, 0x24415, 0x2441C, 0x2441E, 0x2442D, 0x2443C, 0x2443D, 0x2443F, 0x24440, 0x24442, 0x24449, 0x24458, 0x2445A, 0x24540, 0x2455E, 0x24800, 0x24802, - 0x24C00, 0x24C02, 0x25400, 0x25402, 0x25800, 0x25802, 0x25C00, 0x25C02, + 0x24C00, 0x24C02, 0x25400, 0x25402, 0x25800, 0x25802, 0x26000, 0x26002, /* GPU CC ACD */ 0x26400, 0x26416, 0x26420, 0x26427, From 24fb26c295ac018e6d7c8cfe87f29e18946b07e9 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Wed, 2 Nov 2022 15:48:06 +0530 Subject: [PATCH 12/21] core_ctl: Add check for available cpus before accessing per_cpus For qultivate target its trying to call per_cpu() for cpu's which are fused out and leading to crash So, Add a check for available cpu's before calling per_cpu. Change-Id: Idfd97fcfc83baa59afe9010396e7b6314087bf13 Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Chetan C R --- kernel/sched/walt/core_ctl.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/kernel/sched/walt/core_ctl.c b/kernel/sched/walt/core_ctl.c index 44b0fef98e4c..b3e4e5548ace 100644 --- a/kernel/sched/walt/core_ctl.c +++ b/kernel/sched/walt/core_ctl.c @@ -340,7 +340,7 @@ static ssize_t store_not_preferred(struct cluster_data *state, const char *buf, size_t count) { struct cpu_data *c; - unsigned int i; + unsigned int i, mask; unsigned int val[MAX_CPUS_PER_CLUSTER]; unsigned long flags; int ret; @@ -353,10 +353,16 @@ static ssize_t store_not_preferred(struct cluster_data *state, return -EINVAL; spin_lock_irqsave(&state_lock, flags); - for (i = 0; i < state->num_cpus; i++) { - c = &per_cpu(cpu_state, i + state->first_cpu); + for (i = 0, mask = 0; i < state->num_cpus;) { + if (!cpumask_test_cpu(i + mask + state->first_cpu, cpu_possible_mask)) { + mask++; + continue; + } + + c = &per_cpu(cpu_state, i + mask + state->first_cpu); c->not_preferred = val[i]; not_preferred_count += !!val[i]; + i++; } state->nr_not_preferred_cpus = not_preferred_count; spin_unlock_irqrestore(&state_lock, flags); @@ -369,20 +375,26 @@ static ssize_t show_not_preferred(const struct cluster_data *state, char *buf) struct cpu_data *c; ssize_t count = 0; unsigned long flags; - int i; + int i, mask; spin_lock_irqsave(&state_lock, flags); - for (i = 0; i < state->num_cpus; i++) { - c = &per_cpu(cpu_state, i + state->first_cpu); + for (i = 0, mask = 0; i < state->num_cpus;) { + if (!cpumask_test_cpu(i + mask + state->first_cpu, cpu_possible_mask)) { + mask++; + continue; + } + + c = &per_cpu(cpu_state, i + mask + state->first_cpu); count += scnprintf(buf + count, PAGE_SIZE - count, - "CPU#%d: %u\n", c->cpu, c->not_preferred); + "CPU#%d: %u\n", c->cpu, c->not_preferred); + i++; } + spin_unlock_irqrestore(&state_lock, flags); return count; } - struct core_ctl_attr { struct attribute attr; ssize_t (*show)(const struct cluster_data *, char *); From adea9f697361fe8a4649b3065a4fc06358e33276 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 29 Nov 2022 02:47:08 +0530 Subject: [PATCH 13/21] devfreq: memlat: Correct the num_cpus in memlat-mon Correct the num_cpu's value by subtracting with last mask with first cpu mask. Change-Id: Idcaee05db0e1fb97cd8d7668c7aad1d00c4c54c5 Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Chetan C R --- drivers/devfreq/arm-memlat-mon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index 37ebff621d17..4fc8f76918e4 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -907,7 +907,7 @@ static int memlat_mon_probe(struct platform_device *pdev, bool is_compute) } } - num_cpus = cpumask_weight(&mon->cpus); + num_cpus = (cpumask_last(&mon->cpus) - cpumask_first(&mon->cpus)) + 1; hw = &mon->hw; hw->of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0); From f59b80b9d6150a4a8a7d6ab2f02140b429fe4cba Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 29 Nov 2022 02:52:46 +0530 Subject: [PATCH 14/21] cpu-topology: Change the size of allocation for cpu's Change the size of allocation for cpu's cluser. Change-Id: I8c5eded80aa439aa7c6d58d17d7c660093ddccdf Signed-off-by: Avaneesh Kumar Dwivedi --- drivers/base/arch_topology.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 81169261a549..60dcadd283c8 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -26,6 +26,7 @@ DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE; DEFINE_PER_CPU(unsigned long, max_cpu_freq); DEFINE_PER_CPU(unsigned long, max_freq_scale) = SCHED_CAPACITY_SCALE; +#define MAX_CPU 8 void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, unsigned long max_freq) @@ -167,7 +168,7 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) &cpu_capacity); if (!ret) { if (!raw_capacity) { - raw_capacity = kcalloc(num_possible_cpus(), + raw_capacity = kcalloc(MAX_CPU, sizeof(*raw_capacity), GFP_KERNEL); if (!raw_capacity) { From 986781e8e70bd5a7adb7aa8e561d4a6cd174e36b Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Fri, 15 Oct 2021 16:35:01 -0700 Subject: [PATCH 15/21] pci: msm: Add support to retry for sending rpmsg rpmsg_trysend can return EBUSY if remote has not queued the rx intent to receive rpmsg from driver. This is causing rpmsg to get dropped and later when driver sends next message remote goes out of sync. Add 5 retries in 5ms interval and bail out after that. This allows remote to give more time to be able to queue rx intent. Change-Id: I64e05010344e763569180197c9ece94caeb93d93 Signed-off-by: Hemant Kumar --- drivers/pci/controller/pci-msm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index bf1718dfe5a1..d6dc0703f992 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -7760,7 +7760,7 @@ static int msm_pcie_drv_send_rpmsg(struct msm_pcie_dev_t *pcie_dev, struct msm_pcie_drv_msg *msg) { struct msm_pcie_drv_info *drv_info = pcie_dev->drv_info; - int ret; + int ret, re_try = 5; /* sleep 5 ms per re-try */ struct rpmsg_device *rpdev; mutex_lock(&pcie_drv.rpmsg_lock); @@ -7781,8 +7781,15 @@ static int msm_pcie_drv_send_rpmsg(struct msm_pcie_dev_t *pcie_dev, PCIE_DBG(pcie_dev, "PCIe: RC%d: DRV: sending rpmsg: command: 0x%x\n", pcie_dev->rc_idx, msg->pkt.dword[0]); +retry: ret = rpmsg_trysend(rpdev->ept, msg, sizeof(*msg)); if (ret) { + if (ret == -EBUSY && re_try) { + usleep_range(5000, 5001); + re_try--; + goto retry; + } + PCIE_ERR(pcie_dev, "PCIe: RC%d: DRV: failed to send rpmsg, ret:%d\n", pcie_dev->rc_idx, ret); From 90efd0814470297702344ebbe0cabed53bf90e50 Mon Sep 17 00:00:00 2001 From: Sarannya S Date: Wed, 28 Dec 2022 17:28:53 +0530 Subject: [PATCH 16/21] net: qrtr: haven: Add bounds check on tx path Add bounds check on values read from shared memory in the tx path. In cases where the VM is misbehaving, the qrtr haven transport should exit and print a warning when bogus values may cause out of bounds to be read. Change-Id: Ic1177ced6f41de66459970eff4537d82de4f614e Signed-off-by: Sarannya S --- net/qrtr/haven.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/qrtr/haven.c b/net/qrtr/haven.c index b37e779c7e7f..02719209782f 100644 --- a/net/qrtr/haven.c +++ b/net/qrtr/haven.c @@ -188,6 +188,9 @@ static size_t haven_tx_avail(struct haven_pipe *pipe) else avail -= FIFO_FULL_RESERVE; + if (WARN_ON_ONCE(avail > pipe->length)) + avail = 0; + return avail; } @@ -198,6 +201,8 @@ static void haven_tx_write(struct haven_pipe *pipe, u32 head; head = le32_to_cpu(*pipe->head); + if (WARN_ON_ONCE(head > pipe->length)) + return; len = min_t(size_t, count, pipe->length - head); if (len) From 9e97fb51242af0d905f828daa8fa8a836176a995 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Tue, 28 Mar 2023 20:01:44 +0530 Subject: [PATCH 17/21] msm: kgsl: Keep postamble packets in a privileged buffer Postamble packets are executed in privileged mode by gpu. So we should keep them in a privileged scratch buffer to block userspace access. For targets with APRIV feature support, we can mark the preemption scratch buffer as privileged too to avoid similar issues in future. Change-Id: Ifda360dda251083f38dfde80ce1b5dc83daae902 Signed-off-by: Akhil P Oommen Signed-off-by: Kaushal Sanadhya --- drivers/gpu/msm/adreno.h | 5 +---- drivers/gpu/msm/adreno_a6xx_preempt.c | 17 +++++++++-------- drivers/gpu/msm/kgsl.h | 6 ++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index ac685b24144b..ec29d1d40c36 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2008-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. */ #ifndef __ADRENO_H #define __ADRENO_H @@ -16,9 +16,6 @@ #include "adreno_ringbuffer.h" #include "kgsl_sharedmem.h" -/* Index to preemption scratch buffer to store KMD postamble */ -#define KMD_POSTAMBLE_IDX 100 - /* ADRENO_DEVICE - Given a kgsl_device return the adreno device struct */ #define ADRENO_DEVICE(device) \ container_of(device, struct adreno_device, dev) diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index f0c5cf5a4869..cc5b11d30c4b 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, 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. */ #include "adreno.h" @@ -553,8 +553,7 @@ unsigned int a6xx_preemption_pre_ibsubmit( /* Add a KMD post amble to clear the perf counters during preemption */ if (!adreno_dev->perfcounter) { - u64 kmd_postamble_addr = - PREEMPT_SCRATCH_ADDR(adreno_dev, KMD_POSTAMBLE_IDX); + u64 kmd_postamble_addr = SCRATCH_POSTAMBLE_ADDR(KGSL_DEVICE(adreno_dev)); *cmds++ = cp_type7_packet(CP_SET_AMBLE, 3); *cmds++ = lower_32_bits(kmd_postamble_addr); @@ -695,6 +694,7 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev, int a6xx_preemption_init(struct adreno_device *adreno_dev) { + u32 flags = ADRENO_FEATURE(adreno_dev, ADRENO_APRIV) ? KGSL_MEMDESC_PRIVILEGED : 0; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); struct adreno_preemption *preempt = &adreno_dev->preempt; @@ -717,7 +717,7 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) if (IS_ERR_OR_NULL(preempt->scratch)) { preempt->scratch = kgsl_allocate_global(device, PAGE_SIZE, - 0, 0, 0, "preempt_scratch"); + 0, 0, flags, "preempt_scratch"); if (IS_ERR(preempt->scratch)) return PTR_ERR(preempt->scratch); } @@ -733,12 +733,13 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) return ret; /* - * First 8 dwords of the preemption scratch buffer is used to store the address for CP - * to save/restore VPC data. Reserve 11 dwords in the preemption scratch buffer from - * index KMD_POSTAMBLE_IDX for KMD postamble pm4 packets + * First 28 dwords of the device scratch buffer are used to store shadow rb data. + * Reserve 11 dwords in the device scratch buffer from SCRATCH_POSTAMBLE_OFFSET for + * KMD postamble pm4 packets. This should be in *device->scratch* so that userspace + * cannot access it. */ if (!adreno_dev->perfcounter) { - u32 *postamble = preempt->scratch->hostptr + (KMD_POSTAMBLE_IDX * sizeof(u64)); + u32 *postamble = device->scratch->hostptr + SCRATCH_POSTAMBLE_OFFSET; u32 count = 0; postamble[count++] = cp_type7_packet(CP_REG_RMW, 3); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 69fdf288fa68..0f0721522574 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __KGSL_H #define __KGSL_H @@ -71,6 +72,11 @@ #define SCRATCH_RPTR_GPU_ADDR(dev, id) \ ((dev)->scratch->gpuaddr + SCRATCH_RPTR_OFFSET(id)) +/* OFFSET to KMD postamble packets in scratch buffer */ +#define SCRATCH_POSTAMBLE_OFFSET (100 * sizeof(u64)) +#define SCRATCH_POSTAMBLE_ADDR(dev) \ + ((dev)->scratch->gpuaddr + SCRATCH_POSTAMBLE_OFFSET) + /* Timestamp window used to detect rollovers (half of integer range) */ #define KGSL_TIMESTAMP_WINDOW 0x80000000 From ef93ae655cd6e6e4668e1feb9b98525d87c91a5d Mon Sep 17 00:00:00 2001 From: Kamal Agrawal Date: Fri, 3 Feb 2023 15:05:04 +0530 Subject: [PATCH 18/21] msm: kgsl: Check user generated timestamp before queuing drawobjs In ioctls like kgsl_ioctl_submit_commands(), if both syncobj type and cmd/marker/sparseobj type are submitted, the syncobj is queued first followed by the other obj type. After syncobj is successfully queued, in case of failure in get_timestamp while queuing the other obj, both the command objs are destroyed. As sync obj is already queued, accessing this later would cause a crash. Compare the user generated timestamp with the drawctxt timestamp and return early in case of error. This avoids unnecessary queuing of drawobjs. Change-Id: Iedebd480bc18cd74d2f69d24a9dc1032fab01cdb Signed-off-by: Kamal Agrawal --- drivers/gpu/msm/adreno_hwsched.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 085c003e0bcd..6256b7adf086 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "adreno.h" @@ -903,6 +904,23 @@ int adreno_hwsched_queue_cmds(struct kgsl_device_private *dev_priv, user_ts = *timestamp; + /* + * If there is only one drawobj in the array and it is of + * type SYNCOBJ_TYPE, skip comparing user_ts as it can be 0 + */ + if (!(count == 1 && drawobj[0]->type == SYNCOBJ_TYPE) && + (drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS)) { + /* + * User specified timestamps need to be greater than the last + * issued timestamp in the context + */ + if (timestamp_cmp(drawctxt->timestamp, user_ts) >= 0) { + spin_unlock(&drawctxt->lock); + kmem_cache_free(jobs_cache, job); + return -ERANGE; + } + } + for (i = 0; i < count; i++) { switch (drawobj[i]->type) { From 70006e122c91c5f7e21061e45b27737f2232dbc2 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 21 Mar 2023 17:47:19 +0530 Subject: [PATCH 19/21] qcom: cpufreq-hw: Use the topology coreid for offset Use the topology_core_id() API to calculate the offset of the CPU cores. This will help to correctly calculate the offset in case of CPU with fused cores. Change-Id: I877ef9b70f3ed2d39ce18b7744c20b4a906a0106 Signed-off-by: Avaneesh Kumar Dwivedi --- drivers/cpufreq/qcom-cpufreq-hw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 98f9456f8697..5bc9552ab551 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -33,8 +33,8 @@ #define LIMITS_POLLING_DELAY_MS 10 #define MAX_ROW 2 -#define CYCLE_CNTR_OFFSET(c, m, acc_count) \ - (acc_count ? ((c - cpumask_first(m) + 1) * 4) : 0) +#define CYCLE_CNTR_OFFSET(core_id, m, acc_count) \ + (acc_count ? ((core_id + 1) * 4) : 0) enum { REG_ENABLE, @@ -214,7 +214,7 @@ static u64 qcom_cpufreq_get_cpu_cycle_counter(int cpu) cpu_counter = &qcom_cpufreq_counter[cpu]; spin_lock_irqsave(&cpu_counter->lock, flags); - offset = CYCLE_CNTR_OFFSET(cpu, policy->related_cpus, + offset = CYCLE_CNTR_OFFSET(topology_core_id(cpu), policy->related_cpus, accumulative_counter); val = readl_relaxed_no_log(policy->driver_data + offsets[REG_CYCLE_CNTR] + offset); From 994401f8ccb64c165f00eeb293b9e2173f86fd83 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 28 Mar 2023 22:20:21 +0530 Subject: [PATCH 20/21] BACKPORT: of: base: Skip CPU nodes with "fail"/"fail-..." status Allow fully disabling CPU nodes using status = "fail". This allows a bootloader to change the number of available CPUs (for example when a common DTS is used for SoC variants with different numbers of cores) without deleting the nodes altogether, which could require additional fixups to avoid dangling phandle references. Unknown status values (everything that is not "okay"/"ok", "disabled" or "fail"/"fail-...") will continue to be interpreted like "disabled", meaning that the CPU can be enabled during boot. References: - https://www.spinics.net/lists/devicetree-spec/msg01007.html - https://github.com/devicetree-org/dt-schema/pull/61 Bug: 275500667 Change-Id: I0d0028c1d5f529c43f184556ac661c50fe026741 Link: https://lore.kernel.org/all/CAL_Jsq+1LsTBdVaODVfmB0eme2jMpNL4VgKk-OM7rQWyyF0Jbw@mail.gmail.com/ Signed-off-by: Matthias Schiffer Tested-by: Sai Prakash Ranjan Reviewed-by: Frank Rowand Link: https://lore.kernel.org/r/20211122114536.2981-1-matthias.schiffer@ew.tq-group.com Signed-off-by: Rob Herring (cherry picked from commit 4fdd0736a3b1634613d1d2eeb3328d27522052fb) Signed-off-by: Komal Bajaj --- drivers/of/base.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 423764a30e86..f851a1ef9ec0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -665,6 +665,28 @@ bool of_device_is_available(const struct device_node *device) } EXPORT_SYMBOL(of_device_is_available); +/** + * __of_device_is_fail - check if a device has status "fail" or "fail-..." + * + * @device: Node to check status for, with locks already held + * + * Return: True if the status property is set to "fail" or "fail-..." (for any + * error code suffix), false otherwise + */ +static bool __of_device_is_fail(const struct device_node *device) +{ + const char *status; + + if (!device) + return false; + + status = __of_get_property(device, "status", NULL); + if (status == NULL) + return false; + + return !strcmp(status, "fail") || !strncmp(status, "fail-", 5); +} + /** * of_device_is_big_endian - check if a device has BE registers * @@ -813,6 +835,9 @@ EXPORT_SYMBOL(of_get_next_available_child); * of_get_next_cpu_node - Iterate on cpu nodes * @prev: previous child of the /cpus node, or NULL to get first * + * Unusable CPUs (those with the status property set to "fail" or "fail-...") + * will be skipped. + * * Returns a cpu node pointer with refcount incremented, use of_node_put() * on it when done. Returns NULL when prev is the last child. Decrements * the refcount of prev. @@ -834,6 +859,8 @@ struct device_node *of_get_next_cpu_node(struct device_node *prev) of_node_put(node); } for (; next; next = next->sibling) { + if (__of_device_is_fail(next)) + continue; if (!(of_node_name_eq(next, "cpu") || __of_node_is_type(next, "cpu"))) continue; From 7be109d700bd419df5f77299f1cab37322893782 Mon Sep 17 00:00:00 2001 From: Lynus Vaz Date: Thu, 15 Jun 2023 14:12:21 -0700 Subject: [PATCH 21/21] msm: kgsl: Defer drawobj_sync_timeline_fence_work() to a workqueue drawobj_sync_timeline_fence_work() does a cleanup of fence and syncobj allocations. Doing this cleanup in irq context requires the irq_work struct to remain valid after the function executes. Avoid this constraint by deferring this work to the memory workqueue. Change-Id: Icf648a61686c1ef3fd84467a2376b11a9a4bb803 Signed-off-by: Lynus Vaz --- drivers/gpu/msm/kgsl_drawobj.c | 7 ++++--- drivers/gpu/msm/kgsl_drawobj.h | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c index af0054bcd95e..9e00d2c08234 100644 --- a/drivers/gpu/msm/kgsl_drawobj.c +++ b/drivers/gpu/msm/kgsl_drawobj.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ /* @@ -253,7 +254,7 @@ static void drawobj_sync_func(struct kgsl_device *device, kgsl_drawobj_put(&event->syncobj->base); } -static void drawobj_sync_timeline_fence_work(struct irq_work *work) +static void drawobj_sync_timeline_fence_work(struct work_struct *work) { struct kgsl_drawobj_sync_event *event = container_of(work, struct kgsl_drawobj_sync_event, work); @@ -301,7 +302,7 @@ static void drawobj_sync_timeline_fence_callback(struct dma_fence *f, * removing the fence */ if (drawobj_sync_expire(event->device, event)) - irq_work_queue(&event->work); + queue_work(kgsl_driver.mem_workqueue, &event->work); } static void syncobj_destroy(struct kgsl_drawobj *drawobj) @@ -498,7 +499,7 @@ static int drawobj_add_sync_timeline(struct kgsl_device *device, event->device = device; event->context = NULL; event->fence = fence; - init_irq_work(&event->work, drawobj_sync_timeline_fence_work); + INIT_WORK(&event->work, drawobj_sync_timeline_fence_work); INIT_LIST_HEAD(&event->cb.node); diff --git a/drivers/gpu/msm/kgsl_drawobj.h b/drivers/gpu/msm/kgsl_drawobj.h index 3719dc171e1d..a1e160a220fb 100644 --- a/drivers/gpu/msm/kgsl_drawobj.h +++ b/drivers/gpu/msm/kgsl_drawobj.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __KGSL_DRAWOBJ_H @@ -170,8 +171,8 @@ struct kgsl_drawobj_sync_event { struct dma_fence *fence; /** @cb: Callback struct for KGSL_CMD_SYNCPOINT_TYPE_TIMELINE */ struct dma_fence_cb cb; - /** @work : irq worker for KGSL_CMD_SYNCPOINT_TYPE_TIMELINE */ - struct irq_work work; + /** @work : work_struct for KGSL_CMD_SYNCPOINT_TYPE_TIMELINE */ + struct work_struct work; }; #define KGSL_DRAWOBJ_FLAGS \