MALI: rockchip: upgrade bifrost DDK to g25p0-00eac0, from g24p0-00eac0

mali_csffw.bin from Valhall DDK g25(r50) is included.

Change-Id: Ic454428c384456a14b29d9651f537eb59c11284d
Signed-off-by: Zhen Chen <chenzhen@rock-chips.com>
This commit is contained in:
Zhen Chen 2024-08-12 15:30:09 +08:00 committed by Tao Huang
commit d1b62d2e45
132 changed files with 5331 additions and 3263 deletions

View file

@ -0,0 +1,163 @@
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# (C) COPYRIGHT 2022-2024 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
# Foundation, and any use by you of this program is subject to the terms
# of such GNU license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
#
#
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/arm,coresight-mali-source.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM CoreSight Mali Source integration
maintainers:
- ARM Ltd.
description: |
See Documentation/trace/coresight/coresight.rst for detailed information
about Coresight.
This documentation will cover Mali specific devicetree integration.
References to Sink ports are given as examples. Access to Sink is specific
to an implementation and would require dedicated kernel modules.
Arm Mali GPU are supporting 3 different sources: ITM, ETM, ELA
ELA source configuration via SysFS entries:
The register values used by CoreSight for ELA can be configured using SysFS
interfaces. This implicitly includes configuring the ELA for independent or
shared JCN request and response channels.
properties:
compatible:
enum:
- arm,coresight-mali-source-itm
- arm,coresight-mali-source-etm
- arm,coresight-mali-source-ela
gpu:
minItems: 1
maxItems: 1
description:
Phandle to a Mali GPU definition
port:
description:
Output connection to CoreSight Sink Trace bus.
Legacy binding between Coresight Sources and CoreSight Sink.
For Linux kernel < v4.20.
$ref: /schemas/graph.yaml#/properties/port
out-ports:
description:
Binding between Coresight Sources and CoreSight Sink.
For Linux kernel >= v4.20.
$ref: /schemas/graph.yaml#/properties/ports
properties:
port:
description: Output connection to CoreSight Sink Trace bus.
$ref: /schemas/graph.yaml#/properties/port
required:
- compatible
- gpu
- port
- out-ports
additionalProperties: false
examples:
# A Sink node without legacy CoreSight connections
- |
mali-source-itm {
compatible = "arm,coresight-mali-source-itm";
gpu = <&gpu>;
out-ports {
port {
mali_source_itm_out_port0: endpoint {
remote-endpoint = <&mali_sink_in_port0>;
};
};
};
};
mali-source-ela {
compatible = "arm,coresight-mali-source-ela";
gpu = <&gpu>;
out-ports {
port {
mali_source_ela_out_port0: endpoint {
remote-endpoint = <&mali_sink_in_port1>;
};
};
};
};
mali-source-etm {
compatible = "arm,coresight-mali-source-etm";
gpu = <&gpu>;
out-ports {
port {
mali_source_etm_out_port0: endpoint {
remote-endpoint = <&mali_sink_in_port2>;
};
};
};
};
# A Sink node with legacy CoreSight connections
- |
mali-source-itm {
compatible = "arm,coresight-mali-source-itm";
gpu = <&gpu>;
port {
mali_source_itm_out_port0: endpoint {
remote-endpoint = <&mali_sink_in_port0>;
};
};
};
mali-source-etm {
compatible = "arm,coresight-mali-source-etm";
gpu = <&gpu>;
port {
mali_source_etm_out_port0: endpoint {
remote-endpoint = <&mali_sink_in_port1>;
};
};
};
mali-source-ela {
compatible = "arm,coresight-mali-source-ela";
gpu = <&gpu>;
port {
mali_source_ela_out_port0: endpoint {
remote-endpoint = <&mali_sink_in_port2>;
};
};
};

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# (C) COPYRIGHT 2013-2023 ARM Limited. All rights reserved.
# (C) COPYRIGHT 2013-2024 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@ -132,6 +132,10 @@ for details.
set and the setting coresponding to the SYSC_ALLOC register.
- propagate-bits: Used to write to L2_CONFIG.PBHA_HWU. This bitset establishes which
PBHA bits are propagated on the AXI bus.
- mma-wa-id: Sets the PBHA ID to be used for the PBHA override based MMA violation workaround.
The read and write allocation override bits for the PBHA are set to NONCACHEABLE
and the driver encodes the PBHA ID in the PTEs where this workaround is to be applied.
Valid values are from 1 to 15.
Example for a Mali GPU with 1 clock and 1 regulator:
@ -241,6 +245,7 @@ gpu@0xfc010000 {
pbha {
int-id-override = <2 0x32>, <9 0x05>, <16 0x32>;
propagate-bits = /bits/ 8 <0x03>;
mma-wa-id = <2>;
};
...
};

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# (C) COPYRIGHT 2021-2023 ARM Limited. All rights reserved.
# (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software

View file

@ -299,7 +299,8 @@ static int example_mgm_get_import_memory_id(struct memory_group_manager_device *
}
static u64 example_mgm_update_gpu_pte(struct memory_group_manager_device *const mgm_dev,
unsigned int const group_id, int const mmu_level, u64 pte)
unsigned int const group_id, unsigned int const pbha_id,
unsigned int pte_flags, int const mmu_level, u64 pte)
{
struct mgm_groups *const data = mgm_dev->data;
@ -309,7 +310,10 @@ static u64 example_mgm_update_gpu_pte(struct memory_group_manager_device *const
if (WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS))
return pte;
pte |= ((u64)group_id << PTE_PBHA_SHIFT) & PTE_PBHA_MASK;
if (pte_flags & BIT(MMA_VIOLATION)) {
pr_warn_once("MMA violation! Applying PBHA override workaround to PTE\n");
pte |= ((u64)pbha_id << PTE_PBHA_SHIFT) & PTE_PBHA_MASK;
}
/* Address could be translated into a different bus address here */
pte |= ((u64)1 << PTE_RES_BIT_MULTI_AS_SHIFT);
@ -362,6 +366,16 @@ static vm_fault_t example_mgm_vmf_insert_pfn_prot(struct memory_group_manager_de
return fault;
}
static bool example_mgm_get_import_memory_cached_access_permitted(
struct memory_group_manager_device *mgm_dev,
struct memory_group_manager_import_data *import_data)
{
CSTD_UNUSED(mgm_dev);
CSTD_UNUSED(import_data);
return true;
}
static int mgm_initialize_data(struct mgm_groups *mgm_data)
{
int i;
@ -408,6 +422,8 @@ static int memory_group_manager_probe(struct platform_device *pdev)
mgm_dev->ops.mgm_vmf_insert_pfn_prot = example_mgm_vmf_insert_pfn_prot;
mgm_dev->ops.mgm_update_gpu_pte = example_mgm_update_gpu_pte;
mgm_dev->ops.mgm_pte_to_original_pte = example_mgm_pte_to_original_pte;
mgm_dev->ops.mgm_get_import_memory_cached_access_permitted =
example_mgm_get_import_memory_cached_access_permitted;
mgm_data = kzalloc(sizeof(*mgm_data), GFP_KERNEL);
if (!mgm_data) {

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved.
# (C) COPYRIGHT 2012-2024 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@ -69,7 +69,7 @@ endif
#
# Driver version string which is returned to userspace via an ioctl
MALI_RELEASE_NAME ?= '"g24p0-00eac0"'
MALI_RELEASE_NAME ?= '"g25p0-00eac0"'
# Set up defaults if not defined by build system
ifeq ($(CONFIG_MALI_BIFROST_DEBUG), y)
MALI_UNIT_TEST = 1
@ -104,7 +104,6 @@ endif
#
# Experimental features must default to disabled, e.g.:
# MALI_EXPERIMENTAL_FEATURE ?= 0
MALI_INCREMENTAL_RENDERING_JM ?= 0
#
# ccflags
@ -117,7 +116,6 @@ ccflags-y = \
-DMALI_COVERAGE=$(MALI_COVERAGE) \
-DMALI_RELEASE_NAME=$(MALI_RELEASE_NAME) \
-DMALI_JIT_PRESSURE_LIMIT_BASE=$(MALI_JIT_PRESSURE_LIMIT_BASE) \
-DMALI_INCREMENTAL_RENDERING_JM=$(MALI_INCREMENTAL_RENDERING_JM) \
-DMALI_PLATFORM_DIR=$(MALI_PLATFORM_DIR)
@ -212,6 +210,7 @@ endif
INCLUDE_SUBDIR = \
$(src)/arbiter/Kbuild \
$(src)/context/Kbuild \
$(src)/debug/Kbuild \
$(src)/device/Kbuild \
@ -228,9 +227,6 @@ ifeq ($(CONFIG_MALI_CSF_SUPPORT),y)
INCLUDE_SUBDIR += $(src)/csf/Kbuild
endif
ifeq ($(CONFIG_MALI_ARBITER_SUPPORT),y)
INCLUDE_SUBDIR += $(src)/arbiter/Kbuild
endif
ifeq ($(CONFIG_MALI_BIFROST_DEVFREQ),y)
ifeq ($(CONFIG_DEVFREQ_THERMAL),y)

View file

@ -63,6 +63,8 @@ config MALI_BIFROST_NO_MALI
All calls to the simulated hardware will complete immediately as if the hardware
completed the task.
endchoice
config MALI_NO_MALI_DEFAULT_GPU
string "Default GPU for No Mali"
depends on MALI_BIFROST_NO_MALI
@ -70,7 +72,12 @@ config MALI_NO_MALI_DEFAULT_GPU
help
This option sets the default GPU to identify as for No Mali builds.
endchoice
config MALI_IS_FPGA
bool "Enable build of Mali kernel driver for FPGA"
depends on MALI_BIFROST
default n
help
This is the default HW backend.
menu "Platform specific options"
source "$(MALI_KCONFIG_EXT_PREFIX)drivers/gpu/arm/bifrost/platform/Kconfig"
@ -340,7 +347,7 @@ config MALI_PWRSOFT_765
changes have been backported say Y to avoid compilation errors.
config MALI_HW_ERRATA_1485982_NOT_AFFECTED
bool "Disable workaround for BASE_HW_ISSUE_GPU2017_1336"
bool "Disable workaround for KBASE_HW_ISSUE_GPU2017_1336"
depends on MALI_BIFROST && MALI_BIFROST_EXPERT
default n
help
@ -352,7 +359,7 @@ config MALI_HW_ERRATA_1485982_NOT_AFFECTED
coherency mode requires the L2 to be turned off.
config MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE
bool "Use alternative workaround for BASE_HW_ISSUE_GPU2017_1336"
bool "Use alternative workaround for KBASE_HW_ISSUE_GPU2017_1336"
depends on MALI_BIFROST && MALI_BIFROST_EXPERT && !MALI_HW_ERRATA_1485982_NOT_AFFECTED
default n
help

View file

@ -156,7 +156,6 @@ ifeq ($(MALI_KCONFIG_EXT_PREFIX),)
CONFIG_MALI_BIFROST \
CONFIG_MALI_CSF_SUPPORT \
CONFIG_MALI_BIFROST_GATOR_SUPPORT \
CONFIG_MALI_ARBITER_SUPPORT \
CONFIG_MALI_ARBITRATION \
CONFIG_MALI_PARTITION_MANAGER \
CONFIG_MALI_REAL_HW \
@ -170,6 +169,7 @@ ifeq ($(MALI_KCONFIG_EXT_PREFIX),)
CONFIG_MALI_PWRSOFT_765 \
CONFIG_MALI_JOB_DUMP \
CONFIG_MALI_BIFROST_NO_MALI \
CONFIG_MALI_IS_FPGA \
CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED \
CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE \
CONFIG_MALI_PRFCNT_SET_PRIMARY \

View file

@ -108,6 +108,7 @@ static void on_gpu_stop(struct device *dev)
}
KBASE_TLSTREAM_TL_ARBITER_STOP_REQUESTED(kbdev, kbdev);
KBASE_KTRACE_ADD(kbdev, ARB_GPU_STOP_REQUESTED, NULL, 0);
kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_STOP_EVT);
}
@ -133,6 +134,7 @@ static void on_gpu_granted(struct device *dev)
}
KBASE_TLSTREAM_TL_ARBITER_GRANTED(kbdev, kbdev);
KBASE_KTRACE_ADD(kbdev, ARB_GPU_GRANTED, NULL, 0);
kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_GRANTED_EVT);
}
@ -156,7 +158,8 @@ static void on_gpu_lost(struct device *dev)
dev_err(dev, "%s(): kbdev is NULL", __func__);
return;
}
KBASE_TLSTREAM_TL_ARBITER_LOST(kbdev, kbdev);
KBASE_KTRACE_ADD(kbdev, ARB_GPU_LOST, NULL, 0);
kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_LOST_EVT);
}
@ -178,7 +181,7 @@ static int kbase_arbif_of_init(struct kbase_device *kbdev)
if (!arbiter_if_node)
arbiter_if_node = of_parse_phandle(kbdev->dev->of_node, "arbiter_if", 0);
if (!arbiter_if_node) {
dev_dbg(kbdev->dev, "No arbiter_if in Device Tree\n");
dev_dbg(kbdev->dev, "No arbiter_if in Device Tree");
/* no arbiter interface defined in device tree */
kbdev->arb.arb_dev = NULL;
kbdev->arb.arb_if = NULL;
@ -187,19 +190,19 @@ static int kbase_arbif_of_init(struct kbase_device *kbdev)
pdev = of_find_device_by_node(arbiter_if_node);
if (!pdev) {
dev_err(kbdev->dev, "Failed to find arbiter_if device\n");
dev_err(kbdev->dev, "Failed to find arbiter_if device");
return -EPROBE_DEFER;
}
if (!pdev->dev.driver || !try_module_get(pdev->dev.driver->owner)) {
dev_err(kbdev->dev, "arbiter_if driver not available\n");
dev_err(kbdev->dev, "arbiter_if driver not available");
put_device(&pdev->dev);
return -EPROBE_DEFER;
}
kbdev->arb.arb_dev = &pdev->dev;
arb_if = platform_get_drvdata(pdev);
if (!arb_if) {
dev_err(kbdev->dev, "arbiter_if driver not ready\n");
dev_err(kbdev->dev, "arbiter_if driver not ready");
module_put(pdev->dev.driver->owner);
put_device(&pdev->dev);
return -EPROBE_DEFER;
@ -243,6 +246,10 @@ int kbase_arbif_init(struct kbase_device *kbdev)
/* Tries to init with 'arbiter-if' if present in devicetree */
err = kbase_arbif_of_init(kbdev);
if (err == -ENODEV) {
/* devicetree does not support arbitration */
return -EPERM;
}
if (err)
return err;
@ -260,19 +267,19 @@ int kbase_arbif_init(struct kbase_device *kbdev)
arb_if = kbdev->arb.arb_if;
if (arb_if == NULL) {
dev_err(kbdev->dev, "No arbiter interface present\n");
dev_err(kbdev->dev, "No arbiter interface present");
goto failure_term;
}
if (!arb_if->vm_ops.vm_arb_register_dev) {
dev_err(kbdev->dev, "arbiter_if registration callback not present\n");
dev_err(kbdev->dev, "arbiter_if registration callback not present");
goto failure_term;
}
/* register kbase arbiter_if callbacks */
err = arb_if->vm_ops.vm_arb_register_dev(arb_if, kbdev->dev, &ops);
if (err) {
dev_err(kbdev->dev, "Failed to register with arbiter. (err = %d)\n", err);
dev_err(kbdev->dev, "Failed to register with arbiter. (err = %d)", err);
goto failure_term;
}
@ -333,6 +340,7 @@ void kbase_arbif_gpu_request(struct kbase_device *kbdev)
if (arb_if && arb_if->vm_ops.vm_arb_gpu_request) {
KBASE_TLSTREAM_TL_ARBITER_REQUESTED(kbdev, kbdev);
KBASE_KTRACE_ADD(kbdev, ARB_GPU_REQUESTED, NULL, 0);
arb_if->vm_ops.vm_arb_gpu_request(arb_if);
}
}
@ -349,8 +357,11 @@ void kbase_arbif_gpu_stopped(struct kbase_device *kbdev, u8 gpu_required)
if (arb_if && arb_if->vm_ops.vm_arb_gpu_stopped) {
KBASE_TLSTREAM_TL_ARBITER_STOPPED(kbdev, kbdev);
if (gpu_required)
KBASE_KTRACE_ADD(kbdev, ARB_GPU_STOPPED, NULL, 0);
if (gpu_required) {
KBASE_TLSTREAM_TL_ARBITER_REQUESTED(kbdev, kbdev);
KBASE_KTRACE_ADD(kbdev, ARB_GPU_REQUESTED, NULL, 0);
}
arb_if->vm_ops.vm_arb_gpu_stopped(arb_if, gpu_required);
}
}

View file

@ -199,6 +199,7 @@ static void kbase_arbiter_pm_resume_wq(struct work_struct *data)
arb_vm_state->vm_arb_starting = false;
mutex_unlock(&arb_vm_state->vm_state_lock);
KBASE_TLSTREAM_TL_ARBITER_STARTED(kbdev, kbdev);
KBASE_KTRACE_ADD(kbdev, ARB_GPU_STARTED, NULL, 0);
dev_dbg(kbdev->dev, "<%s\n", __func__);
}
@ -295,11 +296,13 @@ int kbase_arbiter_pm_early_init(struct kbase_device *kbdev)
err = kbase_arbif_init(kbdev);
if (err) {
dev_err(kbdev->dev, "Failed to initialise arbif module. (err = %d)\n", err);
if (err != -EPERM)
dev_err(kbdev->dev, "Failed to initialise arbif module. (err = %d)", err);
goto arbif_init_fail;
}
if (kbdev->arb.arb_if) {
if (kbase_has_arbiter(kbdev)) {
kbase_arbif_gpu_request(kbdev);
dev_dbg(kbdev->dev, "Waiting for initial GPU assignment...\n");
@ -345,6 +348,9 @@ void kbase_arbiter_pm_early_term(struct kbase_device *kbdev)
if (arb_vm_state == NULL)
return;
if (!kbase_has_arbiter(kbdev))
return;
kbase_arbiter_pm_release_interrupts(kbdev);
cancel_request_timer(kbdev);
@ -475,6 +481,12 @@ int kbase_arbiter_pm_gpu_assigned(struct kbase_device *kbdev)
if (!kbdev)
return result;
/* If there is no Arbiter, then there is no virtualization
* and current VM always has access to GPU.
*/
if (!kbase_has_arbiter(kbdev))
return 1;
/* First check the GPU_LOST state */
kbase_pm_lock(kbdev);
if (kbase_pm_is_gpu_lost(kbdev)) {
@ -688,7 +700,7 @@ static inline bool kbase_arbiter_pm_vm_os_suspend_ready_state(struct kbase_devic
* @kbdev: The kbase device structure for the device
*
* Prepares OS to be in suspend state until it receives GRANT message
* from Arbiter asynchronously.
* from Arbiter asynchronously. This function assumes there is an active Arbiter.
*/
static void kbase_arbiter_pm_vm_os_prepare_suspend(struct kbase_device *kbdev)
{
@ -696,10 +708,8 @@ static void kbase_arbiter_pm_vm_os_prepare_suspend(struct kbase_device *kbdev)
enum kbase_vm_state prev_state;
lockdep_assert_held(&arb_vm_state->vm_state_lock);
if (kbdev->arb.arb_if) {
if (kbdev->pm.arb_vm_state->vm_state == KBASE_VM_STATE_SUSPENDED)
return;
}
if (kbdev->pm.arb_vm_state->vm_state == KBASE_VM_STATE_SUSPENDED)
return;
/* Block suspend OS function until we are in a stable state
* with vm_state_lock
*/
@ -791,7 +801,7 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev, enum kbase_arbif_evt
{
struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
if (!kbdev->arb.arb_if)
if (!kbase_has_arbiter(kbdev))
return;
mutex_lock(&arb_vm_state->vm_state_lock);
@ -911,7 +921,8 @@ static inline bool kbase_arbiter_pm_vm_gpu_assigned_locked(struct kbase_device *
*
* This function handles a suspend event from the driver,
* communicating with the arbiter and waiting synchronously for the GPU
* to be granted again depending on the VM state.
* to be granted again depending on the VM state. Returns immediately
* with success if there is no Arbiter.
*
* Return: 0 on success else 1 suspend handler isn not possible.
*/
@ -921,58 +932,58 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev,
struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
int res = 0;
if (kbdev->arb.arb_if) {
mutex_lock(&arb_vm_state->vm_state_lock);
while (!kbase_arbiter_pm_vm_gpu_assigned_locked(kbdev)) {
/* Update VM state since we have GPU work to do */
if (arb_vm_state->vm_state == KBASE_VM_STATE_STOPPING_IDLE)
kbase_arbiter_pm_vm_set_state(kbdev,
KBASE_VM_STATE_STOPPING_ACTIVE);
else if (arb_vm_state->vm_state == KBASE_VM_STATE_STOPPED) {
kbase_arbiter_pm_vm_set_state(kbdev,
KBASE_VM_STATE_STOPPED_GPU_REQUESTED);
kbase_arbif_gpu_request(kbdev);
start_request_timer(kbdev);
} else if (arb_vm_state->vm_state == KBASE_VM_STATE_INITIALIZING_WITH_GPU)
if (!kbase_has_arbiter(kbdev))
return res;
mutex_lock(&arb_vm_state->vm_state_lock);
while (!kbase_arbiter_pm_vm_gpu_assigned_locked(kbdev)) {
/* Update VM state since we have GPU work to do */
if (arb_vm_state->vm_state == KBASE_VM_STATE_STOPPING_IDLE)
kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_STOPPING_ACTIVE);
else if (arb_vm_state->vm_state == KBASE_VM_STATE_STOPPED) {
kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_STOPPED_GPU_REQUESTED);
kbase_arbif_gpu_request(kbdev);
start_request_timer(kbdev);
} else if (arb_vm_state->vm_state == KBASE_VM_STATE_INITIALIZING_WITH_GPU)
break;
if (suspend_handler != KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE) {
/* In case of GPU lost, even if
* active_count > 0, we no longer have GPU
* access
*/
if (kbase_pm_is_gpu_lost(kbdev))
res = 1;
switch (suspend_handler) {
case KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE:
res = 1;
break;
if (suspend_handler != KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE) {
/* In case of GPU lost, even if
* active_count > 0, we no longer have GPU
* access
*/
if (kbase_pm_is_gpu_lost(kbdev))
case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE:
if (kbdev->pm.active_count == 0)
res = 1;
switch (suspend_handler) {
case KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE:
res = 1;
break;
case KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE:
if (kbdev->pm.active_count == 0)
res = 1;
break;
case KBASE_PM_SUSPEND_HANDLER_VM_GPU_GRANTED:
break;
default:
WARN(1, "Unknown suspend_handler\n");
res = 1;
break;
}
break;
case KBASE_PM_SUSPEND_HANDLER_VM_GPU_GRANTED:
break;
default:
WARN(1, "Unknown suspend_handler\n");
res = 1;
break;
}
/* Need to synchronously wait for GPU assignment */
atomic_inc(&kbdev->pm.gpu_users_waiting);
mutex_unlock(&arb_vm_state->vm_state_lock);
kbase_pm_unlock(kbdev);
kbase_arbiter_pm_vm_wait_gpu_assignment(kbdev);
kbase_pm_lock(kbdev);
mutex_lock(&arb_vm_state->vm_state_lock);
atomic_dec(&kbdev->pm.gpu_users_waiting);
break;
}
/* Need to synchronously wait for GPU assignment */
atomic_inc(&kbdev->pm.gpu_users_waiting);
mutex_unlock(&arb_vm_state->vm_state_lock);
kbase_pm_unlock(kbdev);
kbase_arbiter_pm_vm_wait_gpu_assignment(kbdev);
kbase_pm_lock(kbdev);
mutex_lock(&arb_vm_state->vm_state_lock);
atomic_dec(&kbdev->pm.gpu_users_waiting);
}
mutex_unlock(&arb_vm_state->vm_state_lock);
return res;
}

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -50,14 +50,22 @@ static struct kbase_clk_rate_trace_op_conf *
get_clk_rate_trace_callbacks(__maybe_unused struct kbase_device *kbdev)
{
/* base case */
const void *arbiter_if_node;
struct kbase_clk_rate_trace_op_conf *callbacks =
(struct kbase_clk_rate_trace_op_conf *)CLK_RATE_TRACE_OPS;
#if defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF)
const void *arbiter_if_node;
/* Nothing left to do here if there is no Arbiter/virtualization or if
* CONFIG_OF is not enabled.
*/
if (!IS_ENABLED(CONFIG_OF))
return callbacks;
if (WARN_ON(!kbdev) || WARN_ON(!kbdev->dev))
return callbacks;
if (!kbase_has_arbiter(kbdev))
return callbacks;
arbiter_if_node = of_get_property(kbdev->dev->of_node, "arbiter-if", NULL);
if (!arbiter_if_node)
arbiter_if_node = of_get_property(kbdev->dev->of_node, "arbiter_if", NULL);
@ -69,8 +77,6 @@ get_clk_rate_trace_callbacks(__maybe_unused struct kbase_device *kbdev)
dev_dbg(kbdev->dev,
"Arbitration supported but disabled by platform. Leaving clk rate callbacks as default.\n");
#endif
return callbacks;
}

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -48,7 +48,7 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev, struct kbasep_gpuprop
/* Not a valid register on TMIX */
/* TGOx specific register */
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_THREAD_TLS_ALLOC))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_THREAD_TLS_ALLOC))
regdump->thread_tls_alloc =
kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(THREAD_TLS_ALLOC));
#endif /* !MALI_USE_CSF */
@ -64,7 +64,7 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev, struct kbasep_gpuprop
/* AMBA_FEATURES enum is mapped to COHERENCY_FEATURES enum */
regdump->coherency_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(COHERENCY_FEATURES));
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_CORE_FEATURES))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_CORE_FEATURES))
regdump->core_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(CORE_FEATURES));
#if MALI_USE_CSF
@ -116,7 +116,7 @@ int kbase_backend_gpuprops_get_curr_config(struct kbase_device *kbdev,
int kbase_backend_gpuprops_get_l2_features(struct kbase_device *kbdev,
struct kbasep_gpuprops_regdump *regdump)
{
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_L2_CONFIG)) {
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_L2_CONFIG)) {
regdump->l2_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(L2_FEATURES));
regdump->l2_config = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(L2_CONFIG));

View file

@ -98,82 +98,6 @@ static u64 kbase_job_write_affinity(struct kbase_device *kbdev, base_jd_core_req
return affinity;
}
/**
* select_job_chain() - Select which job chain to submit to the GPU
* @katom: Pointer to the atom about to be submitted to the GPU
*
* Selects one of the fragment job chains attached to the special atom at the
* end of a renderpass, or returns the address of the single job chain attached
* to any other type of atom.
*
* Which job chain is selected depends upon whether the tiling phase of the
* renderpass completed normally or was soft-stopped because it used too
* much memory. It also depends upon whether one of the fragment job chains
* has already been run as part of the same renderpass.
*
* Return: GPU virtual address of the selected job chain
*/
static u64 select_job_chain(struct kbase_jd_atom *katom)
{
struct kbase_context *const kctx = katom->kctx;
u64 jc = katom->jc;
struct kbase_jd_renderpass *rp;
lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
if (!(katom->core_req & BASE_JD_REQ_END_RENDERPASS))
return jc;
compiletime_assert((1ull << (sizeof(katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[katom->renderpass_id];
/* We can read a subset of renderpass state without holding
* higher-level locks (but not end_katom, for example).
* If the end-of-renderpass atom is running with as-yet indeterminate
* OOM state then assume that the start atom was not soft-stopped.
*/
switch (rp->state) {
case KBASE_JD_RP_OOM:
/* Tiling ran out of memory.
* Start of incremental rendering, used once.
*/
jc = katom->jc_fragment.norm_read_forced_write;
break;
case KBASE_JD_RP_START:
case KBASE_JD_RP_PEND_OOM:
/* Tiling completed successfully first time.
* Single-iteration rendering, used once.
*/
jc = katom->jc_fragment.norm_read_norm_write;
break;
case KBASE_JD_RP_RETRY_OOM:
/* Tiling ran out of memory again.
* Continuation of incremental rendering, used as
* many times as required.
*/
jc = katom->jc_fragment.forced_read_forced_write;
break;
case KBASE_JD_RP_RETRY:
case KBASE_JD_RP_RETRY_PEND_OOM:
/* Tiling completed successfully this time.
* End of incremental rendering, used once.
*/
jc = katom->jc_fragment.forced_read_norm_write;
break;
default:
WARN_ON(1);
break;
}
dev_dbg(kctx->kbdev->dev, "Selected job chain 0x%llx for end atom %pK in state %d\n", jc,
(void *)katom, (int)rp->state);
katom->jc = jc;
return jc;
}
static inline bool kbasep_jm_wait_js_free(struct kbase_device *kbdev, unsigned int js,
struct kbase_context *kctx)
{
@ -196,7 +120,7 @@ int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom,
{
struct kbase_context *kctx;
u32 cfg;
u64 const jc_head = select_job_chain(katom);
u64 jc_head = katom->jc;
u64 affinity;
struct slot_rb *ptr_slot_rb = &kbdev->hwaccess.backend.slot_rb[js];
@ -220,21 +144,21 @@ int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom,
*/
cfg = (u32)kctx->as_nr;
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION) &&
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_REDUCTION) &&
!(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET))
cfg |= JS_CONFIG_ENABLE_FLUSH_REDUCTION;
if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_START)) {
/* Force a cache maintenance operation if the newly submitted
* katom to the slot is from a different kctx. For a JM GPU
* that has the feature BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
* that has the feature KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
* applies a FLUSH_INV_SHADER_OTHER. Otherwise, do a
* FLUSH_CLEAN_INVALIDATE.
*/
u64 tagged_kctx = ptr_slot_rb->last_kctx_tagged;
if (tagged_kctx != SLOT_RB_NULL_TAG_VAL && tagged_kctx != SLOT_RB_TAG_KCTX(kctx)) {
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER))
cfg |= JS_CONFIG_START_FLUSH_INV_SHADER_OTHER;
else
cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE;
@ -246,15 +170,14 @@ int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom,
if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_END) &&
!(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET))
cfg |= JS_CONFIG_END_FLUSH_NO_ACTION;
else if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_CLEAN_ONLY_SAFE))
else if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE))
cfg |= JS_CONFIG_END_FLUSH_CLEAN;
else
cfg |= JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE;
cfg |= JS_CONFIG_THREAD_PRI(8);
if ((katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED) ||
(katom->core_req & BASE_JD_REQ_END_RENDERPASS))
if (katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED)
cfg |= JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK;
if (!ptr_slot_rb->job_chain_flag) {
@ -268,7 +191,7 @@ int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom,
kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, CONFIG_NEXT), cfg);
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_REDUCTION))
kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, FLUSH_ID_NEXT), katom->flush_id);
/* Write an approximate start timestamp.
@ -440,7 +363,7 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done)
* jobs to hang. Reset GPU before allowing
* any other jobs on the slot to continue.
*/
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_3076)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_3076)) {
if (completion_code == BASE_JD_EVENT_JOB_BUS_FAULT) {
if (kbase_prepare_to_reset_gpu_locked(
kbdev, RESET_FLAGS_NONE))
@ -740,66 +663,6 @@ void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx,
}
}
static int softstop_start_rp_nolock(struct kbase_context *kctx, struct kbase_va_region *reg)
{
struct kbase_device *const kbdev = kctx->kbdev;
struct kbase_jd_atom *katom;
struct kbase_jd_renderpass *rp;
lockdep_assert_held(&kbdev->hwaccess_lock);
katom = kbase_gpu_inspect(kbdev, 1, 0);
if (!katom) {
dev_dbg(kctx->kbdev->dev, "No atom on job slot\n");
return -ESRCH;
}
if (!(katom->core_req & BASE_JD_REQ_START_RENDERPASS)) {
dev_dbg(kctx->kbdev->dev, "Atom %pK on job slot is not start RP\n", (void *)katom);
return -EPERM;
}
compiletime_assert((1ull << (sizeof(katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[katom->renderpass_id];
if (WARN_ON(rp->state != KBASE_JD_RP_START && rp->state != KBASE_JD_RP_RETRY))
return -EINVAL;
dev_dbg(kctx->kbdev->dev, "OOM in state %d with region %pK\n", (int)rp->state, (void *)reg);
if (WARN_ON(katom != rp->start_katom))
return -EINVAL;
dev_dbg(kctx->kbdev->dev, "Adding region %pK to list %pK\n", (void *)reg,
(void *)&rp->oom_reg_list);
list_move_tail(&reg->link, &rp->oom_reg_list);
dev_dbg(kctx->kbdev->dev, "Added region to list\n");
rp->state = (rp->state == KBASE_JD_RP_START ? KBASE_JD_RP_PEND_OOM :
KBASE_JD_RP_RETRY_PEND_OOM);
kbase_job_slot_softstop(kbdev, 1, katom);
return 0;
}
int kbase_job_slot_softstop_start_rp(struct kbase_context *const kctx,
struct kbase_va_region *const reg)
{
struct kbase_device *const kbdev = kctx->kbdev;
int err;
unsigned long flags;
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
err = softstop_start_rp_nolock(kctx, reg);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
return err;
}
void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx)
{
struct kbase_device *kbdev = kctx->kbdev;
@ -839,7 +702,7 @@ u32 kbase_backend_get_current_flush_id(struct kbase_device *kbdev)
{
u32 flush_id = 0;
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_FLUSH_REDUCTION)) {
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_REDUCTION)) {
mutex_lock(&kbdev->pm.lock);
if (kbdev->pm.backend.gpu_powered)
flush_id = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(LATEST_FLUSH));
@ -1085,7 +948,7 @@ static void kbasep_reset_timeout_worker(struct work_struct *data)
/* The flush has completed so reset the active indicator */
kbdev->irq_reset_flush = false;
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TMIX_8463)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TMIX_8463)) {
u64 val;
const u32 timeout_us =
kbase_get_timeout_ms(kbdev, KBASE_CLEAN_CACHE_TIMEOUT) * USEC_PER_MSEC;
@ -1268,14 +1131,12 @@ bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev, unsigned int
{
unsigned int i;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbase_pm_is_gpu_lost(kbdev)) {
/* GPU access has been removed, reset will be done by
* Arbiter instead
*/
return false;
}
#endif
if (flags & RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)
kbase_instr_hwcnt_on_unrecoverable_error(kbdev);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -425,7 +425,7 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev, struct kbase_jd_a
}
}
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TGOX_R1_1234)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) {
if (katom->atom_flags & KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT) {
kbase_pm_protected_l2_override(kbdev, false);
katom->atom_flags &= ~KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT;
@ -698,7 +698,7 @@ static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev, struct kbas
kbase_pm_protected_entry_override_disable(kbdev);
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TGOX_R1_1234)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) {
/*
* Power on L2 caches; this will also result in the
* correct value written to coherency enable register.
@ -714,13 +714,13 @@ static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev, struct kbas
katom[idx]->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_FINISHED;
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TGOX_R1_1234))
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234))
return -EAGAIN;
/* ***TRANSITION TO HIGHER STATE*** */
fallthrough;
case KBASE_ATOM_ENTER_PROTECTED_FINISHED:
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TGOX_R1_1234)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) {
/*
* Check that L2 caches are powered and, if so,
* enter protected mode.
@ -864,11 +864,7 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
lockdep_assert_held(&kbdev->hwaccess_lock);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbase_reset_gpu_is_active(kbdev) || kbase_is_gpu_removed(kbdev))
#else
if (kbase_reset_gpu_is_active(kbdev))
#endif
if (kbase_reset_gpu_is_active(kbdev) || (kbase_is_gpu_removed(kbdev)))
return;
for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) {
@ -896,7 +892,7 @@ void kbase_backend_slot_update(struct kbase_device *kbdev)
break;
case KBASE_ATOM_GPU_RB_WAITING_BLOCKED:
if (kbase_js_atom_blocked_on_x_dep(katom[idx]))
if (katom[idx]->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)
break;
katom[idx]->gpu_rb_state =
@ -1236,7 +1232,7 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, unsigned int js, u32 comp
* When a hard-stop is followed close after a soft-stop, the completion
* code may be set to STOPPED, even though the job is terminated
*/
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TMIX_8438)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TMIX_8438)) {
if (completion_code == BASE_JD_EVENT_STOPPED &&
(katom->atom_flags & KBASE_KATOM_FLAG_BEEN_HARD_STOPPED)) {
completion_code = BASE_JD_EVENT_TERMINATED;
@ -1331,6 +1327,9 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, unsigned int js, u32 comp
dev_dbg(kbdev->dev, "Update job chain address of atom %pK to resume from 0x%llx\n",
(void *)katom, job_tail);
/* Some of the job has been executed, so we update the job chain address to where
* we should resume from
*/
katom->jc = job_tail;
KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_UPDATE_HEAD, katom->kctx, katom, job_tail, js);
}
@ -1381,6 +1380,8 @@ void kbase_gpu_complete_hw(struct kbase_device *kbdev, unsigned int js, u32 comp
dev_dbg(kbdev->dev, "Cross-slot dependency %pK has become runnable.\n",
(void *)katom);
/* Cross-slot dependency has now become runnable. Try to submit it. */
/* Check if there are lower priority jobs to soft stop */
kbase_job_slot_ctx_priority_check_locked(kctx, katom);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -46,7 +46,7 @@ static inline bool timer_callback_should_run(struct kbase_device *kbdev, int nr_
}
#endif /* CONFIG_MALI_BIFROST_DEBUG */
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_9435)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_9435)) {
/* Timeouts would have to be 4x longer (due to micro-
* architectural design) to support OpenCL conformance tests, so
* only run the timer when there's:
@ -100,7 +100,7 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer)
/* The current version of the model doesn't support
* Soft-Stop
*/
if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_5736)) {
if (!kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_5736)) {
u32 ticks = atom->ticks++;
#if !defined(CONFIG_MALI_JOB_DUMP) && !defined(CONFIG_MALI_VECTOR_DUMP)

View file

@ -1953,7 +1953,8 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value)
*value = dummy->control_reg_values->gpu_features_lo;
} else if (addr == GPU_CONTROL_REG(GPU_FEATURES_HI)) {
*value = dummy->control_reg_values->gpu_features_hi;
} else {
}
else {
model_error_log(
KBASE_CORE,
"Dummy model register access: Reading unsupported register 0x%x. Returning 0\n",

View file

@ -36,9 +36,7 @@
#include <linux/version_compat_defs.h>
#include <linux/pm_runtime.h>
#include <mali_kbase_reset_gpu.h>
#ifdef CONFIG_MALI_ARBITER_SUPPORT
#include <csf/mali_kbase_csf_scheduler.h>
#endif /* !CONFIG_MALI_ARBITER_SUPPORT */
#endif /* !MALI_USE_CSF */
#include <hwcnt/mali_kbase_hwcnt_context.h>
#include <backend/gpu/mali_kbase_pm_internal.h>
@ -100,10 +98,8 @@ void kbase_pm_register_access_enable(struct kbase_device *kbdev)
if (callbacks)
callbacks->power_on_callback(kbdev);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (WARN_ON(kbase_pm_is_gpu_lost(kbdev)))
dev_err(kbdev->dev, "Attempting to power on while GPU lost\n");
#endif
kbdev->pm.backend.gpu_powered = true;
}
@ -136,9 +132,7 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev)
INIT_WORK(&kbdev->pm.backend.gpu_poweroff_wait_work, kbase_pm_gpu_poweroff_wait_wq);
kbdev->pm.backend.ca_cores_enabled = ~0ull;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
kbase_pm_set_gpu_lost(kbdev, false);
#endif
init_waitqueue_head(&kbdev->pm.backend.gpu_in_desired_state_wait);
#if !MALI_USE_CSF
@ -180,15 +174,18 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev)
kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx);
#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME)
kbdev->pm.backend.gpu_sleep_supported =
kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_GPU_SLEEP) &&
!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TURSEHW_1997) &&
kbdev->pm.backend.callback_power_runtime_gpu_active &&
kbdev->pm.backend.callback_power_runtime_gpu_idle;
kbdev->pm.backend.gpu_sleep_allowed = 0;
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GPU_SLEEP) &&
!kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TURSEHW_1997) &&
kbdev->pm.backend.callback_power_runtime_gpu_active &&
kbdev->pm.backend.callback_power_runtime_gpu_idle)
set_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed);
kbdev->pm.backend.apply_hw_issue_TITANHW_2938_wa =
kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TITANHW_2938) &&
kbdev->pm.backend.gpu_sleep_supported;
kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TITANHW_2938) &&
test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed);
/* FW Sleep-on-Idle is feature is kept disabled */
#endif
if (IS_ENABLED(CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED))
@ -196,14 +193,14 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev)
/* WA1: L2 always_on for GPUs being affected by GPU2017-1336 */
if (!IS_ENABLED(CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE)) {
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_GPU2017_1336))
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_GPU2017_1336))
kbdev->pm.backend.l2_always_on = true;
return 0;
}
/* WA3: Clock slow down for GPUs being affected by GPU2017-1336 */
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_GPU2017_1336)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_GPU2017_1336)) {
kbdev->pm.backend.gpu_clock_slow_down_wa = true;
kbdev->pm.backend.gpu_clock_slow_down_desired = true;
INIT_WORK(&kbdev->pm.backend.gpu_clock_control_work,
@ -348,13 +345,11 @@ static void pm_handle_power_off(struct kbase_device *kbdev)
*/
wait_for_mmu_fault_handling_in_gpu_poweroff_wait_wq(kbdev);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
/* poweron_required may have changed while pm lock
* was released.
*/
if (kbase_pm_is_gpu_lost(kbdev))
backend->poweron_required = false;
#endif
/* Turn off clock now that fault have been handled. We
* dropped locks so poweron_required may have changed -
@ -948,13 +943,11 @@ void kbase_hwaccess_pm_resume(struct kbase_device *kbdev)
/* System resume callback has begun */
kbdev->pm.resuming = true;
kbdev->pm.suspending = false;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbase_pm_is_gpu_lost(kbdev)) {
dev_dbg(kbdev->dev, "%s: GPU lost in progress\n", __func__);
kbase_pm_unlock(kbdev);
return;
}
#endif
kbase_pm_do_poweron(kbdev, true);
#if !MALI_USE_CSF
@ -964,7 +957,6 @@ void kbase_hwaccess_pm_resume(struct kbase_device *kbdev)
kbase_pm_unlock(kbdev);
}
#ifdef CONFIG_MALI_ARBITER_SUPPORT
void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev)
{
unsigned long flags;
@ -975,8 +967,10 @@ void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev)
#endif
struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
if (!kbdev->arb.arb_if)
if (!kbase_has_arbiter(kbdev)) {
dev_warn(kbdev->dev, "%s called with no active arbiter!\n", __func__);
return;
}
mutex_lock(&kbdev->pm.lock);
mutex_lock(&arb_vm_state->vm_state_lock);
@ -991,7 +985,8 @@ void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev)
#if MALI_USE_CSF
/* Full GPU reset will have been done by hypervisor, so cancel */
kbase_reset_gpu_prevent_and_wait(kbdev);
if (kbase_reset_gpu_prevent_and_wait(kbdev))
dev_warn(kbdev->dev, "Failed to prevent GPU reset.");
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
kbase_csf_scheduler_spin_lock(kbdev, &flags_sched);
@ -1041,7 +1036,6 @@ void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev)
mutex_unlock(&arb_vm_state->vm_state_lock);
mutex_unlock(&kbdev->pm.lock);
}
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME)
int kbase_pm_force_mcu_wakeup_after_sleep(struct kbase_device *kbdev)
@ -1253,4 +1247,5 @@ out:
return ret;
}
#endif

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2013-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2013-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -55,11 +55,18 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
unsigned long flags;
#if MALI_USE_CSF
u64 old_core_mask = 0;
#endif
bool mmu_sync_needed = false;
if (!IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) &&
kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_GPU2019_3901)) {
mmu_sync_needed = true;
down_write(&kbdev->csf.mmu_sync_sem);
}
#endif
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
#if MALI_USE_CSF
if (!(core_mask & kbdev->pm.debug_core_mask)) {
dev_err(kbdev->dev,
"OPP core mask 0x%llX does not intersect with debug mask 0x%llX\n",
@ -98,6 +105,9 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
old_core_mask, core_mask);
}
}
if (mmu_sync_needed)
up_write(&kbdev->csf.mmu_sync_sem);
#endif
dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX\n", pm_backend->ca_cores_enabled);
@ -105,6 +115,10 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask)
return;
unlock:
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
#if MALI_USE_CSF
if (mmu_sync_needed)
up_write(&kbdev->csf.mmu_sync_sem);
#endif
}
KBASE_EXPORT_TEST_API(kbase_devfreq_set_core_mask);
#endif

View file

@ -114,6 +114,27 @@ enum kbase_pm_runtime_suspend_abort_reason {
ABORT_REASON_NON_IDLE_CGS
};
/* The following indices point to the corresponding bits stored in
* &kbase_pm_backend_data.gpu_sleep_allowed. They denote the conditions that
* would be checked against to determine the level of support for GPU sleep
* and firmware sleep-on-idle.
*/
#define KBASE_GPU_SUPPORTS_GPU_SLEEP ((uint8_t)0)
#define KBASE_GPU_SUPPORTS_FW_SLEEP_ON_IDLE ((uint8_t)1)
#define KBASE_GPU_PERF_COUNTERS_COLLECTION_ENABLED ((uint8_t)2)
#define KBASE_GPU_IGNORE_IDLE_EVENT ((uint8_t)3)
#define KBASE_GPU_NON_IDLE_OFF_SLOT_GROUPS_AVAILABLE ((uint8_t)4)
/* FW sleep-on-idle could be enabled if
* &kbase_pm_backend_data.gpu_sleep_allowed is equal to this value.
*/
#define KBASE_GPU_FW_SLEEP_ON_IDLE_ALLOWED \
((uint8_t)((1 << KBASE_GPU_SUPPORTS_GPU_SLEEP) | \
(1 << KBASE_GPU_SUPPORTS_FW_SLEEP_ON_IDLE) | \
(0 << KBASE_GPU_PERF_COUNTERS_COLLECTION_ENABLED) | \
(0 << KBASE_GPU_IGNORE_IDLE_EVENT) | \
(0 << KBASE_GPU_NON_IDLE_OFF_SLOT_GROUPS_AVAILABLE)))
/**
* struct kbasep_pm_metrics - Metrics data collected for use by the power
* management framework.
@ -304,7 +325,7 @@ union kbase_pm_policy_data {
* called previously.
* See &struct kbase_pm_callback_conf.
* @ca_cores_enabled: Cores that are currently available
* @apply_hw_issue_TITANHW_2938_wa: Indicates if the workaround for BASE_HW_ISSUE_TITANHW_2938
* @apply_hw_issue_TITANHW_2938_wa: Indicates if the workaround for KBASE_HW_ISSUE_TITANHW_2938
* needs to be applied when unmapping memory from GPU.
* @mcu_state: The current state of the micro-control unit, only applicable
* to GPUs that have such a component
@ -350,10 +371,9 @@ union kbase_pm_policy_data {
* @core_idle_work: Work item used to wait for undesired cores to become inactive.
* The work item is enqueued when Host controls the power for
* shader cores and down scaling of cores is performed.
* @gpu_sleep_supported: Flag to indicate that if GPU sleep feature can be
* supported by the kernel driver or not. If this
* flag is not set, then HW state is directly saved
* when GPU idle notification is received.
* @gpu_sleep_allowed: Bitmask to indicate the conditions that would be
* used to determine what support for GPU sleep is
* available.
* @gpu_sleep_mode_active: Flag to indicate that the GPU needs to be in sleep
* mode. It is set when the GPU idle notification is
* received and is cleared when HW state has been
@ -497,7 +517,7 @@ struct kbase_pm_backend_data {
struct work_struct core_idle_work;
#ifdef KBASE_PM_RUNTIME
bool gpu_sleep_supported;
unsigned long gpu_sleep_allowed;
bool gpu_sleep_mode_active;
bool exit_gpu_sleep_mode;
bool gpu_idled;

View file

@ -47,9 +47,7 @@
#include <backend/gpu/mali_kbase_pm_internal.h>
#include <backend/gpu/mali_kbase_l2_mmu_config.h>
#include <mali_kbase_dummy_job_wa.h>
#ifdef CONFIG_MALI_ARBITER_SUPPORT
#include <arbiter/mali_kbase_arbiter_pm.h>
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
#if MALI_USE_CSF
#include <linux/delay.h>
@ -615,11 +613,11 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev)
/*
* Skip if it is not supported
*/
if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_L2_CONFIG))
if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_L2_CONFIG))
return;
#if MALI_USE_CSF
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU)) {
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PBHA_HWU)) {
val = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(L2_CONFIG));
kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(L2_CONFIG),
L2_CONFIG_PBHA_HWU_SET(val, kbdev->pbha_propagate_bits));
@ -743,16 +741,8 @@ bool kbase_pm_is_mcu_inactive(struct kbase_device *kbdev, enum kbase_mcu_state s
}
#ifdef KBASE_PM_RUNTIME
/**
* kbase_pm_enable_mcu_db_notification - Enable the Doorbell notification on
* MCU side
*
* @kbdev: Pointer to the device.
*
* This function is called to re-enable the Doorbell notification on MCU side
* when MCU needs to beome active again.
*/
static void kbase_pm_enable_mcu_db_notification(struct kbase_device *kbdev)
void kbase_pm_enable_mcu_db_notification(struct kbase_device *kbdev)
{
u32 val = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(MCU_CONTROL));
@ -778,7 +768,7 @@ static void wait_mcu_as_inactive(struct kbase_device *kbdev)
kbase_get_timeout_ms(kbdev, KBASE_AS_INACTIVE_TIMEOUT) * USEC_PER_MSEC;
lockdep_assert_held(&kbdev->hwaccess_lock);
if (!kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TURSEHW_2716))
if (!kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TURSEHW_2716))
return;
/* Wait for the AS_ACTIVE_INT bit to become 0 for the AS used by MCU FW */
@ -927,6 +917,18 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
if (kbase_pm_is_mcu_desired(kbdev) &&
!backend->policy_change_clamp_state_to_off &&
backend->l2_state == KBASE_L2_ON) {
kbdev->csf.mcu_halted = false;
/* Ensure that FW would not go to sleep immediately after
* resumption.
*/
kbase_csf_firmware_global_input_mask(&kbdev->csf.global_iface,
GLB_REQ,
GLB_REQ_REQ_IDLE_DISABLE,
GLB_REQ_IDLE_DISABLE_MASK);
atomic_set(&kbdev->csf.scheduler.gpu_idle_timer_enabled, false);
atomic_set(&kbdev->csf.scheduler.fw_soi_enabled, false);
kbase_csf_firmware_trigger_reload(kbdev);
backend->mcu_state = KBASE_MCU_PEND_ON_RELOAD;
}
@ -1005,7 +1007,6 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
case KBASE_MCU_ON:
backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev);
if (!kbase_pm_is_mcu_desired(kbdev))
backend->mcu_state = KBASE_MCU_ON_HWCNT_DISABLE;
else if (kbdev->csf.firmware_hctl_core_pwr) {
@ -1185,7 +1186,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
break;
case KBASE_MCU_POWER_DOWN:
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TITANHW_2922)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TITANHW_2922)) {
if (!kbdev->csf.firmware_hctl_core_pwr)
kbasep_pm_toggle_power_interrupt(kbdev, true);
backend->mcu_state = KBASE_MCU_OFF;
@ -1206,7 +1207,20 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
#ifdef KBASE_PM_RUNTIME
case KBASE_MCU_ON_SLEEP_INITIATE:
if (!kbase_pm_is_mcu_desired(kbdev)) {
kbase_csf_firmware_trigger_mcu_sleep(kbdev);
bool db_notif_disabled = false;
if (likely(test_bit(KBASE_GPU_SUPPORTS_FW_SLEEP_ON_IDLE,
&kbdev->pm.backend.gpu_sleep_allowed)))
db_notif_disabled =
kbase_reg_read32(kbdev,
GPU_CONTROL_ENUM(MCU_CONTROL)) &
MCU_CNTRL_DOORBELL_DISABLE_MASK;
/* If DB notification is enabled on FW side then send a sleep
* request to FW.
*/
if (!db_notif_disabled)
kbase_csf_firmware_trigger_mcu_sleep(kbdev);
backend->mcu_state = KBASE_MCU_ON_PEND_SLEEP;
} else
backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE;
@ -1240,6 +1254,16 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev)
case KBASE_MCU_IN_SLEEP:
if (kbase_pm_is_mcu_desired(kbdev) && backend->l2_state == KBASE_L2_ON) {
wait_mcu_as_inactive(kbdev);
/* Ensure that FW would not go to sleep immediately after
* resumption.
*/
kbase_csf_firmware_global_input_mask(&kbdev->csf.global_iface,
GLB_REQ,
GLB_REQ_REQ_IDLE_DISABLE,
GLB_REQ_IDLE_DISABLE_MASK);
atomic_set(&kbdev->csf.scheduler.gpu_idle_timer_enabled, false);
atomic_set(&kbdev->csf.scheduler.fw_soi_enabled, false);
KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_REQUEST_WAKEUP(
kbdev, kbase_backend_get_cycle_cnt(kbdev));
kbase_pm_enable_mcu_db_notification(kbdev);
@ -1384,20 +1408,6 @@ static bool need_tiler_control(struct kbase_device *kbdev)
#endif
}
/**
* hctl_l2_power_down - Initiate power down of L2 cache
*
* @kbdev: The kbase device structure for the device.
*
* This function initiates the power down of L2 cache when Host controls the power
* for Tiler block. The function expects that power down of Tiler to already have
* been initiated and it triggers the L2 power down only after the power down for
* Tiler is complete.
* The function shall be called only if L2 is in ready state.
*/
static void hctl_l2_power_down(struct kbase_device *kbdev)
{
}
/**
* hctl_tiler_power_up_done - Check and/or initiate power up of Tiler
@ -1444,7 +1454,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
u64 l2_trans = kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_L2);
u64 l2_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
/*
* kbase_pm_get_ready_cores and kbase_pm_get_trans_cores
* are vulnerable to corruption if gpu is lost
@ -1473,7 +1482,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
}
break;
}
#endif
/* mask off ready from trans in case transitions finished
* between the register reads
@ -1574,7 +1582,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
case KBASE_L2_RESTORE_CLOCKS:
/* We always assume only GPUs being affected by
* BASE_HW_ISSUE_GPU2017_1336 fall into this state
* KBASE_HW_ISSUE_GPU2017_1336 fall into this state
*/
WARN_ON_ONCE(!kbdev->pm.backend.gpu_clock_slow_down_wa);
@ -1676,7 +1684,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
case KBASE_L2_SLOW_DOWN_CLOCKS:
/* We always assume only GPUs being affected by
* BASE_HW_ISSUE_GPU2017_1336 fall into this state
* KBASE_HW_ISSUE_GPU2017_1336 fall into this state
*/
WARN_ON_ONCE(!kbdev->pm.backend.gpu_clock_slow_down_wa);
@ -1725,11 +1733,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
case KBASE_L2_PEND_OFF:
if (likely(!backend->l2_always_on)) {
if (need_tiler_control(kbdev) && l2_ready) {
hctl_l2_power_down(kbdev);
break;
}
if (l2_trans || l2_ready)
break;
} else if (kbdev->cache_clean_in_progress)
@ -1744,11 +1747,10 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev)
}
#endif
/* Disabling MCU after L2 cache power down is to address
* BASE_HW_ISSUE_TITANHW_2922 hardware issue.
* KBASE_HW_ISSUE_TITANHW_2922 hardware issue.
*/
if (backend->l2_force_off_after_mcu_halt) {
kbase_csf_firmware_disable_mcu(kbdev);
kbase_csf_firmware_disable_mcu_wait(kbdev);
kbase_csf_stop_firmware_and_wait(kbdev);
WARN_ON_ONCE(backend->mcu_state != KBASE_MCU_OFF);
backend->l2_force_off_after_mcu_halt = false;
}
@ -1895,12 +1897,7 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
* kbase_pm_get_ready_cores and kbase_pm_get_trans_cores
* are vulnerable to corruption if gpu is lost
*/
if (kbase_is_gpu_removed(kbdev)
#ifdef CONFIG_MALI_ARBITER_SUPPORT
|| kbase_pm_is_gpu_lost(kbdev)) {
#else
) {
#endif
if (kbase_is_gpu_removed(kbdev) || kbase_pm_is_gpu_lost(kbdev)) {
backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF;
dev_dbg(kbdev->dev, "GPU lost has occurred - shaders off\n");
break;
@ -2005,9 +2002,8 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
kbdev, KBASE_PM_POLICY_EVENT_IDLE);
if (kbdev->pm.backend.protected_transition_override ||
#ifdef CONFIG_MALI_ARBITER_SUPPORT
kbase_pm_is_suspending(kbdev) || kbase_pm_is_gpu_lost(kbdev) ||
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
(kbase_has_arbiter(kbdev) && (kbase_pm_is_suspending(kbdev) ||
kbase_pm_is_gpu_lost(kbdev))) ||
!stt->configured_ticks || WARN_ON(stt->cancel_queued)) {
backend->shaders_state =
KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON;
@ -2074,10 +2070,9 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
kbdev, KBASE_PM_POLICY_EVENT_TIMER_MISS);
backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
} else if (kbase_pm_is_suspending(kbdev) || kbase_pm_is_gpu_lost(kbdev)) {
} else if (kbase_has_arbiter(kbdev) &&
(kbase_pm_is_suspending(kbdev) || kbase_pm_is_gpu_lost(kbdev))) {
backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON;
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
}
break;
@ -2096,7 +2091,7 @@ static int kbase_pm_shaders_update_state(struct kbase_device *kbdev)
if (!backend->partial_shaderoff)
shader_poweroff_timer_queue_cancel(kbdev);
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921)) {
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_921)) {
kbase_gpu_start_cache_clean_nolock(kbdev,
GPU_COMMAND_CACHE_CLN_INV_L2);
backend->shaders_state = KBASE_SHADERS_L2_FLUSHING_CORESTACK_ON;
@ -2446,6 +2441,9 @@ void kbase_pm_reset_complete(struct kbase_device *kbdev)
backend->in_reset = false;
#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME)
backend->gpu_wakeup_override = false;
backend->db_mirror_interrupt_enabled = false;
backend->gpu_sleep_mode_active = false;
backend->exit_gpu_sleep_mode = false;
#endif
kbase_pm_update_state(kbdev);
@ -2670,12 +2668,9 @@ static int pm_wait_for_poweroff_work_complete(struct kbase_device *kbdev, bool k
const long timeout = kbase_csf_timeout_in_jiffies(
kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT) + extra_wait_time_ms);
#else
#ifdef CONFIG_MALI_ARBITER_SUPPORT
/* Handling of timeout error isn't supported for arbiter builds */
const long timeout = MAX_SCHEDULE_TIMEOUT;
#else
const long timeout = (long)msecs_to_jiffies(PM_TIMEOUT_MS);
#endif
const long timeout = kbase_has_arbiter(kbdev) ? MAX_SCHEDULE_TIMEOUT :
(long)msecs_to_jiffies(PM_TIMEOUT_MS);
#endif
int err = 0;
@ -2796,7 +2791,8 @@ static void update_user_reg_page_mapping(struct kbase_device *kbdev)
* when the context (user process) needs to access to the page.
*/
unmap_mapping_range(kbdev->csf.user_reg.filp->f_inode->i_mapping,
kctx->csf.user_reg.file_offset << PAGE_SHIFT, PAGE_SIZE, 1);
(loff_t)kctx->csf.user_reg.file_offset << PAGE_SHIFT, PAGE_SIZE,
1);
list_del_init(&kctx->csf.user_reg.link);
dev_dbg(kbdev->dev, "Updated USER Reg page mapping of ctx %d_%d", kctx->tgid,
kctx->id);
@ -2823,12 +2819,10 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
#endif /* !MALI_USE_CSF */
lockdep_assert_held(&kbdev->pm.lock);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (WARN_ON(kbase_pm_is_gpu_lost(kbdev))) {
dev_err(kbdev->dev, "%s: Cannot power up while GPU lost", __func__);
return;
}
#endif
if (backend->gpu_powered) {
#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME)
@ -2876,10 +2870,8 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
* consistent state
*/
kbase_pm_init_hw(kbdev, PM_ENABLE_IRQS);
}
#ifdef CONFIG_MALI_ARBITER_SUPPORT
else {
if (kbdev->arb.arb_if) {
} else {
if (kbase_has_arbiter(kbdev)) {
struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state;
/* In the case that the GPU has just been granted by
@ -2895,8 +2887,8 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume)
* that a repartitioning occurred. In this case the current config
* should be read again.
*/
kbase_gpuprops_get_curr_config_props(kbdev, &kbdev->gpu_props.curr_config);
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
if (kbase_has_arbiter(kbdev))
kbase_gpuprops_get_curr_config_props(kbdev, &kbdev->gpu_props.curr_config);
mutex_lock(&kbdev->mmu_hw_mutex);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
@ -2988,12 +2980,7 @@ bool kbase_pm_clock_off(struct kbase_device *kbdev)
}
#endif
if (kbase_is_gpu_removed(kbdev)
#ifdef CONFIG_MALI_ARBITER_SUPPORT
|| kbase_pm_is_gpu_lost(kbdev)) {
#else
) {
#endif
if (kbase_is_gpu_removed(kbdev) || kbase_pm_is_gpu_lost(kbdev)) {
/* Ensure we unblock any threads that are stuck waiting
* for the GPU
*/
@ -3011,10 +2998,7 @@ bool kbase_pm_clock_off(struct kbase_device *kbdev)
/* GPU is about to be turned off, switch to dummy page */
update_user_reg_page_mapping(kbdev);
#endif
#ifdef CONFIG_MALI_ARBITER_SUPPORT
kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_IDLE_EVENT);
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
if (kbdev->pm.backend.callback_power_off)
kbdev->pm.backend.callback_power_off(kbdev);
@ -3068,6 +3052,7 @@ static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer)
return HRTIMER_NORESTART;
}
static int kbase_set_gpu_quirks(struct kbase_device *kbdev)
{
#if MALI_USE_CSF
@ -3097,7 +3082,7 @@ static int kbase_set_gpu_quirks(struct kbase_device *kbdev)
kbdev->hw_quirks_gpu = hw_quirks_gpu;
#endif /* !MALI_USE_CSF */
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_IDVS_GROUP_SIZE)) {
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_IDVS_GROUP_SIZE)) {
u32 default_idvs_group_size = 0xF;
u32 group_size = 0;
@ -3131,10 +3116,10 @@ static int kbase_set_sc_quirks(struct kbase_device *kbdev)
if (kbase_is_gpu_removed(kbdev))
return -EIO;
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_2968_TTRX_3162))
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162))
hw_quirks_sc |= SC_VAR_ALGORITHM;
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_TLS_HASHING))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_TLS_HASHING))
hw_quirks_sc |= SC_TLS_HASH_ENABLE;
kbdev->hw_quirks_sc = hw_quirks_sc;
@ -3153,7 +3138,7 @@ static int kbase_set_tiler_quirks(struct kbase_device *kbdev)
return -EIO;
/* Set tiler clock gate override if required */
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_T76X_3953))
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_T76X_3953))
hw_quirks_tiler |= TC_CLOCK_GATE_OVERRIDE;
kbdev->hw_quirks_tiler = hw_quirks_tiler;
@ -3370,9 +3355,8 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev)
/* The GPU doesn't seem to be responding to the reset so try a hard
* reset, but only when NOT in arbitration mode.
*/
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (!kbdev->arb.arb_if) {
#endif
if (!kbase_has_arbiter(kbdev)) {
dev_err(kbdev->dev,
"Failed to soft-reset GPU (timed out after %d ms), now attempting a hard reset\n",
RESET_TIMEOUT);
@ -3402,9 +3386,7 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev)
dev_err(kbdev->dev, "Failed to hard-reset the GPU (timed out after %d ms)\n",
RESET_TIMEOUT);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
}
#endif
return -EINVAL;
}
@ -3487,6 +3469,7 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags)
kbase_amba_set_shareable_cache_support(kbdev);
#if MALI_USE_CSF
kbase_backend_update_gpu_timestamp_offset(kbdev);
kbdev->csf.compute_progress_timeout_cc = 0;
#endif
/* Sanity check protected mode was left after reset */

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -821,6 +821,21 @@ bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev);
*/
bool kbase_pm_is_mcu_inactive(struct kbase_device *kbdev, enum kbase_mcu_state state);
#ifdef KBASE_PM_RUNTIME
/**
* kbase_pm_enable_mcu_db_notification - Enable the Doorbell notification on
* MCU side
*
* @kbdev: Pointer to the device.
*
* This function is called to re-enable the Doorbell notification on MCU side
* when MCU needs to beome active again.
*/
void kbase_pm_enable_mcu_db_notification(struct kbase_device *kbdev);
#endif /* KBASE_PM_RUNTIME */
/**
* kbase_pm_idle_groups_sched_suspendable - Check whether the scheduler can be
* suspended to low power state when all
@ -963,11 +978,29 @@ static inline bool kbase_pm_gpu_sleep_allowed(struct kbase_device *kbdev)
* A high positive value of autosuspend_delay can be used to keep the
* GPU in sleep state for a long time.
*/
if (unlikely(!kbdev->dev->power.autosuspend_delay ||
(kbdev->dev->power.autosuspend_delay < 0)))
if (unlikely(kbdev->dev->power.autosuspend_delay <= 0))
return false;
return kbdev->pm.backend.gpu_sleep_supported;
return test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed);
}
/**
* kbase_pm_fw_sleep_on_idle_allowed - Check if FW sleep-on-idle could be enabled
*
* @kbdev: Device pointer
*
* This function should be called whenever the conditions that impact
* FW sleep-on-idle support change so that it could be enabled/disabled
* accordingly.
*
* Return: true if FW sleep-on-idle is allowed
*/
static inline bool kbase_pm_fw_sleep_on_idle_allowed(struct kbase_device *kbdev)
{
if (unlikely(kbdev->dev->power.autosuspend_delay <= 0))
return false;
return kbdev->pm.backend.gpu_sleep_allowed == KBASE_GPU_FW_SLEEP_ON_IDLE_ALLOWED;
}
/**

View file

@ -77,7 +77,16 @@ void kbase_pm_policy_init(struct kbase_device *kbdev)
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
kbdev->pm.backend.pm_current_policy = default_policy;
kbdev->pm.backend.csf_pm_sched_flags = default_policy->pm_sched_flags;
#ifdef KBASE_PM_RUNTIME
if (kbase_pm_idle_groups_sched_suspendable(kbdev))
clear_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed);
else
set_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed);
#endif /* KBASE_PM_RUNTIME */
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
#else
CSTD_UNUSED(flags);
kbdev->pm.backend.pm_current_policy = default_policy;
@ -400,6 +409,13 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_polic
/* New policy in place, release the clamping on mcu/L2 off state */
kbdev->pm.backend.policy_change_clamp_state_to_off = false;
kbase_pm_update_state(kbdev);
#ifdef KBASE_PM_RUNTIME
if (kbase_pm_idle_groups_sched_suspendable(kbdev))
clear_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed);
else
set_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed);
#endif /* KBASE_PM_RUNTIME */
#endif
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);

View file

@ -46,7 +46,6 @@ static struct kbase_timeout_info timeout_info[KBASE_TIMEOUT_SELECTOR_COUNT] = {
CSF_FIRMWARE_PING_TIMEOUT_CYCLES) },
[CSF_PM_TIMEOUT] = { "CSF_PM_TIMEOUT", CSF_PM_TIMEOUT_CYCLES },
[CSF_GPU_RESET_TIMEOUT] = { "CSF_GPU_RESET_TIMEOUT", CSF_GPU_RESET_TIMEOUT_CYCLES },
[CSF_CSG_SUSPEND_TIMEOUT] = { "CSF_CSG_SUSPEND_TIMEOUT", CSF_CSG_SUSPEND_TIMEOUT_CYCLES },
[CSF_CSG_TERM_TIMEOUT] = { "CSF_CSG_TERM_TIMEOUT", CSF_CSG_TERM_TIMEOUT_CYCLES },
[CSF_FIRMWARE_BOOT_TIMEOUT] = { "CSF_FIRMWARE_BOOT_TIMEOUT",
CSF_FIRMWARE_BOOT_TIMEOUT_CYCLES },
@ -236,6 +235,15 @@ void kbase_device_set_timeout_ms(struct kbase_device *kbdev, enum kbase_timeout_
}
selector_str = timeout_info[selector].selector_str;
#if MALI_USE_CSF
if (IS_ENABLED(CONFIG_MALI_REAL_HW) && !IS_ENABLED(CONFIG_MALI_IS_FPGA) &&
unlikely(timeout_ms >= MAX_TIMEOUT_MS)) {
dev_warn(kbdev->dev, "%s is capped from %dms to %dms\n",
timeout_info[selector].selector_str, timeout_ms, MAX_TIMEOUT_MS);
timeout_ms = MAX_TIMEOUT_MS;
}
#endif
kbdev->backend_time.device_scaled_timeouts[selector] = timeout_ms;
dev_dbg(kbdev->dev, "\t%-35s: %ums\n", selector_str, timeout_ms);
}

View file

@ -113,7 +113,7 @@ bob_defaults {
mali_hw_errata_1485982_use_clock_alternative: {
kbuild_options: ["CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE=y"],
},
platform_is_fpga: {
mali_is_fpga: {
kbuild_options: ["CONFIG_MALI_IS_FPGA=y"],
},
mali_coresight: {
@ -148,7 +148,6 @@ bob_defaults {
// is an umbrella feature that would be open for inappropriate use
// (catch-all for experimental CS code without separating it into
// different features).
"MALI_INCREMENTAL_RENDERING_JM={{.incremental_rendering_jm}}",
"MALI_BASE_CSF_PERFORMANCE_TESTS={{.base_csf_performance_tests}}",
],
}
@ -162,6 +161,9 @@ bob_kernel_module {
"*.c",
"*.h",
"Kbuild",
"arbiter/*.c",
"arbiter/*.h",
"arbiter/Kbuild",
"backend/gpu/*.c",
"backend/gpu/*.h",
"backend/gpu/Kbuild",
@ -257,13 +259,6 @@ bob_kernel_module {
"ipa/backend/*_csf.h",
],
},
mali_arbiter_support: {
srcs: [
"arbiter/*.c",
"arbiter/*.h",
"arbiter/Kbuild",
],
},
kbuild_options: [
"CONFIG_MALI_BIFROST=m",
"CONFIG_MALI_KUTF=n",

View file

@ -186,17 +186,15 @@ void kbase_destroy_context(struct kbase_context *kctx)
* Customer side that a hang could occur if context termination is
* not blocked until the resume of GPU device.
*/
#ifdef CONFIG_MALI_ARBITER_SUPPORT
atomic_inc(&kbdev->pm.gpu_users_waiting);
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
if (kbase_has_arbiter(kbdev))
atomic_inc(&kbdev->pm.gpu_users_waiting);
while (kbase_pm_context_active_handle_suspend(kbdev,
KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) {
dev_dbg(kbdev->dev, "Suspend in progress when destroying context");
wait_event(kbdev->pm.resume_wait, !kbase_pm_is_suspending(kbdev));
}
#ifdef CONFIG_MALI_ARBITER_SUPPORT
atomic_dec(&kbdev->pm.gpu_users_waiting);
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
if (kbase_has_arbiter(kbdev))
atomic_dec(&kbdev->pm.gpu_users_waiting);
/* Have synchronized against the System suspend and incremented the
* pm.active_count. So any subsequent invocation of System suspend

View file

@ -231,14 +231,13 @@ void kbase_destroy_context(struct kbase_context *kctx)
if (WARN_ON(!kbdev))
return;
/* Context termination could happen whilst the system suspend of
/* Context termination could happen whilst the system suspend of
* the GPU device is ongoing or has completed. It has been seen on
* Customer side that a hang could occur if context termination is
* not blocked until the resume of GPU device.
*/
#ifdef CONFIG_MALI_ARBITER_SUPPORT
atomic_inc(&kbdev->pm.gpu_users_waiting);
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
if (kbase_has_arbiter(kbdev))
atomic_inc(&kbdev->pm.gpu_users_waiting);
while (kbase_pm_context_active_handle_suspend(kbdev,
KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) {
dev_dbg(kbdev->dev, "Suspend in progress when destroying context");
@ -255,9 +254,8 @@ void kbase_destroy_context(struct kbase_context *kctx)
*/
wait_event(kbdev->pm.resume_wait, !kbase_pm_is_resuming(kbdev));
#ifdef CONFIG_MALI_ARBITER_SUPPORT
atomic_dec(&kbdev->pm.gpu_users_waiting);
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
if (kbase_has_arbiter(kbdev))
atomic_dec(&kbdev->pm.gpu_users_waiting);
kbase_mem_pool_group_mark_dying(&kctx->mem_pools);

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
#
# (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved.
# (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the
# GNU General Public License version 2 as published by the Free Software
@ -48,8 +48,10 @@ bifrost_kbase-y += \
ifeq ($(CONFIG_MALI_BIFROST_NO_MALI),y)
bifrost_kbase-y += csf/mali_kbase_csf_firmware_no_mali.o
bifrost_kbase-y += csf/mali_kbase_csf_fw_io_no_mali.o
else
bifrost_kbase-y += csf/mali_kbase_csf_firmware.o
bifrost_kbase-y += csf/mali_kbase_csf_fw_io.o
endif
bifrost_kbase-$(CONFIG_DEBUG_FS) += csf/mali_kbase_debug_csf_fault.o

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -943,6 +943,8 @@ void kbase_ipa_control_protm_entered(struct kbase_device *kbdev)
struct kbase_ipa_control *ipa_ctrl = &kbdev->csf.ipa_control;
lockdep_assert_held(&kbdev->hwaccess_lock);
ipa_ctrl->protm_start = ktime_get_raw_ns();
}
@ -955,6 +957,7 @@ void kbase_ipa_control_protm_exited(struct kbase_device *kbdev)
lockdep_assert_held(&kbdev->hwaccess_lock);
for (i = 0; i < KBASE_IPA_CONTROL_MAX_SESSIONS; i++) {
struct kbase_ipa_control_session *session = &ipa_ctrl->sessions[i];

View file

@ -45,6 +45,9 @@
#define CS_RING_BUFFER_MAX_SIZE ((uint32_t)(1 << 31)) /* 2GiB */
#define CS_RING_BUFFER_MIN_SIZE ((uint32_t)4096)
/* 0.2 second assuming 600 MHz GPU clock, which is double of iterator disabling timeout */
#define MAX_PROGRESS_TIMEOUT_EVENT_DELAY ((u32)120000000)
#define PROTM_ALLOC_MAX_RETRIES ((u8)5)
const u8 kbasep_csf_queue_group_priority_to_relative[BASE_QUEUE_GROUP_PRIORITY_COUNT] = {
@ -1261,6 +1264,7 @@ static int create_queue_group(struct kbase_context *const kctx,
INIT_LIST_HEAD(&group->error_fatal.link);
INIT_WORK(&group->timer_event_work, timer_event_worker);
INIT_LIST_HEAD(&group->protm_event_work);
group->progress_timer_state = 0;
atomic_set(&group->pending_protm_event_work, 0);
bitmap_zero(group->protm_pending_bitmap, MAX_SUPPORTED_STREAMS_PER_GROUP);
@ -1306,12 +1310,6 @@ int kbase_csf_queue_group_create(struct kbase_context *const kctx,
const u32 tiler_count = hweight64(create->in.tiler_mask);
const u32 fragment_count = hweight64(create->in.fragment_mask);
const u32 compute_count = hweight64(create->in.compute_mask);
size_t i;
for (i = 0; i < ARRAY_SIZE(create->in.padding); i++) {
if (create->in.padding[i] != 0)
return -EINVAL;
}
mutex_lock(&kctx->csf.lock);
@ -2178,19 +2176,74 @@ static void timer_event_worker(struct work_struct *data)
}
/**
* handle_progress_timer_event() - Progress timer timeout event handler.
* handle_progress_timer_events() - Progress timer timeout events handler.
*
* @group: Pointer to GPU queue group for which the timeout event is received.
* @kbdev: Instance of a GPU platform device that implements a CSF interface.
* @slot_mask: Bitmap reflecting the slots on which progress timer timeouts happen.
*
* Notify a waiting user space client of the timeout.
* Enqueue a work item to terminate the group and notify the event notification
* thread of progress timeout fault for the GPU command queue group.
* Ignore fragment timeout if it is following a compute timeout.
*/
static void handle_progress_timer_event(struct kbase_queue_group *const group)
static void handle_progress_timer_events(struct kbase_device *const kbdev, unsigned long *slot_mask)
{
kbase_debug_csf_fault_notify(group->kctx->kbdev, group->kctx, DF_PROGRESS_TIMER_TIMEOUT);
u32 max_csg_slots = kbdev->csf.global_iface.group_num;
u32 csg_nr;
struct kbase_queue_group *group = NULL;
struct kbase_csf_cmd_stream_group_info *ginfo;
queue_work(group->kctx->csf.wq, &group->timer_event_work);
kbase_csf_scheduler_spin_lock_assert_held(kbdev);
if (likely(bitmap_empty(slot_mask, MAX_SUPPORTED_CSGS)))
return;
/* Log each timeout and Update timestamp of compute progress timeout */
for_each_set_bit(csg_nr, slot_mask, max_csg_slots) {
group = kbdev->csf.scheduler.csg_slots[csg_nr].resident_group;
ginfo = &kbdev->csf.global_iface.groups[csg_nr];
group->progress_timer_state =
kbase_csf_firmware_csg_output(ginfo, CSG_PROGRESS_TIMER_STATE);
dev_info(
kbdev->dev,
"[%llu] Iterator PROGRESS_TIMER timeout notification received for group %u of ctx %d_%d on slot %u with state %x",
kbase_backend_get_cycle_cnt(kbdev), group->handle, group->kctx->tgid,
group->kctx->id, csg_nr, group->progress_timer_state);
if (CSG_PROGRESS_TIMER_STATE_GET(group->progress_timer_state) ==
CSG_PROGRESS_TIMER_STATE_COMPUTE)
kbdev->csf.compute_progress_timeout_cc = kbase_backend_get_cycle_cnt(kbdev);
}
/* Ignore fragment timeout if it is following a compute timeout.
* Otherwise, terminate the command stream group.
*/
for_each_set_bit(csg_nr, slot_mask, max_csg_slots) {
group = kbdev->csf.scheduler.csg_slots[csg_nr].resident_group;
/* Check if it is a fragment timeout right after another compute timeout.
* In such case, kill compute CSG and give fragment CSG a second chance
*/
if (CSG_PROGRESS_TIMER_STATE_GET(group->progress_timer_state) ==
CSG_PROGRESS_TIMER_STATE_FRAGMENT) {
u64 cycle_counter = kbase_backend_get_cycle_cnt(kbdev);
u64 compute_progress_timeout_cc = kbdev->csf.compute_progress_timeout_cc;
if (compute_progress_timeout_cc <= cycle_counter &&
cycle_counter <= compute_progress_timeout_cc +
MAX_PROGRESS_TIMEOUT_EVENT_DELAY) {
dev_info(
kbdev->dev,
"Ignored Fragment iterator timeout for group %d on slot %d",
group->handle, group->csg_nr);
continue;
}
}
kbase_debug_csf_fault_notify(group->kctx->kbdev, group->kctx,
DF_PROGRESS_TIMER_TIMEOUT);
queue_work(group->kctx->csf.wq, &group->timer_event_work);
}
}
/**
@ -2291,14 +2344,14 @@ static void handle_fault_event(struct kbase_queue *const queue, const u32 cs_ack
const u8 cs_fault_exception_type = CS_FAULT_EXCEPTION_TYPE_GET(cs_fault);
const u32 cs_fault_exception_data = CS_FAULT_EXCEPTION_DATA_GET(cs_fault);
const u64 cs_fault_info_exception_data = CS_FAULT_INFO_EXCEPTION_DATA_GET(cs_fault_info);
bool use_old_log_format = true;
bool has_trace_info = false;
bool skip_fault_report = kbase_ctx_flag(queue->kctx, KCTX_PAGE_FAULT_REPORT_SKIP);
kbase_csf_scheduler_spin_lock_assert_held(kbdev);
if (use_old_log_format && !skip_fault_report)
if (!has_trace_info && !skip_fault_report)
dev_warn(kbdev->dev,
"Ctx %d_%d Group %d CSG %d CSI: %d\n"
"CS_FAULT.EXCEPTION_TYPE: 0x%x (%s)\n"
@ -2478,13 +2531,13 @@ static void handle_fatal_event(struct kbase_queue *const queue,
const u32 cs_fatal_exception_type = CS_FATAL_EXCEPTION_TYPE_GET(cs_fatal);
const u32 cs_fatal_exception_data = CS_FATAL_EXCEPTION_DATA_GET(cs_fatal);
const u64 cs_fatal_info_exception_data = CS_FATAL_INFO_EXCEPTION_DATA_GET(cs_fatal_info);
bool use_old_log_format = true;
bool has_trace_info = false;
bool skip_fault_report = kbase_ctx_flag(queue->kctx, KCTX_PAGE_FAULT_REPORT_SKIP);
kbase_csf_scheduler_spin_lock_assert_held(kbdev);
if (use_old_log_format && !skip_fault_report)
if (!has_trace_info && !skip_fault_report)
dev_warn(kbdev->dev,
"Ctx %d_%d Group %d CSG %d CSI: %d\n"
"CS_FATAL.EXCEPTION_TYPE: 0x%x (%s)\n"
@ -2649,6 +2702,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group,
* @csg_nr: CSG number.
* @track: Pointer that tracks the highest idle CSG and the newly possible viable
* protected mode requesting group, in current IRQ context.
* @progress_timeout_slot_mask: slot mask to indicate on which slot progress timeout
* happens.
*
* Handles interrupts for a CSG and for CSs within it.
*
@ -2660,7 +2715,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group,
* See process_cs_interrupts() for details of per-stream interrupt handling.
*/
static void process_csg_interrupts(struct kbase_device *const kbdev, u32 const csg_nr,
struct irq_idle_and_protm_track *track)
struct irq_idle_and_protm_track *track,
unsigned long *progress_timeout_slot_mask)
{
struct kbase_csf_cmd_stream_group_info *ginfo;
struct kbase_queue_group *group = NULL;
@ -2747,13 +2803,9 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, u32 const c
KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_PROGRESS_TIMER_EVENT, group,
req ^ ack);
dev_info(
kbdev->dev,
"[%llu] Iterator PROGRESS_TIMER timeout notification received for group %u of ctx %d_%d on slot %u\n",
kbase_backend_get_cycle_cnt(kbdev), group->handle, group->kctx->tgid,
group->kctx->id, csg_nr);
handle_progress_timer_event(group);
set_bit(csg_nr, progress_timeout_slot_mask);
}
process_cs_interrupts(group, ginfo, irqreq, irqack, track);
@ -2863,6 +2915,7 @@ static inline void check_protm_enter_req_complete(struct kbase_device *kbdev, u3
dev_dbg(kbdev->dev, "Protected mode entry interrupt received");
kbdev->protected_mode = true;
kbase_ipa_protection_mode_switch_event(kbdev);
kbase_ipa_control_protm_entered(kbdev);
kbase_hwcnt_backend_csf_protm_entered(&kbdev->hwcnt_gpu_iface);
@ -3047,18 +3100,25 @@ void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val)
struct irq_idle_and_protm_track track = { .protm_grp = NULL,
.idle_seq = U32_MAX,
.idle_slot = S8_MAX };
DECLARE_BITMAP(progress_timeout_csgs, MAX_SUPPORTED_CSGS) = { 0 };
kbase_csf_scheduler_spin_lock(kbdev, &flags);
/* Looping through and track the highest idle and protm groups */
/* Looping through and track the highest idle and protm groups.
* Also track the groups for which progress timer timeout happened.
*/
while (csg_interrupts != 0) {
u32 const csg_nr = (u32)ffs((int)csg_interrupts) - 1;
process_csg_interrupts(kbdev, csg_nr, &track);
process_csg_interrupts(kbdev, csg_nr, &track,
progress_timeout_csgs);
csg_interrupts &= ~(1U << csg_nr);
}
/* Handle protm from the tracked information */
process_tracked_info_for_protm(kbdev, &track);
/* Handle pending progress timeout(s) */
handle_progress_timer_events(kbdev, progress_timeout_csgs);
kbase_csf_scheduler_spin_unlock(kbdev, flags);
}
@ -3087,11 +3147,28 @@ void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val)
/* Handle IDLE Hysteresis notification event */
if ((glb_req ^ glb_ack) & GLB_REQ_IDLE_EVENT_MASK) {
u32 const glb_idle_timer_cfg =
kbase_csf_firmware_global_input_read(
global_iface, GLB_IDLE_TIMER_CONFIG);
dev_dbg(kbdev->dev, "Idle-hysteresis event flagged");
kbase_csf_firmware_global_input_mask(
global_iface, GLB_REQ, glb_ack,
GLB_REQ_IDLE_EVENT_MASK);
if (glb_idle_timer_cfg &
GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_MASK) {
/* The FW is going to sleep, we shall:
* - Enable fast GPU idle handling to avoid
* confirming CSGs status in gpu_idle_worker().
* - Enable doorbell mirroring to minimise the
* chance of KBase raising kernel doorbells which
* would cause the FW to be woken up.
*/
kbdev->csf.scheduler.fast_gpu_idle_handling = true;
kbase_pm_enable_db_mirror_interrupt(kbdev);
}
glb_idle_irq_received = true;
/* Defer handling this IRQ to account for a race condition
* where the idle worker could be executed before we have

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -28,6 +28,8 @@
#include <mali_kbase.h>
#include <linux/seq_file.h>
#include <linux/version_compat_defs.h>
#include <mali_kbase_reset_gpu.h>
#include <mali_kbase_config_defaults.h>
#define MAX_SCHED_STATE_STRING_LEN (16)
/**
@ -268,6 +270,87 @@ static const struct file_operations kbasep_csf_debugfs_scheduler_state_fops = {
.open = simple_open,
.llseek = default_llseek,
};
static int kbasep_csf_debugfs_eviction_timeout_get(void *data, u64 *val)
{
struct kbase_device *const kbdev = data;
unsigned long flags;
kbase_csf_scheduler_spin_lock(kbdev, &flags);
*val = kbdev->csf.csg_suspend_timeout_ms - CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS;
kbase_csf_scheduler_spin_unlock(kbdev, flags);
return 0;
}
static int kbasep_csf_debugfs_eviction_timeout_set(void *data, u64 val)
{
struct kbase_device *const kbdev = data;
unsigned long flags_schd, flags_hw;
u64 dur_ms = val;
int ret = 0;
if (unlikely(dur_ms < CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MIN ||
dur_ms > CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MAX)) {
dev_err(kbdev->dev, "Invalid CSG suspend timeout input (%llu)", dur_ms);
return -EFAULT;
}
dur_ms = dur_ms + CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS;
/* The 'fw_load_lock' is taken to synchronize against the deferred
* loading of FW, update will take effect after firmware gets loaded.
*/
mutex_lock(&kbdev->fw_load_lock);
if (unlikely(!kbdev->csf.firmware_inited)) {
kbase_csf_scheduler_spin_lock(kbdev, &flags_schd);
kbdev->csf.csg_suspend_timeout_ms = (unsigned int)dur_ms;
kbase_csf_scheduler_spin_unlock(kbdev, flags_schd);
mutex_unlock(&kbdev->fw_load_lock);
dev_info(kbdev->dev, "CSF set csg suspend timeout deferred till fw is loaded");
goto end;
}
mutex_unlock(&kbdev->fw_load_lock);
/* Firmware reloading is triggered by silent reset, and then update will take effect.
*/
kbase_csf_scheduler_pm_active(kbdev);
if (kbase_csf_scheduler_killable_wait_mcu_active(kbdev)) {
dev_err(kbdev->dev,
"Unable to activate the MCU, the csg suspend timeout value shall remain unchanged");
kbase_csf_scheduler_pm_idle(kbdev);
ret = -EFAULT;
goto exit;
}
spin_lock_irqsave(&kbdev->hwaccess_lock, flags_hw);
if (kbase_reset_gpu_silent(kbdev)) {
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags_hw);
dev_err(kbdev->dev, "CSF set csg suspend timeout pending reset, try again");
kbase_csf_scheduler_pm_idle(kbdev);
ret = -EFAULT;
goto exit;
}
/* GPU reset is placed and it will take place only after hwaccess_lock is released,
* update on host side should be done after GPU reset is placed and before it takes place.
*/
kbase_csf_scheduler_spin_lock(kbdev, &flags_schd);
kbdev->csf.csg_suspend_timeout_ms = (unsigned int)dur_ms;
kbase_csf_scheduler_spin_unlock(kbdev, flags_schd);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags_hw);
/* Keep PM active until reset finished to allow FW reloading to take place,
* and then update request will be sent to FW during initialization.
*/
kbase_reset_gpu_wait(kbdev);
kbase_csf_scheduler_pm_idle(kbdev);
end:
dev_info(kbdev->dev, "CSF set csg suspend timeout: %u ms", (unsigned int)dur_ms);
exit:
return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(kbasep_csf_debugfs_eviction_timeout_fops,
&kbasep_csf_debugfs_eviction_timeout_get,
&kbasep_csf_debugfs_eviction_timeout_set, "%llu\n");
void kbase_csf_debugfs_init(struct kbase_device *kbdev)
{
@ -280,6 +363,8 @@ void kbase_csf_debugfs_init(struct kbase_device *kbdev)
&kbasep_csf_debugfs_scheduling_timer_kick_fops);
debugfs_create_file("scheduler_state", 0644, kbdev->mali_debugfs_directory, kbdev,
&kbasep_csf_debugfs_scheduler_state_fops);
debugfs_create_file("eviction_timeout_ms", 0644, kbdev->mali_debugfs_directory, kbdev,
&kbasep_csf_debugfs_eviction_timeout_fops);
kbase_csf_tl_reader_debugfs_init(kbdev);
}

View file

@ -30,6 +30,7 @@
#include "mali_kbase_csf_firmware.h"
#include "mali_kbase_csf_event.h"
#include <uapi/gpu/arm/bifrost/csf/mali_kbase_csf_errors_dumpfault.h>
#include "mali_kbase_csf_fw_io.h"
#include <linux/version_compat_defs.h>
@ -267,7 +268,6 @@ enum kbase_queue_group_priority {
* @CSF_PM_TIMEOUT: Timeout for GPU Power Management to reach the desired
* Shader, L2 and MCU state.
* @CSF_GPU_RESET_TIMEOUT: Waiting timeout for GPU reset to complete.
* @CSF_CSG_SUSPEND_TIMEOUT: Timeout given for a CSG to be suspended.
* @CSF_CSG_TERM_TIMEOUT: Timeout given for a CSG to be terminated.
* @CSF_FIRMWARE_BOOT_TIMEOUT: Maximum time to wait for firmware to boot.
* @CSF_FIRMWARE_PING_TIMEOUT: Maximum time to wait for firmware to respond
@ -290,7 +290,6 @@ enum kbase_timeout_selector {
CSF_FIRMWARE_TIMEOUT,
CSF_PM_TIMEOUT,
CSF_GPU_RESET_TIMEOUT,
CSF_CSG_SUSPEND_TIMEOUT,
CSF_CSG_TERM_TIMEOUT,
CSF_FIRMWARE_BOOT_TIMEOUT,
CSF_FIRMWARE_PING_TIMEOUT,
@ -554,6 +553,8 @@ struct kbase_protected_suspend_buffer {
* returned to userspace if such an error has occurred.
* @timer_event_work: Work item to handle the progress timeout fatal event
* for the group.
* @progress_timer_state: Value of CSG_PROGRESS_TIMER_STATE register when progress
* timer timeout is reported for the group.
* @deschedule_deferred_cnt: Counter keeping a track of the number of threads
* that tried to deschedule the group and had to defer
* the descheduling due to the dump on fault.
@ -610,6 +611,7 @@ struct kbase_queue_group {
struct kbase_csf_notification error_fatal;
struct work_struct timer_event_work;
u32 progress_timer_state;
/**
* @dvs_buf: Address and size of scratch memory.
@ -931,13 +933,11 @@ struct kbase_csf_reset_gpu {
* of CSG slots.
* @resident_group: pointer to the queue group that is resident on the CSG slot.
* @state: state of the slot as per enum @kbase_csf_csg_slot_state.
* @trigger_jiffies: value of jiffies when change in slot state is recorded.
* @priority: dynamic priority assigned to CSG slot.
*/
struct kbase_csf_csg_slot {
struct kbase_queue_group *resident_group;
atomic_t state;
unsigned long trigger_jiffies;
u8 priority;
};
@ -1137,6 +1137,8 @@ struct kbase_csf_mcu_shared_regions {
* @gpuq_kthread: Dedicated thread primarily used to handle
* latency-sensitive tasks such as GPU queue
* submissions.
* @gpu_idle_timer_enabled: Tracks whether the GPU idle timer is enabled or disabled.
* @fw_soi_enabled: True if FW Sleep-on-Idle is currently enabled.
*/
struct kbase_csf_scheduler {
struct mutex lock;
@ -1214,6 +1216,8 @@ struct kbase_csf_scheduler {
*/
spinlock_t gpu_metrics_lock;
#endif /* CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD */
atomic_t gpu_idle_timer_enabled;
atomic_t fw_soi_enabled;
};
/*
@ -1677,6 +1681,7 @@ struct kbase_csf_user_reg {
* @gpu_idle_dur_count_no_modifier: Update csffw_glb_req_idle_enable to make the shr(10)
* modifier conditional on the new flag
* in GLB_IDLE_TIMER_CONFIG.
* @csg_suspend_timeout_ms: Timeout given for a CSG to be suspended.
* for any request sent to the firmware.
* @hwcnt: Contain members required for handling the dump of
* HW counters.
@ -1695,8 +1700,21 @@ struct kbase_csf_user_reg {
* kbase_queue.pending_kick_link.
* @quirks_ext: Pointer to an allocated buffer containing the firmware
* workarounds configuration.
* @mmu_sync_sem: RW Semaphore to defer MMU operations till the P.Mode entrance
* or DCS request has been completed.
* @pmode_sync_sem: RW Semaphore to prevent MMU operations during P.Mode entrance.
* @gpu_idle_timer_enabled: Tracks whether the GPU idle timer is enabled or disabled.
* @page_fault_cnt_ptr_address: GPU VA of the location in FW data memory, extracted from the
* FW image header, that will store the GPU VA of FW visible
* memory location where the @page_fault_cnt value will be written to.
* @page_fault_cnt_ptr: CPU VA of the FW visible memory location where the @page_fault_cnt
* value will be written to.
* @page_fault_cnt: Counter that is incremented on every GPU page fault, just before the
* MMU is unblocked to retry the memory transaction that caused the GPU
* page fault. The access to counter is serialized appropriately.
* @mcu_halted: Flag to inform MCU FSM that the MCU has already halted.
* @fw_io: Firmware I/O interface.
* @compute_progress_timeout_cc: Value of GPU cycle count register when progress
* timer timeout is reported for the compute iterator.
*/
struct kbase_csf_device {
struct kbase_mmu_table mcu_mmu;
@ -1734,6 +1752,7 @@ struct kbase_csf_device {
u64 gpu_idle_hysteresis_ns;
u32 gpu_idle_dur_count;
u32 gpu_idle_dur_count_no_modifier;
u32 csg_suspend_timeout_ms;
struct kbase_csf_hwcnt hwcnt;
struct kbase_csf_mcu_fw fw;
struct kbase_csf_firmware_log fw_log;
@ -1752,8 +1771,14 @@ struct kbase_csf_device {
struct list_head pending_gpuq_kick_queues[KBASE_QUEUE_GROUP_PRIORITY_COUNT];
spinlock_t pending_gpuq_kick_queues_lock;
u32 *quirks_ext;
struct rw_semaphore mmu_sync_sem;
struct rw_semaphore pmode_sync_sem;
bool gpu_idle_timer_enabled;
u32 page_fault_cnt_ptr_address;
u32 *page_fault_cnt_ptr;
u32 page_fault_cnt;
bool mcu_halted;
struct kbase_csf_fw_io fw_io;
u64 compute_progress_timeout_cc;
};
/**

View file

@ -40,6 +40,7 @@
#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h"
#include <csf/ipa_control/mali_kbase_csf_ipa_control.h>
#include <csf/mali_kbase_csf_registers.h>
#include <csf/mali_kbase_csf_fw_io.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/firmware.h>
@ -55,6 +56,7 @@
#include <linux/delay.h>
#include <linux/version_compat_defs.h>
#include <mali_kbase_config_defaults.h>
#define MALI_MAX_DEFAULT_FIRMWARE_NAME_LEN ((size_t)64)
#define DEFAULT_FW_NAME MALI_RELEASE_NAME".mali_csffw.bin"
@ -68,6 +70,7 @@ static unsigned int csf_firmware_boot_timeout_ms;
module_param(csf_firmware_boot_timeout_ms, uint, 0444);
MODULE_PARM_DESC(csf_firmware_boot_timeout_ms, "Maximum time to wait for firmware to boot.");
static bool kbase_iter_trace_enable;
#ifdef CONFIG_MALI_BIFROST_DEBUG
/* Makes Driver wait indefinitely for an acknowledgment for the different
@ -97,6 +100,7 @@ MODULE_PARM_DESC(fw_debug, "Enables effective use of a debugger for debugging fi
#define CSF_FIRMWARE_ENTRY_TYPE_TIMELINE_METADATA (4)
#define CSF_FIRMWARE_ENTRY_TYPE_BUILD_INFO_METADATA (6)
#define CSF_FIRMWARE_ENTRY_TYPE_FUNC_CALL_LIST (7)
#define CSF_FIRMWARE_ENTRY_TYPE_PAGE_FAULT_CNT (8)
#define CSF_FIRMWARE_ENTRY_TYPE_CORE_DUMP (9)
#define CSF_FIRMWARE_CACHE_MODE_NONE (0ul << 3)
@ -115,7 +119,8 @@ MODULE_PARM_DESC(fw_debug, "Enables effective use of a debugger for debugging fi
#define CSF_GLB_REQ_CFG_MASK \
(GLB_REQ_CFG_ALLOC_EN_MASK | GLB_REQ_CFG_PROGRESS_TIMER_MASK | \
GLB_REQ_CFG_PWROFF_TIMER_MASK | GLB_REQ_IDLE_ENABLE_MASK)
GLB_REQ_CFG_PWROFF_TIMER_MASK | GLB_REQ_IDLE_ENABLE_MASK | \
GLB_REQ_CFG_EVICTION_TIMER_MASK | GLB_REQ_ITER_TRACE_ENABLE_MASK)
static inline u32 input_page_read(const u32 *const input, const u32 offset)
{
@ -179,6 +184,92 @@ struct firmware_timeline_metadata {
size_t size;
};
static void reinit_page_fault_cnt_firmware_memory(struct kbase_device *kbdev)
{
if (!kbdev->csf.page_fault_cnt_ptr)
return;
/* Store the GPU address of shared memory location, where the page fault counter
* value will be written, inside the FW data memory.
*/
kbase_csf_update_firmware_memory(
kbdev, kbdev->csf.page_fault_cnt_ptr_address,
(u32)((kbdev->csf.firmware_trace_buffers.mcu_rw.va_reg->start_pfn << PAGE_SHIFT) +
PAGE_SIZE - sizeof(u32)));
*kbdev->csf.page_fault_cnt_ptr = kbdev->csf.page_fault_cnt = 0;
}
static void init_page_fault_cnt_firmware_memory(struct kbase_device *kbdev)
{
if (!kbdev->csf.page_fault_cnt_ptr_address)
return;
if (WARN_ON_ONCE(!kbdev->csf.firmware_trace_buffers.mcu_rw.va_reg))
return;
/* Save the CPU address of shared memory location where the page fault counter
* value will be written.
* The shared memory location comes from the last 4 bytes of the page that
* is allocated to maintain the extract offset value for different trace
* buffers. Only the first 4 bytes of every cacheline is used for the extract offset
* value.
*/
kbdev->csf.page_fault_cnt_ptr =
(u32 *)((u8 *)kbdev->csf.firmware_trace_buffers.mcu_rw.cpu_addr + PAGE_SIZE -
sizeof(u32));
reinit_page_fault_cnt_firmware_memory(kbdev);
}
/**
* set_iterator_trace_enable - Set the value for 'kbase_iter_trace_enable' global variable
* according to the value of GLB_FEATURES.ITER_TRACE_SUPPORTED bit,
* and the corresponding device tree entry.
* @kbdev: Kernel base device pointer
*/
static void set_iterator_trace_enable(struct kbase_device *kbdev)
{
const struct kbase_csf_global_iface *iface = &kbdev->csf.global_iface;
bool dev_support_iter_trace = iface->features & GLB_FEATURES_ITER_TRACE_SUPPORTED_MASK;
const void *dt_iter_trace_param;
unsigned int val;
if (!dev_support_iter_trace) {
kbase_iter_trace_enable = false;
return;
}
/* check device tree for iterator trace enable property and
* fallback to "iter_trace_enable" if not found and try again
*/
dt_iter_trace_param = of_get_property(kbdev->dev->of_node, "iter-trace-enable", NULL);
if (!dt_iter_trace_param)
dt_iter_trace_param =
of_get_property(kbdev->dev->of_node, "iter_trace_enable", NULL);
val = (dt_iter_trace_param) ? be32_to_cpup(dt_iter_trace_param) : 0;
dev_dbg(kbdev->dev, "Iterator trace enable device-tree config value: %u", val);
kbase_iter_trace_enable = val ? true : false;
}
static void iterator_trace_reinit(struct kbase_device *kbdev)
{
if (kbase_iter_trace_enable) {
kbase_csf_firmware_global_input_mask(&kbdev->csf.global_iface, GLB_REQ,
GLB_REQ_ITER_TRACE_ENABLE_MASK,
GLB_REQ_ITER_TRACE_ENABLE_MASK);
}
}
static void iterator_trace_init(struct kbase_device *kbdev)
{
set_iterator_trace_enable(kbdev);
iterator_trace_reinit(kbdev);
}
/* The shared interface area, used for communicating with firmware, is managed
* like a virtual memory zone. Reserve the virtual space from that zone
* corresponding to shared interface entry parsed from the firmware image.
@ -217,7 +308,7 @@ void kbase_csf_firmware_disable_mcu(struct kbase_device *kbdev)
kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(MCU_CONTROL), MCU_CONTROL_REQ_DISABLE);
}
static void wait_for_firmware_stop(struct kbase_device *kbdev)
void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev)
{
u32 val;
const u32 timeout_us =
@ -232,17 +323,12 @@ static void wait_for_firmware_stop(struct kbase_device *kbdev)
KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_OFF(kbdev, kbase_backend_get_cycle_cnt(kbdev));
}
void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev)
{
wait_for_firmware_stop(kbdev);
}
static void stop_csf_firmware(struct kbase_device *kbdev)
void kbase_csf_stop_firmware_and_wait(struct kbase_device *kbdev)
{
/* Stop the MCU firmware */
kbase_csf_firmware_disable_mcu(kbdev);
wait_for_firmware_stop(kbdev);
kbase_csf_firmware_disable_mcu_wait(kbdev);
}
static void wait_for_firmware_boot(struct kbase_device *kbdev)
@ -261,7 +347,6 @@ static void wait_for_firmware_boot(struct kbase_device *kbdev)
*/
remaining = wait_event_timeout(kbdev->csf.event_wait, kbdev->csf.interrupt_received == true,
wait_timeout);
if (!remaining)
dev_err(kbdev->dev, "Timed out waiting for fw boot completion");
@ -485,6 +570,8 @@ static int reload_fw_image(struct kbase_device *kbdev)
kbdev->csf.firmware_full_reload_needed = false;
kbase_csf_firmware_reload_trace_buffers_data(kbdev);
reinit_page_fault_cnt_firmware_memory(kbdev);
iterator_trace_reinit(kbdev);
out:
return ret;
}
@ -1043,6 +1130,14 @@ static int load_firmware_entry(struct kbase_device *kbdev, const struct kbase_cs
}
kbase_csf_firmware_log_parse_logging_call_list_entry(kbdev, entry);
return 0;
case CSF_FIRMWARE_ENTRY_TYPE_PAGE_FAULT_CNT:
/* Entry about the location of page fault counter */
if (size < sizeof(*entry)) {
dev_err(kbdev->dev, "Page fault counter entry too short (size=%u)", size);
return -EINVAL;
}
kbdev->csf.page_fault_cnt_ptr_address = *entry;
return 0;
case CSF_FIRMWARE_ENTRY_TYPE_CORE_DUMP:
/* Core Dump section */
if (size < CORE_DUMP_ENTRY_START_ADDR_OFFSET + sizeof(*entry)) {
@ -1657,12 +1752,13 @@ static inline void set_gpu_idle_timer_glb_req(struct kbase_device *const kbdev,
global_iface, GLB_REQ, GLB_REQ_REQ_IDLE_DISABLE, GLB_REQ_IDLE_DISABLE_MASK);
}
kbdev->csf.gpu_idle_timer_enabled = set;
atomic_set(&kbdev->csf.scheduler.gpu_idle_timer_enabled, set);
}
static void enable_gpu_idle_timer(struct kbase_device *const kbdev)
{
struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
bool const fw_soi_allowed = kbase_pm_fw_sleep_on_idle_allowed(kbdev);
kbase_csf_scheduler_spin_lock_assert_held(kbdev);
@ -1670,14 +1766,114 @@ static void enable_gpu_idle_timer(struct kbase_device *const kbdev)
kbdev->csf.gpu_idle_dur_count);
kbase_csf_firmware_global_input_mask(global_iface, GLB_IDLE_TIMER_CONFIG,
kbdev->csf.gpu_idle_dur_count_no_modifier,
kbdev->csf.gpu_idle_dur_count_no_modifier
<< GLB_IDLE_TIMER_CONFIG_NO_MODIFIER_SHIFT,
GLB_IDLE_TIMER_CONFIG_NO_MODIFIER_MASK);
kbase_csf_firmware_global_input_mask(global_iface, GLB_IDLE_TIMER_CONFIG,
fw_soi_allowed
<< GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_SHIFT,
GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_MASK);
set_gpu_idle_timer_glb_req(kbdev, true);
atomic_set(&kbdev->csf.scheduler.fw_soi_enabled, fw_soi_allowed);
dev_dbg(kbdev->dev, "Enabling GPU idle timer with count-value: 0x%.8x",
kbdev->csf.gpu_idle_dur_count);
}
/**
* convert_dur_to_suspend_count() - Convert CSG suspend timeout from ms to cycle count
* @kbdev: Instance of a GPU platform device that implements a CSF interface
* @dur_ms: Timeout value in ms
* @no_modifier: Indicate whether bit-shift is applied, 0 when applied, 1 otherwise
*
* Convert CSG suspend timeout from ms to cycle count, then generate a register value
* combining cycle count and timer source
*
* Return: Register value which will be stored into register GLB_EVICTION_TIMER.
*/
static u32 convert_dur_to_suspend_count(struct kbase_device *kbdev, const u64 dur_ms,
u32 *no_modifier)
{
/* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */
u64 freq = kbase_arch_timer_get_cntfrq(kbdev);
u64 dur_val = dur_ms;
u32 cnt_val_u32, reg_val_u32;
const bool src_system_timestamp = freq > 0;
const u8 SUSPEND_VAL_UNIT_SHIFT = 10;
if (!src_system_timestamp) {
/* Get the cycle_counter source alternative */
spin_lock(&kbdev->pm.clk_rtm.lock);
if (kbdev->pm.clk_rtm.clks[0])
freq = kbdev->pm.clk_rtm.clks[0]->clock_val;
else
dev_err(kbdev->dev, "No GPU clock, unexpected intregration issue!");
spin_unlock(&kbdev->pm.clk_rtm.lock);
dev_info(kbdev->dev,
"No timestamp frequency, use cycle counter for csg suspend timeout!");
}
/* Formula for dur_val = (dur/1e3) * freq_HZ) */
dur_val = dur_val * freq;
dur_val = div_u64(dur_val, MSEC_PER_SEC);
if (dur_val < S32_MAX) {
*no_modifier = 1;
} else {
dur_val = dur_val >> SUSPEND_VAL_UNIT_SHIFT;
*no_modifier = 0;
}
/* Interface limits the value field to S32_MAX */
cnt_val_u32 = (dur_val > S32_MAX) ? S32_MAX : (u32)dur_val;
reg_val_u32 = GLB_EVICTION_TIMER_TIMEOUT_SET(0, cnt_val_u32);
/* add the source flag */
reg_val_u32 = GLB_EVICTION_TIMER_TIMER_SOURCE_SET(
reg_val_u32,
(src_system_timestamp ? GLB_EVICTION_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP :
GLB_EVICTION_TIMER_TIMER_SOURCE_GPU_COUNTER));
return reg_val_u32;
}
/**
* set_csg_suspend_timeout() - Update CSG suspend timeout setting on FW side
*
* @kbdev: Instance of a GPU platform device that implements a CSF interface
*/
static void set_csg_suspend_timeout(struct kbase_device *const kbdev)
{
u32 dur_ms, dur_val;
u32 no_modifier = 0;
struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
kbase_csf_scheduler_spin_lock_assert_held(kbdev);
dur_ms = kbdev->csf.csg_suspend_timeout_ms;
if (unlikely(dur_ms < CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MIN +
CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS ||
dur_ms > CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MAX +
CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS)) {
dev_err(kbdev->dev, "Unexpected CSG suspend timeout: %ums, default to: %ums",
dur_ms, CSG_SUSPEND_TIMEOUT_MS);
kbdev->csf.csg_suspend_timeout_ms = CSG_SUSPEND_TIMEOUT_MS;
dur_ms = CSG_SUSPEND_TIMEOUT_MS;
}
dur_ms = dur_ms - CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS;
dur_val = convert_dur_to_suspend_count(kbdev, dur_ms, &no_modifier);
kbase_csf_firmware_global_input(global_iface, GLB_EVICTION_TIMER, dur_val);
kbase_csf_firmware_global_input_mask(global_iface, GLB_EVICTION_TIMER_CONFIG, no_modifier,
GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_MASK);
set_global_request(global_iface, GLB_REQ_CFG_EVICTION_TIMER_MASK);
dev_dbg(kbdev->dev, "Updating CSG suspend timeout with count-value: 0x%.8x", dur_val);
}
static bool global_debug_request_complete(struct kbase_device *const kbdev, u32 const req_mask)
{
struct kbase_csf_global_iface *global_iface = &kbdev->csf.global_iface;
@ -1766,7 +1962,8 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask)
GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK | GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK |
GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK | GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK |
GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK | GLB_ACK_IRQ_MASK_IDLE_EVENT_MASK |
GLB_REQ_DEBUG_CSF_REQ_MASK | GLB_ACK_IRQ_MASK_IDLE_ENABLE_MASK;
GLB_REQ_DEBUG_CSF_REQ_MASK | GLB_ACK_IRQ_MASK_IDLE_ENABLE_MASK |
GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_MASK | GLB_ACK_IRQ_MASK_ITER_TRACE_ENABLE_MASK;
const struct kbase_csf_global_iface *const global_iface = &kbdev->csf.global_iface;
unsigned long flags;
@ -1781,11 +1978,10 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask)
set_timeout_global(global_iface, kbase_csf_timeout_get(kbdev));
/* The GPU idle timer is always enabled for simplicity. Checks will be
* done before scheduling the GPU idle worker to see if it is
* appropriate for the current power policy.
/* The csg suspend timeout is always enabled so customer has the flexibility to update it
* at any time.
*/
enable_gpu_idle_timer(kbdev);
set_csg_suspend_timeout(kbdev);
/* Unmask the interrupts */
kbase_csf_firmware_global_input(global_iface, GLB_ACK_IRQ_MASK, ack_irq_mask);
@ -1963,6 +2159,7 @@ void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev)
KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_REBOOT, NULL, 0u);
/* Tell MCU state machine to transit to next state */
kbdev->csf.firmware_reloaded = true;
kbase_pm_update_state(kbdev);
@ -2068,23 +2265,34 @@ u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev,
* gets serialized.
*/
kbase_csf_scheduler_lock(kbdev);
while (atomic_read(&kbdev->csf.scheduler.pending_gpu_idle_work) > 0) {
kbase_csf_scheduler_unlock(kbdev);
kbase_csf_scheduler_wait_for_kthread_pending_work(
kbdev, &kbdev->csf.scheduler.pending_gpu_idle_work);
kbase_csf_scheduler_lock(kbdev);
}
kbase_csf_scheduler_spin_lock(kbdev, &flags);
kbdev->csf.gpu_idle_hysteresis_ns = dur_ns;
kbdev->csf.gpu_idle_dur_count = hysteresis_val;
kbdev->csf.gpu_idle_dur_count_no_modifier = no_modifier;
if (kbdev->csf.gpu_idle_timer_enabled) {
if (atomic_read(&kbdev->csf.scheduler.gpu_idle_timer_enabled)) {
/* Timer is already enabled. Disable the timer as FW only reads
* the new idle timer value when timer is re-enabled.
*/
kbase_csf_firmware_disable_gpu_idle_timer(kbdev);
kbase_csf_scheduler_spin_unlock(kbdev, flags);
/* Ensure that the request has taken effect */
wait_for_global_request(kbdev, GLB_REQ_IDLE_DISABLE_MASK);
if (wait_for_global_request(kbdev, GLB_REQ_IDLE_DISABLE_MASK))
dev_err(kbdev->dev,
"Failed to disable GLB_IDLE timer when setting a new idle hysteresis timeout");
kbase_csf_scheduler_spin_lock(kbdev, &flags);
kbase_csf_firmware_enable_gpu_idle_timer(kbdev);
kbase_csf_scheduler_spin_unlock(kbdev, flags);
wait_for_global_request(kbdev, GLB_REQ_IDLE_ENABLE_MASK);
if (wait_for_global_request(kbdev, GLB_REQ_IDLE_ENABLE_MASK))
dev_err(kbdev->dev,
"Failed to re-enable GLB_IDLE timer when setting a new idle hysteresis timeout");
} else {
kbase_csf_scheduler_spin_unlock(kbdev, flags);
}
@ -2190,78 +2398,6 @@ u32 kbase_csf_firmware_reset_mcu_core_pwroff_time(struct kbase_device *kbdev)
return kbase_csf_firmware_set_mcu_core_pwroff_time(kbdev, DEFAULT_GLB_PWROFF_TIMEOUT_NS);
}
/**
* kbase_csf_get_iterator_trace_enable - Parsing the iterator_trace enable firstly from
* the module parameter, and then from device-tree.
* @kbdev: Kernel base device pointer
*
* Return: true on enabled, otherwise false.
*/
static bool kbase_csf_get_iterator_trace_enable(struct kbase_device *kbdev)
{
const void *dt_iter_trace_param;
unsigned int val;
/* check device tree for iterator trace enable property and
* fallback to "iter_trace_enable" if not found and try again
*/
dt_iter_trace_param = of_get_property(kbdev->dev->of_node, "iter-trace-enable", NULL);
if (!dt_iter_trace_param)
dt_iter_trace_param =
of_get_property(kbdev->dev->of_node, "iter_trace_enable", NULL);
val = (dt_iter_trace_param) ? be32_to_cpup(dt_iter_trace_param) : 0;
dev_dbg(kbdev->dev, "Iterator trace enable device-tree config value: %u", val);
return (val != 0);
}
/**
* kbase_device_csf_iterator_trace_init - Send request to enable iterator
* trace port.
* @kbdev: Kernel base device pointer
*
* Return: 0 on success (or if enable request is not sent), or error
* code -EINVAL on failure of GPU to acknowledge enable request.
*/
static int kbase_device_csf_iterator_trace_init(struct kbase_device *kbdev)
{
/* Enable the iterator trace port if supported by the GPU and is
* configured to do so. The FW must advertise this feature in GLB_FEATURES.
*/
if (kbdev->pm.backend.gpu_powered) {
const struct kbase_csf_global_iface *iface = &kbdev->csf.global_iface;
bool dev_support_iter_trace = iface->features &
GLB_FEATURES_ITER_TRACE_SUPPORTED_MASK;
dev_dbg(kbdev->dev, "Device supporting iterator trace: %s\n",
dev_support_iter_trace ? "true" : "false");
if (dev_support_iter_trace && kbase_csf_get_iterator_trace_enable(kbdev)) {
long ack_timeout = kbase_csf_timeout_in_jiffies(
kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_TIMEOUT));
/* write enable request to global input */
kbase_csf_firmware_global_input_mask(iface, GLB_REQ,
GLB_REQ_ITER_TRACE_ENABLE_MASK,
GLB_REQ_ITER_TRACE_ENABLE_MASK);
/* Ring global doorbell */
kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
ack_timeout = wait_event_timeout(
kbdev->csf.event_wait,
!((kbase_csf_firmware_global_input_read(iface, GLB_REQ) ^
kbase_csf_firmware_global_output(iface, GLB_ACK)) &
GLB_REQ_ITER_TRACE_ENABLE_MASK),
ack_timeout);
return ack_timeout ? 0 : -EINVAL;
}
}
return 0;
}
int kbase_csf_firmware_early_init(struct kbase_device *kbdev)
{
init_waitqueue_head(&kbdev->csf.event_wait);
@ -2275,9 +2411,7 @@ int kbase_csf_firmware_early_init(struct kbase_device *kbdev)
INIT_WORK(&kbdev->csf.firmware_reload_work, kbase_csf_firmware_reload_worker);
INIT_WORK(&kbdev->csf.fw_error_work, firmware_error_worker);
kbdev->csf.glb_init_request_pending = true;
init_rwsem(&kbdev->csf.pmode_sync_sem);
init_rwsem(&kbdev->csf.mmu_sync_sem);
mutex_init(&kbdev->csf.reg_lock);
kbase_csf_pending_gpuq_kick_queues_init(kbdev);
@ -2307,6 +2441,8 @@ int kbase_csf_firmware_late_init(struct kbase_device *kbdev)
convert_dur_to_idle_count(kbdev, kbdev->csf.gpu_idle_hysteresis_ns, &no_modifier);
kbdev->csf.gpu_idle_dur_count_no_modifier = no_modifier;
kbdev->csf.csg_suspend_timeout_ms = CSG_SUSPEND_TIMEOUT_MS;
return 0;
}
@ -2495,6 +2631,8 @@ int kbase_csf_firmware_load_init(struct kbase_device *kbdev)
goto err_out;
}
init_page_fault_cnt_firmware_memory(kbdev);
ret = kbase_csf_firmware_cfg_fw_wa_init(kbdev);
if (ret != 0) {
dev_err(kbdev->dev, "Failed to initialize firmware workarounds");
@ -2515,6 +2653,8 @@ int kbase_csf_firmware_load_init(struct kbase_device *kbdev)
if (ret != 0)
goto err_out;
iterator_trace_init(kbdev);
ret = kbase_csf_doorbell_mapping_init(kbdev);
if (ret != 0)
goto err_out;
@ -2545,10 +2685,6 @@ int kbase_csf_firmware_load_init(struct kbase_device *kbdev)
if (ret != 0)
goto err_out;
ret = kbase_device_csf_iterator_trace_init(kbdev);
if (ret != 0)
goto err_out;
if (kbdev->csf.fw_core_dump.available)
kbase_csf_firmware_core_dump_init(kbdev);
@ -2598,7 +2734,7 @@ void kbase_csf_firmware_unload_term(struct kbase_device *kbdev)
kbdev->csf.firmware_inited = false;
if (WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_OFF)) {
kbdev->pm.backend.mcu_state = KBASE_MCU_OFF;
stop_csf_firmware(kbdev);
kbase_csf_stop_firmware_and_wait(kbdev);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
@ -2804,6 +2940,7 @@ void kbase_csf_firmware_disable_gpu_idle_timer(struct kbase_device *kbdev)
kbase_csf_scheduler_spin_lock_assert_held(kbdev);
set_gpu_idle_timer_glb_req(kbdev, false);
atomic_set(&kbdev->csf.scheduler.fw_soi_enabled, false);
dev_dbg(kbdev->dev, "Sending request to disable gpu idle timer");
kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
@ -2947,7 +3084,6 @@ void kbase_csf_firmware_trigger_mcu_sleep(struct kbase_device *kbdev)
KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_REQUEST_SLEEP(kbdev, kbase_backend_get_cycle_cnt(kbdev));
kbase_csf_scheduler_spin_lock(kbdev, &flags);
set_gpu_idle_timer_glb_req(kbdev, false);
set_global_request(global_iface, GLB_REQ_SLEEP_MASK);
dev_dbg(kbdev->dev, "Sending sleep request to MCU");
kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR);
@ -2956,11 +3092,23 @@ void kbase_csf_firmware_trigger_mcu_sleep(struct kbase_device *kbdev)
bool kbase_csf_firmware_is_mcu_in_sleep(struct kbase_device *kbdev)
{
bool db_notif_disabled;
lockdep_assert_held(&kbdev->hwaccess_lock);
return (global_request_complete(kbdev, GLB_REQ_SLEEP_MASK) &&
kbase_csf_firmware_mcu_halted(kbdev));
db_notif_disabled = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(MCU_CONTROL)) &
MCU_CNTRL_DOORBELL_DISABLE_MASK;
if (!db_notif_disabled || !kbase_csf_firmware_mcu_halted(kbdev))
return false;
if (global_request_complete(kbdev, GLB_REQ_SLEEP_MASK))
return true;
kbase_pm_enable_mcu_db_notification(kbdev);
dev_dbg(kbdev->dev, "Enabled DB notification");
return false;
}
#endif
@ -3222,3 +3370,127 @@ void kbase_csf_firmware_mcu_shared_mapping_term(struct kbase_device *kbdev,
vunmap(csf_mapping->cpu_addr);
kfree(csf_mapping->phys);
}
#ifdef KBASE_PM_RUNTIME
void kbase_csf_firmware_soi_update(struct kbase_device *kbdev)
{
struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
unsigned long flags;
/* There are 3 possibilities:
* - Sleep-on-Idle allowed
* - Sleep-on-Idle not allowed, GLB_IDLE timer disabled
* - Sleep-on-Idle not allowed, GLB_IDLE timer enabled
*/
if (kbase_pm_fw_sleep_on_idle_allowed(kbdev)) {
if (likely(atomic_read(&kbdev->csf.scheduler.fw_soi_enabled)))
return;
} else {
if (test_bit(KBASE_GPU_NON_IDLE_OFF_SLOT_GROUPS_AVAILABLE,
&kbdev->pm.backend.gpu_sleep_allowed)) {
if (likely(!atomic_read(&kbdev->csf.scheduler.gpu_idle_timer_enabled)))
return;
} else if (likely(atomic_read(&kbdev->csf.scheduler.gpu_idle_timer_enabled))) {
return;
}
}
if (kbase_reset_gpu_try_prevent(kbdev))
return;
kbase_csf_scheduler_lock(kbdev);
if (atomic_read(&scheduler->pending_gpu_idle_work) > 0)
goto out_unlock_scheduler_lock;
if ((scheduler->state == SCHED_SUSPENDED) || (scheduler->state == SCHED_SLEEPING))
goto out_unlock_scheduler_lock;
if (kbdev->pm.backend.mcu_state != KBASE_MCU_ON)
goto out_unlock_scheduler_lock;
/* Ensure that an existing DISABLE request is completed before
* proceeding. They are made without waiting for them to complete such
* as when enabling the MCU.
*/
if (wait_for_global_request(kbdev, GLB_REQ_IDLE_DISABLE_MASK)) {
dev_err(kbdev->dev,
"Existing GLB_IDLE timer config change failed to complete in time (gpu_sleep_allowed:%lx)",
kbdev->pm.backend.gpu_sleep_allowed);
goto out_unlock_scheduler_lock;
}
/* Disable the GLB IDLE timer if it's currently enabled */
if (atomic_read(&kbdev->csf.scheduler.gpu_idle_timer_enabled)) {
kbase_csf_scheduler_spin_lock(kbdev, &flags);
kbase_csf_firmware_disable_gpu_idle_timer(kbdev);
kbase_csf_scheduler_spin_unlock(kbdev, flags);
if (wait_for_global_request(kbdev, GLB_REQ_IDLE_DISABLE_MASK)) {
dev_err(kbdev->dev,
"Failed to disable GLB_IDLE timer following FW Sleep-on-Idle config change (gpu_sleep_allowed:%lx)",
kbdev->pm.backend.gpu_sleep_allowed);
goto out_unlock_scheduler_lock;
}
}
/* The GLB IDLE timer and, consequently, FW Sleep-on-Idle could remain
* disabled in certain cases. Otherwise, we shall re-enable GLB IDLE
* timer with the new FW Sleep-on-Idle configuration.
*/
if (!test_bit(KBASE_GPU_NON_IDLE_OFF_SLOT_GROUPS_AVAILABLE,
&kbdev->pm.backend.gpu_sleep_allowed)) {
kbase_csf_scheduler_spin_lock(kbdev, &flags);
kbase_csf_firmware_enable_gpu_idle_timer(kbdev);
kbase_csf_scheduler_spin_unlock(kbdev, flags);
if (wait_for_global_request(kbdev, GLB_REQ_IDLE_ENABLE_MASK)) {
dev_err(kbdev->dev,
"Failed to re-enable GLB_IDLE timer following FW Sleep-on-Idle config change (gpu_sleep_allowed:%lx)",
kbdev->pm.backend.gpu_sleep_allowed);
goto out_unlock_scheduler_lock;
}
}
if (atomic_read(&scheduler->fw_soi_enabled)) {
dev_dbg(kbdev->dev, "FW Sleep-on-Idle was enabled");
KBASE_KTRACE_ADD(kbdev, FIRMWARE_SLEEP_ON_IDLE_CHANGED, NULL, true);
} else {
dev_dbg(kbdev->dev, "FW Sleep-on-Idle was disabled");
KBASE_KTRACE_ADD(kbdev, FIRMWARE_SLEEP_ON_IDLE_CHANGED, NULL, false);
}
out_unlock_scheduler_lock:
kbase_csf_scheduler_unlock(kbdev);
kbase_reset_gpu_allow(kbdev);
}
int kbase_csf_firmware_soi_disable_on_scheduler_suspend(struct kbase_device *kbdev)
{
struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
unsigned long flags;
lockdep_assert_held(&scheduler->lock);
if (WARN_ON_ONCE(scheduler->state != SCHED_INACTIVE))
return 0;
if (!atomic_read(&kbdev->csf.scheduler.fw_soi_enabled))
return 0;
kbase_csf_scheduler_spin_lock(kbdev, &flags);
if (atomic_read(&scheduler->fw_soi_enabled)) {
kbase_csf_firmware_disable_gpu_idle_timer(kbdev);
kbase_csf_scheduler_spin_unlock(kbdev, flags);
if (wait_for_global_request(kbdev, GLB_REQ_IDLE_DISABLE_MASK)) {
dev_err(kbdev->dev, "Failed to disable Sleep-on-Idle config");
return -ETIMEDOUT;
}
KBASE_KTRACE_ADD(kbdev, FIRMWARE_SLEEP_ON_IDLE_CHANGED, NULL, false);
} else {
kbase_csf_scheduler_spin_unlock(kbdev, flags);
}
return 0;
}
#endif /* KBASE_PM_RUNTIME */

View file

@ -591,13 +591,20 @@ void kbase_csf_firmware_enable_mcu(struct kbase_device *kbdev);
void kbase_csf_firmware_disable_mcu(struct kbase_device *kbdev);
/**
* kbase_csf_firmware_disable_mcu_wait - Wait for the MCU to reach disabled
* status.
* kbase_csf_firmware_disable_mcu_wait - Wait for the MCU to reach disabled status.
*
* @kbdev: Instance of a GPU platform device that implements a CSF interface.
*/
void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev);
/**
* kbase_csf_stop_firmware_and_wait - Disable firmware and wait for the MCU to reach
* disabled status.
*
* @kbdev: Instance of a GPU platform device that implements a CSF interface.
*/
void kbase_csf_stop_firmware_and_wait(struct kbase_device *kbdev);
#ifdef KBASE_PM_RUNTIME
/**
* kbase_csf_firmware_trigger_mcu_sleep - Send the command to put MCU in sleep
@ -927,4 +934,27 @@ int kbase_csf_trigger_firmware_config_update(struct kbase_device *kbdev);
*/
int kbase_csf_firmware_req_core_dump(struct kbase_device *const kbdev);
#ifdef KBASE_PM_RUNTIME
/**
* kbase_csf_firmware_soi_update - Update FW Sleep-on-Idle config
*
* @kbdev: Device pointer
*
* This function reconfigures the FW Sleep-on-Idle configuration if necessary.
*/
void kbase_csf_firmware_soi_update(struct kbase_device *kbdev);
/**
* kbase_csf_firmware_soi_disable_on_scheduler_suspend - Disable FW Sleep-on-Idle config
* on scheduler suspension
*
* @kbdev: Device pointer
*
* Return: 0 on success, otherwise failure
*/
int kbase_csf_firmware_soi_disable_on_scheduler_suspend(struct kbase_device *kbdev);
#endif /* KBASE_PM_RUNTIME */
#endif

View file

@ -684,7 +684,7 @@ static inline void set_gpu_idle_timer_glb_req(struct kbase_device *const kbdev,
global_iface, GLB_REQ, GLB_REQ_REQ_IDLE_DISABLE, GLB_REQ_IDLE_DISABLE_MASK);
}
kbdev->csf.gpu_idle_timer_enabled = set;
atomic_set(&kbdev->csf.scheduler.gpu_idle_timer_enabled, set);
}
static void enable_gpu_idle_timer(struct kbase_device *const kbdev)
@ -788,12 +788,6 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask)
set_timeout_global(global_iface, kbase_csf_timeout_get(kbdev));
/* The GPU idle timer is always enabled for simplicity. Checks will be
* done before scheduling the GPU idle worker to see if it is
* appropriate for the current power policy.
*/
enable_gpu_idle_timer(kbdev);
/* Unmask the interrupts */
kbase_csf_firmware_global_input(global_iface, GLB_ACK_IRQ_MASK, ack_irq_mask);
@ -901,6 +895,7 @@ void kbase_csf_firmware_trigger_reload(struct kbase_device *kbdev)
kbdev->csf.firmware_reloaded = true;
}
}
KBASE_EXPORT_TEST_API(kbase_csf_firmware_trigger_reload);
void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev)
{
@ -909,6 +904,7 @@ void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev)
if (unlikely(!kbdev->csf.firmware_inited))
return;
/* Tell MCU state machine to transit to next state */
kbdev->csf.firmware_reloaded = true;
kbase_pm_update_state(kbdev);
@ -1019,7 +1015,7 @@ u32 kbase_csf_firmware_set_gpu_idle_hysteresis_time(struct kbase_device *kbdev,
kbdev->csf.gpu_idle_dur_count = hysteresis_val;
kbdev->csf.gpu_idle_dur_count_no_modifier = no_modifier;
if (kbdev->csf.gpu_idle_timer_enabled) {
if (atomic_read(&kbdev->csf.scheduler.gpu_idle_timer_enabled)) {
/* Timer is already enabled. Disable the timer as FW only reads
* the new idle timer value when timer is re-enabled.
*/
@ -1142,7 +1138,7 @@ int kbase_csf_firmware_early_init(struct kbase_device *kbdev)
INIT_WORK(&kbdev->csf.firmware_reload_work, kbase_csf_firmware_reload_worker);
INIT_WORK(&kbdev->csf.fw_error_work, firmware_error_worker);
init_rwsem(&kbdev->csf.pmode_sync_sem);
init_rwsem(&kbdev->csf.mmu_sync_sem);
mutex_init(&kbdev->csf.reg_lock);
kbase_csf_pending_gpuq_kick_queues_init(kbdev);
@ -1210,6 +1206,7 @@ int kbase_csf_firmware_load_init(struct kbase_device *kbdev)
/* NO_MALI: Don't load the MMU tables or boot CSF firmware */
ret = invent_capabilities(kbdev);
if (ret != 0)
goto error;
@ -1540,6 +1537,12 @@ void kbase_csf_firmware_disable_mcu(struct kbase_device *kbdev)
kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(MCU_CONTROL), MCU_CONTROL_REQ_DISABLE);
}
void kbase_csf_stop_firmware_and_wait(struct kbase_device *kbdev)
{
/* Stop the MCU firmware, no wait required on NO_MALI instance */
kbase_csf_firmware_disable_mcu(kbdev);
}
void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev)
{
/* NO_MALI: Nothing to do here */
@ -1662,3 +1665,16 @@ void kbase_csf_firmware_mcu_shared_mapping_term(struct kbase_device *kbdev,
vunmap(csf_mapping->cpu_addr);
kfree(csf_mapping->phys);
}
#ifdef KBASE_PM_RUNTIME
void kbase_csf_firmware_soi_update(struct kbase_device *kbdev)
{
}
int kbase_csf_firmware_soi_disable_on_scheduler_suspend(struct kbase_device *kbdev)
{
return 0;
}
#endif /* KBASE_PM_RUNTIME */

View file

@ -0,0 +1,251 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#include "mali_kbase.h"
#include "mali_kbase_csf_fw_io.h"
#include <mali_kbase_linux.h>
#include <linux/mutex.h>
static inline u32 input_page_read(const u32 *const input, const u32 offset)
{
WARN_ON(offset % sizeof(u32));
return input[offset / sizeof(u32)];
}
static inline void input_page_write(u32 *const input, const u32 offset, const u32 value)
{
WARN_ON(offset % sizeof(u32));
input[offset / sizeof(u32)] = value;
}
static inline void input_page_partial_write(u32 *const input, const u32 offset, u32 value, u32 mask)
{
WARN_ON(offset % sizeof(u32));
input[offset / sizeof(u32)] = (input_page_read(input, offset) & ~mask) | (value & mask);
}
static inline u32 output_page_read(const u32 *const output, const u32 offset)
{
WARN_ON(offset % sizeof(u32));
return output[offset / sizeof(u32)];
}
void kbase_csf_fw_io_init(struct kbase_csf_fw_io *fw_io)
{
spin_lock_init(&fw_io->lock);
bitmap_zero(fw_io->status, KBASE_FW_IO_STATUS_NUM_BITS);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_init);
void kbase_csf_fw_io_term(struct kbase_csf_fw_io *fw_io)
{
/* Nothing to do. */
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_term);
void kbase_csf_fw_io_global_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset, u32 value)
{
const struct kbase_device *const kbdev = iface->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x\n", offset, value);
input_page_write(iface->input, offset, value);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_global_write);
void kbase_csf_fw_io_global_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset,
u32 value, u32 mask)
{
const struct kbase_device *const kbdev = iface->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x mask %08x\n", offset, value, mask);
input_page_partial_write(iface->input, offset, value, mask);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_global_write_mask);
u32 kbase_csf_fw_io_global_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset)
{
const struct kbase_device *const kbdev = iface->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = input_page_read(iface->input, offset);
dev_dbg(kbdev->dev, "glob input r: reg %08x val %08x\n", offset, val);
return val;
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_global_input_read);
u32 kbase_csf_fw_io_global_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset)
{
const struct kbase_device *const kbdev = iface->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = output_page_read(iface->output, offset);
dev_dbg(kbdev->dev, "glob output r: reg %08x val %08x\n", offset, val);
return val;
}
void kbase_csf_fw_io_group_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset,
u32 value)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x\n", offset, value);
input_page_write(info->input, offset, value);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_group_write);
void kbase_csf_fw_io_group_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info,
u32 offset, u32 value, u32 mask)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x mask %08x\n", offset, value, mask);
input_page_partial_write(info->input, offset, value, mask);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_group_write_mask);
u32 kbase_csf_fw_io_group_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = input_page_read(info->input, offset);
dev_dbg(kbdev->dev, "csg input r: reg %08x val %08x\n", offset, val);
return val;
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_group_input_read);
u32 kbase_csf_fw_io_group_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = output_page_read(info->output, offset);
dev_dbg(kbdev->dev, "csg output r: reg %08x val %08x\n", offset, val);
return val;
}
void kbase_csf_fw_io_stream_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset,
u32 value)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x\n", offset, value);
input_page_write(info->input, offset, value);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_write);
void kbase_csf_fw_io_stream_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset,
u32 value, u32 mask)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x mask %08x\n", offset, value, mask);
input_page_partial_write(info->input, offset, value, mask);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_write_mask);
u32 kbase_csf_fw_io_stream_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = input_page_read(info->input, offset);
dev_dbg(kbdev->dev, "cs input r: reg %08x val %08x\n", offset, val);
return val;
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_input_read);
u32 kbase_csf_fw_io_stream_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = output_page_read(info->output, offset);
dev_dbg(kbdev->dev, "cs output r: reg %08x val %08x\n", offset, val);
return val;
}
void kbase_csf_fw_io_set_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit)
{
set_bit(status_bit, fw_io->status);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_set_status);
void kbase_csf_fw_io_clear_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit)
{
clear_bit(status_bit, fw_io->status);
}
bool kbase_csf_fw_io_test_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit)
{
return test_bit(status_bit, fw_io->status);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_test_status);

View file

@ -0,0 +1,362 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#ifndef _KBASE_CSF_FW_IO_H_
#define _KBASE_CSF_FW_IO_H_
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
/** The wait completed because the GPU was lost. */
#define KBASE_CSF_FW_IO_WAIT_GPU_LOST 1
/** The wait was aborted because of an unexpected event. */
#define KBASE_CSF_FW_IO_WAIT_UNSUPPORTED 255
/**
* enum kbase_csf_fw_io_status_bits - Status bits for firmware I/O interface.
*
* @KBASE_FW_IO_STATUS_GPU_SUSPENDED: The GPU is suspended.
* @KBASE_FW_IO_STATUS_NUM_BITS: Number of bits used to encode the state.
*/
enum kbase_csf_fw_io_status_bits {
KBASE_FW_IO_STATUS_GPU_SUSPENDED = 0,
KBASE_FW_IO_STATUS_NUM_BITS,
};
/**
* struct kbase_csf_fw_io - Manager of firmware input/output interface.
*
* @lock: Mutex to serialize access to the interface.
* @status: Internal status of the MCU interface.
*/
struct kbase_csf_fw_io {
spinlock_t lock;
DECLARE_BITMAP(status, KBASE_FW_IO_STATUS_NUM_BITS);
};
struct kbase_csf_global_iface;
struct kbase_csf_cmd_stream_group_info;
struct kbase_csf_cmd_stream_info;
/**
* kbase_csf_fw_io_init() - Initialize manager of firmware input/output interface.
*
* @fw_io: Firmware I/O interface to initialize.
*/
void kbase_csf_fw_io_init(struct kbase_csf_fw_io *fw_io);
/**
* kbase_csf_fw_io_term() - Terminate manager of firmware input/output interface.
*
* @fw_io: Firmware I/O interface to terminate.
*/
void kbase_csf_fw_io_term(struct kbase_csf_fw_io *fw_io);
/**
* kbase_csf_fw_io_open() - Start a transaction with the firmware input/output interface.
*
* @fw_io: Firmware I/O interface to open.
*
* Return: 0 on success, otherwise an error code reflecting the status of the
* interface.
*/
static inline int kbase_csf_fw_io_open(struct kbase_csf_fw_io *fw_io)
{
if (test_bit(KBASE_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status))
return -KBASE_CSF_FW_IO_WAIT_GPU_LOST;
spin_lock(&fw_io->lock);
return 0;
}
/**
* kbase_csf_fw_io_open_force() - Force a transaction with the firmware input/output interface.
*
* @fw_io: Firmware I/O interface to open.
*
* This function forces the start of a transaction regardless of the status
* of the interface.
*/
static inline void kbase_csf_fw_io_open_force(struct kbase_csf_fw_io *fw_io)
{
spin_lock(&fw_io->lock);
}
/**
* kbase_csf_fw_io_close() - End a transaction with the firmware input/output interface.
*
* @fw_io: Firmware I/O interface to close.
*/
static inline void kbase_csf_fw_io_close(struct kbase_csf_fw_io *fw_io)
{
spin_unlock(&fw_io->lock);
}
/**
* kbase_csf_fw_io_assert_opened() - Assert if a transaction with the firmware input/output
* interface has started.
*
* @fw_io: Firmware I/O interface.
*/
static inline void kbase_csf_fw_io_assert_opened(struct kbase_csf_fw_io *fw_io)
{
lockdep_assert_held(&fw_io->lock);
}
/**
* kbase_csf_fw_io_global_write() - Write a word in the global input page.
*
* @fw_io: Firmware I/O manager.
* @iface: CSF interface provided by the firmware.
* @offset: Offset of the word to write, in bytes.
* @value: Value to be written.
*/
void kbase_csf_fw_io_global_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset,
u32 value);
/**
* kbase_csf_fw_io_global_write_mask() - Write part of a word in the global input page.
*
* @fw_io: Firmware I/O manager.
* @iface: CSF interface provided by the firmware.
* @offset: Offset of the word to write, in bytes.
* @value: Value to be written.
* @mask: Bitmask with the bits to be modified set.
*/
void kbase_csf_fw_io_global_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset,
u32 value, u32 mask);
/**
* kbase_csf_fw_io_global_input_read() - Read a word in the global input page.
*
* @fw_io: Firmware I/O manager.
* @iface: CSF interface provided by the firmware.
* @offset: Offset of the word to be read, in bytes.
*
* Return: Value of the word read from the global input page.
*/
u32 kbase_csf_fw_io_global_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset);
/**
* kbase_csf_fw_io_global_read() - Read a word in the global output page.
*
* @fw_io: Firmware I/O manager.
* @iface: CSF interface provided by the firmware.
* @offset: Offset of the word to be read, in bytes.
*
* Return: Value of the word read from the global output page.
*/
u32 kbase_csf_fw_io_global_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset);
/**
* kbase_csf_fw_io_group_write() - Write a word in a CSG's input page.
*
* @fw_io: Firmware I/O manager.
* @info: CSG interface provided by the firmware.
* @offset: Offset of the word to write, in bytes.
* @value: Value to be written.
*/
void kbase_csf_fw_io_group_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset,
u32 value);
/**
* kbase_csf_fw_io_group_write_mask() - Write part of a word in a CSG's input page.
*
* @fw_io: Firmware I/O manager.
* @info: CSG interface provided by the firmware.
* @offset: Offset of the word to write, in bytes.
* @value: Value to be written.
* @mask: Bitmask with the bits to be modified set.
*/
void kbase_csf_fw_io_group_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info,
u32 offset, u32 value, u32 mask);
/**
* kbase_csf_fw_io_group_input_read() - Read a word in a CSG's input page.
*
* @fw_io: Firmware I/O manager.
* @info: CSG interface provided by the firmware.
* @offset: Offset of the word to be read, in bytes.
*
* Return: Value of the word read from a CSG's input page.
*/
u32 kbase_csf_fw_io_group_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info,
u32 offset);
/**
* kbase_csf_fw_io_group_read() - Read a word in a CSG's output page.
*
* @fw_io: Firmware I/O manager.
* @info: CSG interface provided by the firmware.
* @offset: Offset of the word to be read, in bytes.
*
* Return: Value of the word read from the CSG's output page.
*/
u32 kbase_csf_fw_io_group_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset);
/**
* kbase_csf_fw_io_stream_write() - Write a word in a CS's input page.
*
* @fw_io: Firmware I/O manager.
* @info: CSI interface provided by the firmware.
* @offset: Offset of the word to write, in bytes.
* @value: Value to be written.
*/
void kbase_csf_fw_io_stream_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset,
u32 value);
/**
* kbase_csf_fw_io_stream_write_mask() - Write part of a word in a CS's input page.
*
* @fw_io: Firmware I/O manager.
* @info: CSI interface provided by the firmware.
* @offset: Offset of the word to write, in bytes.
* @value: Value to be written.
* @mask: Bitmask with the bits to be modified set.
*/
void kbase_csf_fw_io_stream_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset,
u32 value, u32 mask);
/**
* kbase_csf_fw_io_stream_input_read() - Read a word in a CS's input page.
*
* @fw_io: Firmware I/O manager.
* @info: CSI interface provided by the firmware.
* @offset: Offset of the word to be read, in bytes.
*
* Return: Value of the word read from a CS's input page.
*/
u32 kbase_csf_fw_io_stream_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset);
/**
* kbase_csf_fw_io_stream_read() - Read a word in a CS's output page.
*
* @fw_io: Firmware I/O manager.
* @info: CSI interface provided by the firmware.
* @offset: Offset of the word to be read, in bytes.
*
* Return: Value of the word read from the CS's output page.
*/
u32 kbase_csf_fw_io_stream_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset);
/**
* kbase_csf_fw_io_set_status() - Set a FW I/O status bit.
*
* @fw_io: Firmware I/O manager.
* @status_bit: Status bit to set.
*/
void kbase_csf_fw_io_set_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit);
/**
* kbase_csf_fw_io_clear_status() - Clear a FW I/O status bit.
*
* @fw_io: Firmware I/O manager.
* @status_bit: Status bit to clear.
*/
void kbase_csf_fw_io_clear_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit);
/**
* kbase_csf_fw_io_test_status() - Test a FW I/O status bit.
*
* @fw_io: Firmware I/O manager.
* @status_bit: Status bit to test.
*
* Return: Value of the tested status bit.
*/
bool kbase_csf_fw_io_test_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit);
/**
* kbase_csf_fw_io_wait_event_timeout() - Wait until condition gets true, timeout
* occurs or a FW I/O status bit is set. The rest of the functionalities is equal
* to wait_event_timeout().
*
* @fw_io: Firmware I/O manager.
* @wq_head: The waitqueue to wait on.
* @condition: C expression for the event to wait for
* @timeout: Timeout, in jiffies
*
* Return: Remaining jiffies (at least 1) on success,
* 0 on timeout,
* negative KBASE_CSF_FW_IO_WAIT_* error codes otherwise.
*/
#define kbase_csf_fw_io_wait_event_timeout(fw_io, wq_head, condition, timeout) \
({ \
int __ret; \
int __wait_remaining = wait_event_timeout( \
wq_head, condition || kbasep_csf_fw_io_check_status(fw_io), timeout); \
__ret = kbasep_csf_fw_io_handle_wait_result(fw_io, __wait_remaining); \
__ret; \
})
/**
* kbasep_csf_fw_io_check_status() - Private function to check if any FW I/O status bit is set.
*
* @fw_io: Firmware I/O manager.
*
* Return: True if any FW I/O status bit is set, false otherwise.
*/
static inline bool kbasep_csf_fw_io_check_status(struct kbase_csf_fw_io *fw_io)
{
return !bitmap_empty(fw_io->status, KBASE_FW_IO_STATUS_NUM_BITS);
}
/**
* kbasep_csf_fw_io_handle_wait_result() - Private function to handle the wait_event_timeout()
* result.
*
* @fw_io: Firmware I/O manager
* @wait_remaining: Remaining jiffies returned by wait_event_timeout()
*
* Return: Remaining jiffies (at least 1) on success,
* 0 on timeout,
* negative KBASE_CSF_FW_IO_WAIT_* error codes otherwise.
*/
static inline int kbasep_csf_fw_io_handle_wait_result(struct kbase_csf_fw_io *fw_io,
int wait_remaining)
{
/* Check for any FW IO status bit set */
if (!bitmap_empty(fw_io->status, KBASE_FW_IO_STATUS_NUM_BITS))
return (test_bit(KBASE_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status)) ?
-KBASE_CSF_FW_IO_WAIT_GPU_LOST :
-KBASE_CSF_FW_IO_WAIT_UNSUPPORTED;
return wait_remaining;
}
#endif

View file

@ -0,0 +1,294 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#include "mali_kbase.h"
#include "mali_kbase_csf_fw_io.h"
#include <mali_kbase_linux.h>
#include <linux/mutex.h>
static inline u32 input_page_read(const u32 *const input, const u32 offset)
{
WARN_ON(offset % sizeof(u32));
return input[offset / sizeof(u32)];
}
static inline void input_page_write(u32 *const input, const u32 offset, const u32 value)
{
WARN_ON(offset % sizeof(u32));
input[offset / sizeof(u32)] = value;
}
static inline void input_page_partial_write(u32 *const input, const u32 offset, u32 value, u32 mask)
{
WARN_ON(offset % sizeof(u32));
input[offset / sizeof(u32)] = (input_page_read(input, offset) & ~mask) | (value & mask);
}
static inline u32 output_page_read(const u32 *const output, const u32 offset)
{
WARN_ON(offset % sizeof(u32));
return output[offset / sizeof(u32)];
}
static inline void output_page_write(u32 *const output, const u32 offset, const u32 value)
{
WARN_ON(offset % sizeof(u32));
output[offset / sizeof(u32)] = value;
}
void kbase_csf_fw_io_init(struct kbase_csf_fw_io *fw_io)
{
spin_lock_init(&fw_io->lock);
bitmap_zero(fw_io->status, KBASE_FW_IO_STATUS_NUM_BITS);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_init);
void kbase_csf_fw_io_term(struct kbase_csf_fw_io *fw_io)
{
/* Nothing to do. */
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_term);
void kbase_csf_fw_io_global_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset, u32 value)
{
const struct kbase_device *const kbdev = iface->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x\n", offset, value);
input_page_write(iface->input, offset, value);
if (offset == GLB_REQ) {
/* NO_MALI: Immediately acknowledge requests - except for PRFCNT_ENABLE
* and PRFCNT_SAMPLE. These will be processed along with the
* corresponding performance counter registers when the global doorbell
* is rung in order to emulate the performance counter sampling behavior
* of the real firmware.
*/
const u32 ack = output_page_read(iface->output, GLB_ACK);
const u32 req_mask = ~(GLB_REQ_PRFCNT_ENABLE_MASK | GLB_REQ_PRFCNT_SAMPLE_MASK);
const u32 toggled = (value ^ ack) & req_mask;
output_page_write(iface->output, GLB_ACK, ack ^ toggled);
}
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_global_write);
void kbase_csf_fw_io_global_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset,
u32 value, u32 mask)
{
const struct kbase_device *const kbdev = iface->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "glob input w: reg %08x val %08x mask %08x\n", offset, value, mask);
/* NO_MALI: Go through existing function to capture writes */
kbase_csf_fw_io_global_write(fw_io, iface, offset,
(input_page_read(iface->input, offset) & ~mask) |
(value & mask));
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_global_write_mask);
u32 kbase_csf_fw_io_global_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset)
{
const struct kbase_device *const kbdev = iface->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = input_page_read(iface->input, offset);
dev_dbg(kbdev->dev, "glob input r: reg %08x val %08x\n", offset, val);
return val;
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_global_input_read);
u32 kbase_csf_fw_io_global_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_global_iface *iface, u32 offset)
{
const struct kbase_device *const kbdev = iface->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = output_page_read(iface->output, offset);
dev_dbg(kbdev->dev, "glob output r: reg %08x val %08x\n", offset, val);
return val;
}
void kbase_csf_fw_io_group_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset,
u32 value)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x\n", offset, value);
input_page_write(info->input, offset, value);
if (offset == CSG_REQ) {
/* NO_MALI: Immediately acknowledge requests */
output_page_write(info->output, CSG_ACK, value);
}
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_group_write);
void kbase_csf_fw_io_group_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info,
u32 offset, u32 value, u32 mask)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "csg input w: reg %08x val %08x mask %08x\n", offset, value, mask);
/* NO_MALI: Go through existing function to capture writes */
kbase_csf_fw_io_group_write(fw_io, info, offset,
(input_page_read(info->input, offset) & ~mask) |
(value & mask));
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_group_write_mask);
u32 kbase_csf_fw_io_group_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = input_page_read(info->input, offset);
dev_dbg(kbdev->dev, "csg input r: reg %08x val %08x\n", offset, val);
return val;
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_group_input_read);
u32 kbase_csf_fw_io_group_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_group_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = output_page_read(info->output, offset);
dev_dbg(kbdev->dev, "csg output r: reg %08x val %08x\n", offset, val);
return val;
}
void kbase_csf_fw_io_stream_write(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset,
u32 value)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x\n", offset, value);
input_page_write(info->input, offset, value);
if (offset == CS_REQ) {
/* NO_MALI: Immediately acknowledge requests */
output_page_write(info->output, CS_ACK, value);
}
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_write);
void kbase_csf_fw_io_stream_write_mask(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset,
u32 value, u32 mask)
{
const struct kbase_device *const kbdev = info->kbdev;
lockdep_assert_held(&fw_io->lock);
dev_dbg(kbdev->dev, "cs input w: reg %08x val %08x mask %08x\n", offset, value, mask);
/* NO_MALI: Go through existing function to capture writes */
kbase_csf_fw_io_stream_write(fw_io, info, offset,
(input_page_read(info->input, offset) & ~mask) |
(value & mask));
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_write_mask);
u32 kbase_csf_fw_io_stream_input_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = input_page_read(info->input, offset);
dev_dbg(kbdev->dev, "cs input r: reg %08x val %08x\n", offset, val);
return val;
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_input_read);
u32 kbase_csf_fw_io_stream_read(struct kbase_csf_fw_io *fw_io,
const struct kbase_csf_cmd_stream_info *info, u32 offset)
{
const struct kbase_device *const kbdev = info->kbdev;
u32 val;
lockdep_assert_held(&fw_io->lock);
val = output_page_read(info->output, offset);
dev_dbg(kbdev->dev, "cs output r: reg %08x val %08x\n", offset, val);
return val;
}
void kbase_csf_fw_io_set_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit)
{
set_bit(status_bit, fw_io->status);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_set_status);
void kbase_csf_fw_io_clear_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit)
{
clear_bit(status_bit, fw_io->status);
}
bool kbase_csf_fw_io_test_status(struct kbase_csf_fw_io *fw_io,
enum kbase_csf_fw_io_status_bits status_bit)
{
return test_bit(status_bit, fw_io->status);
}
KBASE_EXPORT_TEST_API(kbase_csf_fw_io_test_status);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -180,8 +180,9 @@ void kbase_csf_heap_context_allocator_term(struct kbase_csf_heap_context_allocat
u64 kbase_csf_heap_context_allocator_alloc(struct kbase_csf_heap_context_allocator *const ctx_alloc)
{
struct kbase_context *const kctx = ctx_alloc->kctx;
u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | BASE_MEM_PROT_CPU_WR |
BASEP_MEM_NO_USER_FREE | BASE_MEM_PROT_CPU_RD;
base_mem_alloc_flags flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR |
BASE_MEM_PROT_CPU_WR | BASEP_MEM_NO_USER_FREE |
BASE_MEM_PROT_CPU_RD;
u64 nr_pages = PFN_UP(MAX_TILER_HEAPS * ctx_alloc->heap_context_size_aligned);
u64 heap_gpu_va = 0;

View file

@ -371,7 +371,7 @@ static int kbase_kcpu_jit_allocate_prepare(struct kbase_kcpu_command_queue *kcpu
goto out;
}
if (copy_from_user(info, data, sizeof(*info) * count) != 0) {
if (copy_from_user(info, data, size_mul(sizeof(*info), count)) != 0) {
ret = -EINVAL;
goto out_free;
}
@ -563,7 +563,7 @@ static int kbase_kcpu_jit_free_prepare(struct kbase_kcpu_command_queue *kcpu_que
goto out_free;
}
if (copy_from_user(ids, data, sizeof(*ids) * count)) {
if (copy_from_user(ids, data, size_mul(sizeof(*ids), count))) {
ret = -EINVAL;
goto out_free;
}
@ -852,7 +852,8 @@ static int kbase_kcpu_cqs_wait_prepare(struct kbase_kcpu_command_queue *queue,
if (!objs)
return -ENOMEM;
if (copy_from_user(objs, u64_to_user_ptr(cqs_wait_info->objs), nr_objs * sizeof(*objs))) {
if (copy_from_user(objs, u64_to_user_ptr(cqs_wait_info->objs),
size_mul(nr_objs, sizeof(*objs)))) {
kfree(objs);
return -ENOMEM;
}
@ -957,7 +958,8 @@ static int kbase_kcpu_cqs_set_prepare(struct kbase_kcpu_command_queue *kcpu_queu
if (!objs)
return -ENOMEM;
if (copy_from_user(objs, u64_to_user_ptr(cqs_set_info->objs), nr_objs * sizeof(*objs))) {
if (copy_from_user(objs, u64_to_user_ptr(cqs_set_info->objs),
size_mul(nr_objs, sizeof(*objs)))) {
kfree(objs);
return -ENOMEM;
}
@ -1115,7 +1117,7 @@ static int kbase_kcpu_cqs_wait_operation_prepare(
return -ENOMEM;
if (copy_from_user(objs, u64_to_user_ptr(cqs_wait_operation_info->objs),
nr_objs * sizeof(*objs))) {
size_mul(nr_objs, sizeof(*objs)))) {
kfree(objs);
return -ENOMEM;
}
@ -1280,7 +1282,7 @@ static int kbase_kcpu_cqs_set_operation_prepare(
return -ENOMEM;
if (copy_from_user(objs, u64_to_user_ptr(cqs_set_operation_info->objs),
nr_objs * sizeof(*objs))) {
size_mul(nr_objs, sizeof(*objs)))) {
kfree(objs);
return -ENOMEM;
}

View file

@ -172,6 +172,11 @@
#define CSG_STATUS_EP_CURRENT 0x0010 /* () Endpoint allocation status register */
#define CSG_STATUS_EP_REQ 0x0014 /* () Endpoint request status register */
#define CSG_RESOURCE_DEP 0x001C /* () Current resource dependencies */
/* TODO: GPUCORE-xxxx: Remove after spec alignment, use 0x1C as CSG_RESOURCE_DEP is deprecated*/
/* CSG_OUTPUT_BLOCK register offsets */
#ifndef CSG_PROGRESS_TIMER_STATE
#define CSG_PROGRESS_TIMER_STATE 0x001C /* () Current resource status */
#endif
/* GLB_CONTROL_BLOCK register offsets */
#define GLB_VERSION 0x0000 /* () Global interface version */
@ -1243,6 +1248,21 @@
CSG_STATUS_EP_REQ_EXCLUSIVE_FRAGMENT_MASK))
/* CSG_PROGRESS_TIMER_STATE register */
#ifndef CSG_PROGRESS_TIMER_STATE_GET
#define CSG_PROGRESS_TIMER_STATE_SHIFT 0
#define CSG_PROGRESS_TIMER_STATE_MASK ((u32)0xFFFFFFFF << CSG_PROGRESS_TIMER_STATE_SHIFT)
#define CSG_PROGRESS_TIMER_STATE_GET(reg_val) \
(((reg_val)&CSG_PROGRESS_TIMER_STATE_MASK) >> CSG_PROGRESS_TIMER_STATE_SHIFT)
#define CSG_PROGRESS_TIMER_STATE_SET(reg_val, value) \
(((reg_val) & ~CSG_PROGRESS_TIMER_STATE_MASK) | \
(((value) << CSG_PROGRESS_TIMER_STATE_SHIFT) & CSG_PROGRESS_TIMER_STATE_MASK))
/* CSG_PROGRESS_TIMER_STATE values */
#define CSG_PROGRESS_TIMER_STATE_COMPUTE 0x0
#define CSG_PROGRESS_TIMER_STATE_FRAGMENT 0x1
#define CSG_PROGRESS_TIMER_STATE_TILER 0x2
#define CSG_PROGRESS_TIMER_STATE_NEURAL 0x3
#endif
/* End of CSG_OUTPUT_BLOCK register set definitions */
/* STREAM_CONTROL_BLOCK register set definitions */
@ -1380,6 +1400,13 @@
#define GLB_REQ_SLEEP_SET(reg_val, value) \
(((reg_val) & ~GLB_REQ_SLEEP_MASK) | \
(((value) << GLB_REQ_SLEEP_SHIFT) & GLB_REQ_SLEEP_MASK))
#define GLB_REQ_CFG_EVICTION_TIMER_SHIFT 16
#define GLB_REQ_CFG_EVICTION_TIMER_MASK (0x1 << GLB_REQ_CFG_EVICTION_TIMER_SHIFT)
#define GLB_REQ_CFG_EVICTION_TIMER_GET(reg_val) \
(((reg_val)&GLB_REQ_CFG_EVICTION_TIMER_MASK) >> GLB_REQ_CFG_EVICTION_TIMER_SHIFT)
#define GLB_REQ_CFG_EVICTION_TIMER_SET(reg_val, value) \
(((reg_val) & ~GLB_REQ_CFG_EVICTION_TIMER_MASK) | \
(((value) << GLB_REQ_CFG_EVICTION_TIMER_SHIFT) & GLB_REQ_CFG_EVICTION_TIMER_MASK))
#define GLB_REQ_INACTIVE_COMPUTE_SHIFT 20
#define GLB_REQ_INACTIVE_COMPUTE_MASK (0x1 << GLB_REQ_INACTIVE_COMPUTE_SHIFT)
#define GLB_REQ_INACTIVE_COMPUTE_GET(reg_val) \
@ -1524,6 +1551,17 @@
(((reg_val) & ~GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK) | \
(((value) << GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_SHIFT) & \
GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK))
#define GLB_ACK_IRQ_MASK_ITER_TRACE_ENABLE_SHIFT 11
#define GLB_ACK_IRQ_MASK_ITER_TRACE_ENABLE_MASK (0x1 << GLB_ACK_IRQ_MASK_ITER_TRACE_ENABLE_SHIFT)
#define GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_SHIFT 16
#define GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_MASK (0x1 << GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_SHIFT)
#define GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_GET(reg_val) \
(((reg_val)&GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_MASK) >> \
GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_SHIFT)
#define GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_SET(reg_val, value) \
(((reg_val) & ~GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_MASK) | \
(((value) << GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_SHIFT) & \
GLB_ACK_IRQ_MASK_CFG_EVICTION_TIMER_MASK))
#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SHIFT 20
#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_MASK (0x1 << GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_SHIFT)
#define GLB_ACK_IRQ_MASK_INACTIVE_COMPUTE_GET(reg_val) \
@ -1635,6 +1673,45 @@
GLB_PWROFF_TIMER_CONFIG_NO_MODIFIER_MASK))
#endif /* End of GLB_PWROFF_TIMER_CONFIG values */
/* GLB_EVICTION_TIMER register */
#ifndef GLB_EVICTION_TIMER
#define GLB_EVICTION_TIMER 0x0090
#define GLB_EVICTION_TIMER_TIMEOUT_SHIFT (0)
#define GLB_EVICTION_TIMER_TIMEOUT_MASK ((0x7FFFFFFF) << GLB_EVICTION_TIMER_TIMEOUT_SHIFT)
#define GLB_EVICTION_TIMER_TIMEOUT_GET(reg_val) \
(((reg_val)&GLB_EVICTION_TIMER_TIMEOUT_MASK) >> GLB_EVICTION_TIMER_TIMEOUT_SHIFT)
#define GLB_EVICTION_TIMER_TIMEOUT_SET(reg_val, value) \
(((reg_val) & ~GLB_EVICTION_TIMER_TIMEOUT_MASK) | \
(((value) << GLB_EVICTION_TIMER_TIMEOUT_SHIFT) & GLB_EVICTION_TIMER_TIMEOUT_MASK))
#define GLB_EVICTION_TIMER_TIMER_SOURCE_SHIFT (31)
#define GLB_EVICTION_TIMER_TIMER_SOURCE_MASK ((0x1) << GLB_EVICTION_TIMER_TIMER_SOURCE_SHIFT)
#define GLB_EVICTION_TIMER_TIMER_SOURCE_GET(reg_val) \
(((reg_val)&GLB_EVICTION_TIMER_TIMER_SOURCE_MASK) >> GLB_EVICTION_TIMER_TIMER_SOURCE_SHIFT)
#define GLB_EVICTION_TIMER_TIMER_SOURCE_SET(reg_val, value) \
(((reg_val) & ~GLB_EVICTION_TIMER_TIMER_SOURCE_MASK) | \
(((value) << GLB_EVICTION_TIMER_TIMER_SOURCE_SHIFT) & \
GLB_EVICTION_TIMER_TIMER_SOURCE_MASK))
/* GLB_EVICTION_TIMER_TIMER_SOURCE values */
#define GLB_EVICTION_TIMER_TIMER_SOURCE_SYSTEM_TIMESTAMP 0x0U
#define GLB_EVICTION_TIMER_TIMER_SOURCE_GPU_COUNTER 0x1U
/* End of GLB_EVICTION_TIMER_TIMER_SOURCE values */
#endif /* End of GLB_EVICTION_TIMER */
/* GLB_EVICTION_TIMER_CONFIG register */
#ifndef GLB_EVICTION_TIMER_CONFIG
#define GLB_EVICTION_TIMER_CONFIG 0x0094 /* () Configuration fields for GLB_EVICTION_TIMER */
#define GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_SHIFT 0
#define GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_MASK \
(0x1 << GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_SHIFT)
#define GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_GET(reg_val) \
(((reg_val)&GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_MASK) >> \
GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_SHIFT)
#define GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_SET(reg_val, value) \
(((reg_val) & ~GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_MASK) | \
(((value) << GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_SHIFT) & \
GLB_EVICTION_TIMER_CONFIG_NO_MODIFIER_MASK))
#endif /* End of GLB_EVICTION_TIMER_CONFIG values */
/* GLB_ALLOC_EN register */
#define GLB_ALLOC_EN_MASK_SHIFT 0
#define GLB_ALLOC_EN_MASK_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << GLB_ALLOC_EN_MASK_SHIFT)
@ -1717,6 +1794,15 @@
(((reg_val) & ~GLB_IDLE_TIMER_CONFIG_NO_MODIFIER_MASK) | \
(((value) << GLB_IDLE_TIMER_CONFIG_NO_MODIFIER_SHIFT) & \
GLB_IDLE_TIMER_CONFIG_NO_MODIFIER_MASK))
#define GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_SHIFT 9
#define GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_MASK (0x1 << GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_SHIFT)
#define GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_GET(reg_val) \
(((reg_val)&GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_MASK) >> \
GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_SHIFT)
#define GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_SET(reg_val, value) \
(((reg_val) & ~GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_MASK) | \
(((value) << GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_SHIFT) & \
GLB_IDLE_TIMER_CONFIG_SLEEP_ON_IDLE_MASK))
#endif /* End of GLB_IDLE_TIMER_CONFIG values */
/* GLB_INSTR_FEATURES register */

View file

@ -496,12 +496,10 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data)
bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev, unsigned int flags)
{
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbase_pm_is_gpu_lost(kbdev)) {
/* GPU access has been removed, reset will be done by Arbiter instead */
return false;
}
#endif
if (flags & RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)
kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface);

View file

@ -42,6 +42,7 @@
#include <csf/mali_kbase_csf_trace_buffer.h>
#endif /* CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD */
/* Value to indicate that a queue group is not groups_to_schedule list */
#define KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID (U32_MAX)
@ -93,6 +94,11 @@ static bool queue_group_scheduled_locked(struct kbase_queue_group *group);
#define kctx_as_enabled(kctx) (!kbase_ctx_flag(kctx, KCTX_AS_DISABLED_ON_FAULT))
bool is_gpu_level_suspend_supported(struct kbase_device *const kbdev)
{
return false;
}
#if IS_ENABLED(CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD)
/**
* gpu_metrics_ctx_init() - Take a reference on GPU metrics context if it exists,
@ -1196,13 +1202,20 @@ static void scheduler_wakeup(struct kbase_device *kbdev, bool kick)
scheduler_enable_tick_timer_nolock(kbdev);
}
static void scheduler_suspend(struct kbase_device *kbdev)
static int scheduler_suspend(struct kbase_device *kbdev)
{
struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
lockdep_assert_held(&scheduler->lock);
if (!WARN_ON(scheduler->state == SCHED_SUSPENDED)) {
#if KBASE_PM_RUNTIME
int ret;
ret = kbase_csf_firmware_soi_disable_on_scheduler_suspend(kbdev);
if (ret)
return ret;
#endif /* KBASE_PM_RUNTIME */
dev_dbg(kbdev->dev, "Suspending the Scheduler");
scheduler_pm_idle(kbdev);
scheduler->state = SCHED_SUSPENDED;
@ -1211,6 +1224,8 @@ static void scheduler_suspend(struct kbase_device *kbdev)
#endif
KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state);
}
return 0;
}
/**
@ -1462,7 +1477,7 @@ static int sched_halt_stream(struct kbase_queue *queue)
long remaining;
int slot;
int err = 0;
const u32 group_schedule_timeout = kbase_get_timeout_ms(kbdev, CSF_CSG_SUSPEND_TIMEOUT);
const u32 group_schedule_timeout = kbdev->csf.csg_suspend_timeout_ms;
const u32 fw_timeout_ms = kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_TIMEOUT);
if (WARN_ON(!group))
@ -1942,7 +1957,6 @@ static enum kbase_csf_csg_slot_state update_csg_slot_status(struct kbase_device
if ((state == CSG_ACK_STATE_START) || (state == CSG_ACK_STATE_RESUME)) {
slot_state = CSG_SLOT_RUNNING;
atomic_set(&csg_slot->state, slot_state);
csg_slot->trigger_jiffies = jiffies;
KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_RUNNING, csg_slot->resident_group,
state);
dev_dbg(kbdev->dev, "Group %u running on slot %d\n",
@ -1953,7 +1967,6 @@ static enum kbase_csf_csg_slot_state update_csg_slot_status(struct kbase_device
if ((state == CSG_ACK_STATE_SUSPEND) || (state == CSG_ACK_STATE_TERMINATE)) {
slot_state = CSG_SLOT_STOPPED;
atomic_set(&csg_slot->state, slot_state);
csg_slot->trigger_jiffies = jiffies;
KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOPPED, csg_slot->resident_group,
state);
dev_dbg(kbdev->dev, "Group %u stopped on slot %d\n",
@ -2052,7 +2065,6 @@ static void halt_csg_slot(struct kbase_queue_group *group, bool suspend)
kbase_csf_ring_csg_doorbell(kbdev, slot);
spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags);
atomic_set(&csg_slot[slot].state, CSG_SLOT_DOWN2STOP);
csg_slot[slot].trigger_jiffies = jiffies;
KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOP_REQ, group, halt_cmd);
KBASE_TLSTREAM_TL_KBASE_DEVICE_HALTING_CSG(kbdev, kbdev->id, (u32)slot, suspend);
@ -2367,11 +2379,6 @@ static void cancel_tock_work(struct kbase_csf_scheduler *const scheduler)
atomic_set(&scheduler->pending_tock_work, false);
}
static void cancel_gpu_idle_work(struct kbase_csf_scheduler *const scheduler)
{
atomic_set(&scheduler->pending_gpu_idle_work, false);
}
static void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler,
struct kbase_queue_group *group,
enum kbase_csf_group_state run_state)
@ -2776,7 +2783,6 @@ static bool cleanup_csg_slot(struct kbase_queue_group *group)
spin_unlock_bh(&kbdev->csf.scheduler.gpu_metrics_lock);
#endif
csg_slot->trigger_jiffies = jiffies;
atomic_set(&csg_slot->state, CSG_SLOT_READY);
KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_CLEANED, group, (u64)slot);
@ -2990,7 +2996,6 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, u8 prio)
/* Update status before rings the door-bell, marking ready => run */
atomic_set(&csg_slot->state, CSG_SLOT_READY2RUN);
csg_slot->trigger_jiffies = jiffies;
csg_slot->priority = prio;
/* Trace the programming of the CSG on the slot */
@ -3556,8 +3561,7 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev)
while (!bitmap_empty(slot_mask, MAX_SUPPORTED_CSGS)) {
DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS);
long remaining = kbase_csf_timeout_in_jiffies(
kbase_get_timeout_ms(kbdev, CSF_CSG_SUSPEND_TIMEOUT));
long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.csg_suspend_timeout_ms);
bitmap_copy(changed, slot_mask, MAX_SUPPORTED_CSGS);
@ -4101,7 +4105,7 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev,
* entry to protected mode happens with a memory region being locked and
* the same region is then accessed by the GPU in protected mode.
*/
down_write(&kbdev->csf.pmode_sync_sem);
down_write(&kbdev->csf.mmu_sync_sem);
spin_lock_irqsave(&scheduler->interrupt_lock, flags);
/* Check if the previous transition to enter & exit the protected
@ -4167,7 +4171,7 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev,
spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
err = kbase_csf_wait_protected_mode_enter(kbdev);
up_write(&kbdev->csf.pmode_sync_sem);
up_write(&kbdev->csf.mmu_sync_sem);
if (err)
schedule_actions_trigger_df(
@ -4182,7 +4186,7 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev,
}
spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
up_write(&kbdev->csf.pmode_sync_sem);
up_write(&kbdev->csf.mmu_sync_sem);
}
/**
@ -4760,27 +4764,28 @@ static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev, bool s
{
struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
DECLARE_BITMAP(slot_mask, MAX_SUPPORTED_CSGS) = { 0 };
int ret;
ret = suspend_active_queue_groups(kbdev, slot_mask, false);
if (unlikely(suspend_active_queue_groups(kbdev, slot_mask, false))) {
if (!is_gpu_level_suspend_supported(kbdev)) {
const int csg_nr = ffs(slot_mask[0]) - 1;
struct kbase_queue_group *group;
enum dumpfault_error_type error_type = DF_CSG_SUSPEND_TIMEOUT;
if (unlikely(ret)) {
const int csg_nr = ffs(slot_mask[0]) - 1;
struct kbase_queue_group *group = scheduler->csg_slots[csg_nr].resident_group;
enum dumpfault_error_type error_type = DF_CSG_SUSPEND_TIMEOUT;
group = scheduler->csg_slots[csg_nr].resident_group;
/* The suspend of CSGs failed,
* trigger the GPU reset to be in a deterministic state.
*/
dev_warn(
kbdev->dev,
"[%llu] Timeout (%d ms) waiting for CSG slots to suspend on power down, slot_mask: 0x%*pb\n",
kbase_backend_get_cycle_cnt(kbdev),
kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_TIMEOUT),
kbdev->csf.global_iface.group_num, slot_mask);
if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS))
error_type = DF_PING_REQUEST_TIMEOUT;
schedule_actions_trigger_df(kbdev, group->kctx, error_type);
/* The suspend of CSGs failed,
* trigger the GPU reset to be in a deterministic state.
*/
dev_warn(
kbdev->dev,
"[%llu] Timeout (%d ms) waiting for CSG slots to suspend on power down, slot_mask: 0x%*pb\n",
kbase_backend_get_cycle_cnt(kbdev),
kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_TIMEOUT),
kbdev->csf.global_iface.group_num, slot_mask);
if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS))
error_type = DF_PING_REQUEST_TIMEOUT;
schedule_actions_trigger_df(kbdev, group->kctx, error_type);
}
if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE))
kbase_reset_gpu(kbdev);
@ -4788,6 +4793,8 @@ static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev, bool s
return -1;
}
kbdev->csf.mcu_halted = false;
/* Check if the groups became active whilst the suspend was ongoing,
* but only for the case where the system suspend is not in progress
*/
@ -4947,9 +4954,13 @@ static bool scheduler_suspend_on_idle(struct kbase_device *kbdev)
}
dev_dbg(kbdev->dev, "Scheduler to be suspended on GPU becoming idle");
scheduler_suspend(kbdev);
cancel_tick_work(scheduler);
return true;
ret = scheduler_suspend(kbdev);
if (!ret) {
cancel_tick_work(scheduler);
return true;
}
return false;
}
static void gpu_idle_worker(struct kbase_device *kbdev)
@ -5193,8 +5204,7 @@ static int wait_csg_slots_suspend(struct kbase_device *kbdev, unsigned long *slo
bitmap_copy(slot_mask_local, slot_mask, MAX_SUPPORTED_CSGS);
while (!bitmap_empty(slot_mask_local, MAX_SUPPORTED_CSGS)) {
long remaining = kbase_csf_timeout_in_jiffies(
kbase_get_timeout_ms(kbdev, CSF_CSG_SUSPEND_TIMEOUT));
long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.csg_suspend_timeout_ms);
DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS);
bitmap_copy(changed, slot_mask_local, MAX_SUPPORTED_CSGS);
@ -5343,20 +5353,6 @@ static void evict_lru_or_blocked_csg(struct kbase_device *kbdev)
}
}
static void scheduler_enable_gpu_idle_timer(struct kbase_device *kbdev)
{
struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
unsigned long flags;
lockdep_assert_held(&scheduler->lock);
if (!kbdev->csf.gpu_idle_timer_enabled) {
spin_lock_irqsave(&scheduler->interrupt_lock, flags);
kbase_csf_firmware_enable_gpu_idle_timer(kbdev);
spin_unlock_irqrestore(&scheduler->interrupt_lock, flags);
}
}
static void schedule_actions(struct kbase_device *kbdev, bool is_tick)
{
struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
@ -5399,7 +5395,6 @@ static void schedule_actions(struct kbase_device *kbdev, bool is_tick)
* in particular, no alterations to on-slot CSGs.
*/
if (keep_lru_on_slots(kbdev)) {
scheduler_enable_gpu_idle_timer(kbdev);
return;
}
}
@ -5472,7 +5467,6 @@ redo_local_tock:
wait_csg_slots_start(kbdev);
wait_csg_slots_finish_prio_update(kbdev);
scheduler_enable_gpu_idle_timer(kbdev);
if (new_protm_top_grp) {
scheduler_group_check_protm_enter(kbdev, scheduler->top_grp);
@ -5495,6 +5489,15 @@ redo_local_tock:
}
evict_lru_or_blocked_csg(kbdev);
#ifdef KBASE_PM_RUNTIME
if (atomic_read(&scheduler->non_idle_offslot_grps))
set_bit(KBASE_GPU_NON_IDLE_OFF_SLOT_GROUPS_AVAILABLE,
&kbdev->pm.backend.gpu_sleep_allowed);
else
clear_bit(KBASE_GPU_NON_IDLE_OFF_SLOT_GROUPS_AVAILABLE,
&kbdev->pm.backend.gpu_sleep_allowed);
#endif /* KBASE_PM_RUNTIME */
}
/**
@ -5653,19 +5656,20 @@ static int suspend_active_queue_groups(struct kbase_device *kbdev, unsigned long
{
struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler;
u32 num_groups = kbdev->csf.global_iface.group_num;
struct kbase_queue_group *group;
u32 slot_num;
int ret;
lockdep_assert_held(&scheduler->lock);
for (slot_num = 0; slot_num < num_groups; slot_num++) {
struct kbase_queue_group *group = scheduler->csg_slots[slot_num].resident_group;
for (slot_num = 0; slot_num < num_groups; slot_num++) {
group = scheduler->csg_slots[slot_num].resident_group;
if (group) {
if (group) {
suspend_queue_group(group);
set_bit(slot_num, slot_mask);
set_bit(slot_num, slot_mask);
}
}
}
ret = wait_csg_slots_suspend(kbdev, slot_mask);
return ret;
@ -5819,7 +5823,10 @@ static void scheduler_inner_reset(struct kbase_device *kbdev)
/* Cancel any potential queued delayed work(s) */
cancel_tick_work(scheduler);
cancel_tock_work(scheduler);
cancel_gpu_idle_work(scheduler);
/* gpu_idle_worker() might already be running at this point, which
* could decrement the pending_gpu_idle_worker counter to below 0.
* It'd be safer to let it run if one has already been scheduled.
*/
cancel_delayed_work_sync(&scheduler->ping_work);
mutex_lock(&scheduler->lock);
@ -5837,10 +5844,22 @@ static void scheduler_inner_reset(struct kbase_device *kbdev)
scheduler->top_kctx = NULL;
scheduler->top_grp = NULL;
atomic_set(&scheduler->gpu_idle_timer_enabled, false);
atomic_set(&scheduler->fw_soi_enabled, false);
KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_TOP_GRP, scheduler->top_grp,
scheduler->num_active_address_spaces |
(((u64)scheduler->total_runnable_grps) << 32));
#ifdef KBASE_PM_RUNTIME
if (scheduler->state == SCHED_SLEEPING) {
#if IS_ENABLED(CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD)
hrtimer_cancel(&scheduler->gpu_metrics_timer);
#endif
scheduler->state = SCHED_SUSPENDED;
KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state);
}
#endif
mutex_unlock(&scheduler->lock);
}
@ -6726,6 +6745,11 @@ static int kbase_csf_scheduler_kthread(void *data)
while (atomic_read(&scheduler->pending_gpu_idle_work) > 0)
gpu_idle_worker(kbdev);
/* Update GLB_IDLE timer/FW Sleep-on-Idle config (which might
* have been disabled during FW boot et. al.).
*/
kbase_csf_firmware_soi_update(kbdev);
dev_dbg(kbdev->dev, "Waking up for event after a scheduling iteration.");
wake_up_all(&kbdev->csf.event_wait);
}
@ -6786,6 +6810,9 @@ int kbase_csf_scheduler_init(struct kbase_device *kbdev)
scheduler->gpu_metrics_timer.function = gpu_metrics_timer_callback;
#endif /* CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD */
atomic_set(&scheduler->gpu_idle_timer_enabled, false);
atomic_set(&scheduler->fw_soi_enabled, false);
return kbase_csf_mcu_shared_regs_data_init(kbdev);
}
@ -6988,8 +7015,9 @@ int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev)
goto exit;
} else {
dev_dbg(kbdev->dev, "Scheduler PM suspend");
scheduler_suspend(kbdev);
cancel_tick_work(scheduler);
result = scheduler_suspend(kbdev);
if (!result)
cancel_tick_work(scheduler);
}
}

View file

@ -693,4 +693,6 @@ void kbase_csf_scheduler_force_wakeup(struct kbase_device *kbdev);
void kbase_csf_scheduler_force_sleep(struct kbase_device *kbdev);
#endif
bool is_gpu_level_suspend_supported(struct kbase_device *const kbdev);
#endif /* _KBASE_CSF_SCHEDULER_H_ */

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -260,8 +260,9 @@ static struct kbase_csf_tiler_heap_chunk *alloc_new_chunk(struct kbase_context *
u64 chunk_size)
{
u64 nr_pages = PFN_UP(chunk_size);
u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | BASE_MEM_PROT_CPU_WR |
BASEP_MEM_NO_USER_FREE | BASE_MEM_COHERENT_LOCAL | BASE_MEM_PROT_CPU_RD;
base_mem_alloc_flags flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR |
BASE_MEM_PROT_CPU_WR | BASEP_MEM_NO_USER_FREE |
BASE_MEM_COHERENT_LOCAL | BASE_MEM_PROT_CPU_RD;
struct kbase_csf_tiler_heap_chunk *chunk = NULL;
/* The chunk kernel mapping needs to be large enough to:
* - initially zero the CHUNK_HDR_SIZE area
@ -350,13 +351,14 @@ static struct kbase_csf_tiler_heap_chunk *alloc_new_chunk(struct kbase_context *
}
remove_external_chunk_mappings(kctx, chunk);
kbase_gpu_vm_unlock(kctx);
/* If page migration is enabled, we don't want to migrate tiler heap pages.
* This does not change if the constituent pages are already marked as isolated.
*/
if (kbase_is_page_migration_enabled())
kbase_set_phy_alloc_page_status(chunk->region->gpu_alloc, NOT_MOVABLE);
kbase_set_phy_alloc_page_status(kctx, chunk->region->gpu_alloc, NOT_MOVABLE);
kbase_gpu_vm_unlock(kctx);
return chunk;
@ -640,7 +642,7 @@ static bool kbasep_is_buffer_descriptor_region_suitable(struct kbase_context *co
if (!(reg->flags & KBASE_REG_CPU_RD) || kbase_is_region_shrinkable(reg) ||
(reg->flags & KBASE_REG_PF_GROW)) {
dev_err(kctx->kbdev->dev, "Region has invalid flags: 0x%lX!\n", reg->flags);
dev_err(kctx->kbdev->dev, "Region has invalid flags: 0x%llX!\n", reg->flags);
return false;
}
@ -737,7 +739,7 @@ int kbase_csf_tiler_heap_init(struct kbase_context *const kctx, u32 const chunk_
KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING);
if (kbase_is_page_migration_enabled())
kbase_set_phy_alloc_page_status(buf_desc_reg->gpu_alloc, NOT_MOVABLE);
kbase_set_phy_alloc_page_status(kctx, buf_desc_reg->gpu_alloc, NOT_MOVABLE);
kbase_gpu_vm_unlock(kctx);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -469,14 +469,15 @@ unsigned int kbase_csf_firmware_trace_buffer_read_data(struct firmware_trace_buf
} else {
unsigned int bytes_copied_head, bytes_copied_tail;
bytes_copied_tail = min_t(unsigned int, num_bytes, (buffer_size - extract_offset));
bytes_copied_tail =
min_t(unsigned int, num_bytes, size_sub(buffer_size, extract_offset));
memcpy(data, &data_cpu_va[extract_offset], bytes_copied_tail);
bytes_copied_head =
min_t(unsigned int, (num_bytes - bytes_copied_tail), insert_offset);
memcpy(&data[bytes_copied_tail], data_cpu_va, bytes_copied_head);
bytes_copied = bytes_copied_head + bytes_copied_tail;
bytes_copied = size_add(bytes_copied_head, bytes_copied_tail);
extract_offset += bytes_copied;
if (extract_offset >= buffer_size)
extract_offset = bytes_copied_head;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2022-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2022-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -443,7 +443,7 @@ kbase_debug_coresight_csf_config_create(void *client_data,
}
config = kzalloc(sizeof(struct kbase_debug_coresight_csf_config), GFP_KERNEL);
if (WARN_ON(!client))
if (WARN_ON(!config))
return NULL;
config->client = client;

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -212,6 +212,9 @@ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_EVICT_CTX_SLOTS_START),
KBASE_KTRACE_CODE_MAKE_CODE(SCHED_BUSY), KBASE_KTRACE_CODE_MAKE_CODE(SCHED_INACTIVE),
KBASE_KTRACE_CODE_MAKE_CODE(SCHED_SUSPENDED), KBASE_KTRACE_CODE_MAKE_CODE(SCHED_SLEEPING),
/* info_val == true if FW Sleep-on-Idle is enabled, false otherwise */
KBASE_KTRACE_CODE_MAKE_CODE(FIRMWARE_SLEEP_ON_IDLE_CHANGED),
/* info_val = mcu state */
#define KBASEP_MCU_STATE(n) KBASE_KTRACE_CODE_MAKE_CODE(PM_MCU_##n),
#include "backend/gpu/mali_kbase_pm_mcu_states.h"

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -69,6 +69,7 @@ DEFINE_MALI_ADD_EVENT(SCHED_BUSY);
DEFINE_MALI_ADD_EVENT(SCHED_INACTIVE);
DEFINE_MALI_ADD_EVENT(SCHED_SUSPENDED);
DEFINE_MALI_ADD_EVENT(SCHED_SLEEPING);
DEFINE_MALI_ADD_EVENT(FIRMWARE_SLEEP_ON_IDLE_CHANGED);
#define KBASEP_MCU_STATE(n) DEFINE_MALI_ADD_EVENT(PM_MCU_##n);
#include "backend/gpu/mali_kbase_pm_mcu_states.h"
#undef KBASEP_MCU_STATE

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -149,13 +149,17 @@ KBASE_KTRACE_CODE_MAKE_CODE(CORE_CTX_DESTROY),
KBASE_KTRACE_CODE_MAKE_CODE(SCHED_RETAIN_CTX_NOLOCK),
/* info_val == kctx->refcount */
KBASE_KTRACE_CODE_MAKE_CODE(SCHED_RELEASE_CTX),
#ifdef CONFIG_MALI_ARBITER_SUPPORT
/*
* Arbitration events
*/
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_LOST), KBASE_KTRACE_CODE_MAKE_CODE(ARB_VM_STATE),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_VM_STATE),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_VM_EVT),
#endif
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_GRANTED),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_LOST),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_STARTED),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_STOP_REQUESTED),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_STOPPED),
KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_REQUESTED),
#if MALI_USE_CSF
#include "debug/backend/mali_kbase_debug_ktrace_codes_csf.h"

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -95,13 +95,16 @@ DEFINE_MALI_ADD_EVENT(PM_RUNTIME_RESUME_CALLBACK);
#undef KBASEP_L2_STATE
DEFINE_MALI_ADD_EVENT(SCHED_RETAIN_CTX_NOLOCK);
DEFINE_MALI_ADD_EVENT(SCHED_RELEASE_CTX);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
DEFINE_MALI_ADD_EVENT(ARB_GPU_LOST);
DEFINE_MALI_ADD_EVENT(ARB_VM_STATE);
DEFINE_MALI_ADD_EVENT(ARB_VM_EVT);
DEFINE_MALI_ADD_EVENT(ARB_GPU_GRANTED);
DEFINE_MALI_ADD_EVENT(ARB_GPU_LOST);
DEFINE_MALI_ADD_EVENT(ARB_GPU_STARTED);
DEFINE_MALI_ADD_EVENT(ARB_GPU_STOP_REQUESTED);
DEFINE_MALI_ADD_EVENT(ARB_GPU_STOPPED);
DEFINE_MALI_ADD_EVENT(ARB_GPU_REQUESTED);
#endif
#if MALI_USE_CSF
#include "backend/mali_kbase_debug_linux_ktrace_csf.h"
#else

View file

@ -132,11 +132,15 @@ static int kbase_backend_late_init(struct kbase_device *kbdev)
fail_update_l2_features:
kbase_backend_devfreq_term(kbdev);
fail_devfreq_init:
kbasep_pm_metrics_term(kbdev);
fail_pm_metrics_init:
kbase_ipa_control_term(kbdev);
fail_devfreq_init:
{
kbasep_pm_metrics_term(kbdev);
}
fail_pm_metrics_init:
{
kbase_ipa_control_term(kbdev);
}
#ifdef CONFIG_MALI_BIFROST_DEBUG
#if IS_ENABLED(CONFIG_MALI_REAL_HW)
fail_interrupt_test:

View file

@ -32,7 +32,7 @@
bool kbase_is_gpu_removed(struct kbase_device *kbdev)
{
if (!IS_ENABLED(CONFIG_MALI_ARBITER_SUPPORT))
if (!kbase_has_arbiter(kbdev))
return false;
@ -88,6 +88,7 @@ static void kbase_gpu_fault_interrupt(struct kbase_device *kbdev)
void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
{
u32 power_changed_mask = (POWER_CHANGED_ALL | MCU_STATUS_GPU_IRQ);
struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, val);
@ -95,7 +96,6 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
kbase_gpu_fault_interrupt(kbdev);
if (val & GPU_PROTECTED_FAULT) {
struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler;
unsigned long flags;
dev_err_ratelimited(kbdev->dev, "GPU fault in protected mode");
@ -149,10 +149,33 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
unsigned long flags;
dev_dbg(kbdev->dev, "Doorbell mirror interrupt received");
/* Assume that the doorbell comes from userspace which
* presents new works in order to invalidate a possible GPU
* idle event.
* If the doorbell was raised by KBase then the FW would handle
* the pending doorbell then raise a 2nd GBL_IDLE IRQ which
* would allow us to put the GPU to sleep.
*/
atomic_set(&scheduler->gpu_no_longer_idle, true);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
kbase_pm_disable_db_mirror_interrupt(kbdev);
kbdev->pm.backend.exit_gpu_sleep_mode = true;
kbase_csf_scheduler_invoke_tick(kbdev);
if (likely(kbdev->pm.backend.mcu_state == KBASE_MCU_IN_SLEEP)) {
kbdev->pm.backend.exit_gpu_sleep_mode = true;
kbase_csf_scheduler_invoke_tick(kbdev);
} else if (likely(test_bit(KBASE_GPU_SUPPORTS_FW_SLEEP_ON_IDLE,
&kbdev->pm.backend.gpu_sleep_allowed)) &&
(kbdev->pm.backend.mcu_state != KBASE_MCU_ON_PEND_SLEEP)) {
/* The firmware is going to sleep on its own but new
* doorbells were rung before we manage to handle
* the GLB_IDLE IRQ in the bottom half. We shall enable
* DB notification to allow the DB to be handled by FW.
*/
dev_dbg(kbdev->dev, "Re-enabling MCU immediately following DB_MIRROR IRQ");
kbase_pm_enable_mcu_db_notification(kbdev);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
}
#endif
@ -179,7 +202,7 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
* cores.
*/
if (kbdev->pm.backend.l2_always_on ||
kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921))
kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_921))
kbase_pm_power_changed(kbdev);
}

View file

@ -30,7 +30,7 @@
bool kbase_is_gpu_removed(struct kbase_device *kbdev)
{
if (!IS_ENABLED(CONFIG_MALI_ARBITER_SUPPORT))
if (!kbase_has_arbiter(kbdev))
return false;
return (KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(GPU_ID)) == 0);
@ -103,7 +103,7 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val)
* cores.
*/
if (kbdev->pm.backend.l2_always_on ||
kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_921))
kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_921))
kbase_pm_power_changed(kbdev);
}

View file

@ -32,10 +32,6 @@
#include <hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h>
#include <backend/gpu/mali_kbase_model_linux.h>
#ifdef CONFIG_MALI_ARBITER_SUPPORT
#include <arbiter/mali_kbase_arbiter_pm.h>
#endif
#include <mali_kbase.h>
#include <backend/gpu/mali_kbase_irq_internal.h>
#include <backend/gpu/mali_kbase_jm_internal.h>

View file

@ -51,10 +51,7 @@
#include "backend/gpu/mali_kbase_irq_internal.h"
#include "mali_kbase_regs_history_debugfs.h"
#include "mali_kbase_pbha.h"
#ifdef CONFIG_MALI_ARBITER_SUPPORT
#include "arbiter/mali_kbase_arbiter_pm.h"
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
#if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI)
@ -69,6 +66,22 @@ static DEFINE_MUTEX(kbase_dev_list_lock);
static LIST_HEAD(kbase_dev_list);
static unsigned int kbase_dev_nr;
static unsigned int mma_wa_id;
static int set_mma_wa_id(const char *val, const struct kernel_param *kp)
{
return kbase_param_set_uint_minmax(val, kp, 1, 15);
}
static const struct kernel_param_ops mma_wa_id_ops = {
.set = set_mma_wa_id,
.get = param_get_uint,
};
module_param_cb(mma_wa_id, &mma_wa_id_ops, &mma_wa_id, 0444);
__MODULE_PARM_TYPE(mma_wa_id, "uint");
MODULE_PARM_DESC(mma_wa_id, "PBHA ID for MMA workaround. Valid range is from 1 to 15.");
struct kbase_device *kbase_device_alloc(void)
{
return vzalloc(sizeof(struct kbase_device));
@ -320,6 +333,10 @@ int kbase_device_misc_init(struct kbase_device *const kbdev)
if (err)
goto dma_set_mask_failed;
/* Set mma_wa_id if it has been passed in as a module parameter */
if ((kbdev->gpu_props.gpu_id.arch_id >= GPU_ID_ARCH_MAKE(14, 8, 0)) && mma_wa_id != 0)
kbdev->mma_wa_id = mma_wa_id;
err = kbase_pbha_read_dtb(kbdev);
if (err)
goto term_as;
@ -597,17 +614,12 @@ int kbase_device_early_init(struct kbase_device *kbdev)
/* We're done accessing the GPU registers for now. */
kbase_pm_register_access_disable(kbdev);
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbdev->arb.arb_if) {
if (kbase_has_arbiter(kbdev)) {
if (kbdev->pm.arb_vm_state)
err = kbase_arbiter_pm_install_interrupts(kbdev);
} else {
err = kbase_install_interrupts(kbdev);
}
#else
err = kbase_install_interrupts(kbdev);
#endif
if (err)
goto gpuprops_term;
@ -633,15 +645,10 @@ ktrace_term:
void kbase_device_early_term(struct kbase_device *kbdev)
{
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbdev->arb.arb_if)
if (kbase_has_arbiter(kbdev))
kbase_arbiter_pm_release_interrupts(kbdev);
else
kbase_release_interrupts(kbdev);
#else
kbase_release_interrupts(kbdev);
#endif
kbase_gpuprops_term(kbdev);
kbase_device_backend_term(kbdev);
kbase_regmap_term(kbdev);

View file

@ -31,8 +31,8 @@
#define KBASE_REGMAP_ACCESS_ALWAYS_POWERED (1U << 16)
static u32 always_powered_regs[] = {
#if MALI_USE_CSF
#else /* MALI_USE_CSF */
#if !MALI_USE_CSF
PTM_AW_IRQ_CLEAR,
PTM_AW_IRQ_INJECTION,
PTM_AW_IRQ_MASK,
@ -44,13 +44,19 @@ static u32 always_powered_regs[] = {
PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1,
PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS,
PTM_ID,
#endif /* MALI_USE_CSF */
#endif /* !MALI_USE_CSF */
};
static void kbasep_reg_setup_always_powered_registers(struct kbase_device *kbdev)
{
u32 i;
#if !MALI_USE_CSF
if (kbdev->gpu_props.gpu_id.arch_id < GPU_ID_ARCH_MAKE(9, 14, 0))
return;
#endif /* MALI_USE_CSF */
for (i = 0; i < ARRAY_SIZE(always_powered_regs); i++) {
u32 reg_enum = always_powered_regs[i];

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software

View file

@ -185,6 +185,7 @@
*/
#define AS_MEMATTR_ATTRIBUTE0_MEMORY_TYPE_SHARED 0x0
/* CSF_CONFIG register */
#define CSF_CONFIG_FORCE_COHERENCY_FEATURES_SHIFT 2

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -78,6 +78,18 @@ typedef int kbase_hwcnt_backend_init_fn(const struct kbase_hwcnt_backend_info *i
*/
typedef void kbase_hwcnt_backend_term_fn(struct kbase_hwcnt_backend *backend);
/**
* typedef kbase_hwcnt_backend_acquire_fn - Enable counter collection.
* @backend: Non-NULL pointer to backend interface.
*/
typedef void kbase_hwcnt_backend_acquire_fn(const struct kbase_hwcnt_backend *backend);
/**
* typedef kbase_hwcnt_backend_release_fn - Disable counter collection.
* @backend: Non-NULL pointer to backend interface.
*/
typedef void kbase_hwcnt_backend_release_fn(const struct kbase_hwcnt_backend *backend);
/**
* typedef kbase_hwcnt_backend_timestamp_ns_fn - Get the current backend
* timestamp.
@ -206,6 +218,10 @@ typedef int kbase_hwcnt_backend_dump_get_fn(struct kbase_hwcnt_backend *backend,
* metadata.
* @init: Function ptr to initialise an instance of the backend.
* @term: Function ptr to terminate an instance of the backend.
* @acquire: Callback to indicate that counter collection has
* been enabled.
* @release: Callback to indicate that counter collection has
* been disabled.
* @timestamp_ns: Function ptr to get the current backend timestamp.
* @dump_enable: Function ptr to enable dumping.
* @dump_enable_nolock: Function ptr to enable dumping while the
@ -222,6 +238,8 @@ struct kbase_hwcnt_backend_interface {
kbase_hwcnt_backend_metadata_fn *metadata;
kbase_hwcnt_backend_init_fn *init;
kbase_hwcnt_backend_term_fn *term;
kbase_hwcnt_backend_acquire_fn *acquire;
kbase_hwcnt_backend_release_fn *release;
kbase_hwcnt_backend_timestamp_ns_fn *timestamp_ns;
kbase_hwcnt_backend_dump_enable_fn *dump_enable;
kbase_hwcnt_backend_dump_enable_nolock_fn *dump_enable_nolock;

View file

@ -1710,6 +1710,22 @@ static void kbasep_hwcnt_backend_csf_term(struct kbase_hwcnt_backend *backend)
kbasep_hwcnt_backend_csf_destroy(backend_csf);
}
static void kbasep_hwcnt_backend_csf_acquire(const struct kbase_hwcnt_backend *backend)
{
struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend;
struct kbase_hwcnt_backend_csf_info *csf_info = backend_csf->info;
csf_info->csf_if->acquire(csf_info->csf_if->ctx);
}
static void kbasep_hwcnt_backend_csf_release(const struct kbase_hwcnt_backend *backend)
{
struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend;
struct kbase_hwcnt_backend_csf_info *csf_info = backend_csf->info;
csf_info->csf_if->release(csf_info->csf_if->ctx);
}
/**
* kbasep_hwcnt_backend_csf_info_destroy() - Destroy a CSF backend info.
* @info: Pointer to info to destroy.
@ -2168,6 +2184,8 @@ int kbase_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_if *csf_if, u3
iface->metadata = kbasep_hwcnt_backend_csf_metadata;
iface->init = kbasep_hwcnt_backend_csf_init;
iface->term = kbasep_hwcnt_backend_csf_term;
iface->acquire = kbasep_hwcnt_backend_csf_acquire;
iface->release = kbasep_hwcnt_backend_csf_release;
iface->timestamp_ns = kbasep_hwcnt_backend_csf_timestamp_ns;
iface->dump_enable = kbasep_hwcnt_backend_csf_dump_enable;
iface->dump_enable_nolock = kbasep_hwcnt_backend_csf_dump_enable_nolock;

View file

@ -114,6 +114,20 @@ typedef void (*kbase_hwcnt_backend_csf_if_lock_fn)(struct kbase_hwcnt_backend_cs
typedef void (*kbase_hwcnt_backend_csf_if_unlock_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx,
unsigned long flags);
/**
* typedef kbase_hwcnt_backend_csf_if_acquire_fn - Enable counter collection.
*
* @ctx: Non-NULL pointer to a CSF context.
*/
typedef void (*kbase_hwcnt_backend_csf_if_acquire_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx);
/**
* typedef kbase_hwcnt_backend_csf_if_release_fn - Disable counter collection.
*
* @ctx: Non-NULL pointer to a CSF context.
*/
typedef void (*kbase_hwcnt_backend_csf_if_release_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx);
/**
* typedef kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn - Get performance
* counter information.
@ -272,6 +286,10 @@ typedef void (*kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn)(
* @assert_lock_held: Function ptr to assert backend spinlock is held.
* @lock: Function ptr to acquire backend spinlock.
* @unlock: Function ptr to release backend spinlock.
* @acquire: Callback to indicate that counter collection has
* been enabled.
* @release: Callback to indicate that counter collection has
* been disabled.
* @get_prfcnt_info: Function ptr to get performance counter related
* information.
* @ring_buf_alloc: Function ptr to allocate ring buffer for CSF HWC.
@ -292,6 +310,8 @@ struct kbase_hwcnt_backend_csf_if {
kbase_hwcnt_backend_csf_if_assert_lock_held_fn assert_lock_held;
kbase_hwcnt_backend_csf_if_lock_fn lock;
kbase_hwcnt_backend_csf_if_unlock_fn unlock;
kbase_hwcnt_backend_csf_if_acquire_fn acquire;
kbase_hwcnt_backend_csf_if_release_fn release;
kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn get_prfcnt_info;
kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn ring_buf_alloc;
kbase_hwcnt_backend_csf_if_ring_buf_sync_fn ring_buf_sync;

View file

@ -131,6 +131,26 @@ static void kbasep_hwcnt_backend_csf_if_fw_unlock(struct kbase_hwcnt_backend_csf
kbase_csf_scheduler_spin_unlock(kbdev, flags);
}
static void kbasep_hwcnt_backend_csf_if_fw_acquire(struct kbase_hwcnt_backend_csf_if_ctx *ctx)
{
struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
(struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
/* Mark performance counters collection as enabled */
set_bit(KBASE_GPU_PERF_COUNTERS_COLLECTION_ENABLED,
&fw_ctx->kbdev->pm.backend.gpu_sleep_allowed);
}
static void kbasep_hwcnt_backend_csf_if_fw_release(struct kbase_hwcnt_backend_csf_if_ctx *ctx)
{
struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx =
(struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx;
/* Mark performance counters collection as disabled */
clear_bit(KBASE_GPU_PERF_COUNTERS_COLLECTION_ENABLED,
&fw_ctx->kbdev->pm.backend.gpu_sleep_allowed);
}
/**
* kbasep_hwcnt_backend_csf_if_fw_on_freq_change() - On freq change callback
*
@ -813,6 +833,8 @@ int kbase_hwcnt_backend_csf_if_fw_create(struct kbase_device *kbdev,
if_fw->assert_lock_held = kbasep_hwcnt_backend_csf_if_fw_assert_lock_held;
if_fw->lock = kbasep_hwcnt_backend_csf_if_fw_lock;
if_fw->unlock = kbasep_hwcnt_backend_csf_if_fw_unlock;
if_fw->acquire = kbasep_hwcnt_backend_csf_if_fw_acquire;
if_fw->release = kbasep_hwcnt_backend_csf_if_fw_release;
if_fw->get_prfcnt_info = kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info;
if_fw->ring_buf_alloc = kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc;
if_fw->ring_buf_sync = kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync;

View file

@ -683,7 +683,7 @@ static int kbasep_hwcnt_backend_jm_dump_alloc(const struct kbase_hwcnt_backend_j
struct kbase_context *kctx, u64 *gpu_dump_va)
{
struct kbase_va_region *reg;
u64 flags;
base_mem_alloc_flags flags;
u64 nr_pages;
/* Calls to this function are inherently asynchronous, with respect to
@ -851,6 +851,14 @@ static void kbasep_hwcnt_backend_jm_term(struct kbase_hwcnt_backend *backend)
kbasep_hwcnt_backend_jm_destroy((struct kbase_hwcnt_backend_jm *)backend);
}
static void kbasep_hwcnt_backend_jm_acquire(const struct kbase_hwcnt_backend *backend)
{
}
static void kbasep_hwcnt_backend_jm_release(const struct kbase_hwcnt_backend *backend)
{
}
/**
* kbasep_hwcnt_backend_jm_info_destroy() - Destroy a JM backend info.
* @info: Pointer to info to destroy.
@ -932,6 +940,8 @@ int kbase_hwcnt_backend_jm_create(struct kbase_device *kbdev,
iface->metadata = kbasep_hwcnt_backend_jm_metadata;
iface->init = kbasep_hwcnt_backend_jm_init;
iface->term = kbasep_hwcnt_backend_jm_term;
iface->acquire = kbasep_hwcnt_backend_jm_acquire;
iface->release = kbasep_hwcnt_backend_jm_release;
iface->timestamp_ns = kbasep_hwcnt_backend_jm_timestamp_ns;
iface->dump_enable = kbasep_hwcnt_backend_jm_dump_enable;
iface->dump_enable_nolock = kbasep_hwcnt_backend_jm_dump_enable_nolock;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2021-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -317,6 +317,14 @@ kbasep_hwcnt_backend_jm_watchdog_term_partial(struct kbase_hwcnt_backend_jm_watc
kfree(wd_backend);
}
static void kbasep_hwcnt_backend_jm_watchdog_acquire(const struct kbase_hwcnt_backend *backend)
{
}
static void kbasep_hwcnt_backend_jm_watchdog_release(const struct kbase_hwcnt_backend *backend)
{
}
/* Job manager watchdog backend, implementation of kbase_hwcnt_backend_term_fn
* Calling term does *not* destroy the interface
*/
@ -807,6 +815,8 @@ int kbase_hwcnt_backend_jm_watchdog_create(struct kbase_hwcnt_backend_interface
.metadata = kbasep_hwcnt_backend_jm_watchdog_metadata,
.init = kbasep_hwcnt_backend_jm_watchdog_init,
.term = kbasep_hwcnt_backend_jm_watchdog_term,
.acquire = kbasep_hwcnt_backend_jm_watchdog_acquire,
.release = kbasep_hwcnt_backend_jm_watchdog_release,
.timestamp_ns = kbasep_hwcnt_backend_jm_watchdog_timestamp_ns,
.dump_enable = kbasep_hwcnt_backend_jm_watchdog_dump_enable,
.dump_enable_nolock = kbasep_hwcnt_backend_jm_watchdog_dump_enable_nolock,

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -599,6 +599,9 @@ int kbase_hwcnt_accumulator_acquire(struct kbase_hwcnt_context *hctx,
return errcode;
}
/* Inform the backend that counter collection has been enabled. */
hctx->iface->acquire(hctx->accum.backend);
spin_lock_irqsave(&hctx->state_lock, flags);
WARN_ON(hctx->disable_count == 0);
@ -646,6 +649,9 @@ void kbase_hwcnt_accumulator_release(struct kbase_hwcnt_accumulator *accum)
mutex_unlock(&hctx->accum_lock);
/* Inform the backend that counter collection has been disabled. */
hctx->iface->release(hctx->accum.backend);
kbasep_hwcnt_accumulator_term(hctx);
mutex_lock(&hctx->accum_lock);

View file

@ -169,7 +169,7 @@ enum kbase_hwcnt_physical_set {
/**
* struct kbase_hwcnt_gpu_info - Information about hwcnt blocks on the GPUs.
* @l2_count: L2 cache count.
* @sc_core_mask: Shader core mask. May be sparse.
* @sc_core_mask: Shader core mask. May be sparse.
* @clk_cnt: Number of clock domains available.
* @csg_cnt: Number of CSGs available.
* @prfcnt_values_per_block: Total entries (header + counters) of performance

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -19,65 +19,6 @@
*
*/
/*
* Hardware counter types.
* Contains structures for describing the physical layout of hardware counter
* dump buffers and enable maps within a system.
*
* Also contains helper functions for manipulation of these dump buffers and
* enable maps.
*
* Through use of these structures and functions, hardware counters can be
* enabled, copied, accumulated, and generally manipulated in a generic way,
* regardless of the physical counter dump layout.
*
* Terminology:
*
* Hardware Counter System:
* A collection of hardware counter blocks, making a full hardware counter
* system.
* Hardware Counter Block:
* A block of hardware counters (e.g. shader block, tiler block).
* Hardware Counter Block Instance:
* An instance of a Hardware Counter Block (e.g. an MP4 GPU might have
* 4 shader block instances).
*
* Block Header:
* A header value inside a counter block. Headers don't count anything,
* so it is only valid to copy or zero them. Headers are always the first
* values in the block.
* Block Counter:
* A counter value inside a counter block. Counters can be zeroed, copied,
* or accumulated. Counters are always immediately after the headers in the
* block.
* Block Value:
* A catch-all term for block headers and block counters.
*
* Enable Map:
* An array of u64 bitfields, where each bit either enables exactly one
* block value, or is unused (padding). Note that this is derived from
* the client configuration, and is not obtained from the hardware.
* Dump Buffer:
* An array of u64 values, where each u64 corresponds either to one block
* value, or is unused (padding).
* Block State Buffer:
* An array of blk_stt_t values, where each blk_stt_t corresponds to one block
* instance and is used to track the on/off power state transitions, as well has
* hardware resource availability, and whether the block was operating
* in normal or protected mode.
* Availability Mask:
* A bitfield, where each bit corresponds to whether a block instance is
* physically available (e.g. an MP3 GPU may have a sparse core mask of
* 0b1011, meaning it only has 3 cores but for hardware counter dumps has the
* same dump buffer layout as an MP4 GPU with a core mask of 0b1111. In this
* case, the availability mask might be 0b1011111 (the exact layout will
* depend on the specific hardware architecture), with the 3 extra early bits
* corresponding to other block instances in the hardware counter system).
* Metadata:
* Structure describing the physical layout of the enable map and dump buffers
* for a specific hardware counter system.
*/
#ifndef _KBASE_HWCNT_TYPES_H_
#define _KBASE_HWCNT_TYPES_H_

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2017-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2017-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -115,7 +115,7 @@ static ssize_t param_string_set(struct file *file, const char __user *user_buf,
goto end;
}
buf_size = min(param->size - 1, count);
buf_size = min(size_sub(param->size, 1), count);
if (copy_from_user(param->addr.str, user_buf, buf_size)) {
ret = -EFAULT;
goto end;

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -308,11 +308,11 @@ enum kbase_atom_gpu_rb_state {
* powered down and GPU shall come out of fully
* coherent mode before entering protected mode.
* @KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY: Prepare coherency change;
* for BASE_HW_ISSUE_TGOX_R1_1234 also request L2 power on
* for KBASE_HW_ISSUE_TGOX_R1_1234 also request L2 power on
* so that coherency register contains correct value when
* GPU enters protected mode.
* @KBASE_ATOM_ENTER_PROTECTED_FINISHED: End state; for
* BASE_HW_ISSUE_TGOX_R1_1234 check
* KBASE_HW_ISSUE_TGOX_R1_1234 check
* that L2 is powered up and switch GPU to protected mode.
*/
enum kbase_atom_enter_protected_state {
@ -500,10 +500,6 @@ enum kbase_atom_exit_protected_state {
* is snapshot of the age_count counter in kbase
* context.
* @jobslot: Job slot to use when BASE_JD_REQ_JOB_SLOT is specified.
* @renderpass_id:Renderpass identifier used to associate an atom that has
* BASE_JD_REQ_START_RENDERPASS set in its core requirements
* with an atom that has BASE_JD_REQ_END_RENDERPASS set.
* @jc_fragment: Set of GPU fragment job chains
*/
struct kbase_jd_atom {
struct work_struct work;
@ -564,8 +560,6 @@ struct kbase_jd_atom {
enum base_jd_event_code event_code;
base_jd_core_req core_req;
u8 jobslot;
u8 renderpass_id;
struct base_jd_fragment jc_fragment;
u32 ticks;
int sched_priority;
@ -676,71 +670,6 @@ static inline bool kbase_jd_atom_is_earlier(const struct kbase_jd_atom *katom_a,
#define KBASE_JD_DEP_QUEUE_SIZE 256
/**
* enum kbase_jd_renderpass_state - State of a renderpass
* @KBASE_JD_RP_COMPLETE: Unused or completed renderpass. Can only transition to
* START.
* @KBASE_JD_RP_START: Renderpass making a first attempt at tiling.
* Can transition to PEND_OOM or COMPLETE.
* @KBASE_JD_RP_PEND_OOM: Renderpass whose first attempt at tiling used too much
* memory and has a soft-stop pending. Can transition to
* OOM or COMPLETE.
* @KBASE_JD_RP_OOM: Renderpass whose first attempt at tiling used too much
* memory and therefore switched to incremental
* rendering. The fragment job chain is forced to run.
* Can only transition to RETRY.
* @KBASE_JD_RP_RETRY: Renderpass making a second or subsequent attempt at
* tiling. Can transition to RETRY_PEND_OOM or COMPLETE.
* @KBASE_JD_RP_RETRY_PEND_OOM: Renderpass whose second or subsequent attempt at
* tiling used too much memory again and has a
* soft-stop pending. Can transition to RETRY_OOM
* or COMPLETE.
* @KBASE_JD_RP_RETRY_OOM: Renderpass whose second or subsequent attempt at
* tiling used too much memory again. The fragment job
* chain is forced to run. Can only transition to RETRY.
*
* A state machine is used to control incremental rendering.
*/
enum kbase_jd_renderpass_state {
KBASE_JD_RP_COMPLETE, /* COMPLETE => START */
KBASE_JD_RP_START, /* START => PEND_OOM or COMPLETE */
KBASE_JD_RP_PEND_OOM, /* PEND_OOM => OOM or COMPLETE */
KBASE_JD_RP_OOM, /* OOM => RETRY */
KBASE_JD_RP_RETRY, /* RETRY => RETRY_PEND_OOM or COMPLETE */
KBASE_JD_RP_RETRY_PEND_OOM, /* RETRY_PEND_OOM => RETRY_OOM or COMPLETE */
KBASE_JD_RP_RETRY_OOM /* RETRY_OOM => RETRY */
};
/**
* struct kbase_jd_renderpass - Data for a renderpass
* @state: Current state of the renderpass. If KBASE_JD_RP_COMPLETE then
* all other members are invalid.
* Both the job dispatcher context and hwaccess_lock must be
* locked to modify this so that it can be read with either
* (or both) locked.
* @start_katom: Address of the atom that is the start of a renderpass.
* Both the job dispatcher context and hwaccess_lock must be
* locked to modify this so that it can be read with either
* (or both) locked.
* @end_katom: Address of the atom that is the end of a renderpass, or NULL
* if that atom hasn't been added to the job scheduler yet.
* The job dispatcher context and hwaccess_lock must be
* locked to modify this so that it can be read with either
* (or both) locked.
* @oom_reg_list: A list of region structures which triggered out-of-memory.
* The hwaccess_lock must be locked to access this.
*
* Atoms tagged with BASE_JD_REQ_START_RENDERPASS or BASE_JD_REQ_END_RENDERPASS
* are associated with an object of this type, which is created and maintained
* by kbase to keep track of each renderpass.
*/
struct kbase_jd_renderpass {
enum kbase_jd_renderpass_state state;
struct kbase_jd_atom *start_katom;
struct kbase_jd_atom *end_katom;
struct list_head oom_reg_list;
};
/**
* struct kbase_jd_context - per context object encapsulating all the
* Job dispatcher related state.
@ -751,9 +680,6 @@ struct kbase_jd_renderpass {
* @atoms: Array of the objects representing atoms,
* containing the complete state and attributes
* of an atom.
* @renderpasses: Array of renderpass state for incremental
* rendering, indexed by user-specified renderpass
* ID.
* @job_nr: Tracks the number of atoms being processed by the
* kbase. This includes atoms that are not tracked by
* scheduler: 'not ready to run' & 'dependency-only'
@ -803,7 +729,6 @@ struct kbase_jd_context {
struct mutex lock;
struct kbasep_js_kctx_info sched_info;
struct kbase_jd_atom atoms[BASE_JD_ATOM_COUNT];
struct kbase_jd_renderpass renderpasses[BASE_JD_RP_COUNT];
struct workqueue_struct *job_done_wq;
wait_queue_head_t zero_jobs_wait;

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -567,22 +567,6 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom
*/
struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_t *end_timestamp);
/**
* kbase_js_atom_blocked_on_x_dep - Decide whether to ignore a cross-slot
* dependency
* @katom: Pointer to an atom in the slot ringbuffer
*
* A cross-slot dependency is ignored if necessary to unblock incremental
* rendering. If the atom at the start of a renderpass used too much memory
* and was soft-stopped then the atom at the end of a renderpass is submitted
* to hardware regardless of its dependency on the start-of-renderpass atom.
* This can happen multiple times for the same pair of atoms.
*
* Return: true to block the atom or false to allow it to be submitted to
* hardware.
*/
bool kbase_js_atom_blocked_on_x_dep(struct kbase_jd_atom *katom);
/**
* kbase_js_sched - Submit atoms from all available contexts.
*
@ -809,8 +793,7 @@ static inline bool
kbasep_js_has_atom_finished(const struct kbasep_js_atom_retained_state *katom_retained_state)
{
return (bool)(katom_retained_state->event_code != BASE_JD_EVENT_STOPPED &&
katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT &&
katom_retained_state->event_code != BASE_JD_EVENT_END_RP_DONE);
katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT);
}
/**

View file

@ -1,163 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features,
* please update base/tools/hwconfig_generator/hwc_{issues,features}.py
* For more information see base/tools/docs/hwconfig_generator.md
*/
#ifndef _BASE_HWCONFIG_FEATURES_H_
#define _BASE_HWCONFIG_FEATURES_H_
#include <linux/version_compat_defs.h>
enum base_hw_feature {
BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_TLS_HASHING,
BASE_HW_FEATURE_THREAD_GROUP_SPLIT,
BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_IDVS_GROUP_SIZE,
BASE_HW_FEATURE_L2_CONFIG,
BASE_HW_FEATURE_L2_SLICE_HASH,
BASE_HW_FEATURE_GPU_SLEEP,
BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
BASE_HW_FEATURE_CORE_FEATURES,
BASE_HW_FEATURE_PBHA_HWU,
BASE_HW_FEATURE_LARGE_PAGE_ALLOC,
BASE_HW_FEATURE_THREAD_TLS_ALLOC,
BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_generic[] = {
BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tMIx[] = {
BASE_HW_FEATURE_THREAD_GROUP_SPLIT, BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tHEx[] = {
BASE_HW_FEATURE_THREAD_GROUP_SPLIT, BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tSIx[] = {
BASE_HW_FEATURE_THREAD_GROUP_SPLIT, BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tDVx[] = {
BASE_HW_FEATURE_THREAD_GROUP_SPLIT, BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tNOx[] = {
BASE_HW_FEATURE_THREAD_GROUP_SPLIT, BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_TLS_HASHING,
BASE_HW_FEATURE_IDVS_GROUP_SIZE, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tGOx[] = {
BASE_HW_FEATURE_THREAD_GROUP_SPLIT, BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_TLS_HASHING,
BASE_HW_FEATURE_IDVS_GROUP_SIZE, BASE_HW_FEATURE_CORE_FEATURES,
BASE_HW_FEATURE_THREAD_TLS_ALLOC, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tTRx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_IDVS_GROUP_SIZE, BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tNAx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_IDVS_GROUP_SIZE, BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tBEx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_IDVS_GROUP_SIZE,
BASE_HW_FEATURE_L2_CONFIG,
BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tBAx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_IDVS_GROUP_SIZE,
BASE_HW_FEATURE_L2_CONFIG,
BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tODx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tGRx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tVAx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tTUx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_L2_SLICE_HASH, BASE_HW_FEATURE_GPU_SLEEP,
BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tTIx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION,
BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_L2_CONFIG,
BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_L2_SLICE_HASH,
BASE_HW_FEATURE_GPU_SLEEP,
BASE_HW_FEATURE_CORE_FEATURES,
BASE_HW_FEATURE_PBHA_HWU,
BASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tKRx[] = {
BASE_HW_FEATURE_FLUSH_REDUCTION, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE,
BASE_HW_FEATURE_L2_SLICE_HASH, BASE_HW_FEATURE_GPU_SLEEP,
BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_PBHA_HWU,
BASE_HW_FEATURE_LARGE_PAGE_ALLOC, BASE_HW_FEATURE_END
};
#endif /* _BASE_HWCONFIG_FEATURES_H_ */

View file

@ -1,621 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
/* AUTOMATICALLY GENERATED FILE. If you want to amend the issues/features,
* please update base/tools/hwconfig_generator/hwc_{issues,features}.py
* For more information see base/tools/docs/hwconfig_generator.md
*/
#ifndef _BASE_HWCONFIG_ISSUES_H_
#define _BASE_HWCONFIG_ISSUES_H_
#include <linux/version_compat_defs.h>
enum base_hw_issue {
BASE_HW_ISSUE_5736,
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_10682,
BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_T76X_3953,
BASE_HW_ISSUE_TMIX_7891,
BASE_HW_ISSUE_TMIX_7940,
BASE_HW_ISSUE_TMIX_8042,
BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TMIX_8138,
BASE_HW_ISSUE_TMIX_8206,
BASE_HW_ISSUE_TMIX_8343,
BASE_HW_ISSUE_TMIX_8463,
BASE_HW_ISSUE_TMIX_8456,
BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TMIX_8438,
BASE_HW_ISSUE_TNOX_1194,
BASE_HW_ISSUE_TGOX_R1_1234,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TSIX_1792,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_3076,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TTRX_3485,
BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_TURSEHW_1997,
BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716,
BASE_HW_ISSUE_GPU2019_3901,
BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_TITANHW_2679,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2922,
BASE_HW_ISSUE_TITANHW_2952,
BASE_HW_ISSUE_KRAKEHW_2151,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_KRAKEHW_2269,
BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__attribute__((
unused)) static const enum base_hw_issue base_hw_issues_generic[] = { BASE_HW_ISSUE_END };
__maybe_unused static const enum base_hw_issue base_hw_issues_tMIx_r0p0_05dev0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_T76X_3953, BASE_HW_ISSUE_TMIX_7891, BASE_HW_ISSUE_TMIX_8042,
BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TMIX_8138, BASE_HW_ISSUE_TMIX_8206,
BASE_HW_ISSUE_TMIX_8343, BASE_HW_ISSUE_TMIX_8463, BASE_HW_ISSUE_TMIX_8456,
BASE_HW_ISSUE_TMIX_8438, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tMIx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_TMIX_7891, BASE_HW_ISSUE_TMIX_7940, BASE_HW_ISSUE_TMIX_8042,
BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TMIX_8138, BASE_HW_ISSUE_TMIX_8206,
BASE_HW_ISSUE_TMIX_8343, BASE_HW_ISSUE_TMIX_8463, BASE_HW_ISSUE_TMIX_8456,
BASE_HW_ISSUE_TMIX_8438, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tMIx_r0p1[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_TMIX_7891, BASE_HW_ISSUE_TMIX_7940, BASE_HW_ISSUE_TMIX_8042,
BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TMIX_8138, BASE_HW_ISSUE_TMIX_8206,
BASE_HW_ISSUE_TMIX_8343, BASE_HW_ISSUE_TMIX_8463, BASE_HW_ISSUE_TMIX_8456,
BASE_HW_ISSUE_TMIX_8438, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tMIx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_7891,
BASE_HW_ISSUE_TMIX_7940, BASE_HW_ISSUE_TMIX_8042, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TMIX_8138, BASE_HW_ISSUE_TMIX_8206, BASE_HW_ISSUE_TMIX_8343,
BASE_HW_ISSUE_TMIX_8456, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_TMIX_7891, BASE_HW_ISSUE_TMIX_8042, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p1[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_TMIX_7891, BASE_HW_ISSUE_TMIX_8042, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p2[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_11054,
BASE_HW_ISSUE_TMIX_7891, BASE_HW_ISSUE_TMIX_8042, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p3[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_10682, BASE_HW_ISSUE_TMIX_7891,
BASE_HW_ISSUE_TMIX_8042, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tHEx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_7891,
BASE_HW_ISSUE_TMIX_8042, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_11054, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TSIX_1792,
BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r0p1[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_11054, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TSIX_1792,
BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r1p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_11054, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r1p1[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tSIx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tDVx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tDVx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tNOx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TNOX_1194, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tNOx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tGOx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TNOX_1194, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tGOx_r1p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133, BASE_HW_ISSUE_TSIX_1116,
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TGOX_R1_1234, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_GPU2017_1336, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tGOx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TMIX_8133,
BASE_HW_ISSUE_TSIX_1116, BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTRx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_3076, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3083, BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TTRX_3485,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTRx_r0p1[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_3076, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3083, BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TTRX_3485,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTRx_r0p2[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_3076,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tTRx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tNAx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_3076, BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3083, BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TTRX_3485,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tNAx_r0p1[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_3076,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_GPU2017_1336,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tNAx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r0p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083, BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TTRX_3485,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r0p1[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r1p0[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r1p1[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tBEx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_lBEx_r1p0[] = {
BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921, BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083, BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TTRX_3485,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_lBEx_r1p1[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBAx_r0p0[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBAx_r0p1[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBAx_r0p2[] = {
BASE_HW_ISSUE_9435,
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TTRX_2968_TTRX_3162,
BASE_HW_ISSUE_TTRX_921,
BASE_HW_ISSUE_TTRX_3414,
BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470,
BASE_HW_ISSUE_TTRX_3464,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tBAx[] = {
BASE_HW_ISSUE_5736, BASE_HW_ISSUE_9435, BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TTRX_3414, BASE_HW_ISSUE_TTRX_3083,
BASE_HW_ISSUE_TTRX_3470, BASE_HW_ISSUE_TTRX_3464, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tODx_r0p0[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tODx[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3212,
BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tGRx_r0p0[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tGRx[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tVAx_r0p0[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tVAx_r0p1[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tVAx[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r0p0[] = {
BASE_HW_ISSUE_TSIX_2033,
BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TURSEHW_1997,
BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716,
BASE_HW_ISSUE_GPU2019_3901,
BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710,
BASE_HW_ISSUE_TITANHW_2679,
BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r0p1[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TURSEHW_1997,
BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2019_3901,
BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_TURSEHW_2934, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tTUx[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p0[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p1[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p2[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p3[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878,
BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tTIx[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TURSEHW_2716,
BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2952,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTIx_r0p0[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TURSEHW_2716,
BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2922, BASE_HW_ISSUE_TITANHW_2952,
BASE_HW_ISSUE_TITANHW_2938, BASE_HW_ISSUE_TURSEHW_2934, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTIx_r0p1[] = {
BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337,
BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2021PRO_290,
BASE_HW_ISSUE_TITANHW_2710, BASE_HW_ISSUE_TITANHW_2679,
BASE_HW_ISSUE_GPU2022PRO_148, BASE_HW_ISSUE_TITANHW_2938,
BASE_HW_ISSUE_TURSEHW_2934, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tKRx_r0p0[] = {
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_KRAKEHW_2151, BASE_HW_ISSUE_KRAKEHW_2269, BASE_HW_ISSUE_TITANHW_2922,
BASE_HW_ISSUE_TURSEHW_2934, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tKRx_r0p1[] = {
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_KRAKEHW_2269, BASE_HW_ISSUE_TURSEHW_2934, BASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tKRx[] = {
BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_TURSEHW_2716, BASE_HW_ISSUE_GPU2022PRO_148,
BASE_HW_ISSUE_KRAKEHW_2151, BASE_HW_ISSUE_KRAKEHW_2269, BASE_HW_ISSUE_TURSEHW_2934,
BASE_HW_ISSUE_END
};
#endif /* _BASE_HWCONFIG_ISSUES_H_ */

View file

@ -345,21 +345,6 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done);
void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx,
struct kbase_jd_atom *katom);
/**
* kbase_job_slot_softstop_start_rp() - Soft-stop the atom at the start
* of a renderpass.
* @kctx: Pointer to a kernel base context.
* @reg: Reference of a growable GPU memory region in the same context.
* Takes ownership of the reference if successful.
*
* Used to switch to incremental rendering if we have nearly run out of
* virtual address space in a growable memory region and the atom currently
* executing on a job slot is the tiler job chain at the start of a renderpass.
*
* Return: 0 if successful, otherwise a negative error code.
*/
int kbase_job_slot_softstop_start_rp(struct kbase_context *kctx, struct kbase_va_region *reg);
/**
* kbase_job_slot_softstop - Soft-stop the specified job slot
*
@ -496,9 +481,7 @@ void kbasep_as_do_poke(struct work_struct *work);
* or a dmb was executed recently (to ensure the value is most up-to-date).
* However, without a lock the value could change afterwards.
*
* Return:
* * false if a suspend is not in progress
* * !=false otherwise
* Return: False if a suspend is not in progress, true otherwise,
*/
static inline bool kbase_pm_is_suspending(struct kbase_device *kbdev)
{
@ -521,21 +504,20 @@ static inline bool kbase_pm_is_resuming(struct kbase_device *kbdev)
return kbdev->pm.resuming;
}
#ifdef CONFIG_MALI_ARBITER_SUPPORT
/*
* Check whether a gpu lost is in progress
*
* @kbdev: The kbase device structure for the device (must be a valid pointer)
*
* Indicates whether a gpu lost has been received and jobs are no longer
* being scheduled
* being scheduled.
*
* Return: false if gpu is lost
* Return: != false otherwise
* Return: false if GPU is already lost or if no Arbiter is present (as GPU will
* always be present in this case), true otherwise.
*/
static inline bool kbase_pm_is_gpu_lost(struct kbase_device *kbdev)
{
return (atomic_read(&kbdev->pm.gpu_lost) == 0 ? false : true);
return (kbdev->arb.arb_if && ((bool)atomic_read(&kbdev->pm.gpu_lost)));
}
/*
@ -556,7 +538,6 @@ static inline void kbase_pm_set_gpu_lost(struct kbase_device *kbdev, bool gpu_lo
if (new_val != cur_val)
KBASE_KTRACE_ADD(kbdev, ARB_GPU_LOST, NULL, (u64)new_val);
}
#endif
/**
* kbase_pm_is_active - Determine whether the GPU is active

View file

@ -33,13 +33,21 @@
*
* @MALI_KBASE_CAP_SYSTEM_MONITOR: System Monitor
* @MALI_KBASE_CAP_JIT_PRESSURE_LIMIT: JIT Pressure limit
* @MALI_KBASE_CAP_MEM_DONT_NEED: Not needed physical memory
* @MALI_KBASE_CAP_MEM_GROW_ON_GPF: Memory grow on page fault
* @MALI_KBASE_CAP_MEM_PROTECTED: Protected memory
* @MALI_KBASE_CAP_MEM_IMPORT_SYNC_ON_MAP_UNMAP: CPU cache maintenance required when
* imported GPU memory is mapped/unmapped
* @MALI_KBASE_CAP_MEM_KERNEL_SYNC: Kernel side cache sync ops required
* @MALI_KBASE_CAP_MEM_SAME_VA: Same VA on CPU and GPU
* @MALI_KBASE_CAP_QUERY_MEM_DONT_NEED: BASE_MEM_DONT_NEED is queryable
* @MALI_KBASE_CAP_QUERY_MEM_GROW_ON_GPF: BASE_MEM_GROW_ON_GPF is queryable
* @MALI_KBASE_CAP_QUERY_MEM_PROTECTED: BASE_MEM_PROTECTED is queryable
* @MALI_KBASE_CAP_QUERY_MEM_IMPORT_SYNC_ON_MAP_UNMAP: BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP is
* queryable
* @MALI_KBASE_CAP_QUERY_MEM_KERNEL_SYNC: BASE_MEM_KERNEL_SYNC is queryable
* @MALI_KBASE_CAP_QUERY_MEM_SAME_VA: BASE_MEM_SAME_VA is queryable
* @MALI_KBASE_CAP_REJECT_ALLOC_MEM_DONT_NEED: BASE_MEM_DONT_NEED is not allocatable
* @MALI_KBASE_CAP_REJECT_ALLOC_MEM_PROTECTED_IN_UNPROTECTED_ALLOCS: BASE_MEM_PROTECTED is not
* allocatable in functions other
* than base_mem_protected
* @MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_8: BASE_MEM_UNUSED_BIT_8 is not allocatable
* @MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_19: BASE_MEM_UNUSED_BIT_19 is not allocatable
* @MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_20: BASE_MEM_UNUSED_BIT_20 is not allocatable
* @MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_27: BASE_MEM_UNUSED_BIT_27 is not allocatable
* @MALI_KBASE_NUM_CAPS: Delimiter
*
* New enumerator must not be negative and smaller than @MALI_KBASE_NUM_CAPS.
@ -47,12 +55,18 @@
enum mali_kbase_cap {
MALI_KBASE_CAP_SYSTEM_MONITOR = 0,
MALI_KBASE_CAP_JIT_PRESSURE_LIMIT,
MALI_KBASE_CAP_MEM_DONT_NEED,
MALI_KBASE_CAP_MEM_GROW_ON_GPF,
MALI_KBASE_CAP_MEM_PROTECTED,
MALI_KBASE_CAP_MEM_IMPORT_SYNC_ON_MAP_UNMAP,
MALI_KBASE_CAP_MEM_KERNEL_SYNC,
MALI_KBASE_CAP_MEM_SAME_VA,
MALI_KBASE_CAP_QUERY_MEM_DONT_NEED,
MALI_KBASE_CAP_QUERY_MEM_GROW_ON_GPF,
MALI_KBASE_CAP_QUERY_MEM_PROTECTED,
MALI_KBASE_CAP_QUERY_MEM_IMPORT_SYNC_ON_MAP_UNMAP,
MALI_KBASE_CAP_QUERY_MEM_KERNEL_SYNC,
MALI_KBASE_CAP_QUERY_MEM_SAME_VA,
MALI_KBASE_CAP_REJECT_ALLOC_MEM_DONT_NEED,
MALI_KBASE_CAP_REJECT_ALLOC_MEM_PROTECTED_IN_UNPROTECTED_ALLOCS,
MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_8,
MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_19,
MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_20,
MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_27,
MALI_KBASE_NUM_CAPS
};
@ -68,34 +82,67 @@ static inline bool mali_kbase_supports_jit_pressure_limit(unsigned long api_vers
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_JIT_PRESSURE_LIMIT);
}
static inline bool mali_kbase_supports_mem_dont_need(unsigned long api_version)
static inline bool mali_kbase_supports_query_mem_dont_need(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_DONT_NEED);
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_QUERY_MEM_DONT_NEED);
}
static inline bool mali_kbase_supports_mem_grow_on_gpf(unsigned long api_version)
static inline bool mali_kbase_supports_query_mem_grow_on_gpf(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_GROW_ON_GPF);
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_QUERY_MEM_GROW_ON_GPF);
}
static inline bool mali_kbase_supports_mem_protected(unsigned long api_version)
static inline bool mali_kbase_supports_query_mem_protected(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_PROTECTED);
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_QUERY_MEM_PROTECTED);
}
static inline bool mali_kbase_supports_mem_import_sync_on_map_unmap(unsigned long api_version)
static inline bool mali_kbase_supports_query_mem_import_sync_on_map_unmap(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_IMPORT_SYNC_ON_MAP_UNMAP);
return mali_kbase_supports_cap(api_version,
MALI_KBASE_CAP_QUERY_MEM_IMPORT_SYNC_ON_MAP_UNMAP);
}
static inline bool mali_kbase_supports_mem_kernel_sync(unsigned long api_version)
static inline bool mali_kbase_supports_query_mem_kernel_sync(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_KERNEL_SYNC);
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_QUERY_MEM_KERNEL_SYNC);
}
static inline bool mali_kbase_supports_mem_same_va(unsigned long api_version)
static inline bool mali_kbase_supports_query_mem_same_va(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_MEM_SAME_VA);
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_QUERY_MEM_SAME_VA);
}
static inline bool mali_kbase_supports_reject_alloc_mem_dont_need(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_REJECT_ALLOC_MEM_DONT_NEED);
}
static inline bool
mali_kbase_supports_reject_alloc_mem_protected_in_unprotected_allocs(unsigned long api_version)
{
return mali_kbase_supports_cap(
api_version, MALI_KBASE_CAP_REJECT_ALLOC_MEM_PROTECTED_IN_UNPROTECTED_ALLOCS);
}
static inline bool mali_kbase_supports_reject_alloc_mem_unused_bit_8(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_8);
}
static inline bool mali_kbase_supports_reject_alloc_mem_unused_bit_19(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_19);
}
static inline bool mali_kbase_supports_reject_alloc_mem_unused_bit_20(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_20);
}
static inline bool mali_kbase_supports_reject_alloc_mem_unused_bit_27(unsigned long api_version)
{
return mali_kbase_supports_cap(api_version, MALI_KBASE_CAP_REJECT_ALLOC_MEM_UNUSED_BIT_27);
}
#endif /* __KBASE_CAPS_H_ */

View file

@ -255,6 +255,42 @@ enum {
*/
#define DEFAULT_PROGRESS_TIMEOUT_CYCLES (2500000000ull)
/* MIN value of iterators' suspend timeout*/
#define CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MIN (200)
#if CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MIN <= 0
#error "CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MIN should be larger than 0"
#endif
/* MAX value of iterators' suspend timeout*/
#define CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MAX (60000)
#if CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MAX >= (0xFFFFFFFF)
#error "CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MAX should be less than U32_MAX"
#endif
/* Firmware iterators' suspend timeout, default 4000ms. Customer can update this by
* using debugfs -- csg_suspend_timeout
*/
#if IS_ENABLED(CONFIG_MALI_REAL_HW) && !IS_ENABLED(CONFIG_MALI_IS_FPGA)
#define CSG_SUSPEND_TIMEOUT_FIRMWARE_MS (4000)
#else
#define CSG_SUSPEND_TIMEOUT_FIRMWARE_MS (31000)
#endif
#if (CSG_SUSPEND_TIMEOUT_FIRMWARE_MS < CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MIN) || \
(CSG_SUSPEND_TIMEOUT_FIRMWARE_MS > CSG_SUSPEND_TIMEOUT_FIRMWARE_MS_MAX)
#error "CSG_SUSPEND_TIMEOUT_FIRMWARE_MS is out of range"
#endif
/* Additional time in milliseconds added to the firmware iterators' suspend timeout,
* default 100ms
*/
#define CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS (100)
/* Host side CSG suspend timeout */
#define CSG_SUSPEND_TIMEOUT_MS (CSG_SUSPEND_TIMEOUT_FIRMWARE_MS + CSG_SUSPEND_TIMEOUT_HOST_ADDED_MS)
/* MAX allowed timeout value(ms) on host side, should be less than ANR timeout */
#define MAX_TIMEOUT_MS (4500)
#else /* MALI_USE_CSF */
/* A default timeout in clock cycles to be used when an invalid timeout
@ -327,14 +363,6 @@ enum {
*/
#define DEFAULT_PROGRESS_TIMEOUT ((u64)5 * 500 * 1024 * 1024)
/* Default threshold at which to switch to incremental rendering
*
* Fraction of the maximum size of an allocation that grows on GPU page fault
* that can be used up before the driver switches to incremental rendering,
* in 256ths. 0 means disable incremental rendering.
*/
#define DEFAULT_IR_THRESHOLD (192)
/* Waiting time in clock cycles for the completion of a MMU operation.
*
* Ideally 1.6M GPU cycles required for the L2 cache (512KiB slice) flush.

View file

@ -62,9 +62,7 @@
#include "csf/mali_kbase_csf_cpu_queue.h"
#include "csf/mali_kbase_csf_event.h"
#endif
#ifdef CONFIG_MALI_ARBITER_SUPPORT
#include "arbiter/mali_kbase_arbiter_pm.h"
#endif
#include "mali_kbase_cs_experimental.h"
@ -76,6 +74,7 @@
#if IS_ENABLED(CONFIG_DEBUG_FS)
#include "mali_kbase_pbha_debugfs.h"
#endif
#include "mali_kbase_ioctl_helpers.h"
#include <linux/module.h>
#include <linux/init.h>
@ -153,21 +152,29 @@ static const struct mali_kbase_capability_def kbase_caps_table[MALI_KBASE_NUM_CA
#if MALI_USE_CSF
{ 1, 0 }, /* SYSTEM_MONITOR */
{ 1, 0 }, /* JIT_PRESSURE_LIMIT */
{ 1, 22 }, /* MEM_DONT_NEED */
{ 1, 0 }, /* MEM_GROW_ON_GPF */
{ 1, 0 }, /* MEM_PROTECTED */
{ 1, 26 }, /* MEM_IMPORT_SYNC_ON_MAP_UNMAP */
{ 1, 26 }, /* MEM_KERNEL_SYNC */
{ 1, 28 } /* MEM_SAME_VA */
{ 1, 22 }, /* QUERY_MEM_DONT_NEED */
{ 1, 0 }, /* QUERY_MEM_GROW_ON_GPF */
{ 1, 0 }, /* QUERY_MEM_PROTECTED */
{ 1, 26 }, /* QUERY_MEM_IMPORT_SYNC_ON_MAP_UNMAP */
{ 1, 26 }, /* QUERY_MEM_KERNEL_SYNC */
{ 1, 28 }, /* QUERY_MEM_SAME_VA */
{ 1, 31 }, /* REJECT_ALLOC_MEM_DONT_NEED */
{ 1, 31 }, /* REJECT_ALLOC_MEM_PROTECTED_IN_UNPROTECTED_ALLOCS */
{ 1, 31 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_20 */
{ 1, 31 } /* REJECT_ALLOC_MEM_UNUSED_BIT_27 */
#else
{ 11, 15 }, /* SYSTEM_MONITOR */
{ 11, 25 }, /* JIT_PRESSURE_LIMIT */
{ 11, 40 }, /* MEM_DONT_NEED */
{ 11, 2 }, /* MEM_GROW_ON_GPF */
{ 11, 2 }, /* MEM_PROTECTED */
{ 11, 43 }, /* MEM_IMPORT_SYNC_ON_MAP_UNMAP */
{ 11, 43 }, /* MEM_KERNEL_SYNC */
{ 11, 44 } /* MEM_SAME_VA */
{ 11, 40 }, /* QUERY_MEM_DONT_NEED */
{ 11, 2 }, /* QUERY_MEM_GROW_ON_GPF */
{ 11, 2 }, /* QUERY_MEM_PROTECTED */
{ 11, 43 }, /* QUERY_MEM_IMPORT_SYNC_ON_MAP_UNMAP */
{ 11, 43 }, /* QUERY_MEM_KERNEL_SYNC */
{ 11, 44 }, /* QUERY_MEM_SAME_VA */
{ 11, 46 }, /* REJECT_ALLOC_MEM_DONT_NEED */
{ 11, 46 }, /* REJECT_ALLOC_MEM_PROTECTED_IN_UNPROTECTED_ALLOCS */
{ 11, 46 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_8 */
{ 11, 46 } /* REJECT_ALLOC_MEM_UNUSED_BIT_19 */
#endif
};
@ -819,7 +826,7 @@ static int kbase_api_mem_alloc_ex(struct kbase_context *kctx,
union kbase_ioctl_mem_alloc_ex *alloc_ex)
{
struct kbase_va_region *reg;
u64 flags = alloc_ex->in.flags;
base_mem_alloc_flags flags = alloc_ex->in.flags;
u64 gpu_va;
/* Calls to this function are inherently asynchronous, with respect to
@ -929,7 +936,7 @@ static int kbase_api_mem_alloc(struct kbase_context *kctx, union kbase_ioctl_mem
static int kbase_api_mem_alloc(struct kbase_context *kctx, union kbase_ioctl_mem_alloc *alloc)
{
struct kbase_va_region *reg;
u64 flags = alloc->in.flags;
base_mem_alloc_flags flags = alloc->in.flags;
u64 gpu_va;
/* Calls to this function are inherently asynchronous, with respect to
@ -1055,16 +1062,6 @@ static int kbase_api_get_ddk_version(struct kbase_context *kctx,
static int kbase_api_mem_jit_init(struct kbase_context *kctx,
struct kbase_ioctl_mem_jit_init *jit_init)
{
size_t i;
for (i = 0; i < sizeof(jit_init->padding); i++) {
/* Ensure all padding bytes are 0 for potential future
* extension
*/
if (jit_init->padding[i])
return -EINVAL;
}
return kbase_region_tracker_init_jit(kctx, jit_init->va_pages, jit_init->max_allocations,
jit_init->trim_level, jit_init->group_id,
jit_init->phys_pages);
@ -1130,7 +1127,7 @@ static int kbase_api_mem_commit(struct kbase_context *kctx, struct kbase_ioctl_m
static int kbase_api_mem_alias(struct kbase_context *kctx, union kbase_ioctl_mem_alias *alias)
{
struct base_mem_aliasing_info *ai;
u64 flags;
base_mem_alloc_flags flags;
int err;
if (alias->in.nents == 0 || alias->in.nents > BASE_MEM_ALIAS_MAX_ENTS)
@ -1141,7 +1138,7 @@ static int kbase_api_mem_alias(struct kbase_context *kctx, union kbase_ioctl_mem
return -ENOMEM;
err = copy_from_user(ai, u64_to_user_ptr(alias->in.aliasing_info),
sizeof(*ai) * alias->in.nents);
size_mul(sizeof(*ai), alias->in.nents));
if (err) {
vfree(ai);
return -EFAULT;
@ -1169,7 +1166,7 @@ static int kbase_api_mem_alias(struct kbase_context *kctx, union kbase_ioctl_mem
static int kbase_api_mem_import(struct kbase_context *kctx, union kbase_ioctl_mem_import *import)
{
int ret;
u64 flags = import->in.flags;
base_mem_alloc_flags flags = import->in.flags;
if (flags & BASEP_MEM_FLAGS_KERNEL_ONLY)
return -ENOMEM;
@ -1281,7 +1278,8 @@ static int kbase_api_sticky_resource_map(struct kbase_context *kctx,
if (!map->count || map->count > BASE_EXT_RES_COUNT_MAX)
return -EOVERFLOW;
ret = copy_from_user(gpu_addr, u64_to_user_ptr(map->address), sizeof(u64) * map->count);
ret = copy_from_user(gpu_addr, u64_to_user_ptr(map->address),
size_mul(sizeof(u64), map->count));
if (ret != 0)
return -EFAULT;
@ -1320,7 +1318,8 @@ static int kbase_api_sticky_resource_unmap(struct kbase_context *kctx,
if (!unmap->count || unmap->count > BASE_EXT_RES_COUNT_MAX)
return -EOVERFLOW;
ret = copy_from_user(gpu_addr, u64_to_user_ptr(unmap->address), sizeof(u64) * unmap->count);
ret = copy_from_user(gpu_addr, u64_to_user_ptr(unmap->address),
size_mul(sizeof(u64), unmap->count));
if (ret != 0)
return -EFAULT;
@ -1402,7 +1401,6 @@ static int kbasep_cs_queue_group_create_1_6(struct kbase_context *kctx,
union kbase_ioctl_cs_queue_group_create_1_6 *create)
{
int ret;
size_t i;
union kbase_ioctl_cs_queue_group_create
new_create = { .in = {
.tiler_mask = create->in.tiler_mask,
@ -1415,13 +1413,7 @@ static int kbasep_cs_queue_group_create_1_6(struct kbase_context *kctx,
.compute_max = create->in.compute_max,
} };
for (i = 0; i < ARRAY_SIZE(create->in.padding); i++) {
if (create->in.padding[i] != 0)
return -EINVAL;
}
ret = kbase_csf_queue_group_create(kctx, &new_create);
create->out.group_handle = new_create.out.group_handle;
create->out.group_uid = new_create.out.group_uid;
@ -1432,7 +1424,6 @@ static int kbasep_cs_queue_group_create_1_18(struct kbase_context *kctx,
union kbase_ioctl_cs_queue_group_create_1_18 *create)
{
int ret;
size_t i;
union kbase_ioctl_cs_queue_group_create
new_create = { .in = {
.tiler_mask = create->in.tiler_mask,
@ -1447,13 +1438,7 @@ static int kbasep_cs_queue_group_create_1_18(struct kbase_context *kctx,
.dvs_buf = create->in.dvs_buf,
} };
for (i = 0; i < ARRAY_SIZE(create->in.padding); i++) {
if (create->in.padding[i] != 0)
return -EINVAL;
}
ret = kbase_csf_queue_group_create(kctx, &new_create);
create->out.group_handle = new_create.out.group_handle;
create->out.group_uid = new_create.out.group_uid;
@ -1580,14 +1565,15 @@ static int kbase_ioctl_cs_get_glb_iface(struct kbase_context *kctx,
&param->out.prfcnt_size, &param->out.instr_features);
if (copy_to_user(user_groups, group_data,
MIN(max_group_num, param->out.group_num) * sizeof(*group_data)))
size_mul(MIN(max_group_num, param->out.group_num),
sizeof(*group_data))))
err = -EFAULT;
}
if (!err)
if (copy_to_user(user_streams, stream_data,
MIN(max_total_stream_num, param->out.total_stream_num) *
sizeof(*stream_data)))
size_mul(MIN(max_total_stream_num, param->out.total_stream_num),
sizeof(*stream_data))))
err = -EFAULT;
kfree(group_data);
@ -1611,10 +1597,6 @@ static int kbase_ioctl_read_user_page(struct kbase_context *kctx,
if (unlikely(user_page->in.offset != LATEST_FLUSH))
return -EINVAL;
/* Validating padding that must be zero */
if (unlikely(user_page->in.padding != 0))
return -EINVAL;
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
if (!kbdev->pm.backend.gpu_powered)
user_page->out.val_lo = POWER_DOWN_LATEST_FLUSH_VALUE;
@ -1641,65 +1623,6 @@ kbasep_ioctl_context_priority_check(struct kbase_context *kctx,
return 0;
}
#define KBASE_HANDLE_IOCTL(cmd, function, arg) \
do { \
int ret; \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
ret = function(arg); \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
#define KBASE_HANDLE_IOCTL_IN(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_WRITE); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
err = copy_from_user(&param, uarg, sizeof(param)); \
if (err) \
return -EFAULT; \
ret = function(arg, &param); \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
#define KBASE_HANDLE_IOCTL_OUT(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_READ); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
memset(&param, 0, sizeof(param)); \
ret = function(arg, &param); \
err = copy_to_user(uarg, &param, sizeof(param)); \
if (err) \
return -EFAULT; \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
#define KBASE_HANDLE_IOCTL_INOUT(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != (_IOC_WRITE | _IOC_READ)); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
err = copy_from_user(&param, uarg, sizeof(param)); \
if (err) \
return -EFAULT; \
ret = function(arg, &param); \
err = copy_to_user(uarg, &param, sizeof(param)); \
if (err) \
return -EFAULT; \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
static int kbasep_ioctl_set_limited_core_count(
struct kbase_context *kctx,
struct kbase_ioctl_set_limited_core_count *set_limited_core_count)
@ -2418,30 +2341,41 @@ static int core_mask_parse(struct kbase_device *const kbdev, const char *const b
static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *const new_mask)
{
u64 new_core_mask = new_mask->new_core_mask;
u64 shader_present = kbdev->gpu_props.shader_present;
u64 shader_present;
unsigned long flags;
int ret = 0;
lockdep_assert_held(&kbdev->pm.lock);
lockdep_assert_held(&kbdev->hwaccess_lock);
kbase_csf_scheduler_lock(kbdev);
kbase_pm_lock(kbdev);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
shader_present = kbdev->gpu_props.shader_present;
if ((new_core_mask & shader_present) != new_core_mask) {
dev_err(kbdev->dev,
"Invalid core mask 0x%llX: Includes non-existent cores (present = 0x%llX)",
"Invalid requested core mask 0x%llX: Includes non-existent cores (present = 0x%llX)",
new_core_mask, shader_present);
return -EINVAL;
ret = -EINVAL;
goto exit;
} else if (!(new_core_mask & shader_present & kbdev->pm.backend.ca_cores_enabled)) {
dev_err(kbdev->dev,
"Invalid core mask 0x%llX: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX)",
"Invalid requested core mask 0x%llX: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX)",
new_core_mask, kbdev->gpu_props.shader_present,
kbdev->pm.backend.ca_cores_enabled);
return -EINVAL;
ret = -EINVAL;
goto exit;
}
if (kbdev->pm.debug_core_mask != new_core_mask)
kbase_pm_set_debug_core_mask(kbdev, new_core_mask);
return 0;
exit:
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
kbase_pm_unlock(kbdev);
kbase_csf_scheduler_unlock(kbdev);
return ret;
}
#else
struct kbase_core_mask {
@ -2478,15 +2412,23 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con
{
u64 shader_present = kbdev->gpu_props.shader_present;
u64 group_core_mask = kbdev->gpu_props.coherency_info.group.core_mask;
u64 *new_core_mask = &new_mask->new_core_mask[0];
u64 *new_core_mask;
unsigned long flags;
int ret = 0;
size_t i;
kbase_pm_lock(kbdev);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
new_core_mask = &new_mask->new_core_mask[0];
for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) {
if ((new_core_mask[i] & shader_present) != new_core_mask[i]) {
dev_err(kbdev->dev,
"Invalid core mask 0x%llX for JS %zu: Includes non-existent cores (present = 0x%llX)",
new_core_mask[i], i, shader_present);
return -EINVAL;
ret = -EINVAL;
goto exit;
} else if (!(new_core_mask[i] & shader_present &
kbdev->pm.backend.ca_cores_enabled)) {
@ -2494,17 +2436,20 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con
"Invalid core mask 0x%llX for JS %zu: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX)",
new_core_mask[i], i, kbdev->gpu_props.shader_present,
kbdev->pm.backend.ca_cores_enabled);
return -EINVAL;
ret = -EINVAL;
goto exit;
} else if (!(new_core_mask[i] & group_core_mask)) {
dev_err(kbdev->dev,
"Invalid core mask 0x%llX for JS %zu: No intersection with group 0 core mask 0x%llX",
new_core_mask[i], i, group_core_mask);
return -EINVAL;
ret = -EINVAL;
goto exit;
} else if (!(new_core_mask[i] & kbdev->gpu_props.curr_config.shader_present)) {
dev_err(kbdev->dev,
"Invalid core mask 0x%llX for JS %zu: No intersection with current core mask 0x%llX",
new_core_mask[i], i, kbdev->gpu_props.curr_config.shader_present);
return -EINVAL;
ret = -EINVAL;
goto exit;
}
}
@ -2515,7 +2460,11 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con
}
}
return 0;
exit:
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
kbase_pm_unlock(kbdev);
return ret;
}
#endif
@ -2539,7 +2488,6 @@ static ssize_t core_mask_store(struct device *dev, struct device_attribute *attr
struct kbase_core_mask core_mask = {};
int err;
unsigned long flags;
CSTD_UNUSED(attr);
@ -2552,14 +2500,8 @@ static ssize_t core_mask_store(struct device *dev, struct device_attribute *attr
if (err)
return err;
mutex_lock(&kbdev->pm.lock);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
err = core_mask_set(kbdev, &core_mask);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
mutex_unlock(&kbdev->pm.lock);
if (err)
return err;
@ -4385,7 +4327,8 @@ void registers_unmap(struct kbase_device *kbdev)
kbase_common_reg_unmap(kbdev);
}
#if defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF)
#if defined(CONFIG_OF)
static bool kbase_is_pm_enabled(const struct device_node *gpu_node)
{
const struct device_node *power_model_node;
@ -4424,13 +4367,13 @@ static bool kbase_is_full_coherency_enabled(const struct device_node *gpu_node)
}
return false;
}
#endif /* defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF) */
#endif /* defined(CONFIG_OF) */
int kbase_device_backend_init(struct kbase_device *kbdev)
{
int err = 0;
#if defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF)
#if defined(CONFIG_OF)
/*
* Attempt to initialize arbitration.
* If the platform is not suitable for arbitration, return -EPERM.
@ -4439,13 +4382,13 @@ int kbase_device_backend_init(struct kbase_device *kbdev)
*/
if (kbase_is_pm_enabled(kbdev->dev->of_node)) {
/* Arbitration AND power management invalid */
dev_err(kbdev->dev, "Invalid combination of arbitration AND power management\n");
dev_dbg(kbdev->dev, "Arbitration not supported with power management");
return -EPERM;
}
if (kbase_is_full_coherency_enabled(kbdev->dev->of_node)) {
/* Arbitration AND full coherency invalid */
dev_err(kbdev->dev, "Invalid combination of arbitration AND full coherency\n");
dev_dbg(kbdev->dev, "Arbitration not supported with full coherency");
return -EPERM;
}
@ -4466,21 +4409,19 @@ int kbase_device_backend_init(struct kbase_device *kbdev)
if (product_model != GPU_ID_PRODUCT_TGOX && product_model != GPU_ID_PRODUCT_TNOX &&
product_model != GPU_ID_PRODUCT_TBAX) {
kbase_arbiter_pm_early_term(kbdev);
dev_err(kbdev->dev, "GPU platform not suitable for arbitration\n");
dev_dbg(kbdev->dev, "GPU platform not suitable for arbitration");
return -EPERM;
}
#endif /* !MALI_USE_CSF */
dev_info(kbdev->dev, "Arbitration interface enabled\n");
dev_info(kbdev->dev, "Arbitration interface enabled");
}
#endif /* defined(CONFIG_MALI_ARBITER_SUPPORT) && defined(CONFIG_OF) */
#endif /* defined(CONFIG_OF) */
return err;
}
void kbase_device_backend_term(struct kbase_device *kbdev)
{
#ifdef CONFIG_MALI_ARBITER_SUPPORT
kbase_arbiter_pm_early_term(kbdev);
#endif
}
int power_control_init(struct kbase_device *kbdev)
@ -4898,7 +4839,7 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev)
if (IS_ERR_OR_NULL(dentry))
return dentry;
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) {
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) {
dentry = debugfs_create_file("protected_debug_mode", 0444,
kbdev->mali_debugfs_directory, kbdev,
&fops_protected_debug_mode);
@ -5785,11 +5726,11 @@ static int kbase_platform_device_probe(struct platform_device *pdev)
#if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE)
mutex_unlock(&kbase_probe_mutex);
#endif
#ifdef CONFIG_MALI_ARBITER_SUPPORT
mutex_lock(&kbdev->pm.lock);
kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_INITIALIZED_EVT);
mutex_unlock(&kbdev->pm.lock);
#endif
if (kbase_has_arbiter(kbdev)) {
mutex_lock(&kbdev->pm.lock);
kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_INITIALIZED_EVT);
mutex_unlock(&kbdev->pm.lock);
}
}
return err;

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -30,9 +30,6 @@
*/
static inline void mali_kbase_print_cs_experimental(void)
{
#if MALI_INCREMENTAL_RENDERING_JM
pr_info("mali_kbase: INCREMENTAL_RENDERING_JM (experimental) enabled");
#endif /* MALI_INCREMENTAL_RENDERING_JM */
}
#endif /* _KBASE_CS_EXPERIMENTAL_H_ */

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2022-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2022-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -58,7 +58,7 @@ static void debug_zone_mem_allocs_show(struct kbase_reg_zone *zone, struct seq_f
for (p = rb_first(rbtree); p; p = rb_next(p)) {
reg = rb_entry(p, struct kbase_va_region, rblink);
if (!(reg->flags & KBASE_REG_FREE)) {
seq_printf(sfile, "%16llx, %16zx, %16zx, %8lx, %s\n",
seq_printf(sfile, "%16llx, %16zx, %16zx, %8llx, %s\n",
reg->start_pfn << PAGE_SHIFT, reg->nr_pages << PAGE_SHIFT,
kbase_reg_current_backed_size(reg) << PAGE_SHIFT, reg->flags,
type_names[reg->gpu_alloc->type]);

View file

@ -28,8 +28,8 @@
#define _KBASE_DEFS_H_
#include <mali_kbase_config.h>
#include <mali_base_hwconfig_features.h>
#include <mali_base_hwconfig_issues.h>
#include <mali_kbase_hwconfig_features.h>
#include <mali_kbase_hwconfig_issues.h>
#include <mali_kbase_mem_lowlevel.h>
#include <mmu/mali_kbase_mmu_hw.h>
#include <backend/gpu/mali_kbase_instr_defs.h>
@ -52,10 +52,6 @@
#include <linux/version_compat_defs.h>
#if IS_ENABLED(CONFIG_DEBUG_FS)
#include <linux/debugfs.h>
#endif /* CONFIG_DEBUG_FS */
#ifdef CONFIG_MALI_BIFROST_DEVFREQ
#include <linux/devfreq.h>
#endif /* CONFIG_MALI_BIFROST_DEVFREQ */
@ -64,9 +60,7 @@
#include <linux/devfreq_cooling.h>
#endif
#ifdef CONFIG_MALI_ARBITER_SUPPORT
#include <arbiter/mali_kbase_arbiter_defs.h>
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
#include <linux/memory_group_manager.h>
#include <soc/rockchip/rockchip_opp_select.h>
@ -78,6 +72,7 @@
#include <linux/file.h>
#include <linux/sizes.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/regulator/consumer.h>
/** Number of milliseconds before we time out on a GPU soft/hard reset */
@ -297,24 +292,33 @@ struct kbase_fault {
#define MAX_PAGES_FOR_FREE_PGDS ((size_t)9)
/* Maximum number of pointers to free PGDs */
#define MAX_FREE_PGDS ((PAGE_SIZE / sizeof(struct page *)) * MAX_PAGES_FOR_FREE_PGDS)
#define MAX_FREE_PGDS ((PAGE_SIZE / sizeof(phys_addr_t)) * MAX_PAGES_FOR_FREE_PGDS)
/**
* struct kbase_mmu_table - object representing a set of GPU page tables
* @mmu_lock: Lock to serialize the accesses made to multi level GPU
* page tables
* @pgd: Physical address of the page allocated for the top
* level page table of the context, this is used for
* MMU HW programming as the address translation will
* start from the top level page table.
* @group_id: A memory group ID to be passed to a platform-specific
* memory group manager.
* Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1).
* @kctx: If this set of MMU tables belongs to a context then
* this is a back-reference to the context, otherwise
* it is NULL.
* @scratch_mem: Scratch memory used for MMU operations, which are
* serialized by the @mmu_lock.
* @mmu_lock: Lock to serialize the accesses made to multi level GPU
* page tables
* @pgd: Physical address of the page allocated for the top
* level page table of the context, this is used for
* MMU HW programming as the address translation will
* start from the top level page table.
* @group_id: A memory group ID to be passed to a platform-specific
* memory group manager.
* Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1).
* @kctx: If this set of MMU tables belongs to a context then
* this is a back-reference to the context, otherwise
* it is NULL.
* @scratch_mem: Scratch memory used for MMU operations, which are
* serialized by the @mmu_lock.
* @pgd_pages_list: List head to link all 16K/64K pages allocated for the PGDs of mmut.
* These pages will be used to allocate 4KB PGD pages for
* the GPU page table.
* Linked with &kbase_page_metadata.data.pt_mapped.pgd_link.
* @last_allocated_pgd_page: Pointer to PGD page from where the last sub page
* was allocated for mmut.
* @last_freed_pgd_page: Pointer to PGD page to which the last freed 4K sub page
* was returned for mmut.
* @num_free_pgd_sub_pages: The total number of free 4K PGD pages in the mmut.
*/
struct kbase_mmu_table {
struct mutex mmu_lock;
@ -332,7 +336,7 @@ struct kbase_mmu_table {
* @levels: Array of PGD pages, large enough to copy one PGD
* for each level of the MMU table.
*/
u64 levels[MIDGARD_MMU_BOTTOMLEVEL][PAGE_SIZE / sizeof(u64)];
u64 levels[MIDGARD_MMU_BOTTOMLEVEL][GPU_PAGE_SIZE / sizeof(u64)];
} teardown_pages;
/**
* @free_pgds: Scratch memory used for insertion, update and teardown
@ -341,11 +345,18 @@ struct kbase_mmu_table {
*/
struct {
/** @pgds: Array of pointers to PGDs to free. */
struct page *pgds[MAX_FREE_PGDS];
phys_addr_t pgds[MAX_FREE_PGDS];
/** @head_index: Index of first free element in the PGDs array. */
size_t head_index;
} free_pgds;
} scratch_mem;
#if GPU_PAGES_PER_CPU_PAGE > 1
struct list_head pgd_pages_list;
struct page *last_allocated_pgd_page;
struct page *last_freed_pgd_page;
u32 num_free_pgd_sub_pages;
#endif
};
#if MALI_USE_CSF
@ -371,14 +382,9 @@ static inline int kbase_as_has_page_fault(struct kbase_as *as, struct kbase_faul
*
* @used_pages: Tracks usage of OS shared memory. Updated when OS memory is
* allocated/freed.
* @ir_threshold: Fraction of the maximum size of an allocation that grows
* on GPU page fault that can be used before the driver
* switches to incremental rendering, in 1/256ths.
* 0 means disabled.
*/
struct kbasep_mem_device {
atomic_t used_pages;
atomic_t ir_threshold;
};
struct kbase_clk_rate_listener;
@ -483,9 +489,7 @@ struct kbase_pm_device_data {
#if MALI_USE_CSF
bool runtime_active;
#endif
#ifdef CONFIG_MALI_ARBITER_SUPPORT
atomic_t gpu_lost;
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
wait_queue_head_t zero_active_count_wait;
wait_queue_head_t resume_wait;
@ -501,10 +505,8 @@ struct kbase_pm_device_data {
void (*callback_power_runtime_term)(struct kbase_device *kbdev);
u32 dvfs_period;
struct kbase_pm_backend_data backend;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
struct kbase_arbiter_vm_state *arb_vm_state;
atomic_t gpu_users_waiting;
#endif /* CONFIG_MALI_ARBITER_SUPPORT */
struct kbase_clk_rate_trace_manager clk_rtm;
};
@ -947,7 +949,7 @@ struct kbase_mem_migrate {
* @ipa.last_sample_time: Records the time when counters, used for dynamic
* energy estimation, were last sampled.
* @previous_frequency: Previous frequency of GPU clock used for
* BASE_HW_ISSUE_GPU2017_1336 workaround, This clock is
* KBASE_HW_ISSUE_GPU2017_1336 workaround, This clock is
* restored when L2 is powered on.
* @job_fault_debug: Flag to control the dumping of debug data for job faults,
* set when the 'job_fault' debugfs file is opened.
@ -1069,7 +1071,8 @@ struct kbase_mem_migrate {
* KCPU queue. These structures may outlive kbase module
* itself. Therefore, in such a case, a warning should be
* be produced.
* @va_region_slab: kmem_cache (slab) for allocated kbase_va_region structures.
* @va_region_slab: kmem_cache (slab) for allocated @kbase_va_region structures.
* @page_metadata_slab: kmem_cache (slab) for allocated @kbase_page_metadata structures.
* @fence_signal_timeout_enabled: Global flag for whether fence signal timeout tracking
* is enabled.
* @pcm_prioritized_process_nb: Notifier block for the Priority Control Manager
@ -1134,8 +1137,8 @@ struct kbase_device {
struct kbase_gpu_props gpu_props;
unsigned long hw_issues_mask[(BASE_HW_ISSUE_END + BITS_PER_LONG - 1) / BITS_PER_LONG];
unsigned long hw_features_mask[(BASE_HW_FEATURE_END + BITS_PER_LONG - 1) / BITS_PER_LONG];
unsigned long hw_issues_mask[(KBASE_HW_ISSUE_END + BITS_PER_LONG - 1) / BITS_PER_LONG];
unsigned long hw_features_mask[(KBASE_HW_FEATURE_END + BITS_PER_LONG - 1) / BITS_PER_LONG];
struct {
atomic_t count;
@ -1151,6 +1154,12 @@ struct kbase_device {
*/
u8 pbha_propagate_bits;
/**
* @mma_wa_id: The PBHA ID to use for the PBHA OVERRIDE based workaround for MMA violation.
*
*/
u32 mma_wa_id;
#if MALI_USE_CSF
struct kbase_hwcnt_backend_csf_if hwcnt_backend_csf_if_fw;
#else
@ -1242,7 +1251,6 @@ struct kbase_device {
atomic_t job_fault_debug;
#endif /* !MALI_USE_CSF */
#if IS_ENABLED(CONFIG_DEBUG_FS)
struct dentry *mali_debugfs_directory;
struct dentry *debugfs_ctx_directory;
struct dentry *debugfs_instr_directory;
@ -1264,7 +1272,6 @@ struct kbase_device {
u32 reg_offset;
} regs_dump_debugfs_data;
#endif /* !MALI_CUSTOMER_RELEASE */
#endif /* CONFIG_DEBUG_FS */
atomic_t ctx_num;
@ -1355,9 +1362,7 @@ struct kbase_device {
} dummy_job_wa;
bool dummy_job_wa_loaded;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
struct kbase_arbiter_device arb;
#endif
/* Priority Control Manager device */
struct priority_control_manager_device *pcm_dev;
@ -1382,6 +1387,9 @@ struct kbase_device {
atomic_t live_fence_metadata;
#endif
struct kmem_cache *va_region_slab;
#if GPU_PAGES_PER_CPU_PAGE > 1
struct kmem_cache *page_metadata_slab;
#endif
#if IS_ENABLED(CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD)
/**
@ -2131,6 +2139,18 @@ static inline u64 kbase_get_lock_region_min_size_log2(struct kbase_gpu_props con
return 15; /* 32 kB */
}
/**
* kbase_has_arbiter - Check whether GPU has an arbiter.
*
* @kbdev: KBase device.
*
* Return: True if there is an arbiter, False otherwise.
*/
static inline bool kbase_has_arbiter(struct kbase_device *kbdev)
{
return (bool)kbdev->arb.arb_if;
}
/* Conversion helpers for setting up high resolution timers */
#define HR_TIMER_DELAY_MSEC(x) (ns_to_ktime(((u64)(x)) * 1000000U))
#define HR_TIMER_DELAY_NSEC(x) (ns_to_ktime(x))

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -218,7 +218,7 @@ static bool wa_blob_load_needed(struct kbase_device *kbdev)
if (of_machine_is_compatible("arm,juno"))
return false;
if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_TTRX_3485))
if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_3485))
return true;
return false;
@ -311,7 +311,7 @@ int kbase_dummy_job_wa_load(struct kbase_device *kbdev)
while (blob_offset) {
const struct wa_blob *blob;
size_t nr_pages;
u64 flags;
base_mem_alloc_flags flags;
u64 gpu_va;
struct kbase_va_region *va_region;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -39,9 +39,6 @@ static inline void validate_tracepoint_data(struct kbase_gpu_metrics_ctx *gpu_me
u64 start_time, u64 end_time, u64 total_active)
{
#if 0
WARN(total_active > NSEC_PER_SEC, "total_active %llu > 1 second for aid %u active_cnt %u",
total_active, gpu_metrics_ctx->aid, gpu_metrics_ctx->active_cnt);
WARN(start_time >= end_time, "start_time %llu >= end_time %llu for aid %u active_cnt %u",
start_time, end_time, gpu_metrics_ctx->aid, gpu_metrics_ctx->active_cnt);

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -437,7 +437,7 @@ int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev)
{
int err = 0;
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_L2_CONFIG)) {
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_L2_CONFIG)) {
struct kbasep_gpuprops_regdump *regdump = &PRIV_DATA_REGDUMP(kbdev);
/* Check for L2 cache size & hash overrides */
@ -699,7 +699,7 @@ static void kbase_populate_user_data(struct kbase_device *kbdev, struct gpu_prop
data->thread_props.max_thread_group_split = THREAD_MTGS_DEFAULT;
}
if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_THREAD_GROUP_SPLIT))
if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_THREAD_GROUP_SPLIT))
data->thread_props.max_thread_group_split = 0;
/* Raw Register Values */

View file

@ -178,6 +178,10 @@ int kbase_gpu_gwt_dump(struct kbase_context *kctx, union kbase_ioctl_cinstr_gwt_
__user void *user_addr = (__user void *)(uintptr_t)gwt_dump->in.addr_buffer;
__user void *user_sizes = (__user void *)(uintptr_t)gwt_dump->in.size_buffer;
/* We don't have any valid user space buffer to copy the write modified addresses. */
if (!gwt_dump->in.len || !gwt_dump->in.addr_buffer || !gwt_dump->in.size_buffer)
return -EINVAL;
kbase_gpu_vm_lock(kctx);
if (!kctx->gwt_enabled) {
@ -186,14 +190,6 @@ int kbase_gpu_gwt_dump(struct kbase_context *kctx, union kbase_ioctl_cinstr_gwt_
return -EPERM;
}
if (!gwt_dump->in.len || !gwt_dump->in.addr_buffer || !gwt_dump->in.size_buffer) {
kbase_gpu_vm_unlock(kctx);
/* We don't have any valid user space buffer to copy the
* write modified addresses.
*/
return -EINVAL;
}
if (list_empty(&kctx->gwt_snapshot_list) && !list_empty(&kctx->gwt_current_list)) {
list_replace_init(&kctx->gwt_current_list, &kctx->gwt_snapshot_list);
@ -227,14 +223,14 @@ int kbase_gpu_gwt_dump(struct kbase_context *kctx, union kbase_ioctl_cinstr_gwt_
if (count) {
err = copy_to_user((user_addr + (ubuf_count * sizeof(u64))),
(void *)addr_buffer, count * sizeof(u64));
(void *)addr_buffer, size_mul(count, sizeof(u64)));
if (err) {
dev_err(kctx->kbdev->dev, "Copy to user failure\n");
kbase_gpu_vm_unlock(kctx);
return err;
}
err = copy_to_user((user_sizes + (ubuf_count * sizeof(u64))),
(void *)num_page_buffer, count * sizeof(u64));
(void *)num_page_buffer, size_mul(count, sizeof(u64)));
if (err) {
dev_err(kctx->kbdev->dev, "Copy to user failure\n");
kbase_gpu_vm_unlock(kctx);

View file

@ -23,8 +23,8 @@
* Run-time work-arounds helpers
*/
#include <mali_base_hwconfig_features.h>
#include <mali_base_hwconfig_issues.h>
#include <mali_kbase_hwconfig_features.h>
#include <mali_kbase_hwconfig_issues.h>
#include <hw_access/mali_kbase_hw_access_regmap.h>
#include "mali_kbase.h"
#include "mali_kbase_hw.h"
@ -92,7 +92,7 @@ void kbase_hw_set_features_mask(struct kbase_device *kbdev)
break;
}
for (; *features != BASE_HW_FEATURE_END; features++)
for (; *features != KBASE_HW_FEATURE_END; features++)
set_bit(*features, &kbdev->hw_features_mask[0]);
#if defined(CONFIG_MALI_VECTOR_DUMP)
@ -103,8 +103,8 @@ void kbase_hw_set_features_mask(struct kbase_device *kbdev)
* in the implementation of flush reduction optimization due to
* unclear or ambiguous ARCH spec.
*/
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_CLEAN_ONLY_SAFE))
clear_bit(BASE_HW_FEATURE_FLUSH_REDUCTION, &kbdev->hw_features_mask[0]);
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE))
clear_bit(KBASE_HW_FEATURE_FLUSH_REDUCTION, &kbdev->hw_features_mask[0]);
#endif
}
@ -113,7 +113,7 @@ void kbase_hw_set_features_mask(struct kbase_device *kbdev)
* @kbdev: Device pointer
*
* Return: pointer to an array of hardware issues, terminated by
* BASE_HW_ISSUE_END.
* KBASE_HW_ISSUE_END.
*
* In debugging versions of the driver, unknown versions of a known GPU will
* be treated as the most recent known version not later than the actual
@ -424,7 +424,7 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev)
gpu_id->product_major, gpu_id->arch_major, gpu_id->arch_minor, gpu_id->arch_rev,
gpu_id->version_major, gpu_id->version_minor, gpu_id->version_status);
for (; *issues != BASE_HW_ISSUE_END; issues++)
for (; *issues != KBASE_HW_ISSUE_END; issues++)
set_bit(*issues, &kbdev->hw_issues_mask[0]);
return 0;

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2012-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -23,8 +23,8 @@
* DOC: Run-time work-arounds helpers
*/
#ifndef _KBASE_HW_H_
#define _KBASE_HW_H_
#ifndef _MALI_KBASE_HW_H_
#define _MALI_KBASE_HW_H_
#include "mali_kbase_defs.h"
@ -47,7 +47,7 @@
* @kbdev: Device pointer
*/
#define kbase_hw_has_l2_slice_hash_feature(kbdev) \
test_bit(BASE_HW_FEATURE_L2_SLICE_HASH, &(kbdev)->hw_features_mask[0])
test_bit(KBASE_HW_FEATURE_L2_SLICE_HASH, &(kbdev)->hw_features_mask[0])
/**
* kbase_hw_set_issues_mask - Set the hardware issues mask based on the GPU ID
@ -73,4 +73,4 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev);
*/
void kbase_hw_set_features_mask(struct kbase_device *kbdev);
#endif /* _KBASE_HW_H_ */
#endif /* _MALI_KBASE_HW_H_ */

View file

@ -0,0 +1,158 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#ifndef _KBASE_HWCONFIG_FEATURES_H_
#define _KBASE_HWCONFIG_FEATURES_H_
#include <linux/version_compat_defs.h>
enum base_hw_feature {
KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_TLS_HASHING,
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT,
KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE,
KBASE_HW_FEATURE_L2_CONFIG,
KBASE_HW_FEATURE_L2_SLICE_HASH,
KBASE_HW_FEATURE_GPU_SLEEP,
KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
KBASE_HW_FEATURE_CORE_FEATURES,
KBASE_HW_FEATURE_PBHA_HWU,
KBASE_HW_FEATURE_LARGE_PAGE_ALLOC,
KBASE_HW_FEATURE_THREAD_TLS_ALLOC,
KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_generic[] = {
KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tMIx[] = {
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT, KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tHEx[] = {
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT, KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tSIx[] = {
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT, KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tDVx[] = {
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT, KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tNOx[] = {
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT, KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE, KBASE_HW_FEATURE_TLS_HASHING,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tGOx[] = {
KBASE_HW_FEATURE_THREAD_GROUP_SPLIT, KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE, KBASE_HW_FEATURE_TLS_HASHING,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE, KBASE_HW_FEATURE_CORE_FEATURES,
KBASE_HW_FEATURE_THREAD_TLS_ALLOC, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tTRx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tNAx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tBEx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE,
KBASE_HW_FEATURE_L2_CONFIG,
KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tBAx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_IDVS_GROUP_SIZE,
KBASE_HW_FEATURE_L2_CONFIG,
KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER,
KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tODx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_L2_CONFIG, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tGRx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_L2_CONFIG, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_CORE_FEATURES, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tVAx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_L2_CONFIG, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_CORE_FEATURES, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tTUx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_L2_CONFIG, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_L2_SLICE_HASH, KBASE_HW_FEATURE_GPU_SLEEP,
KBASE_HW_FEATURE_CORE_FEATURES, KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tTIx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION,
KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_L2_CONFIG,
KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_L2_SLICE_HASH,
KBASE_HW_FEATURE_GPU_SLEEP,
KBASE_HW_FEATURE_CORE_FEATURES,
KBASE_HW_FEATURE_PBHA_HWU,
KBASE_HW_FEATURE_END
};
__maybe_unused static const enum base_hw_feature base_hw_features_tKRx[] = {
KBASE_HW_FEATURE_FLUSH_REDUCTION, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE,
KBASE_HW_FEATURE_L2_CONFIG, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE,
KBASE_HW_FEATURE_L2_SLICE_HASH, KBASE_HW_FEATURE_GPU_SLEEP,
KBASE_HW_FEATURE_CORE_FEATURES, KBASE_HW_FEATURE_PBHA_HWU,
KBASE_HW_FEATURE_LARGE_PAGE_ALLOC, KBASE_HW_FEATURE_END
};
#endif /* _KBASE_HWCONFIG_FEATURES_H_ */

View file

@ -0,0 +1,609 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#ifndef _KBASE_HWCONFIG_ISSUES_H_
#define _KBASE_HWCONFIG_ISSUES_H_
#include <linux/version_compat_defs.h>
enum base_hw_issue {
KBASE_HW_ISSUE_5736,
KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_10682,
KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_T76X_3953,
KBASE_HW_ISSUE_TMIX_7891,
KBASE_HW_ISSUE_TMIX_7940,
KBASE_HW_ISSUE_TMIX_8042,
KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TMIX_8138,
KBASE_HW_ISSUE_TMIX_8206,
KBASE_HW_ISSUE_TMIX_8343,
KBASE_HW_ISSUE_TMIX_8463,
KBASE_HW_ISSUE_TMIX_8456,
KBASE_HW_ISSUE_TSIX_1116,
KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TMIX_8438,
KBASE_HW_ISSUE_TNOX_1194,
KBASE_HW_ISSUE_TGOX_R1_1234,
KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TSIX_1792,
KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_3076,
KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TTRX_3485,
KBASE_HW_ISSUE_GPU2019_3212,
KBASE_HW_ISSUE_TURSEHW_1997,
KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_TURSEHW_2716,
KBASE_HW_ISSUE_GPU2019_3901,
KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_TITANHW_2679,
KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922,
KBASE_HW_ISSUE_TITANHW_2952,
KBASE_HW_ISSUE_KRAKEHW_2151,
KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2269,
KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_generic[] = { KBASE_HW_ISSUE_END };
__maybe_unused static const enum base_hw_issue base_hw_issues_tMIx_r0p0_05dev0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_T76X_3953, KBASE_HW_ISSUE_TMIX_7891, KBASE_HW_ISSUE_TMIX_8042,
KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TMIX_8138, KBASE_HW_ISSUE_TMIX_8206,
KBASE_HW_ISSUE_TMIX_8343, KBASE_HW_ISSUE_TMIX_8463, KBASE_HW_ISSUE_TMIX_8456,
KBASE_HW_ISSUE_TMIX_8438, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tMIx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_TMIX_7891, KBASE_HW_ISSUE_TMIX_7940, KBASE_HW_ISSUE_TMIX_8042,
KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TMIX_8138, KBASE_HW_ISSUE_TMIX_8206,
KBASE_HW_ISSUE_TMIX_8343, KBASE_HW_ISSUE_TMIX_8463, KBASE_HW_ISSUE_TMIX_8456,
KBASE_HW_ISSUE_TMIX_8438, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tMIx_r0p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_TMIX_7891, KBASE_HW_ISSUE_TMIX_7940, KBASE_HW_ISSUE_TMIX_8042,
KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TMIX_8138, KBASE_HW_ISSUE_TMIX_8206,
KBASE_HW_ISSUE_TMIX_8343, KBASE_HW_ISSUE_TMIX_8463, KBASE_HW_ISSUE_TMIX_8456,
KBASE_HW_ISSUE_TMIX_8438, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tMIx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_7891,
KBASE_HW_ISSUE_TMIX_7940, KBASE_HW_ISSUE_TMIX_8042, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TMIX_8138, KBASE_HW_ISSUE_TMIX_8206, KBASE_HW_ISSUE_TMIX_8343,
KBASE_HW_ISSUE_TMIX_8456, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_TMIX_7891, KBASE_HW_ISSUE_TMIX_8042, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_TMIX_7891, KBASE_HW_ISSUE_TMIX_8042, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p2[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_11054,
KBASE_HW_ISSUE_TMIX_7891, KBASE_HW_ISSUE_TMIX_8042, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tHEx_r0p3[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_10682, KBASE_HW_ISSUE_TMIX_7891,
KBASE_HW_ISSUE_TMIX_8042, KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tHEx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_7891,
KBASE_HW_ISSUE_TMIX_8042, KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_11054, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TSIX_1792,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r0p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_11054, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TSIX_1792,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r1p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_11054, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tSIx_r1p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TSIX_1116,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tSIx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tDVx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TSIX_1116,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tDVx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tNOx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TNOX_1194, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tNOx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TSIX_1116,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tGOx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TNOX_1194, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tGOx_r1p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TMIX_8133,
KBASE_HW_ISSUE_TSIX_1116, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TGOX_R1_1234, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_GPU2017_1336, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tGOx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_TMIX_8133, KBASE_HW_ISSUE_TSIX_1116,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTRx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_3076, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TTRX_3485,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTRx_r0p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_3076, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TTRX_3485,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTRx_r0p2[] = {
KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_3076,
KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tTRx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470, KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tNAx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_3076, KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TTRX_3485,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tNAx_r0p1[] = {
KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_3076,
KBASE_HW_ISSUE_TTRX_921,
KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_GPU2017_1336,
KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tNAx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470, KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TTRX_3485,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r0p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r1p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBEx_r1p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tBEx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_lBEx_r1p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TTRX_3485,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_lBEx_r1p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBAx_r0p0[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBAx_r0p1[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tBAx_r0p2[] = {
KBASE_HW_ISSUE_9435, KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TTRX_2968_TTRX_3162,
KBASE_HW_ISSUE_TTRX_921, KBASE_HW_ISSUE_TTRX_3414,
KBASE_HW_ISSUE_TTRX_3083, KBASE_HW_ISSUE_TTRX_3470,
KBASE_HW_ISSUE_TTRX_3464, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tBAx[] = {
KBASE_HW_ISSUE_5736, KBASE_HW_ISSUE_9435,
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TTRX_3414, KBASE_HW_ISSUE_TTRX_3083,
KBASE_HW_ISSUE_TTRX_3470, KBASE_HW_ISSUE_TTRX_3464,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tODx_r0p0[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_GPU2019_3212, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tODx[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_GPU2019_3212, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tGRx_r0p0[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tGRx[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tVAx_r0p0[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tVAx_r0p1[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tVAx[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r0p0[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TURSEHW_1997,
KBASE_HW_ISSUE_GPU2019_3878, KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901,
KBASE_HW_ISSUE_GPU2021PRO_290, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r0p1[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TURSEHW_1997,
KBASE_HW_ISSUE_GPU2019_3878, KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901,
KBASE_HW_ISSUE_GPU2021PRO_290, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2922, KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_TURSEHW_2934, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tTUx[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p0[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p1[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p2[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTUx_r1p3[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_GPU2019_3878,
KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2019_3901, KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tTIx[] = {
KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TURSEHW_2716,
KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_TITANHW_2679,
KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922,
KBASE_HW_ISSUE_TITANHW_2952,
KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTIx_r0p0[] = {
KBASE_HW_ISSUE_TSIX_2033,
KBASE_HW_ISSUE_TTRX_1337,
KBASE_HW_ISSUE_TURSEHW_2716,
KBASE_HW_ISSUE_GPU2021PRO_290,
KBASE_HW_ISSUE_TITANHW_2710,
KBASE_HW_ISSUE_TITANHW_2679,
KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_TITANHW_2922,
KBASE_HW_ISSUE_TITANHW_2952,
KBASE_HW_ISSUE_TITANHW_2938,
KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tTIx_r0p1[] = {
KBASE_HW_ISSUE_TSIX_2033, KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TURSEHW_2716,
KBASE_HW_ISSUE_GPU2021PRO_290, KBASE_HW_ISSUE_TITANHW_2710, KBASE_HW_ISSUE_TITANHW_2679,
KBASE_HW_ISSUE_GPU2022PRO_148, KBASE_HW_ISSUE_TITANHW_2938, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tKRx_r0p0[] = {
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_KRAKEHW_2151, KBASE_HW_ISSUE_KRAKEHW_2269, KBASE_HW_ISSUE_TITANHW_2922,
KBASE_HW_ISSUE_TURSEHW_2934, KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_tKRx_r0p1[] = {
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_KRAKEHW_2269, KBASE_HW_ISSUE_TURSEHW_2934, KBASE_HW_ISSUE_KRAKEHW_2321,
KBASE_HW_ISSUE_END
};
__maybe_unused static const enum base_hw_issue base_hw_issues_model_tKRx[] = {
KBASE_HW_ISSUE_TTRX_1337, KBASE_HW_ISSUE_TURSEHW_2716, KBASE_HW_ISSUE_GPU2022PRO_148,
KBASE_HW_ISSUE_KRAKEHW_2151, KBASE_HW_ISSUE_KRAKEHW_2269, KBASE_HW_ISSUE_TURSEHW_2934,
KBASE_HW_ISSUE_KRAKEHW_2321, KBASE_HW_ISSUE_END
};
#endif /* _KBASE_HWCONFIG_ISSUES_H_ */

View file

@ -0,0 +1,542 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#ifndef _KBASE_IOCTL_HELPERS_H_
#define _KBASE_IOCTL_HELPERS_H_
#include <uapi/gpu/arm/bifrost/mali_kbase_ioctl.h>
/* Macro for IOCTLs that don't have IOCTL struct */
#define KBASE_HANDLE_IOCTL(cmd, function, arg) \
do { \
int ret; \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
ret = function(arg); \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Macro for IOCTLs that have input IOCTL struct */
#define KBASE_HANDLE_IOCTL_IN(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_WRITE); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
err = copy_from_user(&param, uarg, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
err = check_padding_##cmd(&param); \
if (unlikely(err)) \
return -EINVAL; \
ret = function(arg, &param); \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Macro for IOCTLs that have output IOCTL struct */
#define KBASE_HANDLE_IOCTL_OUT(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_READ); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
memset(&param, 0, sizeof(param)); \
ret = function(arg, &param); \
err = copy_to_user(uarg, &param, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Macro for IOCTLs that have input and output IOCTL struct */
#define KBASE_HANDLE_IOCTL_INOUT(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != (_IOC_WRITE | _IOC_READ)); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
err = copy_from_user(&param, uarg, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
err = check_padding_##cmd(&param); \
if (unlikely(err)) \
return -EINVAL; \
ret = function(arg, &param); \
err = copy_to_user(uarg, &param, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Inline functions to check padding bytes in the input IOCTL struct.
* Return 0 if all padding bytes are zero, non-zero otherwise.
*/
static inline int check_padding_KBASE_IOCTL_VERSION_CHECK(struct kbase_ioctl_version_check *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_VERSION_CHECK_RESERVED(struct kbase_ioctl_version_check *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_SET_FLAGS(struct kbase_ioctl_set_flags *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_GET_GPUPROPS(struct kbase_ioctl_get_gpuprops *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_ALLOC(union kbase_ioctl_mem_alloc *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_QUERY(union kbase_ioctl_mem_query *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_FREE(struct kbase_ioctl_mem_free *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_HWCNT_READER_SETUP(struct kbase_ioctl_hwcnt_reader_setup *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_HWCNT_SET(struct kbase_ioctl_hwcnt_values *p)
{
return p->padding;
}
static inline int check_padding_KBASE_IOCTL_GET_DDK_VERSION(struct kbase_ioctl_get_ddk_version *p)
{
return p->padding;
}
static inline int check_padding_KBASE_IOCTL_MEM_JIT_INIT(struct kbase_ioctl_mem_jit_init *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_SYNC(struct kbase_ioctl_mem_sync *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_MEM_FIND_CPU_OFFSET(union kbase_ioctl_mem_find_cpu_offset *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_TLSTREAM_ACQUIRE(struct kbase_ioctl_tlstream_acquire *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_COMMIT(struct kbase_ioctl_mem_commit *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_ALIAS(union kbase_ioctl_mem_alias *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_IMPORT(union kbase_ioctl_mem_import *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_FLAGS_CHANGE(struct kbase_ioctl_mem_flags_change *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_STREAM_CREATE(struct kbase_ioctl_stream_create *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_FENCE_VALIDATE(struct kbase_ioctl_fence_validate *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_PROFILE_ADD(struct kbase_ioctl_mem_profile_add *p)
{
return p->padding;
}
static inline int
check_padding_KBASE_IOCTL_STICKY_RESOURCE_MAP(struct kbase_ioctl_sticky_resource_map *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_STICKY_RESOURCE_UNMAP(struct kbase_ioctl_sticky_resource_unmap *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_FIND_GPU_START_AND_OFFSET(
union kbase_ioctl_mem_find_gpu_start_and_offset *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_CINSTR_GWT_DUMP(union kbase_ioctl_cinstr_gwt_dump *p)
{
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
p->in.padding = 0;
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_EXEC_INIT(struct kbase_ioctl_mem_exec_init *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_GET_CPU_GPU_TIMEINFO(union kbase_ioctl_get_cpu_gpu_timeinfo *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.paddings); i++) {
if (p->in.paddings[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CONTEXT_PRIORITY_CHECK(struct kbase_ioctl_context_priority_check *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_SET_LIMITED_CORE_COUNT(struct kbase_ioctl_set_limited_core_count *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KINSTR_PRFCNT_ENUM_INFO(struct kbase_ioctl_kinstr_prfcnt_enum_info *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KINSTR_PRFCNT_SETUP(union kbase_ioctl_kinstr_prfcnt_setup *p)
{
return 0;
}
#if MALI_UNIT_TEST
#endif /* MALI_UNIT_TEST */
#if MALI_USE_CSF
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_REGISTER(struct kbase_ioctl_cs_queue_register *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_QUEUE_KICK(struct kbase_ioctl_cs_queue_kick *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_QUEUE_BIND(union kbase_ioctl_cs_queue_bind *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++)
p->in.padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_REGISTER_EX(struct kbase_ioctl_cs_queue_register_ex *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
for (i = 0; i < ARRAY_SIZE(p->ex_padding); i++) {
if (p->ex_padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_TERMINATE(struct kbase_ioctl_cs_queue_terminate *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_CREATE_1_6(union kbase_ioctl_cs_queue_group_create_1_6 *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_CREATE_1_18(
union kbase_ioctl_cs_queue_group_create_1_18 *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_CREATE(union kbase_ioctl_cs_queue_group_create *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_TERMINATE(struct kbase_ioctl_cs_queue_group_term *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KCPU_QUEUE_DELETE(struct kbase_ioctl_kcpu_queue_delete *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KCPU_QUEUE_ENQUEUE(struct kbase_ioctl_kcpu_queue_enqueue *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_TILER_HEAP_INIT(union kbase_ioctl_cs_tiler_heap_init *p)
{
return p->in.padding;
}
static inline int
check_padding_KBASE_IOCTL_CS_TILER_HEAP_INIT_1_13(union kbase_ioctl_cs_tiler_heap_init_1_13 *p)
{
return p->in.padding;
}
static inline int
check_padding_KBASE_IOCTL_CS_TILER_HEAP_TERM(struct kbase_ioctl_cs_tiler_heap_term *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_GET_GLB_IFACE(union kbase_ioctl_cs_get_glb_iface *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_CPU_QUEUE_DUMP(struct kbase_ioctl_cs_cpu_queue_info *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_ALLOC_EX(union kbase_ioctl_mem_alloc_ex *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.extra); i++) {
if (p->in.extra[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_READ_USER_PAGE(union kbase_ioctl_read_user_page *p)
{
return p->in.padding;
}
static inline int
check_padding_KBASE_IOCTL_QUEUE_GROUP_CLEAR_FAULTS(struct kbase_ioctl_queue_group_clear_faults *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
#else /* MALI_USE_CSF */
static inline int check_padding_KBASE_IOCTL_JOB_SUBMIT(struct kbase_ioctl_job_submit *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_SOFT_EVENT_UPDATE(struct kbase_ioctl_soft_event_update *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_KINSTR_JM_FD(union kbase_kinstr_jm_fd *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
#endif /* !MALI_USE_CSF */
#endif /* _KBASE_IOCTL_HELPERS_H_ */

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -39,9 +39,6 @@
#include <mali_kbase_hwaccess_jm.h>
#include <tl/mali_kbase_tracepoints.h>
#include <mali_linux_trace.h>
#include <mali_kbase_cs_experimental.h>
#include <mali_kbase_caps.h>
/* Return whether katom will run on the GPU or not. Currently only soft jobs and
@ -209,7 +206,7 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom,
}
if (copy_from_user(input_extres, get_compat_pointer(katom->kctx, user_atom->extres_list),
sizeof(*input_extres) * katom->nr_extres) != 0) {
size_mul(sizeof(*input_extres), katom->nr_extres)) != 0) {
err = -EINVAL;
goto failed_input_copy;
}
@ -697,7 +694,6 @@ static void jd_trace_atom_submit(struct kbase_context *const kctx,
static bool jd_submit_atom(struct kbase_context *const kctx,
const struct base_jd_atom *const user_atom,
const struct base_jd_fragment *const user_jc_incr,
struct kbase_jd_atom *const katom)
{
struct kbase_device *kbdev = kctx->kbdev;
@ -755,8 +751,6 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
}
#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */
katom->renderpass_id = user_atom->renderpass_id;
/* Implicitly sets katom->protected_state.enter as well. */
katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK;
@ -875,20 +869,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx,
/* Create a new atom. */
jd_trace_atom_submit(kctx, katom, &katom->sched_priority);
#if !MALI_INCREMENTAL_RENDERING_JM
/* Reject atoms for incremental rendering if not supported */
if (katom->core_req & (BASE_JD_REQ_START_RENDERPASS | BASE_JD_REQ_END_RENDERPASS)) {
dev_err(kctx->kbdev->dev, "Rejecting atom with unsupported core_req 0x%x\n",
katom->core_req);
katom->event_code = BASE_JD_EVENT_JOB_INVALID;
return kbase_jd_done_nolock(katom, true);
}
#endif /* !MALI_INCREMENTAL_RENDERING_JM */
if (katom->core_req & BASE_JD_REQ_END_RENDERPASS) {
WARN_ON(katom->jc != 0);
katom->jc_fragment = *user_jc_incr;
} else if (!katom->jc && (katom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) {
if (!katom->jc && (katom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) {
/* Reject atoms with job chain = NULL, as these cause issues
* with soft-stop
*/
@ -1018,8 +999,7 @@ int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_a
struct kbase_device *kbdev;
u32 latest_flush;
bool jd_atom_is_v2 = (stride == sizeof(struct base_jd_atom_v2) ||
stride == offsetof(struct base_jd_atom_v2, renderpass_id));
bool jd_atom_is_v2 = (stride == sizeof(struct base_jd_atom_v2));
CSTD_UNUSED(uk6_atom);
@ -1035,10 +1015,7 @@ int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_a
return -EINVAL;
}
if (stride != offsetof(struct base_jd_atom_v2, renderpass_id) &&
stride != sizeof(struct base_jd_atom_v2) &&
stride != offsetof(struct base_jd_atom, renderpass_id) &&
stride != sizeof(struct base_jd_atom)) {
if (stride != sizeof(struct base_jd_atom_v2) && stride != sizeof(struct base_jd_atom)) {
dev_err(kbdev->dev,
"Stride %u passed to job_submit isn't supported by the kernel\n", stride);
return -EINVAL;
@ -1057,7 +1034,6 @@ int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_a
struct base_jd_atom user_atom = {
.seq_nr = 0,
};
struct base_jd_fragment user_jc_incr;
struct kbase_jd_atom *katom;
if (unlikely(jd_atom_is_v2)) {
@ -1082,44 +1058,6 @@ int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_a
}
}
if (stride == offsetof(struct base_jd_atom_v2, renderpass_id)) {
dev_dbg(kbdev->dev, "No renderpass ID: use 0\n");
user_atom.renderpass_id = 0;
} else {
/* Ensure all padding bytes are 0 for potential future
* extension
*/
size_t j;
dev_dbg(kbdev->dev, "Renderpass ID is %d\n", user_atom.renderpass_id);
for (j = 0; j < sizeof(user_atom.padding); j++) {
if (user_atom.padding[j]) {
dev_err(kbdev->dev, "Bad padding byte %zu: %d\n", j,
user_atom.padding[j]);
err = -EINVAL;
break;
}
}
if (err)
break;
}
/* In this case 'jc' is the CPU address of a struct
* instead of a GPU address of a job chain.
*/
if (user_atom.core_req & BASE_JD_REQ_END_RENDERPASS) {
if (copy_from_user(&user_jc_incr, u64_to_user_ptr(user_atom.jc),
sizeof(user_jc_incr))) {
dev_err(kbdev->dev,
"Invalid jc address 0x%llx passed to job_submit\n",
user_atom.jc);
err = -EFAULT;
break;
}
dev_dbg(kbdev->dev, "Copied IR jobchain addresses\n");
user_atom.jc = 0;
}
user_addr = (void __user *)((uintptr_t)user_addr + stride);
mutex_lock(&jctx->lock);
@ -1172,8 +1110,7 @@ int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_a
mutex_lock(&jctx->lock);
}
KBASE_TLSTREAM_TL_JD_SUBMIT_ATOM_START(kbdev, katom);
need_to_try_schedule_context |=
jd_submit_atom(kctx, &user_atom, &user_jc_incr, katom);
need_to_try_schedule_context |= jd_submit_atom(kctx, &user_atom, katom);
KBASE_TLSTREAM_TL_JD_SUBMIT_ATOM_END(kbdev, katom);
/* Register a completed job as a disjoint event when the GPU is in a disjoint state
* (ie. being reset).
@ -1579,9 +1516,6 @@ int kbase_jd_init(struct kbase_context *kctx)
#endif
}
for (i = 0; i < BASE_JD_RP_COUNT; i++)
kctx->jctx.renderpasses[i].state = KBASE_JD_RP_COMPLETE;
mutex_init(&kctx->jctx.lock);
init_waitqueue_head(&kctx->jctx.zero_jobs_wait);

View file

@ -333,19 +333,6 @@ static void jsctx_queue_foreach_prio(struct kbase_context *kctx, unsigned int js
rb_erase(node, &queue->runnable_tree);
callback(kctx->kbdev, entry);
/* Runnable end-of-renderpass atoms can also be in the linked
* list of atoms blocked on cross-slot dependencies. Remove them
* to avoid calling the callback twice.
*/
if (entry->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST) {
WARN_ON(!(entry->core_req & BASE_JD_REQ_END_RENDERPASS));
dev_dbg(kctx->kbdev->dev, "Del runnable atom %pK from X_DEP list\n",
(void *)entry);
list_del(&entry->queue);
entry->atom_flags &= ~KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST;
}
}
while (!list_empty(&queue->x_dep_head)) {
@ -1230,7 +1217,7 @@ static bool kbase_js_ctx_pullable(struct kbase_context *kctx, unsigned int js, b
dev_dbg(kbdev->dev, "JS: Atom %pK is blocked in js_ctx_pullable\n", (void *)katom);
return false; /* next atom blocked */
}
if (kbase_js_atom_blocked_on_x_dep(katom)) {
if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) {
if (katom->x_pre_dep->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB ||
katom->x_pre_dep->will_fail_event_code) {
dev_dbg(kbdev->dev,
@ -1371,9 +1358,6 @@ static bool kbase_js_dep_validate(struct kbase_context *kctx, struct kbase_jd_at
(dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED)) {
katom->atom_flags |= KBASE_KATOM_FLAG_X_DEP_BLOCKED;
dev_dbg(kbdev->dev, "Set X_DEP flag on atom %pK\n",
(void *)katom);
katom->x_pre_dep = dep_atom;
dep_atom->x_post_dep = katom;
if (kbase_jd_katom_dep_type(&katom->dep[i]) ==
@ -1447,110 +1431,12 @@ void kbase_js_update_ctx_priority(struct kbase_context *kctx)
}
KBASE_EXPORT_TEST_API(kbase_js_update_ctx_priority);
/**
* js_add_start_rp() - Add an atom that starts a renderpass to the job scheduler
* @start_katom: Pointer to the atom to be added.
* Return: 0 if successful or a negative value on failure.
*/
static int js_add_start_rp(struct kbase_jd_atom *const start_katom)
{
struct kbase_context *const kctx = start_katom->kctx;
struct kbase_jd_renderpass *rp;
struct kbase_device *const kbdev = kctx->kbdev;
unsigned long flags;
lockdep_assert_held(&kctx->jctx.lock);
if (WARN_ON(!(start_katom->core_req & BASE_JD_REQ_START_RENDERPASS)))
return -EINVAL;
if (start_katom->core_req & BASE_JD_REQ_END_RENDERPASS)
return -EINVAL;
compiletime_assert((1ull << (sizeof(start_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[start_katom->renderpass_id];
if (rp->state != KBASE_JD_RP_COMPLETE)
return -EINVAL;
dev_dbg(kctx->kbdev->dev, "JS add start atom %pK of RP %d\n", (void *)start_katom,
start_katom->renderpass_id);
/* The following members are read when updating the job slot
* ringbuffer/fifo therefore they require additional locking.
*/
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
rp->state = KBASE_JD_RP_START;
rp->start_katom = start_katom;
rp->end_katom = NULL;
INIT_LIST_HEAD(&rp->oom_reg_list);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
return 0;
}
/**
* js_add_end_rp() - Add an atom that ends a renderpass to the job scheduler
* @end_katom: Pointer to the atom to be added.
* Return: 0 if successful or a negative value on failure.
*/
static int js_add_end_rp(struct kbase_jd_atom *const end_katom)
{
struct kbase_context *const kctx = end_katom->kctx;
struct kbase_jd_renderpass *rp;
struct kbase_device *const kbdev = kctx->kbdev;
lockdep_assert_held(&kctx->jctx.lock);
if (WARN_ON(!(end_katom->core_req & BASE_JD_REQ_END_RENDERPASS)))
return -EINVAL;
if (end_katom->core_req & BASE_JD_REQ_START_RENDERPASS)
return -EINVAL;
compiletime_assert((1ull << (sizeof(end_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[end_katom->renderpass_id];
dev_dbg(kbdev->dev, "JS add end atom %pK in state %d of RP %d\n", (void *)end_katom,
(int)rp->state, end_katom->renderpass_id);
if (rp->state == KBASE_JD_RP_COMPLETE)
return -EINVAL;
if (rp->end_katom == NULL) {
/* We can't be in a retry state until the fragment job chain
* has completed.
*/
unsigned long flags;
WARN_ON(rp->state == KBASE_JD_RP_RETRY);
WARN_ON(rp->state == KBASE_JD_RP_RETRY_PEND_OOM);
WARN_ON(rp->state == KBASE_JD_RP_RETRY_OOM);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
rp->end_katom = end_katom;
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
} else
WARN_ON(rp->end_katom != end_katom);
return 0;
}
bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom)
{
unsigned long flags;
struct kbasep_js_kctx_info *js_kctx_info;
struct kbase_device *kbdev;
struct kbasep_js_device_data *js_devdata;
int err = 0;
bool enqueue_required = false;
bool timer_sync = false;
@ -1566,17 +1452,6 @@ bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom)
mutex_lock(&js_devdata->queue_mutex);
mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
if (atom->core_req & BASE_JD_REQ_START_RENDERPASS)
err = js_add_start_rp(atom);
else if (atom->core_req & BASE_JD_REQ_END_RENDERPASS)
err = js_add_end_rp(atom);
if (err < 0) {
atom->event_code = BASE_JD_EVENT_JOB_INVALID;
atom->status = KBASE_JD_ATOM_STATE_COMPLETED;
goto out_unlock;
}
/*
* Begin Runpool transaction
*/
@ -1860,10 +1735,7 @@ kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_
kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, katom_retained_state);
if (new_ref_count == 2 && kbase_ctx_flag(kctx, KCTX_PRIVILEGED) &&
#ifdef CONFIG_MALI_ARBITER_SUPPORT
!kbase_pm_is_gpu_lost(kbdev) &&
#endif
!kbase_pm_is_suspending(kbdev)) {
!kbase_pm_is_gpu_lost(kbdev) && !kbase_pm_is_suspending(kbdev)) {
/* Context is kept scheduled into an address space even when
* there are no jobs, in this case we have to handle the
* situation where all jobs have been evicted from the GPU and
@ -1880,10 +1752,7 @@ kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_
* which was previously acquired by kbasep_js_schedule_ctx().
*/
if (new_ref_count == 1 && (!kbasep_js_is_submit_allowed(js_devdata, kctx) ||
#ifdef CONFIG_MALI_ARBITER_SUPPORT
kbase_pm_is_gpu_lost(kbdev) ||
#endif
kbase_pm_is_suspending(kbdev))) {
kbase_pm_is_gpu_lost(kbdev) || kbase_pm_is_suspending(kbdev))) {
int num_slots = kbdev->gpu_props.num_job_slots;
unsigned int slot;
@ -2189,11 +2058,7 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev, struct kbase_cont
* of it being called strictly after the suspend flag is set, and will
* wait for this lock to drop)
*/
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbase_pm_is_suspending(kbdev) || kbase_pm_is_gpu_lost(kbdev)) {
#else
if (kbase_pm_is_suspending(kbdev)) {
#endif
/* Cause it to leave at some later point */
bool retained;
CSTD_UNUSED(retained);
@ -2267,7 +2132,6 @@ void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_
js_devdata = &kbdev->js_data;
js_kctx_info = &kctx->jctx.sched_info;
#ifdef CONFIG_MALI_ARBITER_SUPPORT
/* This should only happen in response to a system call
* from a user-space thread.
* In a non-arbitrated environment this can never happen
@ -2279,18 +2143,10 @@ void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_
* the wait event for KCTX_SCHEDULED, since no context
* can be scheduled until we have the GPU again.
*/
if (kbdev->arb.arb_if == NULL)
if (!kbase_has_arbiter(kbdev)) {
if (WARN_ON(kbase_pm_is_suspending(kbdev)))
return;
#else
/* This should only happen in response to a system call
* from a user-space thread.
* In a non-arbitrated environment this can never happen
* whilst suspending.
*/
if (WARN_ON(kbase_pm_is_suspending(kbdev)))
return;
#endif
}
mutex_lock(&js_devdata->queue_mutex);
mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
@ -2416,63 +2272,63 @@ void kbasep_js_resume(struct kbase_device *kbdev)
struct kbase_context *kctx, *n;
unsigned long flags;
#ifndef CONFIG_MALI_ARBITER_SUPPORT
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
if (kbase_has_arbiter(kbdev)) {
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
list_for_each_entry_safe(kctx, n,
&kbdev->js_data.ctx_list_unpullable[js][prio],
jctx.sched_info.ctx.ctx_list_entry[js]) {
struct kbasep_js_kctx_info *js_kctx_info;
list_for_each_entry_safe(
kctx, n, &kbdev->js_data.ctx_list_unpullable[js][prio],
jctx.sched_info.ctx.ctx_list_entry[js]) {
struct kbasep_js_kctx_info *js_kctx_info;
bool timer_sync = false;
/* Drop lock so we can take kctx mutexes */
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
js_kctx_info = &kctx->jctx.sched_info;
mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
mutex_lock(&js_devdata->runpool_mutex);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) &&
kbase_js_ctx_pullable(kctx, js, false))
timer_sync = kbase_js_ctx_list_add_pullable_nolock(
kbdev, kctx, js);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
if (timer_sync)
kbase_backend_ctx_count_changed(kbdev);
mutex_unlock(&js_devdata->runpool_mutex);
mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
/* Take lock before accessing list again */
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
} else {
bool timer_sync = false;
/* Drop lock so we can take kctx mutexes */
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
js_kctx_info = &kctx->jctx.sched_info;
mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
mutex_lock(&js_devdata->runpool_mutex);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) &&
kbase_js_ctx_pullable(kctx, js, false))
timer_sync = kbase_js_ctx_list_add_pullable_nolock(
kbdev, kctx, js);
list_for_each_entry_safe(
kctx, n, &kbdev->js_data.ctx_list_unpullable[js][prio],
jctx.sched_info.ctx.ctx_list_entry[js]) {
if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) &&
kbase_js_ctx_pullable(kctx, js, false))
timer_sync |= kbase_js_ctx_list_add_pullable_nolock(
kbdev, kctx, js);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
if (timer_sync)
if (timer_sync) {
mutex_lock(&js_devdata->runpool_mutex);
kbase_backend_ctx_count_changed(kbdev);
mutex_unlock(&js_devdata->runpool_mutex);
mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
/* Take lock before accessing list again */
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
mutex_unlock(&js_devdata->runpool_mutex);
}
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
#else
bool timer_sync = false;
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
list_for_each_entry_safe(kctx, n,
&kbdev->js_data.ctx_list_unpullable[js][prio],
jctx.sched_info.ctx.ctx_list_entry[js]) {
if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) &&
kbase_js_ctx_pullable(kctx, js, false))
timer_sync |= kbase_js_ctx_list_add_pullable_nolock(
kbdev, kctx, js);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
if (timer_sync) {
mutex_lock(&js_devdata->runpool_mutex);
kbase_backend_ctx_count_changed(kbdev);
mutex_unlock(&js_devdata->runpool_mutex);
}
#endif
}
}
mutex_unlock(&js_devdata->queue_mutex);
@ -2515,7 +2371,7 @@ static unsigned int kbase_js_get_slot(struct kbase_device *kbdev, struct kbase_j
bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_atom *katom)
{
bool enqueue_required, add_required = true;
bool enqueue_required;
katom->slot_nr = kbase_js_get_slot(kctx->kbdev, katom);
@ -2525,10 +2381,7 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_at
/* If slot will transition from unpullable to pullable then add to
* pullable list
*/
if (jsctx_rb_none_to_pull(kctx, katom->slot_nr))
enqueue_required = true;
else
enqueue_required = false;
enqueue_required = jsctx_rb_none_to_pull(kctx, katom->slot_nr);
if ((katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) ||
(katom->pre_dep &&
@ -2541,15 +2394,9 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_at
list_add_tail(&katom->queue, &queue->x_dep_head);
katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST;
if (kbase_js_atom_blocked_on_x_dep(katom)) {
enqueue_required = false;
add_required = false;
}
enqueue_required = false;
} else {
dev_dbg(kctx->kbdev->dev, "Atom %pK not added to X_DEP list\n", (void *)katom);
}
if (add_required) {
/* Check if there are lower priority jobs to soft stop */
kbase_job_slot_ctx_priority_check_locked(kctx, katom);
@ -2575,30 +2422,22 @@ bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_at
*/
static void kbase_js_move_to_tree(struct kbase_jd_atom *katom)
{
struct kbase_context *const kctx = katom->kctx;
lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
lockdep_assert_held(&katom->kctx->kbdev->hwaccess_lock);
while (katom) {
WARN_ON(!(katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST));
if (!kbase_js_atom_blocked_on_x_dep(katom)) {
dev_dbg(kctx->kbdev->dev,
if (!(katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) {
dev_dbg(katom->kctx->kbdev->dev,
"Del atom %pK from X_DEP list in js_move_to_tree\n", (void *)katom);
list_del(&katom->queue);
katom->atom_flags &= ~KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST;
/* For incremental rendering, an end-of-renderpass atom
* may have had its dependency on start-of-renderpass
* ignored and may therefore already be in the tree.
*/
if (!(katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE)) {
jsctx_tree_add(kctx, katom);
katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE;
}
jsctx_tree_add(katom->kctx, katom);
katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE;
} else {
dev_dbg(kctx->kbdev->dev, "Atom %pK blocked on x-dep in js_move_to_tree\n",
(void *)katom);
dev_dbg(katom->kctx->kbdev->dev,
"Atom %pK blocked on x-dep in js_move_to_tree\n", (void *)katom);
break;
}
@ -2671,11 +2510,7 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, unsigned int js)
dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %pK\n", (void *)kctx);
return NULL;
}
#ifdef CONFIG_MALI_ARBITER_SUPPORT
if (kbase_pm_is_suspending(kbdev) || kbase_pm_is_gpu_lost(kbdev))
#else
if (kbase_pm_is_suspending(kbdev))
#endif
return NULL;
katom = jsctx_rb_peek(kctx, js);
@ -2705,7 +2540,7 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, unsigned int js)
return NULL;
}
if (kbase_js_atom_blocked_on_x_dep(katom)) {
if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) {
if (katom->x_pre_dep->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB ||
katom->x_pre_dep->will_fail_event_code) {
dev_dbg(kbdev->dev,
@ -2745,190 +2580,6 @@ struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, unsigned int js)
return katom;
}
/**
* js_return_of_start_rp() - Handle soft-stop of an atom that starts a
* renderpass
* @start_katom: Pointer to the start-of-renderpass atom that was soft-stopped
*
* This function is called to switch to incremental rendering if the tiler job
* chain at the start of a renderpass has used too much memory. It prevents the
* tiler job being pulled for execution in the job scheduler again until the
* next phase of incremental rendering is complete.
*
* If the end-of-renderpass atom is already in the job scheduler (because a
* previous attempt at tiling used too much memory during the same renderpass)
* then it is unblocked; otherwise, it is run by handing it to the scheduler.
*/
static void js_return_of_start_rp(struct kbase_jd_atom *const start_katom)
{
struct kbase_context *const kctx = start_katom->kctx;
struct kbase_device *const kbdev = kctx->kbdev;
struct kbase_jd_renderpass *rp;
struct kbase_jd_atom *end_katom;
unsigned long flags;
lockdep_assert_held(&kctx->jctx.lock);
if (WARN_ON(!(start_katom->core_req & BASE_JD_REQ_START_RENDERPASS)))
return;
compiletime_assert((1ull << (sizeof(start_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[start_katom->renderpass_id];
if (WARN_ON(rp->start_katom != start_katom))
return;
dev_dbg(kctx->kbdev->dev, "JS return start atom %pK in state %d of RP %d\n",
(void *)start_katom, (int)rp->state, start_katom->renderpass_id);
if (WARN_ON(rp->state == KBASE_JD_RP_COMPLETE))
return;
/* The tiler job might have been soft-stopped for some reason other
* than running out of memory.
*/
if (rp->state == KBASE_JD_RP_START || rp->state == KBASE_JD_RP_RETRY) {
dev_dbg(kctx->kbdev->dev, "JS return isn't OOM in state %d of RP %d\n",
(int)rp->state, start_katom->renderpass_id);
return;
}
dev_dbg(kctx->kbdev->dev, "JS return confirm OOM in state %d of RP %d\n", (int)rp->state,
start_katom->renderpass_id);
if (WARN_ON(rp->state != KBASE_JD_RP_PEND_OOM && rp->state != KBASE_JD_RP_RETRY_PEND_OOM))
return;
/* Prevent the tiler job being pulled for execution in the
* job scheduler again.
*/
dev_dbg(kbdev->dev, "Blocking start atom %pK\n", (void *)start_katom);
atomic_inc(&start_katom->blocked);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
rp->state = (rp->state == KBASE_JD_RP_PEND_OOM) ? KBASE_JD_RP_OOM : KBASE_JD_RP_RETRY_OOM;
/* Was the fragment job chain submitted to kbase yet? */
end_katom = rp->end_katom;
if (end_katom) {
dev_dbg(kctx->kbdev->dev, "JS return add end atom %pK\n", (void *)end_katom);
if (rp->state == KBASE_JD_RP_RETRY_OOM) {
/* Allow the end of the renderpass to be pulled for
* execution again to continue incremental rendering.
*/
dev_dbg(kbdev->dev, "Unblocking end atom %pK\n", (void *)end_katom);
atomic_dec(&end_katom->blocked);
WARN_ON(!(end_katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE));
WARN_ON(end_katom->status != KBASE_JD_ATOM_STATE_IN_JS);
kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, end_katom->slot_nr);
/* Expect the fragment job chain to be scheduled without
* further action because this function is called when
* returning an atom to the job scheduler ringbuffer.
*/
end_katom = NULL;
} else {
WARN_ON(end_katom->status != KBASE_JD_ATOM_STATE_QUEUED &&
end_katom->status != KBASE_JD_ATOM_STATE_IN_JS);
}
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
if (end_katom)
kbase_jd_dep_clear_locked(end_katom);
}
/**
* js_return_of_end_rp() - Handle completion of an atom that ends a renderpass
* @end_katom: Pointer to the end-of-renderpass atom that was completed
*
* This function is called to continue incremental rendering if the tiler job
* chain at the start of a renderpass used too much memory. It resets the
* mechanism for detecting excessive memory usage then allows the soft-stopped
* tiler job chain to be pulled for execution again.
*
* The start-of-renderpass atom must already been submitted to kbase.
*/
static void js_return_of_end_rp(struct kbase_jd_atom *const end_katom)
{
struct kbase_context *const kctx = end_katom->kctx;
struct kbase_device *const kbdev = kctx->kbdev;
struct kbase_jd_renderpass *rp;
struct kbase_jd_atom *start_katom;
unsigned long flags;
lockdep_assert_held(&kctx->jctx.lock);
if (WARN_ON(!(end_katom->core_req & BASE_JD_REQ_END_RENDERPASS)))
return;
compiletime_assert((1ull << (sizeof(end_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[end_katom->renderpass_id];
if (WARN_ON(rp->end_katom != end_katom))
return;
dev_dbg(kctx->kbdev->dev, "JS return end atom %pK in state %d of RP %d\n",
(void *)end_katom, (int)rp->state, end_katom->renderpass_id);
if (WARN_ON(rp->state != KBASE_JD_RP_OOM && rp->state != KBASE_JD_RP_RETRY_OOM))
return;
/* Reduce the number of mapped pages in the memory regions that
* triggered out-of-memory last time so that we can detect excessive
* memory usage again.
*/
kbase_gpu_vm_lock(kctx);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
while (!list_empty(&rp->oom_reg_list)) {
struct kbase_va_region *reg =
list_first_entry(&rp->oom_reg_list, struct kbase_va_region, link);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
dev_dbg(kbdev->dev, "Reset backing to %zu pages for region %pK\n",
reg->threshold_pages, (void *)reg);
if (!WARN_ON(reg->flags & KBASE_REG_VA_FREED))
kbase_mem_shrink(kctx, reg, reg->threshold_pages);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
dev_dbg(kbdev->dev, "Deleting region %pK from list\n", (void *)reg);
list_del_init(&reg->link);
kbase_va_region_alloc_put(kctx, reg);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
kbase_gpu_vm_unlock(kctx);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
rp->state = KBASE_JD_RP_RETRY;
dev_dbg(kbdev->dev, "Changed state to %d for retry\n", rp->state);
/* Allow the start of the renderpass to be pulled for execution again
* to begin/continue incremental rendering.
*/
start_katom = rp->start_katom;
if (!WARN_ON(!start_katom)) {
dev_dbg(kbdev->dev, "Unblocking start atom %pK\n", (void *)start_katom);
atomic_dec(&start_katom->blocked);
(void)kbase_js_ctx_list_add_pullable_head_nolock(kbdev, kctx, start_katom->slot_nr);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
}
static void js_return_worker(struct work_struct *data)
{
struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work);
@ -2949,9 +2600,7 @@ static void js_return_worker(struct work_struct *data)
katom->event_code);
KBASE_KTRACE_ADD_JM(kbdev, JS_RETURN_WORKER, kctx, katom, katom->jc, 0);
if (katom->event_code != BASE_JD_EVENT_END_RP_DONE)
KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_EX(kbdev, katom);
KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_EX(kbdev, katom);
kbase_backend_complete_wq(kbdev, katom);
@ -2960,8 +2609,7 @@ static void js_return_worker(struct work_struct *data)
mutex_lock(&js_devdata->queue_mutex);
mutex_lock(&js_kctx_info->ctx.jsctx_mutex);
if (katom->event_code != BASE_JD_EVENT_END_RP_DONE)
atomic_dec(&katom->blocked);
atomic_dec(&katom->blocked);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
@ -3026,16 +2674,6 @@ static void js_return_worker(struct work_struct *data)
mutex_unlock(&js_kctx_info->ctx.jsctx_mutex);
mutex_unlock(&js_devdata->queue_mutex);
if (katom->core_req & BASE_JD_REQ_START_RENDERPASS) {
mutex_lock(&kctx->jctx.lock);
js_return_of_start_rp(katom);
mutex_unlock(&kctx->jctx.lock);
} else if (katom->event_code == BASE_JD_EVENT_END_RP_DONE) {
mutex_lock(&kctx->jctx.lock);
js_return_of_end_rp(katom);
mutex_unlock(&kctx->jctx.lock);
}
dev_dbg(kbdev->dev, "JS: retained state %s finished",
kbasep_js_has_atom_finished(&retained_state) ? "has" : "hasn't");
@ -3071,144 +2709,6 @@ void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom)
queue_work(kctx->jctx.job_done_wq, &katom->work);
}
/**
* js_complete_start_rp() - Handle completion of atom that starts a renderpass
* @kctx: Context pointer
* @start_katom: Pointer to the atom that completed
*
* Put any references to virtual memory regions that might have been added by
* kbase_job_slot_softstop_start_rp() because the tiler job chain completed
* despite any pending soft-stop request.
*
* If the atom that just completed was soft-stopped during a previous attempt to
* run it then there should be a blocked end-of-renderpass atom waiting for it,
* which we must unblock to process the output of the tiler job chain.
*
* Return: true if caller should call kbase_backend_ctx_count_changed()
*/
static bool js_complete_start_rp(struct kbase_context *kctx,
struct kbase_jd_atom *const start_katom)
{
struct kbase_device *const kbdev = kctx->kbdev;
struct kbase_jd_renderpass *rp;
bool timer_sync = false;
lockdep_assert_held(&kctx->jctx.lock);
if (WARN_ON(!(start_katom->core_req & BASE_JD_REQ_START_RENDERPASS)))
return false;
compiletime_assert((1ull << (sizeof(start_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[start_katom->renderpass_id];
if (WARN_ON(rp->start_katom != start_katom))
return false;
dev_dbg(kctx->kbdev->dev, "Start atom %pK is done in state %d of RP %d\n",
(void *)start_katom, (int)rp->state, start_katom->renderpass_id);
if (WARN_ON(rp->state == KBASE_JD_RP_COMPLETE))
return false;
if (rp->state == KBASE_JD_RP_PEND_OOM || rp->state == KBASE_JD_RP_RETRY_PEND_OOM) {
unsigned long flags;
dev_dbg(kctx->kbdev->dev, "Start atom %pK completed before soft-stop\n",
(void *)start_katom);
kbase_gpu_vm_lock(kctx);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
while (!list_empty(&rp->oom_reg_list)) {
struct kbase_va_region *reg =
list_first_entry(&rp->oom_reg_list, struct kbase_va_region, link);
WARN_ON(reg->flags & KBASE_REG_VA_FREED);
dev_dbg(kctx->kbdev->dev, "Deleting region %pK from list\n", (void *)reg);
list_del_init(&reg->link);
kbase_va_region_alloc_put(kctx, reg);
}
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
kbase_gpu_vm_unlock(kctx);
} else {
dev_dbg(kctx->kbdev->dev, "Start atom %pK did not exceed memory threshold\n",
(void *)start_katom);
WARN_ON(rp->state != KBASE_JD_RP_START && rp->state != KBASE_JD_RP_RETRY);
}
if (rp->state == KBASE_JD_RP_RETRY || rp->state == KBASE_JD_RP_RETRY_PEND_OOM) {
struct kbase_jd_atom *const end_katom = rp->end_katom;
if (!WARN_ON(!end_katom)) {
unsigned long flags;
/* Allow the end of the renderpass to be pulled for
* execution again to continue incremental rendering.
*/
dev_dbg(kbdev->dev, "Unblocking end atom %pK!\n", (void *)end_katom);
atomic_dec(&end_katom->blocked);
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
timer_sync = kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx,
end_katom->slot_nr);
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
}
}
return timer_sync;
}
/**
* js_complete_end_rp() - Handle final completion of atom that ends a renderpass
* @kctx: Context pointer
* @end_katom: Pointer to the atom that completed for the last time
*
* This function must only be called if the renderpass actually completed
* without the tiler job chain at the start using too much memory; otherwise
* completion of the end-of-renderpass atom is handled similarly to a soft-stop.
*/
static void js_complete_end_rp(struct kbase_context *kctx, struct kbase_jd_atom *const end_katom)
{
struct kbase_device *const kbdev = kctx->kbdev;
unsigned long flags;
struct kbase_jd_renderpass *rp;
lockdep_assert_held(&kctx->jctx.lock);
if (WARN_ON(!(end_katom->core_req & BASE_JD_REQ_END_RENDERPASS)))
return;
compiletime_assert((1ull << (sizeof(end_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[end_katom->renderpass_id];
if (WARN_ON(rp->end_katom != end_katom))
return;
dev_dbg(kbdev->dev, "End atom %pK is done in state %d of RP %d\n", (void *)end_katom,
(int)rp->state, end_katom->renderpass_id);
if (WARN_ON(rp->state == KBASE_JD_RP_COMPLETE) || WARN_ON(rp->state == KBASE_JD_RP_OOM) ||
WARN_ON(rp->state == KBASE_JD_RP_RETRY_OOM))
return;
/* Rendering completed without running out of memory.
*/
spin_lock_irqsave(&kbdev->hwaccess_lock, flags);
WARN_ON(!list_empty(&rp->oom_reg_list));
rp->state = KBASE_JD_RP_COMPLETE;
spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags);
dev_dbg(kbdev->dev, "Renderpass %d is complete\n", end_katom->renderpass_id);
}
bool kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom *katom)
{
struct kbasep_js_kctx_info *js_kctx_info;
@ -3225,13 +2725,6 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom
dev_dbg(kbdev->dev, "%s for atom %pK (s:%u)\n", __func__, (void *)katom, atom_slot);
/* Update the incremental rendering state machine.
*/
if (katom->core_req & BASE_JD_REQ_START_RENDERPASS)
timer_sync |= js_complete_start_rp(kctx, katom);
else if (katom->core_req & BASE_JD_REQ_END_RENDERPASS)
js_complete_end_rp(kctx, katom);
js_kctx_info = &kctx->jctx.sched_info;
js_devdata = &kbdev->js_data;
@ -3320,61 +2813,6 @@ bool kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom
return context_idle;
}
/**
* js_end_rp_is_complete() - Check whether an atom that ends a renderpass has
* completed for the last time.
*
* @end_katom: Pointer to the atom that completed on the hardware.
*
* An atom that ends a renderpass may be run on the hardware several times
* before notifying userspace or allowing dependent atoms to be executed.
*
* This function is used to decide whether or not to allow end-of-renderpass
* atom completion. It only returns false if the atom at the start of the
* renderpass was soft-stopped because it used too much memory during the most
* recent attempt at tiling.
*
* Return: True if the atom completed for the last time.
*/
static bool js_end_rp_is_complete(struct kbase_jd_atom *const end_katom)
{
struct kbase_context *const kctx = end_katom->kctx;
struct kbase_device *const kbdev = kctx->kbdev;
struct kbase_jd_renderpass *rp;
lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
if (WARN_ON(!(end_katom->core_req & BASE_JD_REQ_END_RENDERPASS)))
return true;
compiletime_assert((1ull << (sizeof(end_katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[end_katom->renderpass_id];
if (WARN_ON(rp->end_katom != end_katom))
return true;
dev_dbg(kbdev->dev, "JS complete end atom %pK in state %d of RP %d\n", (void *)end_katom,
(int)rp->state, end_katom->renderpass_id);
if (WARN_ON(rp->state == KBASE_JD_RP_COMPLETE))
return true;
/* Failure of end-of-renderpass atoms must not return to the
* start of the renderpass.
*/
if (end_katom->event_code != BASE_JD_EVENT_DONE)
return true;
if (rp->state != KBASE_JD_RP_OOM && rp->state != KBASE_JD_RP_RETRY_OOM)
return true;
dev_dbg(kbdev->dev, "Suppressing end atom completion\n");
return false;
}
struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_t *end_timestamp)
{
struct kbase_device *kbdev;
@ -3387,12 +2825,6 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_
lockdep_assert_held(&kctx->kbdev->hwaccess_lock);
if ((katom->core_req & BASE_JD_REQ_END_RENDERPASS) && !js_end_rp_is_complete(katom)) {
katom->event_code = BASE_JD_EVENT_END_RP_DONE;
kbase_js_unpull(kctx, katom);
return NULL;
}
if (katom->will_fail_event_code)
katom->event_code = katom->will_fail_event_code;
@ -3442,70 +2874,6 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_
return NULL;
}
/**
* kbase_js_atom_blocked_on_x_dep - Decide whether to ignore a cross-slot
* dependency
* @katom: Pointer to an atom in the slot ringbuffer
*
* A cross-slot dependency is ignored if necessary to unblock incremental
* rendering. If the atom at the start of a renderpass used too much memory
* and was soft-stopped then the atom at the end of a renderpass is submitted
* to hardware regardless of its dependency on the start-of-renderpass atom.
* This can happen multiple times for the same pair of atoms.
*
* Return: true to block the atom or false to allow it to be submitted to
* hardware
*/
bool kbase_js_atom_blocked_on_x_dep(struct kbase_jd_atom *const katom)
{
struct kbase_context *const kctx = katom->kctx;
struct kbase_device *kbdev = kctx->kbdev;
struct kbase_jd_renderpass *rp;
lockdep_assert_held(&kbdev->hwaccess_lock);
if (!(katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) {
dev_dbg(kbdev->dev, "Atom %pK is not blocked on a cross-slot dependency",
(void *)katom);
return false;
}
if (!(katom->core_req & BASE_JD_REQ_END_RENDERPASS)) {
dev_dbg(kbdev->dev, "Atom %pK is blocked on a cross-slot dependency",
(void *)katom);
return true;
}
compiletime_assert((1ull << (sizeof(katom->renderpass_id) * 8)) <=
ARRAY_SIZE(kctx->jctx.renderpasses),
"Should check invalid access to renderpasses");
rp = &kctx->jctx.renderpasses[katom->renderpass_id];
/* We can read a subset of renderpass state without holding
* higher-level locks (but not end_katom, for example).
*/
WARN_ON(rp->state == KBASE_JD_RP_COMPLETE);
dev_dbg(kbdev->dev, "End atom has cross-slot dep in state %d\n", (int)rp->state);
if (rp->state != KBASE_JD_RP_OOM && rp->state != KBASE_JD_RP_RETRY_OOM)
return true;
/* Tiler ran out of memory so allow the fragment job chain to run
* if it only depends on the tiler job chain.
*/
if (katom->x_pre_dep != rp->start_katom) {
dev_dbg(kbdev->dev, "Dependency is on %pK not start atom %pK\n",
(void *)katom->x_pre_dep, (void *)rp->start_katom);
return true;
}
dev_dbg(kbdev->dev, "Ignoring cross-slot dep on atom %pK\n", (void *)katom->x_pre_dep);
return false;
}
void kbase_js_sched(struct kbase_device *kbdev, unsigned int js_mask)
{
struct kbasep_js_device_data *js_devdata;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -516,7 +516,8 @@ static ssize_t reader_changes_copy_to_user(struct reader_changes *const changes,
do {
changes_tail = changes->tail;
changes_count = reader_changes_count_locked(changes);
read_size = min(changes_count * entry_size, buffer_size & ~(entry_size - 1));
read_size =
min(size_mul(changes_count, entry_size), buffer_size & ~(entry_size - 1));
if (!read_size)
break;
@ -743,7 +744,6 @@ int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx, union kbase_kinstr
size_t const change_size = sizeof(struct kbase_kinstr_jm_atom_state_change);
int status;
int fd;
size_t i;
if (!ctx || !jm_fd_arg)
return -EINVAL;
@ -753,10 +753,6 @@ int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx, union kbase_kinstr
if (!is_power_of_2(in->count))
return -EINVAL;
for (i = 0; i < sizeof(in->padding); ++i)
if (in->padding[i])
return -EINVAL;
status = reader_init(&reader, ctx, in->count);
if (status < 0)
return status;

View file

@ -35,6 +35,7 @@
#include <mali_kbase_config.h>
#include <mali_kbase.h>
#include <mali_kbase_reg_track.h>
#include <mali_kbase_caps.h>
#include <hw_access/mali_kbase_hw_access_regmap.h>
#include <mali_kbase_cache_policy.h>
#include <mali_kbase_hw.h>
@ -42,7 +43,6 @@
#include <mali_kbase_native_mgm.h>
#include <mali_kbase_mem_pool_group.h>
#include <mmu/mali_kbase_mmu.h>
#include <mali_kbase_config_defaults.h>
#include <mali_kbase_trace_gpu_mem.h>
#include <linux/version_compat_defs.h>
@ -52,6 +52,11 @@ static DEFINE_STATIC_KEY_FALSE(large_pages_static_key);
#define VA_REGION_SLAB_NAME_PREFIX "va-region-slab-"
#define VA_REGION_SLAB_NAME_SIZE (DEVNAME_SIZE + sizeof(VA_REGION_SLAB_NAME_PREFIX) + 1)
#if GPU_PAGES_PER_CPU_PAGE > 1
#define PAGE_METADATA_SLAB_NAME_PREFIX "page-metadata-slab-"
#define PAGE_METADATA_SLAB_NAME_SIZE (DEVNAME_SIZE + sizeof(PAGE_METADATA_SLAB_NAME_PREFIX) + 1)
#endif
#if MALI_JIT_PRESSURE_LIMIT_BASE
/*
@ -152,7 +157,7 @@ static void kbasep_mem_page_size_init(struct kbase_device *kbdev)
switch (large_page_conf) {
case LARGE_PAGE_AUTO: {
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_LARGE_PAGE_ALLOC))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_LARGE_PAGE_ALLOC))
static_branch_inc(&large_pages_static_key);
dev_info(kbdev->dev, "Large page allocation set to %s after hardware feature check",
static_branch_unlikely(&large_pages_static_key) ? "true" : "false");
@ -160,7 +165,7 @@ static void kbasep_mem_page_size_init(struct kbase_device *kbdev)
}
case LARGE_PAGE_ON: {
static_branch_inc(&large_pages_static_key);
if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_LARGE_PAGE_ALLOC))
if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_LARGE_PAGE_ALLOC))
dev_warn(kbdev->dev,
"Enabling large page allocations on unsupporting GPU!");
else
@ -196,16 +201,16 @@ KBASE_EXPORT_TEST_API(kbase_is_large_pages_enabled);
int kbase_mem_init(struct kbase_device *kbdev)
{
int err = 0;
struct kbasep_mem_device *memdev;
char va_region_slab_name[VA_REGION_SLAB_NAME_SIZE];
#if GPU_PAGES_PER_CPU_PAGE > 1
char page_metadata_slab_name[PAGE_METADATA_SLAB_NAME_SIZE];
#endif
#if IS_ENABLED(CONFIG_OF)
struct device_node *mgm_node = NULL;
#endif
KBASE_DEBUG_ASSERT(kbdev);
memdev = &kbdev->memdev;
kbasep_mem_page_size_init(kbdev);
scnprintf(va_region_slab_name, VA_REGION_SLAB_NAME_SIZE, VA_REGION_SLAB_NAME_PREFIX "%s",
@ -219,6 +224,17 @@ int kbase_mem_init(struct kbase_device *kbdev)
return -ENOMEM;
}
#if GPU_PAGES_PER_CPU_PAGE > 1
scnprintf(page_metadata_slab_name, PAGE_METADATA_SLAB_NAME_SIZE,
PAGE_METADATA_SLAB_NAME_PREFIX "%s", kbdev->devname);
kbdev->page_metadata_slab = kmem_cache_create(
page_metadata_slab_name, sizeof(struct kbase_page_metadata), 0, 0, NULL);
if (kbdev->page_metadata_slab == NULL) {
dev_err(kbdev->dev, "Failed to create page_metadata_slab");
return -ENOMEM;
}
#endif
kbase_mem_migrate_init(kbdev);
kbase_mem_pool_group_config_set_max_size(&kbdev->mem_pool_defaults,
KBASE_MEM_POOL_MAX_SIZE_KCTX);
@ -228,12 +244,6 @@ int kbase_mem_init(struct kbase_device *kbdev)
kbdev->dma_buf_root = RB_ROOT;
mutex_init(&kbdev->dma_buf_lock);
#ifdef IR_THRESHOLD
atomic_set(&memdev->ir_threshold, IR_THRESHOLD);
#else
atomic_set(&memdev->ir_threshold, DEFAULT_IR_THRESHOLD);
#endif
kbdev->mgm_dev = &kbase_native_mgm_dev;
#if IS_ENABLED(CONFIG_OF)
@ -299,6 +309,10 @@ void kbase_mem_term(struct kbase_device *kbdev)
kbase_mem_migrate_term(kbdev);
#if GPU_PAGES_PER_CPU_PAGE > 1
kmem_cache_destroy(kbdev->page_metadata_slab);
kbdev->page_metadata_slab = NULL;
#endif
kmem_cache_destroy(kbdev->va_region_slab);
kbdev->va_region_slab = NULL;
@ -1221,6 +1235,7 @@ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, size_t nr_pa
* to satisfy the memory allocation request.
*/
size_t nr_pages_to_account = 0;
size_t nr_pages_from_partials = 0;
if (WARN_ON(alloc->type != KBASE_MEM_TYPE_NATIVE) ||
WARN_ON(alloc->imported.native.kctx == NULL) ||
@ -1279,6 +1294,7 @@ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, size_t nr_pa
*tp++ = as_tagged_tag(page_to_phys(sa->page + pidx),
FROM_PARTIAL);
nr_left--;
nr_pages_from_partials++;
if (bitmap_full(sa->sub_pages,
NUM_PAGES_IN_2MB_LARGE_PAGE)) {
@ -1386,6 +1402,13 @@ alloc_failed:
alloc->nents += nr_pages_to_free;
kbase_free_phy_pages_helper(alloc, nr_pages_to_free);
/* Notice that the sub-pages from "partials" are not subtracted
* from the counter by the free pages helper, because they just go
* back to the "partials" they belong to, therefore they must be
* subtracted from the counter here.
*/
nr_left += nr_pages_from_partials;
}
/* Undo the preliminary memory accounting that was done early on
@ -1994,11 +2017,13 @@ out_term:
}
KBASE_EXPORT_TEST_API(kbase_alloc_phy_pages);
void kbase_set_phy_alloc_page_status(struct kbase_mem_phy_alloc *alloc,
void kbase_set_phy_alloc_page_status(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc,
enum kbase_page_status status)
{
u32 i = 0;
lockdep_assert_held(&kctx->reg_lock);
for (; i < alloc->nents; i++) {
struct tagged_addr phys = alloc->pages[i];
struct kbase_page_metadata *page_md = kbase_page_private(as_page(phys));
@ -2018,7 +2043,7 @@ void kbase_set_phy_alloc_page_status(struct kbase_mem_phy_alloc *alloc,
}
}
bool kbase_check_alloc_flags(unsigned long flags)
bool kbase_check_alloc_flags(struct kbase_context *kctx, unsigned long flags)
{
/* Only known input flags should be set. */
if (flags & ~BASE_MEM_FLAGS_INPUT_MASK)
@ -2094,6 +2119,36 @@ bool kbase_check_alloc_flags(unsigned long flags)
return false;
#endif
/* Cannot be set only allocation, only with base_mem_set */
if ((flags & BASE_MEM_DONT_NEED) &&
(mali_kbase_supports_reject_alloc_mem_dont_need(kctx->api_version)))
return false;
/* Cannot directly allocate protected memory, it is imported instead */
if ((flags & BASE_MEM_PROTECTED) &&
(mali_kbase_supports_reject_alloc_mem_protected_in_unprotected_allocs(
kctx->api_version)))
return false;
/* No unused bits are valid for allocations */
#if MALI_USE_CSF
if ((flags & BASE_MEM_UNUSED_BIT_20) &&
(mali_kbase_supports_reject_alloc_mem_unused_bit_20(kctx->api_version)))
return false;
if ((flags & BASE_MEM_UNUSED_BIT_27) &&
(mali_kbase_supports_reject_alloc_mem_unused_bit_27(kctx->api_version)))
return false;
#else /* MALI_USE_CSF */
if ((flags & BASE_MEM_UNUSED_BIT_8) &&
(mali_kbase_supports_reject_alloc_mem_unused_bit_8(kctx->api_version)))
return false;
if ((flags & BASE_MEM_UNUSED_BIT_19) &&
(mali_kbase_supports_reject_alloc_mem_unused_bit_19(kctx->api_version)))
return false;
#endif /* MALI_USE_CSF */
return true;
}
@ -2258,7 +2313,7 @@ KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock);
void kbase_gpu_vm_lock_with_pmode_sync(struct kbase_context *kctx)
{
#if MALI_USE_CSF
down_read(&kctx->kbdev->csf.pmode_sync_sem);
down_read(&kctx->kbdev->csf.mmu_sync_sem);
#endif
kbase_gpu_vm_lock(kctx);
}
@ -2274,7 +2329,7 @@ void kbase_gpu_vm_unlock_with_pmode_sync(struct kbase_context *kctx)
{
kbase_gpu_vm_unlock(kctx);
#if MALI_USE_CSF
up_read(&kctx->kbdev->csf.pmode_sync_sem);
up_read(&kctx->kbdev->csf.mmu_sync_sem);
#endif
}
@ -3230,15 +3285,17 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
if (kbase_is_page_migration_enabled()) {
kbase_gpu_vm_lock(kctx);
mutex_lock(&kctx->jit_evict_lock);
kbase_set_phy_alloc_page_status(reg->gpu_alloc, ALLOCATED_MAPPED);
kbase_set_phy_alloc_page_status(kctx, reg->gpu_alloc,
ALLOCATED_MAPPED);
mutex_unlock(&kctx->jit_evict_lock);
kbase_gpu_vm_unlock(kctx);
}
}
} else {
/* No suitable JIT allocation was found so create a new one */
u64 flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR |
BASE_MEM_GROW_ON_GPF | BASE_MEM_COHERENT_LOCAL | BASEP_MEM_NO_USER_FREE;
base_mem_alloc_flags flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD |
BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF |
BASE_MEM_COHERENT_LOCAL | BASEP_MEM_NO_USER_FREE;
u64 gpu_addr;
#if !MALI_USE_CSF
@ -3335,6 +3392,7 @@ end:
return reg;
}
KBASE_EXPORT_TEST_API(kbase_jit_allocate);
void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
{
@ -3376,13 +3434,30 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
trace_jit_stats(kctx, reg->jit_bin_id, UINT_MAX);
kbase_gpu_vm_lock_with_pmode_sync(kctx);
if (unlikely(atomic_read(&reg->cpu_alloc->kernel_mappings))) {
WARN_ON(atomic64_read(&reg->no_user_free_count) > 1);
kbase_va_region_no_user_free_dec(reg);
mutex_lock(&kctx->jit_evict_lock);
list_del(&reg->jit_node);
mutex_unlock(&kctx->jit_evict_lock);
kbase_mem_free_region(kctx, reg);
kbase_gpu_vm_unlock_with_pmode_sync(kctx);
return;
}
kbase_mem_evictable_mark_reclaim(reg->gpu_alloc);
kbase_gpu_vm_lock(kctx);
reg->flags |= KBASE_REG_DONT_NEED;
reg->flags &= ~KBASE_REG_ACTIVE_JIT_ALLOC;
kbase_mem_shrink_cpu_mapping(kctx, reg, 0, reg->gpu_alloc->nents);
kbase_gpu_vm_unlock(kctx);
/* Inactive JIT regions should be freed by the shrinker and not impacted
* by page migration. Once freed, they will enter into the page migration
* state machine via the mempools.
*/
if (kbase_is_page_migration_enabled())
kbase_set_phy_alloc_page_status(kctx, reg->gpu_alloc, NOT_MOVABLE);
kbase_gpu_vm_unlock_with_pmode_sync(kctx);
/*
* Add the allocation to the eviction list and the jit pool, after this
@ -3397,14 +3472,9 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg)
list_move(&reg->jit_node, &kctx->jit_pool_head);
/* Inactive JIT regions should be freed by the shrinker and not impacted
* by page migration. Once freed, they will enter into the page migration
* state machine via the mempools.
*/
if (kbase_is_page_migration_enabled())
kbase_set_phy_alloc_page_status(reg->gpu_alloc, NOT_MOVABLE);
mutex_unlock(&kctx->jit_evict_lock);
}
KBASE_EXPORT_TEST_API(kbase_jit_free);
void kbase_jit_backing_lost(struct kbase_va_region *reg)
{

View file

@ -104,8 +104,8 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int
/* Index of chosen MEMATTR for this region (0..7) */
#define KBASE_REG_MEMATTR_MASK (7ul << 16)
#define KBASE_REG_MEMATTR_INDEX(x) (((x)&7) << 16)
#define KBASE_REG_MEMATTR_VALUE(x) (((x)&KBASE_REG_MEMATTR_MASK) >> 16)
#define KBASE_REG_MEMATTR_INDEX(x) (((x) & 7) << 16)
#define KBASE_REG_MEMATTR_VALUE(x) (((x) & KBASE_REG_MEMATTR_MASK) >> 16)
/* AS<n>_MEMATTR values from MMU_MEMATTR_STAGE1: */
/* Use GPU implementation-defined caching policy. */
@ -482,6 +482,26 @@ struct kbase_page_metadata {
struct kbase_mmu_table *mmut;
/* GPU virtual page frame number info is in GPU_PAGE_SIZE units */
u64 pgd_vpfn_level;
#if GPU_PAGES_PER_CPU_PAGE > 1
/**
* @pgd_link: Link to the &kbase_mmu_table.pgd_pages_list
*/
struct list_head pgd_link;
/**
* @pgd_page: Back pointer to the PGD page that the metadata is
* associated with
*/
struct page *pgd_page;
/**
* @allocated_sub_pages: Bitmap representing the allocation status
* of sub pages in the @pgd_page
*/
DECLARE_BITMAP(allocated_sub_pages, GPU_PAGES_PER_CPU_PAGE);
/**
* @num_allocated_sub_pages: The number of allocated sub pages in @pgd_page
*/
s8 num_allocated_sub_pages;
#endif
} pt_mapped;
struct {
struct kbase_device *kbdev;
@ -510,6 +530,7 @@ enum kbase_jit_report_flags { KBASE_JIT_REPORT_ON_ALLOC_OR_FREE = (1u << 0) };
/**
* kbase_set_phy_alloc_page_status - Set the page migration status of the underlying
* physical allocation.
* @kctx: Pointer to Kbase context.
* @alloc: the physical allocation containing the pages whose metadata is going
* to be modified
* @status: the status the pages should end up in
@ -518,7 +539,7 @@ enum kbase_jit_report_flags { KBASE_JIT_REPORT_ON_ALLOC_OR_FREE = (1u << 0) };
* proper states are set. Instead, it is only used when we change the allocation
* to NOT_MOVABLE or from NOT_MOVABLE to ALLOCATED_MAPPED
*/
void kbase_set_phy_alloc_page_status(struct kbase_mem_phy_alloc *alloc,
void kbase_set_phy_alloc_page_status(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc,
enum kbase_page_status status);
static inline void kbase_mem_phy_alloc_gpu_mapped(struct kbase_mem_phy_alloc *alloc)
@ -620,9 +641,6 @@ static inline struct kbase_mem_phy_alloc *kbase_mem_phy_alloc_put(struct kbase_m
* @nr_pages: The size of the region in pages.
* @initial_commit: Initial commit, for aligning the start address and
* correctly growing KBASE_REG_TILER_ALIGN_TOP regions.
* @threshold_pages: If non-zero and the amount of memory committed to a region
* that can grow on page fault exceeds this number of pages
* then the driver switches to incremental rendering.
* @flags: Flags
* @extension: Number of pages allocated on page fault.
* @cpu_alloc: The physical memory we mmap to the CPU when mapping this region.
@ -659,8 +677,7 @@ struct kbase_va_region {
void *user_data;
size_t nr_pages;
size_t initial_commit;
size_t threshold_pages;
unsigned long flags;
base_mem_alloc_flags flags;
size_t extension;
struct kbase_mem_phy_alloc *cpu_alloc;
struct kbase_mem_phy_alloc *gpu_alloc;
@ -914,10 +931,12 @@ static inline struct kbase_mem_phy_alloc *kbase_alloc_create(struct kbase_contex
atomic_set(&alloc->gpu_mappings, 0);
atomic_set(&alloc->kernel_mappings, 0);
alloc->nents = 0;
alloc->pages = (void *)(alloc + 1);
/* fill pages with invalid address value */
for (i = 0; i < nr_pages; i++)
alloc->pages[i] = as_tagged(KBASE_INVALID_PHYSICAL_ADDRESS);
if (type != KBASE_MEM_TYPE_ALIAS) {
alloc->pages = (void *)(alloc + 1);
/* fill pages with invalid address value */
for (i = 0; i < nr_pages; i++)
alloc->pages[i] = as_tagged(KBASE_INVALID_PHYSICAL_ADDRESS);
}
INIT_LIST_HEAD(&alloc->mappings);
alloc->type = type;
alloc->group_id = group_id;
@ -1307,7 +1326,7 @@ struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool, const bool alloc_
*/
void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, struct page *p);
bool kbase_check_alloc_flags(unsigned long flags);
bool kbase_check_alloc_flags(struct kbase_context *kctx, unsigned long flags);
bool kbase_check_import_flags(unsigned long flags);
static inline bool kbase_import_size_is_valid(struct kbase_device *kbdev, u64 va_pages)
@ -1799,8 +1818,8 @@ static inline dma_addr_t kbase_dma_addr_from_tagged(struct tagged_addr tagged_pa
phys_addr_t pa = as_phys_addr_t(tagged_pa);
struct page *page = pfn_to_page(PFN_DOWN(pa));
dma_addr_t dma_addr = (is_huge(tagged_pa) || is_partial(tagged_pa)) ?
kbase_dma_addr_as_priv(page) :
kbase_dma_addr(page);
kbase_dma_addr_as_priv(page) :
kbase_dma_addr(page);
return dma_addr;
}

View file

@ -83,8 +83,6 @@
#define KBASE_MEM_ION_SYNC_WORKAROUND
#endif
#define IR_THRESHOLD_STEPS (256u)
/*
* fully_backed_gpf_memory - enable full physical backing of all grow-on-GPU-page-fault
* allocations in the kernel.
@ -295,7 +293,7 @@ void kbase_phy_alloc_mapping_put(struct kbase_context *kctx, struct kbase_vmap_s
}
struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages, u64 commit_pages,
u64 extension, u64 *flags, u64 *gpu_va,
u64 extension, base_mem_alloc_flags *flags, u64 *gpu_va,
enum kbase_caller_mmu_sync_info mmu_sync_info)
{
struct kbase_va_region *reg;
@ -320,9 +318,8 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages
else
dev_dbg(dev, "Keeping requested GPU VA of 0x%llx\n", (unsigned long long)*gpu_va);
if (!kbase_check_alloc_flags(*flags)) {
dev_warn(dev, "%s called with bad flags (%llx)", __func__,
(unsigned long long)*flags);
if (!kbase_check_alloc_flags(kctx, *flags)) {
dev_warn(dev, "%s called with bad flags (%llx)", __func__, *flags);
goto bad_flags;
}
@ -335,6 +332,12 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages
}
#endif
/* Ensure GPU cached if CPU cached */
if ((*flags & BASE_MEM_CACHED_CPU) != 0) {
dev_warn_once(dev, "Clearing BASE_MEM_UNCACHED_GPU flag to avoid MMA violation\n");
*flags &= ~BASE_MEM_UNCACHED_GPU;
}
if ((*flags & BASE_MEM_UNCACHED_GPU) != 0 &&
(*flags & BASE_MEM_COHERENT_SYSTEM_REQUIRED) != 0) {
/* Remove COHERENT_SYSTEM_REQUIRED flag if uncached GPU mapping is requested */
@ -406,17 +409,8 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages
*flags &= ~BASE_MEM_CACHED_CPU;
if (*flags & BASE_MEM_GROW_ON_GPF) {
unsigned int const ir_threshold =
(unsigned int)atomic_read(&kctx->kbdev->memdev.ir_threshold);
reg->threshold_pages =
((va_pages * ir_threshold) + (IR_THRESHOLD_STEPS / 2)) / IR_THRESHOLD_STEPS;
} else
reg->threshold_pages = 0;
if (*flags & BASE_MEM_GROW_ON_GPF) {
/* kbase_check_alloc_sizes() already checks extension is valid for
* assigning to reg->extension
/* kbase_check_alloc_sizes() already checks extension is valid for assigning to
* reg->extension.
*/
reg->extension = extension;
#if !MALI_USE_CSF
@ -597,11 +591,11 @@ int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query, u64 *co
*out |= BASE_MEM_COHERENT_SYSTEM;
if (KBASE_REG_SHARE_IN & reg->flags)
*out |= BASE_MEM_COHERENT_LOCAL;
if (mali_kbase_supports_mem_dont_need(kctx->api_version)) {
if (mali_kbase_supports_query_mem_dont_need(kctx->api_version)) {
if (KBASE_REG_DONT_NEED & reg->flags)
*out |= BASE_MEM_DONT_NEED;
}
if (mali_kbase_supports_mem_grow_on_gpf(kctx->api_version)) {
if (mali_kbase_supports_query_mem_grow_on_gpf(kctx->api_version)) {
/* Prior to this version, this was known about by
* user-side but we did not return them. Returning
* it caused certain clients that were not expecting
@ -611,7 +605,7 @@ int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query, u64 *co
if (KBASE_REG_PF_GROW & reg->flags)
*out |= BASE_MEM_GROW_ON_GPF;
}
if (mali_kbase_supports_mem_protected(kctx->api_version)) {
if (mali_kbase_supports_query_mem_protected(kctx->api_version)) {
/* Prior to this version, this was known about by
* user-side but we did not return them. Returning
* it caused certain clients that were not expecting
@ -640,17 +634,17 @@ int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query, u64 *co
#endif /* MALI_USE_CSF */
if (KBASE_REG_GPU_VA_SAME_4GB_PAGE & reg->flags)
*out |= BASE_MEM_GPU_VA_SAME_4GB_PAGE;
if (mali_kbase_supports_mem_import_sync_on_map_unmap(kctx->api_version)) {
if (mali_kbase_supports_query_mem_import_sync_on_map_unmap(kctx->api_version)) {
if (reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) {
if (reg->gpu_alloc->imported.umm.need_sync)
*out |= BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP;
}
}
if (mali_kbase_supports_mem_kernel_sync(kctx->api_version)) {
if (mali_kbase_supports_query_mem_kernel_sync(kctx->api_version)) {
if (unlikely(reg->cpu_alloc != reg->gpu_alloc))
*out |= BASE_MEM_KERNEL_SYNC;
}
if (mali_kbase_supports_mem_same_va(kctx->api_version)) {
if (mali_kbase_supports_query_mem_same_va(kctx->api_version)) {
if (kbase_bits_to_zone(reg->flags) == SAME_VA_ZONE) {
/* Imported memory is an edge case, where declaring it SAME_VA
* would be ambiguous.
@ -746,7 +740,7 @@ static unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s
kctx = KBASE_GET_KBASE_DATA_FROM_SHRINKER(s, struct kbase_context, reclaim);
#if MALI_USE_CSF
if (!down_read_trylock(&kctx->kbdev->csf.pmode_sync_sem)) {
if (!down_read_trylock(&kctx->kbdev->csf.mmu_sync_sem)) {
dev_warn(kctx->kbdev->dev,
"Can't shrink GPU memory when P.Mode entrance is in progress");
return 0;
@ -791,7 +785,7 @@ static unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s
mutex_unlock(&kctx->jit_evict_lock);
#if MALI_USE_CSF
up_read(&kctx->kbdev->csf.pmode_sync_sem);
up_read(&kctx->kbdev->csf.mmu_sync_sem);
#endif
return freed;
}
@ -886,7 +880,7 @@ void kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc)
/* Indicate to page migration that the memory can be reclaimed by the shrinker.
*/
if (kbase_is_page_migration_enabled())
kbase_set_phy_alloc_page_status(gpu_alloc, NOT_MOVABLE);
kbase_set_phy_alloc_page_status(kctx, gpu_alloc, NOT_MOVABLE);
mutex_unlock(&kctx->jit_evict_lock);
kbase_mem_evictable_mark_reclaim(gpu_alloc);
@ -944,7 +938,7 @@ bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *gpu_alloc)
* from.
*/
if (kbase_is_page_migration_enabled())
kbase_set_phy_alloc_page_status(gpu_alloc, ALLOCATED_MAPPED);
kbase_set_phy_alloc_page_status(kctx, gpu_alloc, ALLOCATED_MAPPED);
}
}
@ -962,7 +956,8 @@ bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *gpu_alloc)
*
* Return: 0 on success, error code otherwise.
*/
static int kbase_mem_flags_change_imported_umm(struct kbase_context *kctx, unsigned int flags,
static int kbase_mem_flags_change_imported_umm(struct kbase_context *kctx,
base_mem_alloc_flags flags,
struct kbase_va_region *reg)
{
unsigned int real_flags = 0;
@ -1045,7 +1040,7 @@ static int kbase_mem_flags_change_imported_umm(struct kbase_context *kctx, unsig
*
* Return: 0 on success, error code otherwise.
*/
static int kbase_mem_flags_change_native(struct kbase_context *kctx, unsigned int flags,
static int kbase_mem_flags_change_native(struct kbase_context *kctx, base_mem_alloc_flags flags,
struct kbase_va_region *reg)
{
bool kbase_reg_dont_need_flag = (KBASE_REG_DONT_NEED & reg->flags);
@ -1077,8 +1072,8 @@ static int kbase_mem_flags_change_native(struct kbase_context *kctx, unsigned in
return ret;
}
int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned int flags,
unsigned int mask)
int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, base_mem_alloc_flags flags,
base_mem_alloc_flags mask)
{
struct kbase_va_region *reg;
int ret = -EINVAL;
@ -1468,7 +1463,7 @@ static int get_umm_memory_group_id(struct kbase_context *kctx, struct dma_buf *d
* object that wraps the dma-buf.
*/
static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx, int fd, u64 *va_pages,
u64 *flags, u32 padding)
base_mem_alloc_flags *flags, u32 padding)
{
struct kbase_va_region *reg;
struct dma_buf *dma_buf;
@ -1614,7 +1609,8 @@ u32 kbase_get_cache_line_alignment(struct kbase_device *kbdev)
static struct kbase_va_region *kbase_mem_from_user_buffer(struct kbase_context *kctx,
unsigned long address, unsigned long size,
u64 *va_pages, u64 *flags)
u64 *va_pages,
base_mem_alloc_flags *flags)
{
struct kbase_va_region *reg;
enum kbase_memory_zone zone = CUSTOM_VA_ZONE;
@ -1746,7 +1742,7 @@ bad_size:
return NULL;
}
u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, u64 nents,
u64 kbase_mem_alias(struct kbase_context *kctx, base_mem_alloc_flags *flags, u64 stride, u64 nents,
struct base_mem_aliasing_info *ai, u64 *num_pages)
{
struct kbase_va_region *reg;
@ -1968,7 +1964,8 @@ bad_flags:
}
int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type,
void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages, u64 *flags)
void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages,
base_mem_alloc_flags *flags)
{
struct kbase_va_region *reg;
@ -3107,7 +3104,7 @@ static int kbase_vmap_phy_pages(struct kbase_context *kctx, struct kbase_va_regi
return -ENOMEM;
}
if (reg->flags & KBASE_REG_DONT_NEED)
if (kbase_is_region_shrinkable(reg))
return -EINVAL;
prot = PAGE_KERNEL;

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -51,7 +51,7 @@ struct kbase_hwc_dma_mapping {
* Return: 0 on success or error code
*/
struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages, u64 commit_pages,
u64 extension, u64 *flags, u64 *gpu_va,
u64 extension, base_mem_alloc_flags *flags, u64 *gpu_va,
enum kbase_caller_mmu_sync_info mmu_sync_info);
/**
@ -84,7 +84,8 @@ int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query, u64 *co
* Return: 0 on success or error code
*/
int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type,
void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages, u64 *flags);
void __user *phandle, u32 padding, u64 *gpu_va, u64 *va_pages,
base_mem_alloc_flags *flags);
/**
* kbase_mem_alias - Create a new allocation for GPU, aliasing one or more
@ -99,7 +100,7 @@ int kbase_mem_import(struct kbase_context *kctx, enum base_mem_import_type type,
*
* Return: 0 on failure or otherwise the GPU VA for the alias
*/
u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, u64 nents,
u64 kbase_mem_alias(struct kbase_context *kctx, base_mem_alloc_flags *flags, u64 stride, u64 nents,
struct base_mem_aliasing_info *ai, u64 *num_pages);
/**
@ -112,8 +113,8 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, u64 nent
*
* Return: 0 on success or error code
*/
int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned int flags,
unsigned int mask);
int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, base_mem_alloc_flags flags,
base_mem_alloc_flags mask);
/**
* kbase_mem_commit - Change the physical backing size of a region

View file

@ -68,6 +68,12 @@ bool kbase_alloc_page_metadata(struct kbase_device *kbdev, struct page *p, dma_a
if (!IS_ENABLED(CONFIG_PAGE_MIGRATION_SUPPORT))
return false;
/* Composite large-page is excluded from migration, trigger a warn if a development
* wrongly leads to it.
*/
if (is_huge_head(as_tagged(page_to_phys(p))) || is_partial(as_tagged(page_to_phys(p))))
dev_WARN(kbdev->dev, "%s: migration-metadata attempted on large-page.", __func__);
page_md = kzalloc(sizeof(struct kbase_page_metadata), GFP_KERNEL);
if (!page_md)
return false;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -122,12 +122,16 @@ static vm_fault_t kbase_native_mgm_vmf_insert_pfn_prot(struct memory_group_manag
}
static u64 kbase_native_mgm_update_gpu_pte(struct memory_group_manager_device *mgm_dev,
unsigned int group_id, int mmu_level, u64 pte)
unsigned int group_id, unsigned int pbha_id,
unsigned int pte_flags, int mmu_level, u64 pte)
{
if (WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS))
return pte;
pte |= ((u64)group_id << PTE_PBHA_SHIFT) & PTE_PBHA_MASK;
if ((pte_flags & BIT(MMA_VIOLATION)) && pbha_id) {
pr_warn_once("MMA violation! Applying PBHA override workaround to PTE\n");
pte |= ((u64)pbha_id << PTE_PBHA_SHIFT) & PTE_PBHA_MASK;
}
/* Address could be translated into a different bus address here */
pte |= ((u64)1 << PTE_RES_BIT_MULTI_AS_SHIFT);
@ -150,14 +154,24 @@ static u64 kbase_native_mgm_pte_to_original_pte(struct memory_group_manager_devi
return pte;
}
static bool kbase_native_mgm_get_import_memory_cached_access_permitted(
struct memory_group_manager_device *mgm_dev,
struct memory_group_manager_import_data *import_data)
{
CSTD_UNUSED(mgm_dev);
CSTD_UNUSED(import_data);
return true;
}
struct memory_group_manager_device kbase_native_mgm_dev = {
.ops = {
.mgm_alloc_page = kbase_native_mgm_alloc,
.mgm_free_page = kbase_native_mgm_free,
.mgm_get_import_memory_id = NULL,
.mgm_vmf_insert_pfn_prot = kbase_native_mgm_vmf_insert_pfn_prot,
.mgm_update_gpu_pte = kbase_native_mgm_update_gpu_pte,
.mgm_pte_to_original_pte = kbase_native_mgm_pte_to_original_pte,
},
.ops = { .mgm_alloc_page = kbase_native_mgm_alloc,
.mgm_free_page = kbase_native_mgm_free,
.mgm_get_import_memory_id = NULL,
.mgm_vmf_insert_pfn_prot = kbase_native_mgm_vmf_insert_pfn_prot,
.mgm_update_gpu_pte = kbase_native_mgm_update_gpu_pte,
.mgm_pte_to_original_pte = kbase_native_mgm_pte_to_original_pte,
.mgm_get_import_memory_cached_access_permitted =
kbase_native_mgm_get_import_memory_cached_access_permitted },
.data = NULL
};

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
* (C) COPYRIGHT 2021-2023 ARM Limited. All rights reserved.
* (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@ -220,6 +220,24 @@ void kbase_pbha_write_settings(struct kbase_device *kbdev)
for (i = 0; i < GPU_SYSC_ALLOC_COUNT; ++i)
kbase_reg_write32(kbdev, GPU_SYSC_ALLOC_OFFSET(i), kbdev->sysc_alloc[i]);
}
if (kbdev->mma_wa_id) {
/* PBHA OVERRIDE register index (0-3) */
uint reg_index = kbdev->mma_wa_id >> 2;
/* PBHA index within a PBHA OVERRIDE register (0-3) */
uint pbha_index = kbdev->mma_wa_id & 0x3;
/* 4 bits of read attributes + 4 bits of write attributes for each PBHA */
uint pbha_shift = pbha_index * 8;
/* Noncacheable read = noncacheable write = b0001*/
uint pbha_override_rw_noncacheable = 0x01 | 0x10;
u32 pbha_override_val =
kbase_reg_read32(kbdev, GPU_SYSC_PBHA_OVERRIDE_OFFSET(reg_index));
pbha_override_val &= ~((u32)0xFF << pbha_shift);
pbha_override_val |= ((u32)pbha_override_rw_noncacheable << pbha_shift);
kbase_reg_write32(kbdev, GPU_SYSC_PBHA_OVERRIDE_OFFSET(reg_index),
pbha_override_val);
}
#else
CSTD_UNUSED(kbdev);
#endif /* MALI_USE_CSF */
@ -280,7 +298,7 @@ static int kbase_pbha_read_propagate_bits_property(struct kbase_device *kbdev,
u8 bits = 0;
int err;
if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU))
if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PBHA_HWU))
return 0;
err = of_property_read_u8(pbha_node, "propagate-bits", &bits);
@ -310,6 +328,43 @@ static int kbase_pbha_read_propagate_bits_property(struct kbase_device *kbdev,
kbdev->pbha_propagate_bits = bits;
return 0;
}
static int kbase_pbha_read_mma_wa_id_property(struct kbase_device *kbdev,
const struct device_node *pbha_node)
{
u32 mma_wa_id = 0;
int err;
/* Skip if kbdev->mma_wa_id has already been set via the module parameter */
if ((kbdev->gpu_props.gpu_id.arch_id < GPU_ID_ARCH_MAKE(14, 8, 0)) || kbdev->mma_wa_id != 0)
return 0;
err = of_property_read_u32(pbha_node, "mma-wa-id", &mma_wa_id);
/* Property does not exist. This is not a mandatory property, ignore this error */
if (err == -EINVAL)
return 0;
if (err == -ENODATA) {
dev_err(kbdev->dev, "DTB property mma-wa-id has no value\n");
return err;
}
if (err == -EOVERFLOW) {
dev_err(kbdev->dev, "DTB value for mma-wa-id is out of range\n");
return err;
}
if (mma_wa_id == 0 || mma_wa_id > 15) {
dev_err(kbdev->dev,
"Invalid DTB value for mma-wa-id: %u. Valid range is between 1 and 15.\n",
mma_wa_id);
return -EINVAL;
}
kbdev->mma_wa_id = mma_wa_id;
return 0;
}
#endif /* MALI_USE_CSF */
int kbase_pbha_read_dtb(struct kbase_device *kbdev)
@ -331,6 +386,12 @@ int kbase_pbha_read_dtb(struct kbase_device *kbdev)
return err;
err = kbase_pbha_read_propagate_bits_property(kbdev, pbha_node);
if (err < 0)
return err;
err = kbase_pbha_read_mma_wa_id_property(kbdev, pbha_node);
return err;
#else
return 0;

View file

@ -234,7 +234,7 @@ void kbase_pbha_debugfs_init(struct kbase_device *kbdev)
debugfs_create_file("int_id_overrides", mode, debugfs_pbha_dir, kbdev,
&pbha_int_id_overrides_fops);
#if MALI_USE_CSF
if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU))
if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PBHA_HWU))
debugfs_create_file("propagate_bits", mode, debugfs_pbha_dir, kbdev,
&pbha_propagate_bits_fops);
#endif /* MALI_USE_CSF */

Some files were not shown because too many files have changed in this diff Show more