Merge b2680ba4a2 ("Merge tag 'spi-fix-v7.1-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi") into android-mainline
Steps on the way to v7.1-rc1 Change-Id: I62f12709eed9c3c2ba9550cd36dc8a3ac42c89b7 Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
commit
618e820017
226 files changed
+2807
-1461
No files matched your search
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2022 - 2025 Texas Instruments Incorporated
|
||||
# Copyright (C) 2022 - 2026 Texas Instruments Incorporated
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/ti,tas2781.yaml#
|
||||
@@ -107,6 +107,9 @@ properties:
|
||||
|
||||
ti,tas5830: 65-W Stereo, Digital Input, High Efficiency Closed-Loop
|
||||
Class-D Amplifier with Class-H Algorithm
|
||||
|
||||
ti,tas5832: 81-W Stereo, Digital Input, High Efficiency Closed-Loop
|
||||
Class-D Amplifier with Class-H Algorithm
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
@@ -128,6 +131,7 @@ properties:
|
||||
- ti,tas5827
|
||||
- ti,tas5828
|
||||
- ti,tas5830
|
||||
- ti,tas5832
|
||||
- const: ti,tas2781
|
||||
- enum:
|
||||
- ti,tas2781
|
||||
@@ -264,6 +268,7 @@ allOf:
|
||||
- ti,tas5827
|
||||
- ti,tas5828
|
||||
- ti,tas5830
|
||||
- ti,tas5832
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
|
||||
@@ -59,7 +59,7 @@ unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi@4c0 {
|
||||
compatible = "fsl,spi";
|
||||
@@ -67,8 +67,8 @@ examples:
|
||||
cell-index = <0>;
|
||||
interrupts = <82 0>;
|
||||
mode = "cpu";
|
||||
cs-gpios = <&gpio 18 IRQ_TYPE_EDGE_RISING // device reg=<0>
|
||||
&gpio 19 IRQ_TYPE_EDGE_RISING>; // device reg=<1>
|
||||
cs-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>, // device reg=<0>
|
||||
<&gpio 19 GPIO_ACTIVE_HIGH>; // device reg=<1>
|
||||
};
|
||||
|
||||
...
|
||||
@@ -20,7 +20,7 @@
|
||||
| openrisc: | TODO |
|
||||
| parisc: | TODO |
|
||||
| powerpc: | ok |
|
||||
| riscv: | TODO |
|
||||
| riscv: | ok |
|
||||
| s390: | ok |
|
||||
| sh: | ok |
|
||||
| sparc: | TODO |
|
||||
|
||||
+12
-5
@@ -8602,10 +8602,17 @@ S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/gma500/
|
||||
|
||||
DRM DRIVERS FOR HISILICON
|
||||
M: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
DRM DRIVERS FOR HISILICON HIBMC
|
||||
M: Yongbang Shi <shiyongbang@huawei.com>
|
||||
M: Tian Tao <tiantao6@hisilicon.com>
|
||||
R: Xinwei Kong <kong.kongxinwei@hisilicon.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/hisilicon/hibmc
|
||||
|
||||
DRM DRIVERS FOR HISILICON KIRIN
|
||||
M: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
R: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
R: Yongqin Liu <yongqin.liu@linaro.org>
|
||||
R: John Stultz <jstultz@google.com>
|
||||
@@ -8613,7 +8620,7 @@ L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/hisilicon/
|
||||
F: drivers/gpu/drm/hisilicon/
|
||||
F: drivers/gpu/drm/hisilicon/kirin
|
||||
|
||||
DRM DRIVERS FOR LIMA
|
||||
M: Qiang Yu <yuq825@gmail.com>
|
||||
@@ -24656,8 +24663,8 @@ F: Documentation/devicetree/bindings/net/socionext,synquacer-netsec.yaml
|
||||
F: drivers/net/ethernet/socionext/netsec.c
|
||||
|
||||
SOCIONEXT (SNI) Synquacer SPI DRIVER
|
||||
M: Masahisa Kojima <masahisa.kojima@linaro.org>
|
||||
M: Jassi Brar <jaswinder.singh@linaro.org>
|
||||
M: Masahisa Kojima <kojima.masahisa@socionext.com>
|
||||
M: Jassi Brar <jassisinghbrar@gmail.com>
|
||||
L: linux-spi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml
|
||||
|
||||
+24
-63
@@ -47,8 +47,8 @@ config RISCV
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SET_DIRECT_MAP if MMU
|
||||
select ARCH_HAS_SET_MEMORY if MMU
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if MMU
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if MMU
|
||||
select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
|
||||
select ARCH_HAS_SYSCALL_WRAPPER
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
@@ -84,7 +84,7 @@ config RISCV
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select ARCH_WANT_GENERAL_HUGETLB if !RISCV_ISA_SVNAPOT
|
||||
select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
|
||||
select ARCH_WANT_LD_ORPHAN_WARN if !XIP_KERNEL
|
||||
select ARCH_WANT_LD_ORPHAN_WARN
|
||||
select ARCH_WANT_OPTIMIZE_DAX_VMEMMAP
|
||||
select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP
|
||||
select ARCH_WANTS_NO_INSTR
|
||||
@@ -112,6 +112,7 @@ config RISCV
|
||||
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO && 64BIT
|
||||
select GENERIC_IDLE_POLL_SETUP
|
||||
select GENERIC_IOREMAP if MMU
|
||||
select HAVE_IOREMAP_PROT if MMU
|
||||
select GENERIC_IRQ_IPI if SMP
|
||||
select GENERIC_IRQ_IPI_MUX if SMP
|
||||
select GENERIC_IRQ_MULTI_HANDLER
|
||||
@@ -129,13 +130,13 @@ config RISCV
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP
|
||||
select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_KASAN if MMU && 64BIT
|
||||
select HAVE_ARCH_KASAN_VMALLOC if MMU && 64BIT
|
||||
select HAVE_ARCH_KFENCE if MMU && 64BIT
|
||||
select HAVE_ARCH_KSTACK_ERASE
|
||||
select HAVE_ARCH_KGDB if !XIP_KERNEL
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_KGDB_QXFER_PKT
|
||||
select HAVE_ARCH_MMAP_RND_BITS if MMU
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
||||
@@ -153,7 +154,7 @@ config RISCV
|
||||
select HAVE_CONTEXT_TRACKING_USER
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_DMA_CONTIGUOUS if MMU
|
||||
select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE)
|
||||
select HAVE_DYNAMIC_FTRACE if MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE)
|
||||
select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI)
|
||||
@@ -161,7 +162,7 @@ config RISCV
|
||||
select HAVE_FTRACE_GRAPH_FUNC
|
||||
select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
select HAVE_FUNCTION_GRAPH_FREGS
|
||||
select HAVE_FUNCTION_TRACER if !XIP_KERNEL && HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FUNCTION_TRACER if HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_EBPF_JIT if MMU
|
||||
select HAVE_GENERIC_TIF_BITS
|
||||
select HAVE_GUP_FAST if MMU
|
||||
@@ -170,16 +171,16 @@ config RISCV
|
||||
select HAVE_GCC_PLUGINS
|
||||
select HAVE_GENERIC_VDSO if MMU
|
||||
select HAVE_IRQ_TIME_ACCOUNTING
|
||||
select HAVE_KERNEL_BZIP2 if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_GZIP if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_LZ4 if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_LZMA if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_LZO if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_UNCOMPRESSED if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_ZSTD if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_XZ if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KPROBES if !XIP_KERNEL
|
||||
select HAVE_KRETPROBES if !XIP_KERNEL
|
||||
select HAVE_KERNEL_BZIP2 if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_GZIP if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_LZ4 if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_LZMA if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_LZO if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_UNCOMPRESSED if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_ZSTD if !EFI_ZBOOT
|
||||
select HAVE_KERNEL_XZ if !EFI_ZBOOT
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
# https://github.com/ClangBuiltLinux/linux/issues/1881
|
||||
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD
|
||||
select HAVE_MOVE_PMD
|
||||
@@ -190,9 +191,9 @@ config RISCV
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_POSIX_CPU_TIMERS_TASK_WORK
|
||||
select HAVE_PREEMPT_DYNAMIC_KEY if !XIP_KERNEL
|
||||
select HAVE_PREEMPT_DYNAMIC_KEY
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RETHOOK if !XIP_KERNEL
|
||||
select HAVE_RETHOOK
|
||||
select HAVE_RSEQ
|
||||
select HAVE_RUST if RUSTC_SUPPORTS_RISCV && CC_IS_CLANG
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT
|
||||
@@ -213,7 +214,7 @@ config RISCV
|
||||
select PCI_ECAM if (ACPI && PCI)
|
||||
select PCI_MSI if PCI
|
||||
select RELOCATABLE if !MMU && !PHYS_RAM_BASE_FIXED
|
||||
select RISCV_ALTERNATIVE if !XIP_KERNEL
|
||||
select RISCV_ALTERNATIVE
|
||||
select RISCV_APLIC
|
||||
select RISCV_IMSIC
|
||||
select RISCV_INTC
|
||||
@@ -537,7 +538,6 @@ endchoice
|
||||
|
||||
config RISCV_ALTERNATIVE
|
||||
bool
|
||||
depends on !XIP_KERNEL
|
||||
help
|
||||
This Kconfig allows the kernel to automatically patch the
|
||||
erratum or cpufeature required by the execution platform at run
|
||||
@@ -1126,7 +1126,6 @@ config PARAVIRT_TIME_ACCOUNTING
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Build a relocatable kernel"
|
||||
depends on !XIP_KERNEL
|
||||
select MODULE_SECTIONS if MODULES
|
||||
select ARCH_VMLINUX_NEEDS_RELOCS
|
||||
help
|
||||
@@ -1143,7 +1142,7 @@ config RELOCATABLE
|
||||
config RANDOMIZE_BASE
|
||||
bool "Randomize the address of the kernel image"
|
||||
select RELOCATABLE
|
||||
depends on MMU && 64BIT && !XIP_KERNEL
|
||||
depends on MMU && 64BIT
|
||||
help
|
||||
Randomizes the virtual address at which the kernel image is
|
||||
loaded, as a security feature that deters exploit attempts
|
||||
@@ -1233,7 +1232,7 @@ config EFI_STUB
|
||||
|
||||
config EFI
|
||||
bool "UEFI runtime support"
|
||||
depends on OF && !XIP_KERNEL
|
||||
depends on OF
|
||||
depends on MMU
|
||||
default y
|
||||
select ARCH_SUPPORTS_ACPI if 64BIT
|
||||
@@ -1284,44 +1283,6 @@ config PHYS_RAM_BASE
|
||||
explicitly specified to run early relocations of read-write data
|
||||
from flash to RAM.
|
||||
|
||||
config XIP_KERNEL
|
||||
bool "Kernel Execute-In-Place from ROM"
|
||||
depends on MMU && SPARSEMEM && NONPORTABLE
|
||||
# This prevents XIP from being enabled by all{yes,mod}config, which
|
||||
# fail to build since XIP doesn't support large kernels.
|
||||
depends on !COMPILE_TEST
|
||||
select PHYS_RAM_BASE_FIXED
|
||||
help
|
||||
Execute-In-Place allows the kernel to run from non-volatile storage
|
||||
directly addressable by the CPU, such as NOR flash. This saves RAM
|
||||
space since the text section of the kernel is not loaded from flash
|
||||
to RAM. Read-write sections, such as the data section and stack,
|
||||
are still copied to RAM. The XIP kernel is not compressed since
|
||||
it has to run directly from flash, so it will take more space to
|
||||
store it. The flash address used to link the kernel object files,
|
||||
and for storing it, is configuration dependent. Therefore, if you
|
||||
say Y here, you must know the proper physical address where to
|
||||
store the kernel image depending on your own flash memory usage.
|
||||
|
||||
Also note that the make target becomes "make xipImage" rather than
|
||||
"make zImage" or "make Image". The final kernel binary to put in
|
||||
ROM memory will be arch/riscv/boot/xipImage.
|
||||
|
||||
SPARSEMEM is required because the kernel text and rodata that are
|
||||
flash resident are not backed by memmap, then any attempt to get
|
||||
a struct page on those regions will trigger a fault.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config XIP_PHYS_ADDR
|
||||
hex "XIP Kernel Physical Location"
|
||||
depends on XIP_KERNEL
|
||||
default "0x21000000"
|
||||
help
|
||||
This is the physical address in your flash memory the kernel will
|
||||
be linked for and stored to. This address is dependent on your
|
||||
own flash usage.
|
||||
|
||||
config RISCV_ISA_FALLBACK
|
||||
bool "Permit falling back to parsing riscv,isa for extension support by default"
|
||||
default y
|
||||
|
||||
@@ -2,7 +2,7 @@ menu "SoC selection"
|
||||
|
||||
config ARCH_ANDES
|
||||
bool "Andes SoCs"
|
||||
depends on MMU && !XIP_KERNEL
|
||||
depends on MMU
|
||||
select ERRATA_ANDES
|
||||
help
|
||||
This enables support for Andes SoC platform hardware.
|
||||
@@ -33,7 +33,7 @@ config ARCH_RENESAS
|
||||
|
||||
config ARCH_SIFIVE
|
||||
bool "SiFive SoCs"
|
||||
select ERRATA_SIFIVE if !XIP_KERNEL
|
||||
select ERRATA_SIFIVE
|
||||
help
|
||||
This enables support for SiFive SoC platform hardware.
|
||||
|
||||
@@ -61,7 +61,7 @@ config SOC_STARFIVE
|
||||
|
||||
config ARCH_SUNXI
|
||||
bool "Allwinner sun20i SoCs"
|
||||
depends on MMU && !XIP_KERNEL
|
||||
depends on MMU
|
||||
select ERRATA_THEAD
|
||||
select SUN4I_TIMER
|
||||
help
|
||||
@@ -78,7 +78,7 @@ config ARCH_TENSTORRENT
|
||||
|
||||
config ARCH_THEAD
|
||||
bool "T-HEAD RISC-V SoCs"
|
||||
depends on MMU && !XIP_KERNEL
|
||||
depends on MMU
|
||||
select ERRATA_THEAD
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
|
||||
+2
-5
@@ -28,7 +28,6 @@ endif
|
||||
export BITS
|
||||
ifeq ($(CONFIG_ARCH_RV64I),y)
|
||||
BITS := 64
|
||||
UTS_MACHINE := riscv64
|
||||
|
||||
KBUILD_CFLAGS += -mabi=lp64
|
||||
KBUILD_AFLAGS += -mabi=lp64
|
||||
@@ -39,13 +38,14 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
|
||||
-Cno-redzone
|
||||
else
|
||||
BITS := 32
|
||||
UTS_MACHINE := riscv32
|
||||
|
||||
KBUILD_CFLAGS += -mabi=ilp32
|
||||
KBUILD_AFLAGS += -mabi=ilp32
|
||||
KBUILD_LDFLAGS += -melf32lriscv
|
||||
endif
|
||||
|
||||
UTS_MACHINE := riscv$(BITS)
|
||||
|
||||
# LLVM has an issue with target-features and LTO: https://github.com/llvm/llvm-project/issues/59350
|
||||
# Ensure it is aware of linker relaxation with LTO, otherwise relocations may
|
||||
# be incorrect: https://github.com/llvm/llvm-project/issues/65090
|
||||
@@ -150,7 +150,6 @@ ifdef CONFIG_RISCV_M_MODE
|
||||
boot-image-$(CONFIG_SOC_CANAAN_K210) := loader.bin
|
||||
endif
|
||||
boot-image-$(CONFIG_EFI_ZBOOT) := vmlinuz.efi
|
||||
boot-image-$(CONFIG_XIP_KERNEL) := xipImage
|
||||
KBUILD_IMAGE := $(boot)/$(boot-image-y)
|
||||
|
||||
libs-y += arch/riscv/lib/
|
||||
@@ -218,8 +217,6 @@ define archhelp
|
||||
echo ' Image.xz - Compressed kernel image (arch/riscv/boot/Image.xz)'
|
||||
echo ' vmlinuz.efi - Compressed EFI kernel image (arch/riscv/boot/vmlinuz.efi)'
|
||||
echo ' Default when CONFIG_EFI_ZBOOT=y'
|
||||
echo ' xipImage - Execute-in-place kernel image (arch/riscv/boot/xipImage)'
|
||||
echo ' Default when CONFIG_XIP_KERNEL=y'
|
||||
echo ' install - Install kernel using (your) ~/bin/$(INSTALLKERNEL) or'
|
||||
echo ' (distribution) /sbin/$(INSTALLKERNEL) or install to '
|
||||
echo ' $$(INSTALL_PATH)'
|
||||
|
||||
@@ -20,17 +20,6 @@ OBJCOPYFLAGS_xipImage :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
|
||||
|
||||
targets := Image Image.* loader loader.o loader.lds loader.bin xipImage
|
||||
|
||||
ifeq ($(CONFIG_XIP_KERNEL),y)
|
||||
|
||||
quiet_cmd_mkxip = $(quiet_cmd_objcopy)
|
||||
cmd_mkxip = $(cmd_objcopy)
|
||||
|
||||
$(obj)/xipImage: vmlinux FORCE
|
||||
$(call if_changed,mkxip)
|
||||
@$(kecho) ' Physical Address of xipImage: $(CONFIG_XIP_PHYS_ADDR)'
|
||||
|
||||
endif
|
||||
|
||||
$(obj)/Image: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ static bool errata_probe_ghostwrite(unsigned int stage,
|
||||
* target-c9xx cores report arch_id and impid as 0
|
||||
*
|
||||
* While ghostwrite may not affect all c9xx cores that implement
|
||||
* xtheadvector, there is no futher granularity than c9xx. Assume
|
||||
* xtheadvector, there is no further granularity than c9xx. Assume
|
||||
* vulnerable for this entire class of processors when xtheadvector is
|
||||
* enabled.
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,7 @@ asmlinkage void riscv_v_context_nesting_end(struct pt_regs *regs);
|
||||
#define DECLARE_DO_ERROR_INFO(name) asmlinkage void name(struct pt_regs *regs)
|
||||
|
||||
DECLARE_DO_ERROR_INFO(do_trap_unknown);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_hardware_error);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_insn_misaligned);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_insn_fault);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_insn_illegal);
|
||||
|
||||
@@ -46,7 +46,7 @@ static __always_inline void arch_atomic64_set(atomic64_t *v, s64 i)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* First, the atomic ops that have no ordering constraints and therefor don't
|
||||
* First, the atomic ops that have no ordering constraints and therefore don't
|
||||
* have the AQ or RL bits set. These don't return anything, so there's only
|
||||
* one version to worry about.
|
||||
*/
|
||||
@@ -81,7 +81,7 @@ ATOMIC_OPS(xor, xor, i)
|
||||
|
||||
/*
|
||||
* Atomic ops that have ordered, relaxed, acquire, and release variants.
|
||||
* There's two flavors of these: the arithmatic ops have both fetch and return
|
||||
* There's two flavors of these: the arithmetic ops have both fetch and return
|
||||
* versions, while the logical ops only have fetch versions.
|
||||
*/
|
||||
#define ATOMIC_FETCH_OP(op, asm_op, I, asm_type, c_type, prefix) \
|
||||
|
||||
@@ -59,8 +59,8 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provides information on the availiable set of ISA extensions to userspace,
|
||||
* via a bitmap that coorespends to each single-letter ISA extension. This is
|
||||
* Provides information on the available set of ISA extensions to userspace,
|
||||
* via a bitmap that corresponds to each single-letter ISA extension. This is
|
||||
* essentially defunct, but will remain for compatibility with userspace.
|
||||
*/
|
||||
#define ELF_HWCAP riscv_get_elf_hwcap()
|
||||
|
||||
@@ -29,11 +29,7 @@
|
||||
#define PAGE_OFFSET_L5 _AC(0xff60000000000000, UL)
|
||||
#define PAGE_OFFSET_L4 _AC(0xffffaf8000000000, UL)
|
||||
#define PAGE_OFFSET_L3 _AC(0xffffffd600000000, UL)
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define PAGE_OFFSET PAGE_OFFSET_L3
|
||||
#else
|
||||
#define PAGE_OFFSET kernel_map.page_offset
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
#else
|
||||
#define PAGE_OFFSET _AC(0xc0000000, UL)
|
||||
#endif /* CONFIG_64BIT */
|
||||
@@ -104,15 +100,8 @@ struct kernel_mapping {
|
||||
/* Offset between linear mapping virtual address and kernel load address */
|
||||
unsigned long va_pa_offset;
|
||||
/* Offset between kernel mapping virtual address and kernel load address */
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
unsigned long va_kernel_xip_text_pa_offset;
|
||||
unsigned long va_kernel_xip_data_pa_offset;
|
||||
uintptr_t xiprom;
|
||||
uintptr_t xiprom_sz;
|
||||
#else
|
||||
unsigned long page_offset;
|
||||
unsigned long va_kernel_pa_offset;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct kernel_mapping kernel_map;
|
||||
@@ -131,16 +120,7 @@ extern unsigned long vmemmap_start_pfn;
|
||||
void *linear_mapping_pa_to_va(unsigned long x);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define kernel_mapping_pa_to_va(y) ({ \
|
||||
unsigned long _y = (unsigned long)(y); \
|
||||
(_y < phys_ram_base) ? \
|
||||
(void *)(_y + kernel_map.va_kernel_xip_text_pa_offset) : \
|
||||
(void *)(_y + kernel_map.va_kernel_xip_data_pa_offset); \
|
||||
})
|
||||
#else
|
||||
#define kernel_mapping_pa_to_va(y) ((void *)((unsigned long)(y) + kernel_map.va_kernel_pa_offset))
|
||||
#endif
|
||||
|
||||
#define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x)
|
||||
|
||||
@@ -150,16 +130,7 @@ void *linear_mapping_pa_to_va(unsigned long x);
|
||||
phys_addr_t linear_mapping_va_to_pa(unsigned long x);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define kernel_mapping_va_to_pa(y) ({ \
|
||||
unsigned long _y = (unsigned long)(y); \
|
||||
(_y < kernel_map.virt_addr + kernel_map.xiprom_sz) ? \
|
||||
(_y - kernel_map.va_kernel_xip_text_pa_offset) : \
|
||||
(_y - kernel_map.va_kernel_xip_data_pa_offset); \
|
||||
})
|
||||
#else
|
||||
#define kernel_mapping_va_to_pa(y) ((unsigned long)(y) - kernel_map.va_kernel_pa_offset)
|
||||
#endif
|
||||
|
||||
#define __va_to_pa_nodebug(x) ({ \
|
||||
unsigned long _x = x; \
|
||||
@@ -190,7 +161,10 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
|
||||
|
||||
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
|
||||
|
||||
unsigned long kaslr_offset(void);
|
||||
static inline unsigned long kaslr_offset(void)
|
||||
{
|
||||
return kernel_map.virt_offset;
|
||||
}
|
||||
|
||||
static __always_inline void *pfn_to_kaddr(unsigned long pfn)
|
||||
{
|
||||
|
||||
@@ -134,21 +134,6 @@
|
||||
|
||||
#include <linux/page_table_check.h>
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define XIP_FIXUP(addr) ({ \
|
||||
extern char _sdata[], _start[], _end[]; \
|
||||
uintptr_t __rom_start_data = CONFIG_XIP_PHYS_ADDR \
|
||||
+ (uintptr_t)&_sdata - (uintptr_t)&_start; \
|
||||
uintptr_t __rom_end_data = CONFIG_XIP_PHYS_ADDR \
|
||||
+ (uintptr_t)&_end - (uintptr_t)&_start; \
|
||||
uintptr_t __a = (uintptr_t)(addr); \
|
||||
(__a >= __rom_start_data && __a < __rom_end_data) ? \
|
||||
__a - __rom_start_data + CONFIG_PHYS_RAM_BASE : __a; \
|
||||
})
|
||||
#else
|
||||
#define XIP_FIXUP(addr) (addr)
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
struct pt_alloc_ops {
|
||||
pte_t *(*get_pte_virt)(phys_addr_t pa);
|
||||
phys_addr_t (*alloc_pte)(uintptr_t va);
|
||||
@@ -1272,13 +1257,8 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
|
||||
extern char _start[];
|
||||
extern void *_dtb_early_va;
|
||||
extern uintptr_t _dtb_early_pa;
|
||||
#if defined(CONFIG_XIP_KERNEL) && defined(CONFIG_MMU)
|
||||
#define dtb_early_va (*(void **)XIP_FIXUP(&_dtb_early_va))
|
||||
#define dtb_early_pa (*(uintptr_t *)XIP_FIXUP(&_dtb_early_pa))
|
||||
#else
|
||||
#define dtb_early_va _dtb_early_va
|
||||
#define dtb_early_pa _dtb_early_pa
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
extern u64 satp_mode;
|
||||
|
||||
void paging_init(void);
|
||||
|
||||
@@ -86,7 +86,7 @@ struct pt_regs;
|
||||
* preempt_v. All preempt_v context should be dropped in such case because
|
||||
* V-regs are caller-saved. Only sstatus.VS=ON is persisted across a
|
||||
* schedule() call.
|
||||
* - bit 30: The in-kernel preempt_v context is saved, and requries to be
|
||||
* - bit 30: The in-kernel preempt_v context is saved, and is required to be
|
||||
* restored when returning to the context that owns the preempt_v.
|
||||
* - bit 31: The in-kernel preempt_v context is dirty, as signaled by the
|
||||
* trap entry code. Any context switches out-of current task need to save
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
/* Load init_shadow_call_stack to gp. */
|
||||
.macro scs_load_init_stack
|
||||
la gp, init_shadow_call_stack
|
||||
XIP_FIXUP_OFFSET gp
|
||||
.endm
|
||||
|
||||
/* Load the per-CPU IRQ shadow call stack to gp. */
|
||||
|
||||
@@ -47,7 +47,7 @@ bool kernel_page_present(struct page *page);
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_XIP_KERNEL)
|
||||
#if defined(CONFIG_STRICT_KERNEL_RWX)
|
||||
#ifdef CONFIG_64BIT
|
||||
#define SECTION_ALIGN (1 << 21)
|
||||
#else
|
||||
|
||||
@@ -105,7 +105,7 @@ static inline void riscv_ipi_set_virq_range(int virq, int nr)
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP)
|
||||
#if defined(CONFIG_HOTPLUG_CPU)
|
||||
bool cpu_has_hotplug(unsigned int cpu);
|
||||
#else
|
||||
static inline bool cpu_has_hotplug(unsigned int cpu)
|
||||
|
||||
@@ -28,6 +28,15 @@ extern asmlinkage __kernel_size_t strlen(const char *);
|
||||
|
||||
#define __HAVE_ARCH_STRNCMP
|
||||
extern asmlinkage int strncmp(const char *cs, const char *ct, size_t count);
|
||||
|
||||
#define __HAVE_ARCH_STRNLEN
|
||||
extern asmlinkage __kernel_size_t strnlen(const char *, size_t);
|
||||
|
||||
#define __HAVE_ARCH_STRCHR
|
||||
extern asmlinkage char *strchr(const char *, int);
|
||||
|
||||
#define __HAVE_ARCH_STRRCHR
|
||||
extern asmlinkage char *strrchr(const char *, int);
|
||||
#endif
|
||||
|
||||
/* For those files which don't want to check by kasan. */
|
||||
|
||||
@@ -120,7 +120,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
|
||||
#include <asm-generic/thread_info_tif.h>
|
||||
|
||||
#define TIF_32BIT 16 /* compat-mode 32bit process */
|
||||
#define TIF_RISCV_V_DEFER_RESTORE 17 /* restore Vector before returing to user */
|
||||
#define TIF_RISCV_V_DEFER_RESTORE 17 /* restore Vector before returning to user */
|
||||
|
||||
#define _TIF_RISCV_V_DEFER_RESTORE BIT(TIF_RISCV_V_DEFER_RESTORE)
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* XIP fixup macros, only useful in assembly.
|
||||
*/
|
||||
#ifndef _ASM_RISCV_XIP_FIXUP_H
|
||||
#define _ASM_RISCV_XIP_FIXUP_H
|
||||
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
.macro XIP_FIXUP_OFFSET reg
|
||||
/* Fix-up address in Flash into address in RAM early during boot before
|
||||
* MMU is up. Because generated code "thinks" data is in Flash, but it
|
||||
* is actually in RAM (actually data is also in Flash, but Flash is
|
||||
* read-only, thus we need to use the data residing in RAM).
|
||||
*
|
||||
* The start of data in Flash is _sdata and the start of data in RAM is
|
||||
* CONFIG_PHYS_RAM_BASE. So this fix-up essentially does this:
|
||||
* reg += CONFIG_PHYS_RAM_BASE - _start
|
||||
*/
|
||||
li t0, CONFIG_PHYS_RAM_BASE
|
||||
add \reg, \reg, t0
|
||||
la t0, _sdata
|
||||
sub \reg, \reg, t0
|
||||
.endm
|
||||
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||
/* In linker script, at the transition from read-only section to
|
||||
* writable section, the VMA is increased while LMA remains the same.
|
||||
* (See in linker script how _sdata, __data_loc and LOAD_OFFSET is
|
||||
* changed)
|
||||
*
|
||||
* Consequently, early during boot before MMU is up, the generated code
|
||||
* reads the "writable" section at wrong addresses, because VMA is used
|
||||
* by compiler to generate code, but the data is located in Flash using
|
||||
* LMA.
|
||||
*/
|
||||
la t0, _sdata
|
||||
sub \reg, \reg, t0
|
||||
la t0, __data_loc
|
||||
add \reg, \reg, t0
|
||||
.endm
|
||||
#else
|
||||
.macro XIP_FIXUP_OFFSET reg
|
||||
.endm
|
||||
.macro XIP_FIXUP_FLASH_OFFSET reg
|
||||
.endm
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,6 @@
|
||||
#ifndef _UAPI_ASM_RISCV_SETUP_H
|
||||
#define _UAPI_ASM_RISCV_SETUP_H
|
||||
|
||||
#define COMMAND_LINE_SIZE 1024
|
||||
#define COMMAND_LINE_SIZE 2048
|
||||
|
||||
#endif /* _UAPI_ASM_RISCV_SETUP_H */
|
||||
@@ -69,7 +69,7 @@ static int __init acpi_fadt_sanity_check(void)
|
||||
|
||||
/*
|
||||
* FADT is required on riscv; retrieve it to check its presence
|
||||
* and carry out revision and ACPI HW reduced compliancy tests
|
||||
* and carry out revision and ACPI HW reduced compliance tests
|
||||
*/
|
||||
status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@@ -85,12 +85,12 @@ static int __init acpi_fadt_sanity_check(void)
|
||||
* The revision in the table header is the FADT's Major revision. The
|
||||
* FADT also has a minor revision, which is stored in the FADT itself.
|
||||
*
|
||||
* TODO: Currently, we check for 6.5 as the minimum version to check
|
||||
* for HW_REDUCED flag. However, once RISC-V updates are released in
|
||||
* the ACPI spec, we need to update this check for exact minor revision
|
||||
* ACPI 6.6 is required for RISC-V as it introduces RISC-V specific
|
||||
* tables such as RHCT (RISC-V Hart Capabilities Table) and RIMT
|
||||
* (RISC-V I/O Mapping Table).
|
||||
*/
|
||||
if (table->revision < 6 || (table->revision == 6 && fadt->minor_revision < 5))
|
||||
pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 6.5+\n",
|
||||
if (table->revision < 6 || (table->revision == 6 && fadt->minor_revision < 6))
|
||||
pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 6.6+\n",
|
||||
table->revision, fadt->minor_revision);
|
||||
|
||||
if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
|
||||
|
||||
@@ -43,7 +43,6 @@ int __cpu_disable(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/*
|
||||
* Called on the thread which is asking for a CPU to be shutdown, if the
|
||||
* CPU reported dead to the hotplug core.
|
||||
@@ -75,4 +74,3 @@ void __noreturn arch_cpu_idle_dead(void)
|
||||
/* It should never reach here */
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
@@ -498,6 +498,7 @@ SYM_DATA_START_LOCAL(excp_vect_table)
|
||||
RISCV_PTR do_trap_unknown /* cause=16 */
|
||||
RISCV_PTR do_trap_unknown /* cause=17 */
|
||||
RISCV_PTR do_trap_software_check /* cause=18 is sw check exception */
|
||||
RISCV_PTR do_trap_hardware_error /* hardware error (19) */
|
||||
SYM_DATA_END_LABEL(excp_vect_table, SYM_L_LOCAL, excp_vect_table_end)
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
|
||||
@@ -148,7 +148,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long ad
|
||||
|
||||
/*
|
||||
* This is called early on, and isn't wrapped by
|
||||
* ftrace_arch_code_modify_{prepare,post_process}() and therefor doesn't hold
|
||||
* ftrace_arch_code_modify_{prepare,post_process}() and therefore doesn't hold
|
||||
* text_mutex, which triggers a lockdep failure. SMP isn't running so we could
|
||||
* just directly poke the text, but it's simpler to just take the lock
|
||||
* ourselves.
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/image.h>
|
||||
#include <asm/scs.h>
|
||||
#include <asm/xip_fixup.h>
|
||||
#include <asm/usercfi.h>
|
||||
#include "efi-header.S"
|
||||
|
||||
@@ -75,13 +74,12 @@ pe_head_start:
|
||||
relocate_enable_mmu:
|
||||
/* Relocate return address */
|
||||
la a1, kernel_map
|
||||
XIP_FIXUP_OFFSET a1
|
||||
REG_L a1, KERNEL_MAP_VIRT_ADDR(a1)
|
||||
la a2, _start
|
||||
sub a1, a1, a2
|
||||
add ra, ra, a1
|
||||
|
||||
/* Point stvec to virtual address of intruction after satp write */
|
||||
/* Point stvec to virtual address of instruction after satp write */
|
||||
la a2, 1f
|
||||
add a2, a2, a1
|
||||
csrw CSR_TVEC, a2
|
||||
@@ -89,7 +87,6 @@ relocate_enable_mmu:
|
||||
/* Compute satp for kernel page tables, but don't load it yet */
|
||||
srl a2, a0, PAGE_SHIFT
|
||||
la a1, satp_mode
|
||||
XIP_FIXUP_OFFSET a1
|
||||
REG_L a1, 0(a1)
|
||||
or a2, a2, a1
|
||||
|
||||
@@ -100,7 +97,6 @@ relocate_enable_mmu:
|
||||
* to ensure the new translations are in use.
|
||||
*/
|
||||
la a0, trampoline_pg_dir
|
||||
XIP_FIXUP_OFFSET a0
|
||||
srl a0, a0, PAGE_SHIFT
|
||||
or a0, a0, a1
|
||||
sfence.vma
|
||||
@@ -154,11 +150,9 @@ secondary_start_sbi:
|
||||
|
||||
/* a0 contains the hartid & a1 contains boot data */
|
||||
li a2, SBI_HART_BOOT_TASK_PTR_OFFSET
|
||||
XIP_FIXUP_OFFSET a2
|
||||
add a2, a2, a1
|
||||
REG_L tp, (a2)
|
||||
li a3, SBI_HART_BOOT_STACK_PTR_OFFSET
|
||||
XIP_FIXUP_OFFSET a3
|
||||
add a3, a3, a1
|
||||
REG_L sp, (a3)
|
||||
|
||||
@@ -167,7 +161,6 @@ secondary_start_sbi:
|
||||
#ifdef CONFIG_MMU
|
||||
/* Enable virtual memory and relocate to virtual address */
|
||||
la a0, swapper_pg_dir
|
||||
XIP_FIXUP_OFFSET a0
|
||||
call relocate_enable_mmu
|
||||
#endif
|
||||
call .Lsetup_trap_vector
|
||||
@@ -269,40 +262,13 @@ SYM_CODE_START(_start_kernel)
|
||||
.Lgood_cores:
|
||||
|
||||
/* The lottery system is only required for spinwait booting method */
|
||||
#ifndef CONFIG_XIP_KERNEL
|
||||
/* Pick one hart to run the main boot sequence */
|
||||
la a3, hart_lottery
|
||||
li a2, 1
|
||||
amoadd.w a3, a2, (a3)
|
||||
bnez a3, .Lsecondary_start
|
||||
|
||||
#else
|
||||
/* hart_lottery in flash contains a magic number */
|
||||
la a3, hart_lottery
|
||||
mv a2, a3
|
||||
XIP_FIXUP_OFFSET a2
|
||||
XIP_FIXUP_FLASH_OFFSET a3
|
||||
lw t1, (a3)
|
||||
amoswap.w t0, t1, (a2)
|
||||
/* first time here if hart_lottery in RAM is not set */
|
||||
beq t0, t1, .Lsecondary_start
|
||||
|
||||
#endif /* CONFIG_XIP */
|
||||
#endif /* CONFIG_RISCV_BOOT_SPINWAIT */
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
la sp, _end + THREAD_SIZE
|
||||
XIP_FIXUP_OFFSET sp
|
||||
mv s0, a0
|
||||
mv s1, a1
|
||||
call __copy_data
|
||||
|
||||
/* Restore a0 & a1 copy */
|
||||
mv a0, s0
|
||||
mv a1, s1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_XIP_KERNEL
|
||||
/* Clear BSS for flat non-ELF images */
|
||||
la a3, __bss_start
|
||||
la a4, __bss_stop
|
||||
@@ -312,20 +278,16 @@ SYM_CODE_START(_start_kernel)
|
||||
add a3, a3, RISCV_SZPTR
|
||||
blt a3, a4, .Lclear_bss
|
||||
.Lclear_bss_done:
|
||||
#endif
|
||||
la a2, boot_cpu_hartid
|
||||
XIP_FIXUP_OFFSET a2
|
||||
REG_S a0, (a2)
|
||||
|
||||
/* Initialize page tables and relocate to virtual addresses */
|
||||
la tp, init_task
|
||||
la sp, init_thread_union + THREAD_SIZE
|
||||
XIP_FIXUP_OFFSET sp
|
||||
addi sp, sp, -PT_SIZE_ON_STACK
|
||||
scs_load_init_stack
|
||||
#ifdef CONFIG_BUILTIN_DTB
|
||||
la a0, __dtb_start
|
||||
XIP_FIXUP_OFFSET a0
|
||||
#else
|
||||
mv a0, a1
|
||||
#endif /* CONFIG_BUILTIN_DTB */
|
||||
@@ -335,7 +297,6 @@ SYM_CODE_START(_start_kernel)
|
||||
call setup_vm
|
||||
#ifdef CONFIG_MMU
|
||||
la a0, early_pg_dir
|
||||
XIP_FIXUP_OFFSET a0
|
||||
call relocate_enable_mmu
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
@@ -374,9 +335,7 @@ SYM_CODE_START(_start_kernel)
|
||||
|
||||
slli a3, a0, LGREG
|
||||
la a1, __cpu_spinwait_stack_pointer
|
||||
XIP_FIXUP_OFFSET a1
|
||||
la a2, __cpu_spinwait_task_pointer
|
||||
XIP_FIXUP_OFFSET a2
|
||||
add a1, a3, a1
|
||||
add a2, a3, a2
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
extern atomic_t hart_lottery;
|
||||
|
||||
asmlinkage void __init setup_vm(uintptr_t dtb_pa);
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
asmlinkage void __init __copy_data(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RISCV_BOOT_SPINWAIT
|
||||
extern void *__cpu_spinwait_stack_pointer[];
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
* 8(sp) stores the function return address (i.e. parent IP) that
|
||||
* can be accessed by &(fregs)->ra in tracing function.
|
||||
*
|
||||
* The other regs are saved at the respective localtion and accessed
|
||||
* The other regs are saved at the respective location and accessed
|
||||
* by the respective ftrace_regs member.
|
||||
*
|
||||
* Here is the layout of stack for your reference.
|
||||
|
||||
@@ -148,7 +148,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Calculate the maxinum number of entries */
|
||||
/* Calculate the maximum number of entries */
|
||||
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||
size_t num_relas = sechdrs[i].sh_size / sizeof(Elf_Rela);
|
||||
Elf_Rela *relas = (void *)ehdr + sechdrs[i].sh_offset;
|
||||
|
||||
@@ -149,7 +149,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
|
||||
|
||||
/*
|
||||
* Interrupts need to be disabled before single-step mode is set, and not
|
||||
* reenabled until after single-step mode ends.
|
||||
* re-enabled until after single-step mode ends.
|
||||
* Without disabling interrupt on local CPU, there is a chance of
|
||||
* interrupt occurrence in the period of exception return and start of
|
||||
* out-of-line single-step, that result in wrongly single stepping
|
||||
|
||||
@@ -111,7 +111,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
|
||||
current->thread.bad_cause = utask->autask.saved_cause;
|
||||
/*
|
||||
* Task has received a fatal signal, so reset back to probbed
|
||||
* Task has received a fatal signal, so reset back to probed
|
||||
* address.
|
||||
*/
|
||||
instruction_pointer_set(regs, utask->vaddr);
|
||||
|
||||
@@ -46,11 +46,7 @@
|
||||
* This is used before the kernel initializes the BSS so it can't be in the
|
||||
* BSS.
|
||||
*/
|
||||
atomic_t hart_lottery __section(".sdata")
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
= ATOMIC_INIT(0xC001BEEF)
|
||||
#endif
|
||||
;
|
||||
atomic_t hart_lottery __section(".sdata");
|
||||
unsigned long boot_cpu_hartid;
|
||||
EXPORT_SYMBOL_GPL(boot_cpu_hartid);
|
||||
|
||||
|
||||
@@ -251,18 +251,14 @@ asmlinkage __visible void smp_callin(void)
|
||||
set_cpu_online(curr_cpuid, true);
|
||||
|
||||
/*
|
||||
* Remote cache and TLB flushes are ignored while the CPU is offline,
|
||||
* so flush them both right now just in case.
|
||||
* Remote instruction cache and TLB flushes are ignored while the CPU
|
||||
* is offline, so flush them both right now just in case.
|
||||
*/
|
||||
local_flush_icache_all();
|
||||
local_flush_tlb_all();
|
||||
#ifndef CONFIG_HOTPLUG_PARALLEL
|
||||
complete(&cpu_running);
|
||||
#endif
|
||||
/*
|
||||
* Disable preemption before enabling interrupts, so we don't try to
|
||||
* schedule a CPU that hasn't actually started yet.
|
||||
*/
|
||||
local_irq_enable();
|
||||
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <asm/soc.h>
|
||||
|
||||
/*
|
||||
* This is called extremly early, before parse_dtb(), to allow initializing
|
||||
* This is called extremely early, before parse_dtb(), to allow initializing
|
||||
* SoC hardware before memory or any device driver initialization.
|
||||
*/
|
||||
void __init soc_early_init(void)
|
||||
|
||||
@@ -78,7 +78,7 @@ int cpu_suspend(unsigned long arg,
|
||||
suspend_save_csrs(&context);
|
||||
|
||||
/*
|
||||
* Function graph tracer state gets incosistent when the kernel
|
||||
* Function graph tracer state gets inconsistent when the kernel
|
||||
* calls functions that never return (aka finishers) hence disable
|
||||
* graph tracing during their execution.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/xip_fixup.h>
|
||||
|
||||
.text
|
||||
.altmacro
|
||||
@@ -70,7 +69,6 @@ SYM_TYPED_FUNC_START(__cpu_resume_enter)
|
||||
|
||||
/* Enable MMU */
|
||||
la a0, swapper_pg_dir
|
||||
XIP_FIXUP_OFFSET a0
|
||||
call relocate_enable_mmu
|
||||
|
||||
/* Restore A0 and A1 */
|
||||
|
||||
@@ -142,11 +142,7 @@ static void do_trap_error(struct pt_regs *regs, int signo, int code,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_XIP_KERNEL) && defined(CONFIG_RISCV_ALTERNATIVE)
|
||||
#define __trap_section __noinstr_section(".xip.traps")
|
||||
#else
|
||||
#define __trap_section noinstr
|
||||
#endif
|
||||
#define DO_ERROR_INFO(name, signo, code, str) \
|
||||
asmlinkage __visible __trap_section void name(struct pt_regs *regs) \
|
||||
{ \
|
||||
@@ -165,6 +161,8 @@ asmlinkage __visible __trap_section void name(struct pt_regs *regs) \
|
||||
|
||||
DO_ERROR_INFO(do_trap_unknown,
|
||||
SIGILL, ILL_ILLTRP, "unknown exception");
|
||||
DO_ERROR_INFO(do_trap_hardware_error,
|
||||
SIGBUS, BUS_MCEERR_AR, "hardware error");
|
||||
DO_ERROR_INFO(do_trap_insn_misaligned,
|
||||
SIGBUS, BUS_ADRALN, "instruction address misaligned");
|
||||
DO_ERROR_INFO(do_trap_insn_fault,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "copy-unaligned.h"
|
||||
|
||||
#define MISALIGNED_ACCESS_JIFFIES_LG2 1
|
||||
#define MISALIGNED_ACCESS_NS 8000000
|
||||
#define MISALIGNED_BUFFER_SIZE 0x4000
|
||||
#define MISALIGNED_BUFFER_ORDER get_order(MISALIGNED_BUFFER_SIZE)
|
||||
#define MISALIGNED_COPY_SIZE ((MISALIGNED_BUFFER_SIZE / 2) - 0x80)
|
||||
@@ -29,109 +29,125 @@ static long unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNO
|
||||
|
||||
static cpumask_t fast_misaligned_access;
|
||||
|
||||
#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS
|
||||
static int check_unaligned_access(void *param)
|
||||
static u64 __maybe_unused
|
||||
measure_cycles(void (*func)(void *dst, const void *src, size_t len),
|
||||
void *dst, void *src, size_t len)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
u64 start_cycles, end_cycles;
|
||||
u64 word_cycles;
|
||||
u64 byte_cycles;
|
||||
int ratio;
|
||||
unsigned long start_jiffies, now;
|
||||
struct page *page = param;
|
||||
void *dst;
|
||||
void *src;
|
||||
long speed = RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW;
|
||||
u64 start_cycles, end_cycles, cycles = -1ULL;
|
||||
u64 start_ns;
|
||||
|
||||
if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN)
|
||||
return 0;
|
||||
|
||||
/* Make an unaligned destination buffer. */
|
||||
dst = (void *)((unsigned long)page_address(page) | 0x1);
|
||||
/* Unalign src as well, but differently (off by 1 + 2 = 3). */
|
||||
src = dst + (MISALIGNED_BUFFER_SIZE / 2);
|
||||
src += 2;
|
||||
word_cycles = -1ULL;
|
||||
/* Do a warmup. */
|
||||
__riscv_copy_words_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
func(dst, src, len);
|
||||
|
||||
preempt_disable();
|
||||
start_jiffies = jiffies;
|
||||
while ((now = jiffies) == start_jiffies)
|
||||
cpu_relax();
|
||||
|
||||
/*
|
||||
* For a fixed amount of time, repeatedly try the function, and take
|
||||
* the best time in cycles as the measurement.
|
||||
*/
|
||||
while (time_before(jiffies, now + (1 << MISALIGNED_ACCESS_JIFFIES_LG2))) {
|
||||
start_ns = ktime_get_mono_fast_ns();
|
||||
while (ktime_get_mono_fast_ns() < start_ns + MISALIGNED_ACCESS_NS) {
|
||||
start_cycles = get_cycles64();
|
||||
/* Ensure the CSR read can't reorder WRT to the copy. */
|
||||
mb();
|
||||
__riscv_copy_words_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
func(dst, src, len);
|
||||
/* Ensure the copy ends before the end time is snapped. */
|
||||
mb();
|
||||
end_cycles = get_cycles64();
|
||||
if ((end_cycles - start_cycles) < word_cycles)
|
||||
word_cycles = end_cycles - start_cycles;
|
||||
}
|
||||
|
||||
byte_cycles = -1ULL;
|
||||
__riscv_copy_bytes_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
start_jiffies = jiffies;
|
||||
while ((now = jiffies) == start_jiffies)
|
||||
cpu_relax();
|
||||
|
||||
while (time_before(jiffies, now + (1 << MISALIGNED_ACCESS_JIFFIES_LG2))) {
|
||||
start_cycles = get_cycles64();
|
||||
mb();
|
||||
__riscv_copy_bytes_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
mb();
|
||||
end_cycles = get_cycles64();
|
||||
if ((end_cycles - start_cycles) < byte_cycles)
|
||||
byte_cycles = end_cycles - start_cycles;
|
||||
if ((end_cycles - start_cycles) < cycles)
|
||||
cycles = end_cycles - start_cycles;
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return:
|
||||
* 1 if unaligned accesses are fast
|
||||
* 0 if unaligned accesses are slow
|
||||
* -1 if check cannot be done
|
||||
*/
|
||||
static int __maybe_unused
|
||||
compare_unaligned_access(void (*word_copy)(void *dst, const void *src, size_t len),
|
||||
void (*byte_copy)(void *dst, const void *src, size_t len),
|
||||
void *buf, const char *type)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
u64 word_cycles;
|
||||
u64 byte_cycles;
|
||||
void *dst, *src;
|
||||
bool fast;
|
||||
int ratio;
|
||||
|
||||
/* Make an unaligned destination buffer. */
|
||||
dst = (void *)((unsigned long)buf | 0x1);
|
||||
/* Unalign src as well, but differently (off by 1 + 2 = 3). */
|
||||
src = dst + (MISALIGNED_BUFFER_SIZE / 2);
|
||||
src += 2;
|
||||
|
||||
word_cycles = measure_cycles(word_copy, dst, src, MISALIGNED_COPY_SIZE);
|
||||
byte_cycles = measure_cycles(byte_copy, dst, src, MISALIGNED_COPY_SIZE);
|
||||
|
||||
/* Don't divide by zero. */
|
||||
if (!word_cycles || !byte_cycles) {
|
||||
pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned access speed\n",
|
||||
cpu);
|
||||
pr_warn("cpu%d: rdtime lacks granularity needed to measure %s unaligned access speed\n",
|
||||
cpu, type);
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (word_cycles < byte_cycles)
|
||||
speed = RISCV_HWPROBE_MISALIGNED_SCALAR_FAST;
|
||||
fast = word_cycles < byte_cycles;
|
||||
|
||||
ratio = div_u64((byte_cycles * 100), word_cycles);
|
||||
pr_info("cpu%d: Ratio of byte access time to unaligned word access is %d.%02d, unaligned accesses are %s\n",
|
||||
pr_info("cpu%d: %s unaligned word access speed is %d.%02dx byte access speed (%s)\n",
|
||||
cpu,
|
||||
type,
|
||||
ratio / 100,
|
||||
ratio % 100,
|
||||
(speed == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST) ? "fast" : "slow");
|
||||
fast ? "fast" : "slow");
|
||||
|
||||
per_cpu(misaligned_access_speed, cpu) = speed;
|
||||
return fast;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS
|
||||
static int check_unaligned_access(struct page *page)
|
||||
{
|
||||
void *buf = page_address(page);
|
||||
int cpu = smp_processor_id();
|
||||
int ret;
|
||||
|
||||
if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN)
|
||||
return 0;
|
||||
|
||||
ret = compare_unaligned_access(__riscv_copy_words_unaligned,
|
||||
__riscv_copy_bytes_unaligned,
|
||||
buf, "scalar");
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Set the value of fast_misaligned_access of a CPU. These operations
|
||||
* are atomic to avoid race conditions.
|
||||
*/
|
||||
if (speed == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST)
|
||||
if (ret) {
|
||||
per_cpu(misaligned_access_speed, cpu) = RISCV_HWPROBE_MISALIGNED_SCALAR_FAST;
|
||||
cpumask_set_cpu(cpu, &fast_misaligned_access);
|
||||
else
|
||||
} else {
|
||||
per_cpu(misaligned_access_speed, cpu) = RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW;
|
||||
cpumask_clear_cpu(cpu, &fast_misaligned_access);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init check_unaligned_access_nonboot_cpu(void *param)
|
||||
static void __init _check_unaligned_access(void *param)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct page **pages = param;
|
||||
|
||||
if (smp_processor_id() != 0)
|
||||
check_unaligned_access(pages[cpu]);
|
||||
check_unaligned_access(pages[cpu]);
|
||||
}
|
||||
|
||||
/* Measure unaligned access speed on all CPUs present at boot in parallel. */
|
||||
@@ -158,11 +174,7 @@ static void __init check_unaligned_access_speed_all_cpus(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check everybody except 0, who stays behind to tend jiffies. */
|
||||
on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1);
|
||||
|
||||
/* Check core 0. */
|
||||
smp_call_on_cpu(0, check_unaligned_access, bufs[0], true);
|
||||
on_each_cpu(_check_unaligned_access, bufs, 1);
|
||||
|
||||
out:
|
||||
for_each_cpu(cpu, cpu_online_mask) {
|
||||
@@ -281,15 +293,8 @@ static int riscv_offline_cpu(unsigned int cpu)
|
||||
static void check_vector_unaligned_access(struct work_struct *work __always_unused)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
u64 start_cycles, end_cycles;
|
||||
u64 word_cycles;
|
||||
u64 byte_cycles;
|
||||
int ratio;
|
||||
unsigned long start_jiffies, now;
|
||||
struct page *page;
|
||||
void *dst;
|
||||
void *src;
|
||||
long speed = RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW;
|
||||
int ret;
|
||||
|
||||
if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN)
|
||||
return;
|
||||
@@ -300,76 +305,20 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make an unaligned destination buffer. */
|
||||
dst = (void *)((unsigned long)page_address(page) | 0x1);
|
||||
/* Unalign src as well, but differently (off by 1 + 2 = 3). */
|
||||
src = dst + (MISALIGNED_BUFFER_SIZE / 2);
|
||||
src += 2;
|
||||
word_cycles = -1ULL;
|
||||
|
||||
/* Do a warmup. */
|
||||
kernel_vector_begin();
|
||||
__riscv_copy_vec_words_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
|
||||
start_jiffies = jiffies;
|
||||
while ((now = jiffies) == start_jiffies)
|
||||
cpu_relax();
|
||||
|
||||
/*
|
||||
* For a fixed amount of time, repeatedly try the function, and take
|
||||
* the best time in cycles as the measurement.
|
||||
*/
|
||||
while (time_before(jiffies, now + (1 << MISALIGNED_ACCESS_JIFFIES_LG2))) {
|
||||
start_cycles = get_cycles64();
|
||||
/* Ensure the CSR read can't reorder WRT to the copy. */
|
||||
mb();
|
||||
__riscv_copy_vec_words_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
/* Ensure the copy ends before the end time is snapped. */
|
||||
mb();
|
||||
end_cycles = get_cycles64();
|
||||
if ((end_cycles - start_cycles) < word_cycles)
|
||||
word_cycles = end_cycles - start_cycles;
|
||||
}
|
||||
|
||||
byte_cycles = -1ULL;
|
||||
__riscv_copy_vec_bytes_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
start_jiffies = jiffies;
|
||||
while ((now = jiffies) == start_jiffies)
|
||||
cpu_relax();
|
||||
|
||||
while (time_before(jiffies, now + (1 << MISALIGNED_ACCESS_JIFFIES_LG2))) {
|
||||
start_cycles = get_cycles64();
|
||||
/* Ensure the CSR read can't reorder WRT to the copy. */
|
||||
mb();
|
||||
__riscv_copy_vec_bytes_unaligned(dst, src, MISALIGNED_COPY_SIZE);
|
||||
/* Ensure the copy ends before the end time is snapped. */
|
||||
mb();
|
||||
end_cycles = get_cycles64();
|
||||
if ((end_cycles - start_cycles) < byte_cycles)
|
||||
byte_cycles = end_cycles - start_cycles;
|
||||
}
|
||||
|
||||
ret = compare_unaligned_access(__riscv_copy_vec_words_unaligned,
|
||||
__riscv_copy_vec_bytes_unaligned,
|
||||
page_address(page), "vector");
|
||||
kernel_vector_end();
|
||||
|
||||
/* Don't divide by zero. */
|
||||
if (!word_cycles || !byte_cycles) {
|
||||
pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned vector access speed\n",
|
||||
cpu);
|
||||
|
||||
if (ret < 0)
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (word_cycles < byte_cycles)
|
||||
speed = RISCV_HWPROBE_MISALIGNED_VECTOR_FAST;
|
||||
|
||||
ratio = div_u64((byte_cycles * 100), word_cycles);
|
||||
pr_info("cpu%d: Ratio of vector byte access time to vector unaligned word access is %d.%02d, unaligned accesses are %s\n",
|
||||
cpu,
|
||||
ratio / 100,
|
||||
ratio % 100,
|
||||
(speed == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST) ? "fast" : "slow");
|
||||
|
||||
per_cpu(vector_misaligned_access, cpu) = speed;
|
||||
if (ret)
|
||||
per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_FAST;
|
||||
else
|
||||
per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW;
|
||||
|
||||
free:
|
||||
__free_pages(page, MISALIGNED_BUFFER_ORDER);
|
||||
@@ -494,4 +443,4 @@ static int __init check_unaligned_access_all_cpus(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(check_unaligned_access_all_cpus);
|
||||
late_initcall(check_unaligned_access_all_cpus);
|
||||
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copied source files from the main vdso directory
|
||||
*.c
|
||||
*.S
|
||||
!vdso-cfi.S
|
||||
vdso.lds
|
||||
*.tmp
|
||||
vdso-syms.S
|
||||
@@ -23,3 +23,6 @@ $(vdso_c_objects): $(obj)/%.c: $(src)/%.c
|
||||
# Include the main VDSO Makefile which contains all the build rules and sources
|
||||
# The VDSO_CFI_BUILD variable will be passed to it to enable CFI compilation
|
||||
include $(src)/Makefile
|
||||
|
||||
# Clean rules - remove the copied source files
|
||||
clean-files += $(notdir $(vdso_c_sources)) $(notdir $(vdso_S_sources))
|
||||
@@ -3,6 +3,11 @@
|
||||
#include <linux/vmcore_info.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
static inline u64 get_satp_value(void)
|
||||
{
|
||||
return csr_read(CSR_SATP);
|
||||
}
|
||||
|
||||
void arch_crash_save_vmcoreinfo(void)
|
||||
{
|
||||
VMCOREINFO_NUMBER(phys_ram_base);
|
||||
@@ -19,13 +24,8 @@ void arch_crash_save_vmcoreinfo(void)
|
||||
#endif
|
||||
#endif
|
||||
vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR);
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
/* TODO: Communicate with crash-utility developers on the information to
|
||||
* export. The XIP case is more complicated, because the virtual-physical
|
||||
* address offset depends on whether the address is in ROM or in RAM.
|
||||
*/
|
||||
#else
|
||||
vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n",
|
||||
kernel_map.va_kernel_pa_offset);
|
||||
#endif
|
||||
vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
|
||||
vmcoreinfo_append_str("NUMBER(satp)=0x%llx\n", get_satp_value());
|
||||
}
|
||||
@@ -7,10 +7,6 @@
|
||||
#define RO_EXCEPTION_TABLE_ALIGN 4
|
||||
#define RUNTIME_DISCARD_EXIT
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#include "vmlinux-xip.lds.S"
|
||||
#else
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#define LOAD_OFFSET KERNEL_LINK_ADDR
|
||||
|
||||
@@ -176,4 +172,3 @@ SECTIONS
|
||||
|
||||
DISCARDS
|
||||
}
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
@@ -182,7 +182,7 @@ void kvm_riscv_local_tlb_sanitize(struct kvm_vcpu *vcpu)
|
||||
|
||||
/*
|
||||
* Flush VS-stage TLB entries for implementation where VS-stage
|
||||
* TLB does not cahce guest physical address and VMID.
|
||||
* TLB does not cache guest physical address and VMID.
|
||||
*/
|
||||
if (static_branch_unlikely(&kvm_riscv_vsstage_tlb_no_gpa))
|
||||
kvm_riscv_local_hfence_vvma_all(vmid);
|
||||
|
||||
@@ -694,7 +694,7 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base,
|
||||
pmc->counter_val += perf_event_read_value(pmc->perf_event,
|
||||
&enabled, &running);
|
||||
/*
|
||||
* The counter and overflow indicies in the snapshot region are w.r.to
|
||||
* The counter and overflow indices in the snapshot region are w.r.to
|
||||
* cbase. Modify the set bit in the counter mask instead of the pmc_index
|
||||
* which indicates the absolute counter index.
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,9 @@ ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),)
|
||||
lib-y += strcmp.o
|
||||
lib-y += strlen.o
|
||||
lib-y += strncmp.o
|
||||
lib-y += strnlen.o
|
||||
lib-y += strchr.o
|
||||
lib-y += strrchr.o
|
||||
endif
|
||||
lib-y += csum.o
|
||||
ifeq ($(CONFIG_MMU), y)
|
||||
|
||||
@@ -269,7 +269,7 @@ unsigned int do_csum(const unsigned char *buff, int len)
|
||||
* on machines with fast misaligned accesses.
|
||||
*
|
||||
* There is some duplicate code between the "with_alignment" and
|
||||
* "no_alignment" implmentations, but the overlap is too awkward to be
|
||||
* "no_alignment" implementations, but the overlap is too awkward to be
|
||||
* able to fit in one function without introducing multiple static
|
||||
* branches. The largest chunk of overlap was delegated into the
|
||||
* do_csum_common function.
|
||||
|
||||
@@ -40,8 +40,8 @@ SYM_FUNC_START(__memmove)
|
||||
* Both Copy Modes: t1 - Temporary for load-store
|
||||
* Both Copy Modes: t2 - Temporary for load-store
|
||||
* Both Copy Modes: a5 - dest to src alignment offset
|
||||
* Both Copy Modes: a6 - Shift ammount
|
||||
* Both Copy Modes: a7 - Inverse Shift ammount
|
||||
* Both Copy Modes: a6 - Shift amount
|
||||
* Both Copy Modes: a7 - Inverse Shift amount
|
||||
* Both Copy Modes: a2 - Alternate breakpoint for unrolled loops
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2025 Feng Jiang <jiangfeng@kylinos.cn>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
/* char *strchr(const char *s, int c) */
|
||||
SYM_FUNC_START(strchr)
|
||||
/*
|
||||
* Parameters
|
||||
* a0 - The string to be searched
|
||||
* a1 - The character to search for
|
||||
*
|
||||
* Returns
|
||||
* a0 - Address of first occurrence of 'c' or 0
|
||||
*
|
||||
* Clobbers
|
||||
* t0
|
||||
*/
|
||||
andi a1, a1, 0xff
|
||||
1:
|
||||
lbu t0, 0(a0)
|
||||
beq t0, a1, 2f
|
||||
addi a0, a0, 1
|
||||
bnez t0, 1b
|
||||
li a0, 0
|
||||
2:
|
||||
ret
|
||||
SYM_FUNC_END(strchr)
|
||||
|
||||
SYM_FUNC_ALIAS_WEAK(__pi_strchr, strchr)
|
||||
EXPORT_SYMBOL(strchr)
|
||||
@@ -0,0 +1,164 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/*
|
||||
* Base on arch/riscv/lib/strlen.S
|
||||
*
|
||||
* Copyright (C) Feng Jiang <jiangfeng@kylinos.cn>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/alternative-macros.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
/* size_t strnlen(const char *s, size_t count) */
|
||||
SYM_FUNC_START(strnlen)
|
||||
|
||||
__ALTERNATIVE_CFG("nop", "j strnlen_zbb", 0, RISCV_ISA_EXT_ZBB,
|
||||
IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB))
|
||||
|
||||
|
||||
/*
|
||||
* Returns
|
||||
* a0 - String length
|
||||
*
|
||||
* Parameters
|
||||
* a0 - String to measure
|
||||
* a1 - Max length of string
|
||||
*
|
||||
* Clobbers
|
||||
* t0, t1, t2
|
||||
*/
|
||||
addi t1, a0, -1
|
||||
add t2, a0, a1
|
||||
1:
|
||||
addi t1, t1, 1
|
||||
beq t1, t2, 2f
|
||||
lbu t0, 0(t1)
|
||||
bnez t0, 1b
|
||||
2:
|
||||
sub a0, t1, a0
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* Variant of strnlen using the ZBB extension if available
|
||||
*/
|
||||
#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB)
|
||||
strnlen_zbb:
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
# define CZ clz
|
||||
# define SHIFT sll
|
||||
#else
|
||||
# define CZ ctz
|
||||
# define SHIFT srl
|
||||
#endif
|
||||
|
||||
.option push
|
||||
.option arch,+zbb
|
||||
|
||||
/*
|
||||
* Returns
|
||||
* a0 - String length
|
||||
*
|
||||
* Parameters
|
||||
* a0 - String to measure
|
||||
* a1 - Max length of string
|
||||
*
|
||||
* Clobbers
|
||||
* t0, t1, t2, t3, t4
|
||||
*/
|
||||
|
||||
/* If maxlen is 0, return 0. */
|
||||
beqz a1, 3f
|
||||
|
||||
/* Number of irrelevant bytes in the first word. */
|
||||
andi t2, a0, SZREG-1
|
||||
|
||||
/* Align pointer. */
|
||||
andi t0, a0, -SZREG
|
||||
|
||||
li t3, SZREG
|
||||
sub t3, t3, t2
|
||||
slli t2, t2, 3
|
||||
|
||||
/* Aligned boundary. */
|
||||
add t4, a0, a1
|
||||
andi t4, t4, -SZREG
|
||||
|
||||
/* Get the first word. */
|
||||
REG_L t1, 0(t0)
|
||||
|
||||
/*
|
||||
* Shift away the partial data we loaded to remove the irrelevant bytes
|
||||
* preceding the string with the effect of adding NUL bytes at the
|
||||
* end of the string's first word.
|
||||
*/
|
||||
SHIFT t1, t1, t2
|
||||
|
||||
/* Convert non-NUL into 0xff and NUL into 0x00. */
|
||||
orc.b t1, t1
|
||||
|
||||
/* Convert non-NUL into 0x00 and NUL into 0xff. */
|
||||
not t1, t1
|
||||
|
||||
/*
|
||||
* Search for the first set bit (corresponding to a NUL byte in the
|
||||
* original chunk).
|
||||
*/
|
||||
CZ t1, t1
|
||||
|
||||
/*
|
||||
* The first chunk is special: compare against the number
|
||||
* of valid bytes in this chunk.
|
||||
*/
|
||||
srli a0, t1, 3
|
||||
|
||||
/* Limit the result by maxlen. */
|
||||
minu a0, a0, a1
|
||||
|
||||
bgtu t3, a0, 2f
|
||||
|
||||
/* Prepare for the word comparison loop. */
|
||||
addi t2, t0, SZREG
|
||||
li t3, -1
|
||||
|
||||
/*
|
||||
* Our critical loop is 4 instructions and processes data in
|
||||
* 4 byte or 8 byte chunks.
|
||||
*/
|
||||
.p2align 3
|
||||
1:
|
||||
REG_L t1, SZREG(t0)
|
||||
addi t0, t0, SZREG
|
||||
orc.b t1, t1
|
||||
bgeu t0, t4, 4f
|
||||
beq t1, t3, 1b
|
||||
4:
|
||||
not t1, t1
|
||||
CZ t1, t1
|
||||
srli t1, t1, 3
|
||||
|
||||
/* Get number of processed bytes. */
|
||||
sub t2, t0, t2
|
||||
|
||||
/* Add number of characters in the first word. */
|
||||
add a0, a0, t2
|
||||
|
||||
/* Add number of characters in the last word. */
|
||||
add a0, a0, t1
|
||||
|
||||
/* Ensure the final result does not exceed maxlen. */
|
||||
minu a0, a0, a1
|
||||
2:
|
||||
ret
|
||||
3:
|
||||
mv a0, a1
|
||||
ret
|
||||
|
||||
.option pop
|
||||
#endif
|
||||
SYM_FUNC_END(strnlen)
|
||||
SYM_FUNC_ALIAS(__pi_strnlen, strnlen)
|
||||
EXPORT_SYMBOL(strnlen)
|
||||
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2025 Feng Jiang <jiangfeng@kylinos.cn>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
/* char *strrchr(const char *s, int c) */
|
||||
SYM_FUNC_START(strrchr)
|
||||
/*
|
||||
* Parameters
|
||||
* a0 - The string to be searched
|
||||
* a1 - The character to seaerch for
|
||||
*
|
||||
* Returns
|
||||
* a0 - Address of last occurrence of 'c' or 0
|
||||
*
|
||||
* Clobbers
|
||||
* t0, t1
|
||||
*/
|
||||
andi a1, a1, 0xff
|
||||
mv t1, a0
|
||||
li a0, 0
|
||||
1:
|
||||
lbu t0, 0(t1)
|
||||
bne t0, a1, 2f
|
||||
mv a0, t1
|
||||
2:
|
||||
addi t1, t1, 1
|
||||
bnez t0, 1b
|
||||
ret
|
||||
SYM_FUNC_END(strrchr)
|
||||
|
||||
SYM_FUNC_ALIAS_WEAK(__pi_strrchr, strrchr)
|
||||
EXPORT_SYMBOL(strrchr)
|
||||
@@ -29,7 +29,7 @@ void flush_icache_all(void)
|
||||
* Make sure all previous writes to the D$ are ordered before making
|
||||
* the IPI. The RISC-V spec states that a hart must execute a data fence
|
||||
* before triggering a remote fence.i in order to make the modification
|
||||
* visable for remote harts.
|
||||
* visible for remote harts.
|
||||
*
|
||||
* IPIs on RISC-V are triggered by MMIO writes to either CLINT or
|
||||
* S-IMSIC, so the fence ensures previous data writes "happen before"
|
||||
|
||||
+10
-108
@@ -41,20 +41,17 @@ u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1];
|
||||
|
||||
struct kernel_mapping kernel_map __ro_after_init;
|
||||
EXPORT_SYMBOL(kernel_map);
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define kernel_map (*(struct kernel_mapping *)XIP_FIXUP(&kernel_map))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
u64 satp_mode __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL) ? SATP_MODE_57 : SATP_MODE_39;
|
||||
u64 satp_mode __ro_after_init = SATP_MODE_57;
|
||||
#else
|
||||
u64 satp_mode __ro_after_init = SATP_MODE_32;
|
||||
#endif
|
||||
EXPORT_SYMBOL(satp_mode);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
bool pgtable_l4_enabled __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL);
|
||||
bool pgtable_l5_enabled __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL);
|
||||
bool pgtable_l4_enabled __ro_after_init = true;
|
||||
bool pgtable_l5_enabled __ro_after_init = true;
|
||||
EXPORT_SYMBOL(pgtable_l4_enabled);
|
||||
EXPORT_SYMBOL(pgtable_l5_enabled);
|
||||
#endif
|
||||
@@ -190,9 +187,6 @@ void __init arch_mm_preinit(void)
|
||||
|
||||
/* Limit the memory size via mem. */
|
||||
static phys_addr_t memory_limit;
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define memory_limit (*(phys_addr_t *)XIP_FIXUP(&memory_limit))
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
static int __init early_mem(char *p)
|
||||
{
|
||||
@@ -216,10 +210,7 @@ static void __init setup_bootmem(void)
|
||||
phys_addr_t max_mapped_addr;
|
||||
phys_addr_t phys_ram_end, vmlinux_start;
|
||||
|
||||
if (IS_ENABLED(CONFIG_XIP_KERNEL))
|
||||
vmlinux_start = __pa_symbol(&_sdata);
|
||||
else
|
||||
vmlinux_start = __pa_symbol(&_start);
|
||||
vmlinux_start = __pa_symbol(&_start);
|
||||
|
||||
memblock_enforce_memory_limit(memory_limit);
|
||||
|
||||
@@ -239,12 +230,10 @@ static void __init setup_bootmem(void)
|
||||
* Make sure we align the start of the memory on a PMD boundary so that
|
||||
* at worst, we map the linear mapping with PMD mappings.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_XIP_KERNEL)) {
|
||||
phys_ram_base = memblock_start_of_DRAM() & PMD_MASK;
|
||||
phys_ram_base = memblock_start_of_DRAM() & PMD_MASK;
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
|
||||
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* In 64-bit, any use of __va/__pa before this point is wrong as we
|
||||
@@ -357,13 +346,6 @@ static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
|
||||
|
||||
pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define pt_ops (*(struct pt_alloc_ops *)XIP_FIXUP(&pt_ops))
|
||||
#define trampoline_pg_dir ((pgd_t *)XIP_FIXUP(trampoline_pg_dir))
|
||||
#define fixmap_pte ((pte_t *)XIP_FIXUP(fixmap_pte))
|
||||
#define early_pg_dir ((pgd_t *)XIP_FIXUP(early_pg_dir))
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
static const pgprot_t protection_map[16] = {
|
||||
[VM_NONE] = PAGE_NONE,
|
||||
[VM_READ] = PAGE_READ,
|
||||
@@ -460,32 +442,14 @@ static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||
static pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||
static pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd))
|
||||
#define fixmap_pmd ((pmd_t *)XIP_FIXUP(fixmap_pmd))
|
||||
#define early_pmd ((pmd_t *)XIP_FIXUP(early_pmd))
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
static p4d_t trampoline_p4d[PTRS_PER_P4D] __page_aligned_bss;
|
||||
static p4d_t fixmap_p4d[PTRS_PER_P4D] __page_aligned_bss;
|
||||
static p4d_t early_p4d[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define trampoline_p4d ((p4d_t *)XIP_FIXUP(trampoline_p4d))
|
||||
#define fixmap_p4d ((p4d_t *)XIP_FIXUP(fixmap_p4d))
|
||||
#define early_p4d ((p4d_t *)XIP_FIXUP(early_p4d))
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
static pud_t trampoline_pud[PTRS_PER_PUD] __page_aligned_bss;
|
||||
static pud_t fixmap_pud[PTRS_PER_PUD] __page_aligned_bss;
|
||||
static pud_t early_pud[PTRS_PER_PUD] __initdata __aligned(PAGE_SIZE);
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define trampoline_pud ((pud_t *)XIP_FIXUP(trampoline_pud))
|
||||
#define fixmap_pud ((pud_t *)XIP_FIXUP(fixmap_pud))
|
||||
#define early_pud ((pud_t *)XIP_FIXUP(early_pud))
|
||||
#endif /* CONFIG_XIP_KERNEL */
|
||||
|
||||
static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
|
||||
{
|
||||
/* Before MMU is enabled */
|
||||
@@ -756,21 +720,6 @@ static uintptr_t __meminit best_map_size(phys_addr_t pa, uintptr_t va, phys_addr
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define phys_ram_base (*(phys_addr_t *)XIP_FIXUP(&phys_ram_base))
|
||||
extern char _xiprom[], _exiprom[], __data_loc;
|
||||
|
||||
/* called from head.S with MMU off */
|
||||
asmlinkage void __init __copy_data(void)
|
||||
{
|
||||
void *from = (void *)(&__data_loc);
|
||||
void *to = (void *)CONFIG_PHYS_RAM_BASE;
|
||||
size_t sz = (size_t)((uintptr_t)(&_end) - (uintptr_t)(&_sdata));
|
||||
|
||||
memcpy(to, from, sz);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
static __meminit pgprot_t pgprot_from_va(uintptr_t va)
|
||||
{
|
||||
@@ -806,7 +755,7 @@ static __meminit pgprot_t pgprot_from_va(uintptr_t va)
|
||||
}
|
||||
#endif /* CONFIG_STRICT_KERNEL_RWX */
|
||||
|
||||
#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL)
|
||||
#if defined(CONFIG_64BIT)
|
||||
u64 __pi_set_satp_mode_from_cmdline(uintptr_t dtb_pa);
|
||||
u64 __pi_set_satp_mode_from_fdt(uintptr_t dtb_pa);
|
||||
|
||||
@@ -931,28 +880,6 @@ retry:
|
||||
#error "setup_vm() is called from head.S before relocate so it should not use absolute addressing."
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
static void __init create_kernel_page_table(pgd_t *pgdir,
|
||||
__always_unused bool early)
|
||||
{
|
||||
uintptr_t va, start_va, end_va;
|
||||
|
||||
/* Map the flash resident part */
|
||||
end_va = kernel_map.virt_addr + kernel_map.xiprom_sz;
|
||||
for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE)
|
||||
create_pgd_mapping(pgdir, va,
|
||||
kernel_map.xiprom + (va - kernel_map.virt_addr),
|
||||
PMD_SIZE, PAGE_KERNEL_EXEC);
|
||||
|
||||
/* Map the data in RAM */
|
||||
start_va = kernel_map.virt_addr + (uintptr_t)&_sdata - (uintptr_t)&_start;
|
||||
end_va = kernel_map.virt_addr + kernel_map.size;
|
||||
for (va = start_va; va < end_va; va += PMD_SIZE)
|
||||
create_pgd_mapping(pgdir, va,
|
||||
kernel_map.phys_addr + (va - start_va),
|
||||
PMD_SIZE, PAGE_KERNEL);
|
||||
}
|
||||
#else
|
||||
static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
|
||||
{
|
||||
uintptr_t va, end_va;
|
||||
@@ -965,7 +892,6 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
|
||||
early ?
|
||||
PAGE_KERNEL_EXEC : pgprot_from_va(va));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel,
|
||||
@@ -1075,11 +1001,6 @@ static int __init print_nokaslr(char *p)
|
||||
return 0;
|
||||
}
|
||||
early_param("nokaslr", print_nokaslr);
|
||||
|
||||
unsigned long kaslr_offset(void)
|
||||
{
|
||||
return kernel_map.virt_offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
@@ -1107,27 +1028,11 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
|
||||
kernel_map.virt_addr = KERNEL_LINK_ADDR + kernel_map.virt_offset;
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
kernel_map.xiprom = (uintptr_t)CONFIG_XIP_PHYS_ADDR;
|
||||
kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom);
|
||||
|
||||
phys_ram_base = CONFIG_PHYS_RAM_BASE;
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
|
||||
#endif
|
||||
kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
|
||||
kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
|
||||
|
||||
kernel_map.va_kernel_xip_text_pa_offset = kernel_map.virt_addr - kernel_map.xiprom;
|
||||
kernel_map.va_kernel_xip_data_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr
|
||||
+ (uintptr_t)&_sdata - (uintptr_t)&_start;
|
||||
#else
|
||||
kernel_map.phys_addr = (uintptr_t)(&_start);
|
||||
kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr;
|
||||
kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL)
|
||||
#if defined(CONFIG_64BIT)
|
||||
set_satp_mode(dtb_pa);
|
||||
set_mmap_rnd_bits_max();
|
||||
#endif
|
||||
@@ -1200,13 +1105,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
if (pgtable_l4_enabled)
|
||||
create_pud_mapping(trampoline_pud, kernel_map.virt_addr,
|
||||
(uintptr_t)trampoline_pmd, PUD_SIZE, PAGE_TABLE);
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr,
|
||||
kernel_map.xiprom, PMD_SIZE, PAGE_KERNEL_EXEC);
|
||||
#else
|
||||
create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr,
|
||||
kernel_map.phys_addr, PMD_SIZE, PAGE_KERNEL_EXEC);
|
||||
#endif
|
||||
#else
|
||||
/* Setup trampoline PGD */
|
||||
create_pgd_mapping(trampoline_pg_dir, kernel_map.virt_addr,
|
||||
@@ -1450,6 +1350,8 @@ int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
|
||||
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
|
||||
struct vmem_altmap *altmap)
|
||||
{
|
||||
WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
|
||||
|
||||
/*
|
||||
* Note that SPARSEMEM_VMEMMAP is only selected for rv64 and that we
|
||||
* can't use hugepage mappings for 2-level page table because in case of
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
phys_addr_t __virt_to_phys(unsigned long x)
|
||||
{
|
||||
/*
|
||||
* Boundary checking aginst the kernel linear mapping space.
|
||||
* Boundary checking against the kernel linear mapping space.
|
||||
*/
|
||||
WARN(!is_linear_mapping(x) && !is_kernel_mapping(x),
|
||||
"virt_to_phys used for non-linear address: %p (%pS)\n",
|
||||
@@ -25,7 +25,7 @@ phys_addr_t __phys_addr_symbol(unsigned long x)
|
||||
unsigned long kernel_end = kernel_start + kernel_map.size;
|
||||
|
||||
/*
|
||||
* Boundary checking aginst the kernel image mapping.
|
||||
* Boundary checking against the kernel image mapping.
|
||||
* __pa_symbol should only be used on kernel symbol addresses.
|
||||
*/
|
||||
VIRTUAL_BUG_ON(x < kernel_start || x > kernel_end);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o
|
||||
ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),)
|
||||
purgatory-y += strcmp.o strlen.o strncmp.o
|
||||
purgatory-y += strcmp.o strlen.o strncmp.o strnlen.o strchr.o strrchr.o
|
||||
endif
|
||||
|
||||
targets += $(purgatory-y)
|
||||
@@ -32,6 +32,15 @@ $(obj)/strncmp.o: $(srctree)/arch/riscv/lib/strncmp.S FORCE
|
||||
$(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE
|
||||
$(call if_changed_rule,cc_o_c)
|
||||
|
||||
$(obj)/strnlen.o: $(srctree)/arch/riscv/lib/strnlen.S FORCE
|
||||
$(call if_changed_rule,as_o_S)
|
||||
|
||||
$(obj)/strchr.o: $(srctree)/arch/riscv/lib/strchr.S FORCE
|
||||
$(call if_changed_rule,as_o_S)
|
||||
|
||||
$(obj)/strrchr.o: $(srctree)/arch/riscv/lib/strrchr.S FORCE
|
||||
$(call if_changed_rule,as_o_S)
|
||||
|
||||
CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY
|
||||
CFLAGS_string.o := -D__DISABLE_EXPORTS
|
||||
CFLAGS_ctype.o := -D__DISABLE_EXPORTS
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
kexec_purgatory:
|
||||
.globl kexec_purgatory
|
||||
.incbin "arch/riscv/purgatory/purgatory.ro"
|
||||
.Lkexec_purgatroy_end:
|
||||
.Lkexec_purgatory_end:
|
||||
|
||||
.align 8
|
||||
kexec_purgatory_size:
|
||||
.globl kexec_purgatory_size
|
||||
.quad .Lkexec_purgatroy_end - kexec_purgatory
|
||||
.quad .Lkexec_purgatory_end - kexec_purgatory
|
||||
@@ -1885,6 +1885,7 @@ config X86_USER_SHADOW_STACK
|
||||
bool "X86 userspace shadow stack"
|
||||
depends on AS_WRUSS
|
||||
depends on X86_64
|
||||
depends on PER_VMA_LOCK
|
||||
select ARCH_USES_HIGH_VMA_FLAGS
|
||||
select ARCH_HAS_USER_SHADOW_STACK
|
||||
select X86_CET
|
||||
|
||||
+23
-19
@@ -326,10 +326,8 @@ static int shstk_push_sigframe(unsigned long *ssp)
|
||||
|
||||
static int shstk_pop_sigframe(unsigned long *ssp)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long token_addr;
|
||||
bool need_to_check_vma;
|
||||
int err = 1;
|
||||
unsigned int seq;
|
||||
|
||||
/*
|
||||
* It is possible for the SSP to be off the end of a shadow stack by 4
|
||||
@@ -340,25 +338,35 @@ static int shstk_pop_sigframe(unsigned long *ssp)
|
||||
if (!IS_ALIGNED(*ssp, 8))
|
||||
return -EINVAL;
|
||||
|
||||
need_to_check_vma = PAGE_ALIGN(*ssp) == *ssp;
|
||||
do {
|
||||
struct vm_area_struct *vma;
|
||||
bool valid_vma;
|
||||
int err;
|
||||
|
||||
if (need_to_check_vma)
|
||||
if (mmap_read_lock_killable(current->mm))
|
||||
return -EINTR;
|
||||
|
||||
err = get_shstk_data(&token_addr, (unsigned long __user *)*ssp);
|
||||
if (unlikely(err))
|
||||
goto out_err;
|
||||
|
||||
if (need_to_check_vma) {
|
||||
vma = find_vma(current->mm, *ssp);
|
||||
if (!vma || !(vma->vm_flags & VM_SHADOW_STACK)) {
|
||||
err = -EFAULT;
|
||||
goto out_err;
|
||||
}
|
||||
valid_vma = vma && (vma->vm_flags & VM_SHADOW_STACK);
|
||||
|
||||
/*
|
||||
* VMAs can change between get_shstk_data() and find_vma().
|
||||
* Watch for changes and ensure that 'token_addr' comes from
|
||||
* 'vma' by recording a seqcount.
|
||||
*
|
||||
* Ignore the return value of mmap_lock_speculate_try_begin()
|
||||
* because the mmap lock excludes the possibility of writers.
|
||||
*/
|
||||
mmap_lock_speculate_try_begin(current->mm, &seq);
|
||||
mmap_read_unlock(current->mm);
|
||||
}
|
||||
|
||||
if (!valid_vma)
|
||||
return -EINVAL;
|
||||
|
||||
err = get_shstk_data(&token_addr, (unsigned long __user *)*ssp);
|
||||
if (err)
|
||||
return err;
|
||||
} while (mmap_lock_speculate_retry(current->mm, seq));
|
||||
|
||||
/* Restore SSP aligned? */
|
||||
if (unlikely(!IS_ALIGNED(token_addr, 8)))
|
||||
@@ -371,10 +379,6 @@ static int shstk_pop_sigframe(unsigned long *ssp)
|
||||
*ssp = token_addr;
|
||||
|
||||
return 0;
|
||||
out_err:
|
||||
if (need_to_check_vma)
|
||||
mmap_read_unlock(current->mm);
|
||||
return err;
|
||||
}
|
||||
|
||||
int setup_signal_shadow_stack(struct ksignal *ksig)
|
||||
|
||||
@@ -399,6 +399,15 @@ static void cpa_flush_all(unsigned long cache)
|
||||
on_each_cpu(__cpa_flush_all, (void *) cache, 1);
|
||||
}
|
||||
|
||||
static void __cpa_flush_tlb(void *data)
|
||||
{
|
||||
struct cpa_data *cpa = data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < cpa->numpages; i++)
|
||||
flush_tlb_one_kernel(fix_addr(__cpa_addr(cpa, i)));
|
||||
}
|
||||
|
||||
static int collapse_large_pages(unsigned long addr, struct list_head *pgtables);
|
||||
|
||||
static void cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
@@ -435,7 +444,6 @@ static void cpa_collapse_large_pages(struct cpa_data *cpa)
|
||||
|
||||
static void cpa_flush(struct cpa_data *cpa, int cache)
|
||||
{
|
||||
unsigned long start, end;
|
||||
unsigned int i;
|
||||
|
||||
BUG_ON(irqs_disabled() && !early_boot_irqs_disabled);
|
||||
@@ -445,12 +453,10 @@ static void cpa_flush(struct cpa_data *cpa, int cache)
|
||||
goto collapse_large_pages;
|
||||
}
|
||||
|
||||
start = fix_addr(__cpa_addr(cpa, 0));
|
||||
end = start + cpa->numpages * PAGE_SIZE;
|
||||
if (cpa->force_flush_all)
|
||||
end = TLB_FLUSH_ALL;
|
||||
|
||||
flush_tlb_kernel_range(start, end);
|
||||
if (cpa->force_flush_all || cpa->numpages > tlb_single_page_flush_ceiling)
|
||||
flush_tlb_all();
|
||||
else
|
||||
on_each_cpu(__cpa_flush_tlb, cpa, 1);
|
||||
|
||||
if (!cache)
|
||||
goto collapse_large_pages;
|
||||
|
||||
@@ -105,6 +105,11 @@ void __init pti_check_boottime_disable(void)
|
||||
pr_debug("PTI enabled, disabling INVLPGB\n");
|
||||
setup_clear_cpu_cap(X86_FEATURE_INVLPGB);
|
||||
}
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_FRED)) {
|
||||
pr_debug("PTI enabled, disabling FRED\n");
|
||||
setup_clear_cpu_cap(X86_FEATURE_FRED);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pti_parse_cmdline(char *arg)
|
||||
|
||||
@@ -303,6 +303,50 @@ static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
|
||||
.max_raw_write = I2C_SMBUS_BLOCK_MAX - 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* SMBus byte/word reg16 support for adapters that have SMBUS_BYTE_DATA
|
||||
* and SMBUS_WORD_DATA but lack I2C_FUNC_I2C and I2C_FUNC_SMBUS_I2C_BLOCK,
|
||||
* such as the AMD PIIX4.
|
||||
*
|
||||
* READ: set 16-bit EEPROM address via write_byte_data(addr_lo, addr_hi),
|
||||
* then sequentially read bytes via read_byte() (EEPROM auto-
|
||||
* increments the address pointer). Same as the I2C-block reg16
|
||||
* read path above.
|
||||
*
|
||||
* WRITE: encode the low address byte and data into a word transaction:
|
||||
* write_word_data(addr_hi, (data_byte << 8) | addr_lo).
|
||||
* Only single-byte writes are supported (one value per transaction).
|
||||
*/
|
||||
static int regmap_smbus_word_write_reg16(void *context, const void *data,
|
||||
size_t count)
|
||||
{
|
||||
struct device *dev = context;
|
||||
struct i2c_client *i2c = to_i2c_client(dev);
|
||||
u8 addr_hi, addr_lo, val;
|
||||
|
||||
/*
|
||||
* data layout: [addr_hi, addr_lo, val0, val1, ...].
|
||||
* Only single-byte value writes are supported; multi-byte would
|
||||
* require raw I2C (or repeated word writes with incrementing address).
|
||||
*/
|
||||
if (count != 3)
|
||||
return -EINVAL;
|
||||
|
||||
addr_hi = ((u8 *)data)[0];
|
||||
addr_lo = ((u8 *)data)[1];
|
||||
val = ((u8 *)data)[2];
|
||||
|
||||
return i2c_smbus_write_word_data(i2c, addr_hi,
|
||||
cpu_to_le16(((u16)val << 8) | addr_lo));
|
||||
}
|
||||
|
||||
static const struct regmap_bus regmap_smbus_byte_word_reg16 = {
|
||||
.write = regmap_smbus_word_write_reg16,
|
||||
.read = regmap_i2c_smbus_i2c_read_reg16,
|
||||
.max_raw_read = I2C_SMBUS_BLOCK_MAX - 2,
|
||||
.max_raw_write = 1,
|
||||
};
|
||||
|
||||
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
|
||||
const struct regmap_config *config)
|
||||
{
|
||||
@@ -321,6 +365,11 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
|
||||
i2c_check_functionality(i2c->adapter,
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK))
|
||||
bus = ®map_i2c_smbus_i2c_block_reg16;
|
||||
else if (config->val_bits == 8 && config->reg_bits == 16 &&
|
||||
i2c_check_functionality(i2c->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
bus = ®map_smbus_byte_word_reg16;
|
||||
else if (config->val_bits == 16 && config->reg_bits == 8 &&
|
||||
i2c_check_functionality(i2c->adapter,
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
|
||||
@@ -71,11 +71,17 @@ struct regmap *__regmap_init_ram(struct device *dev,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
data->written = kzalloc_objs(bool, config->max_register + 1);
|
||||
if (!data->written)
|
||||
if (!data->written) {
|
||||
kfree(data->read);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
map = __regmap_init(dev, ®map_ram, data, config,
|
||||
lock_key, lock_name);
|
||||
if (IS_ERR(map)) {
|
||||
kfree(data->read);
|
||||
kfree(data->written);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg,
|
||||
|
||||
static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
|
||||
unsigned int reg, unsigned int val,
|
||||
int mbq_size, bool deferrable)
|
||||
int mbq_size)
|
||||
{
|
||||
int shift = mbq_size * BITS_PER_BYTE;
|
||||
int ret;
|
||||
@@ -88,17 +88,14 @@ static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sdw_write_no_pm(slave, reg, val & 0xff);
|
||||
if (deferrable && ret == -ENODATA)
|
||||
return -EAGAIN;
|
||||
|
||||
return ret;
|
||||
return sdw_write_no_pm(slave, reg, val & 0xff);
|
||||
}
|
||||
|
||||
static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct regmap_mbq_context *ctx = context;
|
||||
struct sdw_slave *slave = ctx->sdw;
|
||||
struct device *dev = ctx->dev;
|
||||
bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
|
||||
int mbq_size = regmap_sdw_mbq_size(ctx, reg);
|
||||
int ret;
|
||||
@@ -113,13 +110,16 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va
|
||||
* process a single wait/timeout on function busy and a single retry
|
||||
* of the transaction.
|
||||
*/
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, deferrable);
|
||||
if (ret == -EAGAIN) {
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size);
|
||||
if (ret == -ENODATA) {
|
||||
if (!deferrable)
|
||||
dev_warn(dev, "Defer on undeferrable control: %x\n", reg);
|
||||
|
||||
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, false);
|
||||
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -127,18 +127,14 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va
|
||||
|
||||
static int regmap_sdw_mbq_read_impl(struct sdw_slave *slave,
|
||||
unsigned int reg, unsigned int *val,
|
||||
int mbq_size, bool deferrable)
|
||||
int mbq_size)
|
||||
{
|
||||
int shift = BITS_PER_BYTE;
|
||||
int read;
|
||||
|
||||
read = sdw_read_no_pm(slave, reg);
|
||||
if (read < 0) {
|
||||
if (deferrable && read == -ENODATA)
|
||||
return -EAGAIN;
|
||||
|
||||
if (read < 0)
|
||||
return read;
|
||||
}
|
||||
|
||||
*val = read;
|
||||
|
||||
@@ -158,6 +154,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
|
||||
{
|
||||
struct regmap_mbq_context *ctx = context;
|
||||
struct sdw_slave *slave = ctx->sdw;
|
||||
struct device *dev = ctx->dev;
|
||||
bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
|
||||
int mbq_size = regmap_sdw_mbq_size(ctx, reg);
|
||||
int ret;
|
||||
@@ -172,13 +169,16 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
|
||||
* process a single wait/timeout on function busy and a single retry
|
||||
* of the transaction.
|
||||
*/
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, deferrable);
|
||||
if (ret == -EAGAIN) {
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
|
||||
if (ret == -ENODATA) {
|
||||
if (!deferrable)
|
||||
dev_warn(dev, "Defer on undeferable control: %x\n", reg);
|
||||
|
||||
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, false);
|
||||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -847,9 +847,8 @@ void dma_buf_put(struct dma_buf *dmabuf)
|
||||
if (WARN_ON(!dmabuf || !dmabuf->file))
|
||||
return;
|
||||
|
||||
fput(dmabuf->file);
|
||||
|
||||
DMA_BUF_TRACE(trace_dma_buf_put, dmabuf);
|
||||
fput(dmabuf->file);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF");
|
||||
|
||||
|
||||
@@ -1037,8 +1037,8 @@ EXPORT_SYMBOL(dma_fence_set_deadline);
|
||||
*/
|
||||
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
|
||||
{
|
||||
const char __rcu *timeline = "";
|
||||
const char __rcu *driver = "";
|
||||
const char __rcu *timeline = (const char __rcu *)"";
|
||||
const char __rcu *driver = (const char __rcu *)"";
|
||||
const char *signaled = "";
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
#define GPIO_G7_CTRL_IRQ_TYPE1 BIT(4)
|
||||
#define GPIO_G7_CTRL_IRQ_TYPE2 BIT(5)
|
||||
#define GPIO_G7_CTRL_RST_TOLERANCE BIT(6)
|
||||
#define GPIO_G7_CTRL_DEBOUNCE_SEL1 BIT(7)
|
||||
#define GPIO_G7_CTRL_DEBOUNCE_SEL2 BIT(8)
|
||||
#define GPIO_G7_CTRL_DEBOUNCE_SEL2 BIT(7)
|
||||
#define GPIO_G7_CTRL_DEBOUNCE_SEL1 BIT(8)
|
||||
#define GPIO_G7_CTRL_INPUT_MASK BIT(9)
|
||||
#define GPIO_G7_CTRL_IRQ_STS BIT(12)
|
||||
#define GPIO_G7_CTRL_IN_DATA BIT(13)
|
||||
|
||||
@@ -617,7 +617,7 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
|
||||
gc->base, gc->ngpio);
|
||||
bank->pin_base, bank->nr_pins);
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "Failed to add pin range\n");
|
||||
goto fail;
|
||||
|
||||
@@ -1735,7 +1735,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
alloc_flags = 0;
|
||||
} else {
|
||||
alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE |
|
||||
AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
||||
alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
|
||||
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
|
||||
|
||||
|
||||
@@ -866,6 +866,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
||||
if (dret) {
|
||||
amdgpu_connector->detected_by_load = false;
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
amdgpu_connector_get_edid(connector);
|
||||
|
||||
if (!amdgpu_connector->edid) {
|
||||
@@ -882,6 +883,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
||||
*/
|
||||
if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) {
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
ret = connector_status_disconnected;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
@@ -977,6 +979,7 @@ static void amdgpu_connector_shared_ddc(enum drm_connector_status *status,
|
||||
if (!amdgpu_display_hpd_sense(adev,
|
||||
amdgpu_connector->hpd.hpd)) {
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
*status = connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
@@ -1046,6 +1049,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
||||
if (dret) {
|
||||
amdgpu_connector->detected_by_load = false;
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
amdgpu_connector_get_edid(connector);
|
||||
|
||||
if (!amdgpu_connector->edid) {
|
||||
@@ -1062,6 +1066,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
||||
*/
|
||||
if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) {
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
ret = connector_status_disconnected;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
@@ -1412,6 +1417,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
|
||||
}
|
||||
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
|
||||
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
||||
|
||||
@@ -32,6 +32,8 @@ static const guid_t BOOT = BOOT_TYPE;
|
||||
static const guid_t CRASHDUMP = AMD_CRASHDUMP;
|
||||
static const guid_t RUNTIME = AMD_GPU_NONSTANDARD_ERROR;
|
||||
|
||||
#define CPER_SIGNATURE_SZ (sizeof(((struct cper_hdr *)0)->signature))
|
||||
|
||||
static void __inc_entry_length(struct cper_hdr *hdr, uint32_t size)
|
||||
{
|
||||
hdr->record_length += size;
|
||||
@@ -425,23 +427,40 @@ int amdgpu_cper_generate_ce_records(struct amdgpu_device *adev,
|
||||
|
||||
static bool amdgpu_cper_is_hdr(struct amdgpu_ring *ring, u64 pos)
|
||||
{
|
||||
struct cper_hdr *chdr;
|
||||
char signature[CPER_SIGNATURE_SZ];
|
||||
|
||||
chdr = (struct cper_hdr *)&(ring->ring[pos]);
|
||||
return strcmp(chdr->signature, "CPER") ? false : true;
|
||||
if ((pos << 2) >= ring->ring_size)
|
||||
return false;
|
||||
|
||||
if ((pos << 2) + CPER_SIGNATURE_SZ <= ring->ring_size) {
|
||||
memcpy(signature, &ring->ring[pos], CPER_SIGNATURE_SZ);
|
||||
} else {
|
||||
u32 chunk = ring->ring_size - (pos << 2);
|
||||
|
||||
memcpy(signature, &ring->ring[pos], chunk);
|
||||
memcpy(signature + chunk, ring->ring, CPER_SIGNATURE_SZ - chunk);
|
||||
}
|
||||
|
||||
return !memcmp(signature, "CPER", CPER_SIGNATURE_SZ);
|
||||
}
|
||||
|
||||
static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
|
||||
{
|
||||
struct cper_hdr *chdr;
|
||||
struct cper_hdr chdr;
|
||||
u64 p;
|
||||
u32 chunk, rec_len = 0;
|
||||
|
||||
chdr = (struct cper_hdr *)&(ring->ring[pos]);
|
||||
chunk = ring->ring_size - (pos << 2);
|
||||
|
||||
if (!strcmp(chdr->signature, "CPER")) {
|
||||
rec_len = chdr->record_length;
|
||||
if (amdgpu_cper_is_hdr(ring, pos)) {
|
||||
if (chunk >= sizeof(chdr)) {
|
||||
memcpy(&chdr, &ring->ring[pos], sizeof(chdr));
|
||||
} else {
|
||||
memcpy(&chdr, &ring->ring[pos], chunk);
|
||||
memcpy((u8 *)&chdr + chunk, ring->ring, sizeof(chdr) - chunk);
|
||||
}
|
||||
|
||||
rec_len = chdr.record_length;
|
||||
goto calc;
|
||||
}
|
||||
|
||||
@@ -450,8 +469,7 @@ static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
|
||||
goto calc;
|
||||
|
||||
for (p = pos + 1; p <= ring->buf_mask; p++) {
|
||||
chdr = (struct cper_hdr *)&(ring->ring[p]);
|
||||
if (!strcmp(chdr->signature, "CPER")) {
|
||||
if (amdgpu_cper_is_hdr(ring, p)) {
|
||||
rec_len = (p - pos) << 2;
|
||||
goto calc;
|
||||
}
|
||||
|
||||
@@ -464,6 +464,9 @@ static void amdgpu_devcoredump_deferred_work(struct work_struct *work)
|
||||
struct amdgpu_device *adev = container_of(work, typeof(*adev), coredump_work);
|
||||
struct amdgpu_coredump_info *coredump = adev->coredump;
|
||||
|
||||
if (!coredump)
|
||||
goto end;
|
||||
|
||||
/* Do a one-time preparation of the coredump output because
|
||||
* repeatingly calling drm_coredump_printer is very slow.
|
||||
*/
|
||||
@@ -499,7 +502,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
int i, off, idx;
|
||||
|
||||
/* No need to generate a new coredump if there's one in progress already. */
|
||||
if (work_pending(&adev->coredump_work))
|
||||
if (work_busy(&adev->coredump_work))
|
||||
return;
|
||||
|
||||
if (job && job->pasid)
|
||||
@@ -511,7 +514,6 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
|
||||
coredump->skip_vram_check = skip_vram_check;
|
||||
coredump->reset_vram_lost = vram_lost;
|
||||
coredump->pasid = job->pasid;
|
||||
|
||||
if (job && job->pasid) {
|
||||
struct amdgpu_task_info *ti;
|
||||
@@ -521,6 +523,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
coredump->reset_task_info = *ti;
|
||||
amdgpu_vm_put_task_info(ti);
|
||||
}
|
||||
coredump->pasid = job->pasid;
|
||||
coredump->num_ibs = job->num_ibs;
|
||||
for (i = 0; i < job->num_ibs; ++i) {
|
||||
coredump->ibs[i].gpu_addr = job->ibs[i].gpu_addr;
|
||||
@@ -563,7 +566,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
coredump->rings[idx].offset = off;
|
||||
|
||||
memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
|
||||
off += ring->ring_size;
|
||||
off += ring->ring_size / 4;
|
||||
idx++;
|
||||
}
|
||||
coredump->num_rings = idx;
|
||||
|
||||
@@ -1334,18 +1334,15 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
|
||||
#if IS_ENABLED(CONFIG_X86)
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
if (!(amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 0) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 1)))
|
||||
return false;
|
||||
|
||||
if (c->x86 == 6 &&
|
||||
adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5) {
|
||||
if (c->x86_vendor == X86_VENDOR_INTEL) {
|
||||
switch (c->x86_model) {
|
||||
case VFM_MODEL(INTEL_ALDERLAKE):
|
||||
case VFM_MODEL(INTEL_ALDERLAKE_L):
|
||||
case VFM_MODEL(INTEL_RAPTORLAKE):
|
||||
case VFM_MODEL(INTEL_RAPTORLAKE_P):
|
||||
case VFM_MODEL(INTEL_RAPTORLAKE_S):
|
||||
case VFM_MODEL(INTEL_TIGERLAKE):
|
||||
case VFM_MODEL(INTEL_TIGERLAKE_L):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -5518,8 +5515,6 @@ static void amdgpu_device_recovery_prepare(struct amdgpu_device *adev,
|
||||
list_add_tail(&tmp_adev->reset_list, device_list);
|
||||
if (adev->shutdown)
|
||||
tmp_adev->shutdown = true;
|
||||
if (amdgpu_reset_in_dpc(adev))
|
||||
tmp_adev->pcie_reset_ctx.in_link_reset = true;
|
||||
}
|
||||
if (!list_is_first(&adev->reset_list, device_list))
|
||||
list_rotate_to_front(&adev->reset_list, device_list);
|
||||
@@ -6291,6 +6286,9 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
|
||||
amdgpu_reset_set_dpc_status(adev, true);
|
||||
|
||||
mutex_lock(&hive->hive_lock);
|
||||
} else {
|
||||
if (amdgpu_device_bus_status_check(adev))
|
||||
amdgpu_reset_set_dpc_status(adev, true);
|
||||
}
|
||||
memset(&reset_context, 0, sizeof(reset_context));
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
@@ -6411,6 +6409,7 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
|
||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
|
||||
tmp_adev->pcie_reset_ctx.in_link_reset = true;
|
||||
} else {
|
||||
adev->pcie_reset_ctx.in_link_reset = true;
|
||||
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
|
||||
}
|
||||
|
||||
@@ -6467,9 +6466,10 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
|
||||
tmp_adev->pcie_reset_ctx.in_link_reset = false;
|
||||
list_add_tail(&tmp_adev->reset_list, &device_list);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
adev->pcie_reset_ctx.in_link_reset = false;
|
||||
list_add_tail(&adev->reset_list, &device_list);
|
||||
|
||||
}
|
||||
amdgpu_device_sched_resume(&device_list, NULL, NULL);
|
||||
amdgpu_device_gpu_resume(adev, &device_list, false);
|
||||
amdgpu_device_recovery_put_reset_lock(adev, &device_list);
|
||||
|
||||
@@ -535,10 +535,11 @@ static int amdgpu_discovery_get_table_info(struct amdgpu_device *adev,
|
||||
*info = &bhdrv2->table_list[table_id];
|
||||
break;
|
||||
case 1:
|
||||
case 0:
|
||||
*info = &bhdr->table_list[table_id];
|
||||
break;
|
||||
default:
|
||||
dev_err(adev->dev, "Invalid ip discovery table version\n");
|
||||
dev_err(adev->dev, "Invalid ip discovery table version %d\n",bhdr->version_major);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -2013,6 +2013,8 @@ static void amdgpu_gfx_sysfs_xcp_fini(struct amdgpu_device *adev)
|
||||
(xcp_mgr->funcs && xcp_mgr->funcs->switch_partition_mode);
|
||||
device_remove_file(adev->dev, &dev_attr_current_compute_partition);
|
||||
|
||||
device_remove_file(adev->dev, &dev_attr_compute_partition_mem_alloc_mode);
|
||||
|
||||
if (xcp_switch_supported)
|
||||
device_remove_file(adev->dev,
|
||||
&dev_attr_available_compute_partition);
|
||||
|
||||
@@ -239,13 +239,12 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
|
||||
u64 size;
|
||||
int r = 0;
|
||||
|
||||
/* Caller must hold vm->root.bo reservation */
|
||||
dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
|
||||
|
||||
user_addr = (addr & AMDGPU_GMC_HOLE_MASK) >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
size = expected_size >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
|
||||
r = amdgpu_bo_reserve(vm->root.bo, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
va_map = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
|
||||
if (!va_map) {
|
||||
r = -EINVAL;
|
||||
@@ -255,13 +254,11 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
|
||||
if (user_addr >= va_map->start &&
|
||||
va_map->last - user_addr + 1 >= size) {
|
||||
amdgpu_userq_buffer_va_list_add(queue, va_map, user_addr);
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = -EINVAL;
|
||||
out_err:
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -270,15 +267,13 @@ static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
|
||||
struct amdgpu_bo_va_mapping *mapping;
|
||||
bool r;
|
||||
|
||||
if (amdgpu_bo_reserve(vm->root.bo, false))
|
||||
return false;
|
||||
dma_resv_assert_held(vm->root.bo->tbo.base.resv);
|
||||
|
||||
mapping = amdgpu_vm_bo_lookup_mapping(vm, addr);
|
||||
if (!IS_ERR_OR_NULL(mapping) && atomic_read(&mapping->bo_va->userq_va_mapped))
|
||||
r = true;
|
||||
else
|
||||
r = false;
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -314,25 +309,21 @@ static int amdgpu_userq_buffer_vas_list_cleanup(struct amdgpu_device *adev,
|
||||
{
|
||||
struct amdgpu_userq_va_cursor *va_cursor, *tmp;
|
||||
struct amdgpu_bo_va_mapping *mapping;
|
||||
int r;
|
||||
|
||||
r = amdgpu_bo_reserve(queue->vm->root.bo, false);
|
||||
if (r)
|
||||
return r;
|
||||
/* Caller must hold vm->root.bo reservation */
|
||||
dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
|
||||
|
||||
list_for_each_entry_safe(va_cursor, tmp, &queue->userq_va_list, list) {
|
||||
mapping = amdgpu_vm_bo_lookup_mapping(queue->vm, va_cursor->gpu_addr);
|
||||
if (!mapping) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_dbg(adev->dev, "delete the userq:%p va:%llx\n",
|
||||
queue, va_cursor->gpu_addr);
|
||||
amdgpu_userq_buffer_va_list_del(mapping, va_cursor);
|
||||
}
|
||||
err:
|
||||
amdgpu_bo_unreserve(queue->vm->root.bo);
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_userq_preempt_helper(struct amdgpu_usermode_queue *queue)
|
||||
@@ -446,8 +437,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
|
||||
/* Wait for mode-1 reset to complete */
|
||||
down_read(&adev->reset_domain->sem);
|
||||
|
||||
/* Drop the userq reference. */
|
||||
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
|
||||
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
|
||||
@@ -455,11 +444,19 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
|
||||
queue->fence_drv = NULL;
|
||||
queue->userq_mgr = NULL;
|
||||
list_del(&queue->userq_va_list);
|
||||
kfree(queue);
|
||||
|
||||
up_read(&adev->reset_domain->sem);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_userq_ensure_ev_fence - ensure a valid, unsignaled eviction fence exists
|
||||
* @uq_mgr: the usermode queue manager for this process
|
||||
* @evf_mgr: the eviction fence manager to check and rearm
|
||||
*
|
||||
* Ensures that a valid and not yet signaled eviction fence is attached to the
|
||||
* usermode queue before any queue operations proceed. If it is signalled, then
|
||||
* rearm a new eviction fence.
|
||||
*/
|
||||
void
|
||||
amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
|
||||
struct amdgpu_eviction_fence_mgr *evf_mgr)
|
||||
@@ -619,6 +616,9 @@ static int
|
||||
amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
struct amdgpu_device *adev = uq_mgr->adev;
|
||||
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
|
||||
int r = 0;
|
||||
|
||||
cancel_delayed_work_sync(&uq_mgr->resume_work);
|
||||
@@ -626,38 +626,44 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
||||
/* Cancel any pending hang detection work and cleanup */
|
||||
cancel_delayed_work_sync(&queue->hang_detect_work);
|
||||
|
||||
r = amdgpu_bo_reserve(vm->root.bo, false);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to reserve root bo during userqueue destroy\n");
|
||||
return r;
|
||||
}
|
||||
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
queue->hang_detect_fence = NULL;
|
||||
amdgpu_userq_wait_for_last_fence(queue);
|
||||
|
||||
r = amdgpu_bo_reserve(queue->db_obj.obj, true);
|
||||
if (!r) {
|
||||
amdgpu_bo_unpin(queue->db_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->db_obj.obj);
|
||||
}
|
||||
amdgpu_bo_unref(&queue->db_obj.obj);
|
||||
|
||||
r = amdgpu_bo_reserve(queue->wptr_obj.obj, true);
|
||||
if (!r) {
|
||||
amdgpu_bo_unpin(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->wptr_obj.obj);
|
||||
}
|
||||
amdgpu_bo_unref(&queue->wptr_obj.obj);
|
||||
|
||||
atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
debugfs_remove_recursive(queue->debugfs_queue);
|
||||
#endif
|
||||
amdgpu_userq_detect_and_reset_queues(uq_mgr);
|
||||
r = amdgpu_userq_unmap_helper(queue);
|
||||
/*TODO: It requires a reset for userq hw unmap error*/
|
||||
if (unlikely(r != AMDGPU_USERQ_STATE_UNMAPPED)) {
|
||||
if (r) {
|
||||
drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n");
|
||||
queue->state = AMDGPU_USERQ_STATE_HUNG;
|
||||
}
|
||||
|
||||
atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
|
||||
amdgpu_userq_cleanup(queue);
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
||||
amdgpu_bo_reserve(queue->db_obj.obj, true);
|
||||
amdgpu_bo_unpin(queue->db_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->db_obj.obj);
|
||||
amdgpu_bo_unref(&queue->db_obj.obj);
|
||||
|
||||
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
|
||||
amdgpu_bo_unpin(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unref(&queue->wptr_obj.obj);
|
||||
kfree(queue);
|
||||
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
|
||||
return r;
|
||||
@@ -730,35 +736,25 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||
r = pm_runtime_resume_and_get(adev_to_drm(adev)->dev);
|
||||
if (r < 0) {
|
||||
drm_file_err(uq_mgr->file, "pm_runtime_get_sync() failed for userqueue create\n");
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
drm_file_err(uq_mgr->file, "pm_runtime_resume_and_get() failed for userqueue create\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* There could be a situation that we are creating a new queue while
|
||||
* the other queues under this UQ_mgr are suspended. So if there is any
|
||||
* resume work pending, wait for it to get done.
|
||||
*
|
||||
* This will also make sure we have a valid eviction fence ready to be used.
|
||||
*/
|
||||
amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
|
||||
|
||||
uq_funcs = adev->userq_funcs[args->in.ip_type];
|
||||
if (!uq_funcs) {
|
||||
drm_file_err(uq_mgr->file, "Usermode queue is not supported for this IP (%u)\n",
|
||||
args->in.ip_type);
|
||||
r = -EINVAL;
|
||||
goto unlock;
|
||||
goto err_pm_runtime;
|
||||
}
|
||||
|
||||
queue = kzalloc_obj(struct amdgpu_usermode_queue);
|
||||
if (!queue) {
|
||||
drm_file_err(uq_mgr->file, "Failed to allocate memory for queue\n");
|
||||
r = -ENOMEM;
|
||||
goto unlock;
|
||||
goto err_pm_runtime;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&queue->userq_va_list);
|
||||
@@ -773,20 +769,27 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
db_info.doorbell_offset = args->in.doorbell_offset;
|
||||
|
||||
queue->userq_mgr = uq_mgr;
|
||||
|
||||
/* Validate the userq virtual address.*/
|
||||
r = amdgpu_bo_reserve(fpriv->vm.root.bo, false);
|
||||
if (r)
|
||||
goto free_queue;
|
||||
|
||||
if (amdgpu_userq_input_va_validate(adev, queue, args->in.queue_va, args->in.queue_size) ||
|
||||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va, AMDGPU_GPU_PAGE_SIZE) ||
|
||||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va, AMDGPU_GPU_PAGE_SIZE)) {
|
||||
r = -EINVAL;
|
||||
goto free_queue;
|
||||
amdgpu_bo_unreserve(fpriv->vm.root.bo);
|
||||
goto clean_mapping;
|
||||
}
|
||||
amdgpu_bo_unreserve(fpriv->vm.root.bo);
|
||||
|
||||
/* Convert relative doorbell offset into absolute doorbell index */
|
||||
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
|
||||
if (index == (uint64_t)-EINVAL) {
|
||||
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
|
||||
r = -EINVAL;
|
||||
goto free_queue;
|
||||
goto clean_mapping;
|
||||
}
|
||||
|
||||
queue->doorbell_index = index;
|
||||
@@ -794,7 +797,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
|
||||
goto free_queue;
|
||||
goto clean_mapping;
|
||||
}
|
||||
|
||||
r = uq_funcs->mqd_create(queue, &args->in);
|
||||
@@ -803,6 +806,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
goto clean_fence_driver;
|
||||
}
|
||||
|
||||
amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
|
||||
|
||||
/* don't map the queue if scheduling is halted */
|
||||
if (adev->userq_halt_for_enforce_isolation &&
|
||||
((queue->queue_type == AMDGPU_HW_IP_GFX) ||
|
||||
@@ -814,7 +819,6 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
r = amdgpu_userq_map_helper(queue);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
|
||||
down_read(&adev->reset_domain->sem);
|
||||
goto clean_mqd;
|
||||
}
|
||||
}
|
||||
@@ -830,9 +834,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
if (r) {
|
||||
if (!skip_map_queue)
|
||||
amdgpu_userq_unmap_helper(queue);
|
||||
|
||||
r = -ENOMEM;
|
||||
goto clean_mqd;
|
||||
goto clean_reset_domain;
|
||||
}
|
||||
|
||||
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
|
||||
@@ -840,8 +843,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
xa_erase(&uq_mgr->userq_xa, qid);
|
||||
if (!skip_map_queue)
|
||||
amdgpu_userq_unmap_helper(queue);
|
||||
|
||||
goto clean_mqd;
|
||||
goto clean_reset_domain;
|
||||
}
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
@@ -853,16 +855,21 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
return 0;
|
||||
|
||||
clean_mqd:
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
clean_reset_domain:
|
||||
up_read(&adev->reset_domain->sem);
|
||||
clean_mqd:
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
clean_fence_driver:
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
clean_mapping:
|
||||
amdgpu_bo_reserve(fpriv->vm.root.bo, true);
|
||||
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
|
||||
amdgpu_bo_unreserve(fpriv->vm.root.bo);
|
||||
free_queue:
|
||||
kfree(queue);
|
||||
unlock:
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
||||
err_pm_runtime:
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -992,10 +999,16 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
|
||||
static int
|
||||
amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
|
||||
{
|
||||
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
unsigned long queue_id;
|
||||
int ret = 0, r;
|
||||
|
||||
|
||||
if (amdgpu_bo_reserve(vm->root.bo, false))
|
||||
return false;
|
||||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
/* Resume all the queues for this process */
|
||||
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
|
||||
@@ -1013,6 +1026,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
|
||||
|
||||
}
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
|
||||
if (ret)
|
||||
drm_file_err(uq_mgr->file,
|
||||
|
||||
@@ -145,13 +145,22 @@ amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
|
||||
amdgpu_userq_fence_driver_put(userq->fence_drv);
|
||||
}
|
||||
|
||||
static void
|
||||
amdgpu_userq_fence_put_fence_drv_array(struct amdgpu_userq_fence *userq_fence)
|
||||
{
|
||||
unsigned long i;
|
||||
for (i = 0; i < userq_fence->fence_drv_array_count; i++)
|
||||
amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]);
|
||||
userq_fence->fence_drv_array_count = 0;
|
||||
}
|
||||
|
||||
void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_drv)
|
||||
{
|
||||
struct amdgpu_userq_fence *userq_fence, *tmp;
|
||||
LIST_HEAD(to_be_signaled);
|
||||
struct dma_fence *fence;
|
||||
unsigned long flags;
|
||||
u64 rptr;
|
||||
int i;
|
||||
|
||||
if (!fence_drv)
|
||||
return;
|
||||
@@ -159,21 +168,26 @@ void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_d
|
||||
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
|
||||
rptr = amdgpu_userq_fence_read(fence_drv);
|
||||
|
||||
list_for_each_entry_safe(userq_fence, tmp, &fence_drv->fences, link) {
|
||||
fence = &userq_fence->base;
|
||||
|
||||
if (rptr < fence->seqno)
|
||||
list_for_each_entry(userq_fence, &fence_drv->fences, link) {
|
||||
if (rptr < userq_fence->base.seqno)
|
||||
break;
|
||||
}
|
||||
|
||||
list_cut_before(&to_be_signaled, &fence_drv->fences,
|
||||
&userq_fence->link);
|
||||
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(userq_fence, tmp, &to_be_signaled, link) {
|
||||
fence = &userq_fence->base;
|
||||
list_del_init(&userq_fence->link);
|
||||
dma_fence_signal(fence);
|
||||
|
||||
for (i = 0; i < userq_fence->fence_drv_array_count; i++)
|
||||
amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]);
|
||||
|
||||
list_del(&userq_fence->link);
|
||||
/* Drop fence_drv_array outside fence_list_lock
|
||||
* to avoid the recursion lock.
|
||||
*/
|
||||
amdgpu_userq_fence_put_fence_drv_array(userq_fence);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
void amdgpu_userq_fence_driver_destroy(struct kref *ref)
|
||||
@@ -228,6 +242,7 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
|
||||
struct amdgpu_userq_fence_driver *fence_drv;
|
||||
struct dma_fence *fence;
|
||||
unsigned long flags;
|
||||
bool signaled = false;
|
||||
|
||||
fence_drv = userq->fence_drv;
|
||||
if (!fence_drv)
|
||||
@@ -274,13 +289,17 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
|
||||
|
||||
/* Check if hardware has already processed the job */
|
||||
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
|
||||
if (!dma_fence_is_signaled(fence))
|
||||
if (!dma_fence_is_signaled(fence)) {
|
||||
list_add_tail(&userq_fence->link, &fence_drv->fences);
|
||||
else
|
||||
} else {
|
||||
signaled = true;
|
||||
dma_fence_put(fence);
|
||||
|
||||
}
|
||||
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
|
||||
|
||||
if (signaled)
|
||||
amdgpu_userq_fence_put_fence_drv_array(userq_fence);
|
||||
|
||||
*f = fence;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_pm.h"
|
||||
#include "amdgpu_vcn.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "soc15d.h"
|
||||
|
||||
/* Firmware Names */
|
||||
@@ -361,7 +362,7 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i)
|
||||
|
||||
/* err_event_athub and dpc recovery will corrupt VCPU buffer, so we need to
|
||||
* restore fw data and clear buffer in amdgpu_vcn_resume() */
|
||||
if (in_ras_intr || adev->pcie_reset_ctx.in_link_reset)
|
||||
if (in_ras_intr || amdgpu_reset_in_dpc(adev))
|
||||
return 0;
|
||||
|
||||
return amdgpu_vcn_save_vcpu_bo_inst(adev, i);
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
#include "amdgpu_vm.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_object.h"
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
@@ -108,11 +110,19 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p,
|
||||
static int amdgpu_vm_cpu_commit(struct amdgpu_vm_update_params *p,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_device *adev = p->adev;
|
||||
|
||||
if (p->needs_flush)
|
||||
atomic64_inc(&p->vm->tlb_seq);
|
||||
|
||||
mb();
|
||||
amdgpu_device_flush_hdp(p->adev, NULL);
|
||||
/* A reset flushed the HDP anyway, so that here can be skipped when a reset is ongoing */
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return 0;
|
||||
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -693,8 +693,11 @@ static void amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params *params,
|
||||
!(flags & AMDGPU_PTE_VALID) &&
|
||||
!(flags & AMDGPU_PTE_PRT_FLAG(params->adev))) {
|
||||
|
||||
/* Workaround for fault priority problem on GMC9 */
|
||||
flags |= AMDGPU_PTE_EXECUTABLE;
|
||||
/* Workaround for fault priority problem on GMC9 and GFX12,
|
||||
* EXECUTABLE for GMC9 fault priority and init_pte_flags
|
||||
* (e.g. AMDGPU_PTE_IS_PTE on GFX12)
|
||||
*/
|
||||
flags |= AMDGPU_PTE_EXECUTABLE | adev->gmc.init_pte_flags;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
#define regPC_CONFIG_CNTL_1 0x194d
|
||||
#define regPC_CONFIG_CNTL_1_BASE_IDX 1
|
||||
|
||||
#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0 0x0030
|
||||
#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0_BASE_IDX 1
|
||||
#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0 0x0031
|
||||
#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0_BASE_IDX 1
|
||||
|
||||
#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100
|
||||
#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000
|
||||
#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000
|
||||
@@ -5234,11 +5239,27 @@ static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
} else {
|
||||
preempt_disable();
|
||||
clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
|
||||
clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
|
||||
if (clock_counter_hi_pre != clock_counter_hi_after)
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
|
||||
if (amdgpu_ip_version(adev, SMUIO_HWIP, 0) < IP_VERSION(15, 0, 0)) {
|
||||
clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER);
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER);
|
||||
clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER);
|
||||
if (clock_counter_hi_pre != clock_counter_hi_after)
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER);
|
||||
} else {
|
||||
clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0);
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0);
|
||||
clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0);
|
||||
if (clock_counter_hi_pre != clock_counter_hi_after)
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0);
|
||||
}
|
||||
preempt_enable();
|
||||
}
|
||||
clock = clock_counter_lo | (clock_counter_hi_after << 32ULL);
|
||||
|
||||
@@ -736,15 +736,35 @@ static void jpeg_v4_0_3_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
*/
|
||||
void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(ring->adev)) {
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
int jpeg_inst = GET_INST(JPEG, ring->me);
|
||||
uint32_t value = 0x80004000; /* default DS14 */
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
|
||||
|
||||
/* PCTL0__MMHUB_DEEPSLEEP_IB could be different on different mmhub version */
|
||||
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
amdgpu_ring_write(ring, 0x69004);
|
||||
value = 0x80010000;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 0):
|
||||
amdgpu_ring_write(ring, 0x60804);
|
||||
if (jpeg_inst & 1)
|
||||
value = 0x80010000;
|
||||
break;
|
||||
default:
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
break;
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0,
|
||||
0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x80004000);
|
||||
amdgpu_ring_write(ring, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,15 +777,35 @@ void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
*/
|
||||
void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(ring->adev)) {
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
int jpeg_inst = GET_INST(JPEG, ring->me);
|
||||
uint32_t value = 0x00004000; /* default DS14 */
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
|
||||
/* PCTL0__MMHUB_DEEPSLEEP_IB could be different on different mmhub version */
|
||||
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
amdgpu_ring_write(ring, 0x69004);
|
||||
value = 0x00010000;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 0):
|
||||
amdgpu_ring_write(ring, 0x60804);
|
||||
if (jpeg_inst & 1)
|
||||
value = 0x00010000;
|
||||
break;
|
||||
default:
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
break;
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0,
|
||||
0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x00004000);
|
||||
amdgpu_ring_write(ring, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -322,8 +322,14 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_reserve(queue->vm->root.bo, false);
|
||||
if (r) {
|
||||
kfree(compute_mqd);
|
||||
goto free_mqd;
|
||||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
|
||||
2048);
|
||||
amdgpu_bo_unreserve(queue->vm->root.bo);
|
||||
if (r) {
|
||||
kfree(compute_mqd);
|
||||
goto free_mqd;
|
||||
@@ -365,14 +371,22 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
||||
userq_props->tmz_queue =
|
||||
mqd_user->flags & AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE;
|
||||
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
|
||||
shadow_info.shadow_size);
|
||||
r = amdgpu_bo_reserve(queue->vm->root.bo, false);
|
||||
if (r) {
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
|
||||
shadow_info.shadow_size);
|
||||
if (r) {
|
||||
amdgpu_bo_unreserve(queue->vm->root.bo);
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
|
||||
shadow_info.csa_size);
|
||||
amdgpu_bo_unreserve(queue->vm->root.bo);
|
||||
if (r) {
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
@@ -394,8 +408,15 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
||||
r = -ENOMEM;
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_reserve(queue->vm->root.bo, false);
|
||||
if (r) {
|
||||
kfree(mqd_sdma_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
|
||||
32);
|
||||
amdgpu_bo_unreserve(queue->vm->root.bo);
|
||||
if (r) {
|
||||
kfree(mqd_sdma_v11);
|
||||
goto free_mqd;
|
||||
|
||||
@@ -2028,7 +2028,7 @@ static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id,
|
||||
int num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
int sdma_ring_align = 0x10, compute_ring_align = 0x100;
|
||||
uint32_t tmp, xcc_offset;
|
||||
int r = 0, i, wptr = 0;
|
||||
int r = 0, i, j, wptr = 0;
|
||||
|
||||
if (queue_type == AMDGPU_RING_TYPE_COMPUTE) {
|
||||
if (!adev->mes.enable_coop_mode) {
|
||||
@@ -2077,11 +2077,11 @@ static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id,
|
||||
tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
|
||||
regSCRATCH_REG0);
|
||||
} else {
|
||||
for (i = 0; i < num_xcc; i++) {
|
||||
if (xcc_id != adev->mes.master_xcc_ids[i])
|
||||
for (j = 0; j < num_xcc; j++) {
|
||||
if (xcc_id != adev->mes.master_xcc_ids[j])
|
||||
continue;
|
||||
|
||||
tmp = RREG32_SOC15(GC, GET_INST(GC, i),
|
||||
tmp = RREG32_SOC15(GC, GET_INST(GC, j),
|
||||
regSCRATCH_REG0);
|
||||
if (tmp != 0xDEADBEEF)
|
||||
break;
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10_BASE_IDX 3
|
||||
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10 0x4f0af6
|
||||
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10_BASE_IDX 3
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10 0x0021
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10_BASE_IDX 2
|
||||
|
||||
static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
@@ -65,7 +67,12 @@ static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
|
||||
static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
|
||||
u32 tmp;
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10);
|
||||
else
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
|
||||
|
||||
tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK;
|
||||
tmp >>= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "mp/mp_15_0_0_sh_mask.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/psp_15_0_0_toc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_15_0_0_ta.bin");
|
||||
|
||||
static int psp_v15_0_0_init_microcode(struct psp_context *psp)
|
||||
{
|
||||
|
||||
@@ -1268,6 +1268,18 @@ static int sdma_v7_1_early_init(struct amdgpu_ip_block *ip_block)
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
int r;
|
||||
|
||||
switch (amdgpu_user_queue) {
|
||||
case -1:
|
||||
default:
|
||||
adev->sdma.no_user_submission = true;
|
||||
adev->sdma.disable_uq = true;
|
||||
break;
|
||||
case 0:
|
||||
adev->sdma.no_user_submission = false;
|
||||
adev->sdma.disable_uq = true;
|
||||
break;
|
||||
}
|
||||
|
||||
r = amdgpu_sdma_init_microcode(adev, 0, true);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to init sdma firmware!\n");
|
||||
|
||||
@@ -776,6 +776,9 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (args->num_of_nodes > kfd_topology_get_num_devices())
|
||||
return -EINVAL;
|
||||
|
||||
/* Fill in process-aperture information for all available
|
||||
* nodes, but not more than args->num_of_nodes as that is
|
||||
* the amount of memory allocated by user
|
||||
|
||||
@@ -1191,6 +1191,7 @@ static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev,
|
||||
return NULL;
|
||||
}
|
||||
int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_node **kdev);
|
||||
uint32_t kfd_topology_get_num_devices(void);
|
||||
int kfd_numa_node_to_apic_id(int numa_node_id);
|
||||
uint32_t kfd_gpu_node_num(void);
|
||||
|
||||
|
||||
@@ -2297,6 +2297,17 @@ int kfd_topology_remove_device(struct kfd_node *gpu)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t kfd_topology_get_num_devices(void)
|
||||
{
|
||||
uint32_t num_devices;
|
||||
|
||||
down_read(&topology_lock);
|
||||
num_devices = sys_props.num_devices;
|
||||
up_read(&topology_lock);
|
||||
|
||||
return num_devices;
|
||||
}
|
||||
|
||||
/* kfd_topology_enum_kfd_devices - Enumerate through all devices in KFD
|
||||
* topology. If GPU device is found @idx, then valid kfd_dev pointer is
|
||||
* returned through @kdev
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
#include <drm/drm_utils.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_audio_component.h>
|
||||
#include <drm/drm_colorop.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
@@ -2255,6 +2256,10 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
|
||||
adev->dm.idle_workqueue = NULL;
|
||||
}
|
||||
|
||||
/* Disable ISM before dc_destroy() invalidates dm->dc */
|
||||
scoped_guard(mutex, &adev->dm.dc_lock)
|
||||
amdgpu_dm_ism_disable(&adev->dm);
|
||||
|
||||
amdgpu_dm_destroy_drm_device(&adev->dm);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
|
||||
@@ -3994,7 +3999,7 @@ void amdgpu_dm_update_connector_after_detect(
|
||||
|
||||
if (sink) {
|
||||
if (aconnector->dc_sink) {
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL);
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL, true);
|
||||
/*
|
||||
* retain and release below are used to
|
||||
* bump up refcount for sink because the link doesn't point
|
||||
@@ -4006,9 +4011,9 @@ void amdgpu_dm_update_connector_after_detect(
|
||||
aconnector->dc_sink = sink;
|
||||
dc_sink_retain(aconnector->dc_sink);
|
||||
amdgpu_dm_update_freesync_caps(connector,
|
||||
aconnector->drm_edid);
|
||||
aconnector->drm_edid, true);
|
||||
} else {
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL);
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL, true);
|
||||
if (!aconnector->dc_sink) {
|
||||
aconnector->dc_sink = aconnector->dc_em_sink;
|
||||
dc_sink_retain(aconnector->dc_sink);
|
||||
@@ -4052,7 +4057,7 @@ void amdgpu_dm_update_connector_after_detect(
|
||||
* If yes, put it here.
|
||||
*/
|
||||
if (aconnector->dc_sink) {
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL);
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL, true);
|
||||
dc_sink_release(aconnector->dc_sink);
|
||||
}
|
||||
|
||||
@@ -4085,13 +4090,13 @@ void amdgpu_dm_update_connector_after_detect(
|
||||
"failed to create aconnector->requested_timing\n");
|
||||
}
|
||||
|
||||
amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid);
|
||||
amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid, true);
|
||||
update_connector_ext_caps(aconnector);
|
||||
dm_set_panel_type(aconnector);
|
||||
} else {
|
||||
hdmi_cec_unset_edid(aconnector);
|
||||
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL);
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL, true);
|
||||
aconnector->num_modes = 0;
|
||||
dc_sink_release(aconnector->dc_sink);
|
||||
aconnector->dc_sink = NULL;
|
||||
@@ -8855,7 +8860,7 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
|
||||
* drm_edid_connector_add_modes() and need to be
|
||||
* restored here.
|
||||
*/
|
||||
amdgpu_dm_update_freesync_caps(connector, drm_edid);
|
||||
amdgpu_dm_update_freesync_caps(connector, drm_edid, false);
|
||||
} else {
|
||||
amdgpu_dm_connector->num_modes = 0;
|
||||
}
|
||||
@@ -12329,6 +12334,38 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
|
||||
* available.
|
||||
*/
|
||||
|
||||
/**
|
||||
* dm_plane_color_pipeline_active() - Check if a plane's color pipeline active.
|
||||
* @state: DRM atomic state
|
||||
* @plane: DRM plane to check
|
||||
* @use_old: if true, inspect the old colorop states; otherwise the new ones
|
||||
*
|
||||
* A color pipeline may be selected (color_pipeline != NULL) but still is
|
||||
* inactive if every colorop in the chain is bypassed. Only return
|
||||
* true when at least one colorop has bypass == false, meaning the cursor
|
||||
* would be subjected to the transformation in native mode.
|
||||
*
|
||||
* Return: true if the pipeline modifies pixels, false otherwise.
|
||||
*/
|
||||
static bool dm_plane_color_pipeline_active(struct drm_atomic_state *state,
|
||||
struct drm_plane *plane,
|
||||
bool use_old)
|
||||
{
|
||||
struct drm_colorop *colorop;
|
||||
struct drm_colorop_state *old_colorop_state, *new_colorop_state;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_colorop_in_state(state, colorop, old_colorop_state, new_colorop_state, i) {
|
||||
struct drm_colorop_state *cstate = use_old ? old_colorop_state : new_colorop_state;
|
||||
|
||||
if (cstate->colorop->plane != plane)
|
||||
continue;
|
||||
if (!cstate->bypass)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_crtc_get_cursor_mode() - Determine the required cursor mode on crtc
|
||||
* @adev: amdgpu device
|
||||
@@ -12340,8 +12377,8 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
|
||||
* the dm_crtc_state.
|
||||
*
|
||||
* The cursor should be enabled in overlay mode if there exists an underlying
|
||||
* plane - on which the cursor may be blended - that is either YUV formatted, or
|
||||
* scaled differently from the cursor.
|
||||
* plane - on which the cursor may be blended - that is either YUV formatted,
|
||||
* scaled differently from the cursor, or has a color pipeline active.
|
||||
*
|
||||
* Since zpos info is required, drm_atomic_normalize_zpos must be called before
|
||||
* calling this function.
|
||||
@@ -12379,7 +12416,7 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
|
||||
|
||||
/*
|
||||
* Cursor mode can change if a plane's format changes, scale changes, is
|
||||
* enabled/disabled, or z-order changes.
|
||||
* enabled/disabled, z-order changes, or color management properties change.
|
||||
*/
|
||||
for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
|
||||
int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
|
||||
@@ -12404,6 +12441,12 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
|
||||
consider_mode_change = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dm_plane_color_pipeline_active(state, plane, true) !=
|
||||
dm_plane_color_pipeline_active(state, plane, false)) {
|
||||
consider_mode_change = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!consider_mode_change && !crtc_state->zpos_changed)
|
||||
@@ -12444,6 +12487,12 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Underlying plane has an active color pipeline - cursor would be transformed */
|
||||
if (dm_plane_color_pipeline_active(state, plane, false)) {
|
||||
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_get_plane_scale(plane_state,
|
||||
&underlying_scale_w, &underlying_scale_h);
|
||||
dm_get_plane_scale(cursor_state,
|
||||
@@ -12823,7 +12872,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
goto fail;
|
||||
} else if (required_cursor_mode == DM_CURSOR_OVERLAY_MODE) {
|
||||
drm_dbg_driver(crtc->dev,
|
||||
"[CRTC:%d:%s] Cannot enable native cursor due to scaling or YUV restrictions\n",
|
||||
"[CRTC:%d:%s] Cannot enable native cursor due to scaling, YUV, or color pipeline restrictions\n",
|
||||
crtc->base.id, crtc->name);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
@@ -13088,6 +13137,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
|
||||
vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version;
|
||||
vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate;
|
||||
vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate;
|
||||
vsdb->freesync_mccs_vcp_code = output->amd_vsdb.freesync_mccs_vcp_code;
|
||||
} else {
|
||||
drm_warn(adev_to_drm(dm->adev), "Unknown EDID CEA parser results\n");
|
||||
return false;
|
||||
@@ -13122,6 +13172,8 @@ static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
|
||||
vsdb_info->amd_vsdb_version = version;
|
||||
vsdb_info->min_refresh_rate_hz = min_rate;
|
||||
vsdb_info->max_refresh_rate_hz = max_rate;
|
||||
/* Not enabled on DMCU*/
|
||||
vsdb_info->freesync_mccs_vcp_code = 0;
|
||||
return true;
|
||||
}
|
||||
/* not amd vsdb */
|
||||
@@ -13260,6 +13312,10 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
|
||||
*
|
||||
* @connector: Connector to query.
|
||||
* @drm_edid: DRM EDID from monitor
|
||||
* @do_mccs: Controls whether MCCS (Monitor Control Command Set) over
|
||||
* DDC (Display Data Channel) transactions are performed. When true,
|
||||
* the driver queries the monitor to get or update additional FreeSync
|
||||
* capability information. When false, these transactions are skipped.
|
||||
*
|
||||
* Amdgpu supports Freesync in DP and HDMI displays, and it is required to keep
|
||||
* track of some of the display information in the internal data struct used by
|
||||
@@ -13267,7 +13323,7 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
|
||||
* FreeSync parameters.
|
||||
*/
|
||||
void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
const struct drm_edid *drm_edid)
|
||||
const struct drm_edid *drm_edid, bool do_mccs)
|
||||
{
|
||||
int i = 0;
|
||||
struct amdgpu_dm_connector *amdgpu_dm_connector =
|
||||
@@ -13333,14 +13389,19 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
|
||||
} else if (drm_edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) {
|
||||
i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
|
||||
if (i >= 0 && vsdb_info.freesync_supported) {
|
||||
amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
|
||||
freesync_capable = true;
|
||||
if (i >= 0) {
|
||||
amdgpu_dm_connector->vsdb_info = vsdb_info;
|
||||
sink->edid_caps.freesync_vcp_code = vsdb_info.freesync_mccs_vcp_code;
|
||||
|
||||
connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
if (vsdb_info.freesync_supported) {
|
||||
amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
|
||||
freesync_capable = true;
|
||||
|
||||
connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13349,22 +13410,38 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
|
||||
if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) {
|
||||
i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
|
||||
if (i >= 0 && vsdb_info.freesync_supported && vsdb_info.amd_vsdb_version > 0) {
|
||||
|
||||
amdgpu_dm_connector->pack_sdp_v1_3 = true;
|
||||
amdgpu_dm_connector->as_type = as_type;
|
||||
if (i >= 0) {
|
||||
amdgpu_dm_connector->vsdb_info = vsdb_info;
|
||||
sink->edid_caps.freesync_vcp_code = vsdb_info.freesync_mccs_vcp_code;
|
||||
|
||||
amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
|
||||
freesync_capable = true;
|
||||
if (vsdb_info.freesync_supported && vsdb_info.amd_vsdb_version > 0) {
|
||||
amdgpu_dm_connector->pack_sdp_v1_3 = true;
|
||||
amdgpu_dm_connector->as_type = as_type;
|
||||
|
||||
connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
|
||||
freesync_capable = true;
|
||||
|
||||
connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
|
||||
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle MCCS */
|
||||
if (do_mccs)
|
||||
dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
|
||||
|
||||
if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) &&
|
||||
(!sink->edid_caps.freesync_vcp_code ||
|
||||
(sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
|
||||
freesync_capable = false;
|
||||
|
||||
if (do_mccs && sink->mccs_caps.freesync_supported && freesync_capable)
|
||||
dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
|
||||
|
||||
update:
|
||||
if (dm_con_state)
|
||||
dm_con_state->freesync_capable = freesync_capable;
|
||||
|
||||
@@ -758,6 +758,11 @@ struct amdgpu_hdmi_vsdb_info {
|
||||
*/
|
||||
unsigned int max_refresh_rate_hz;
|
||||
|
||||
/**
|
||||
* @freesync_mccs_vcp_code: MCCS VCP code for freesync state
|
||||
*/
|
||||
unsigned int freesync_mccs_vcp_code;
|
||||
|
||||
/**
|
||||
* @replay_mode: Replay supported
|
||||
*/
|
||||
@@ -1066,7 +1071,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev,
|
||||
struct drm_connector *connector);
|
||||
|
||||
void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
const struct drm_edid *drm_edid);
|
||||
const struct drm_edid *drm_edid, bool do_mccs);
|
||||
|
||||
void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
|
||||
|
||||
|
||||
@@ -457,9 +457,12 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
|
||||
|
||||
static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
|
||||
/*
|
||||
* amdgpu_dm_ism_fini() is intentionally called in amdgpu_dm_fini().
|
||||
* It must be called before dc_destroy() in amdgpu_dm_fini()
|
||||
* to avoid ISM accessing an invalid dc handle once dc is released.
|
||||
*/
|
||||
|
||||
amdgpu_dm_ism_fini(&acrtc->ism);
|
||||
drm_crtc_cleanup(crtc);
|
||||
kfree(crtc);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,45 @@
|
||||
#include "ddc_service_types.h"
|
||||
#include "clk_mgr.h"
|
||||
|
||||
#define MCCS_DEST_ADDR (0x6E >> 1)
|
||||
#define MCCS_SRC_ADDR 0x51
|
||||
#define MCCS_LENGTH_OFFSET 0x80
|
||||
#define MCCS_MAX_DATA_SIZE 0x20
|
||||
|
||||
enum mccs_op_code {
|
||||
MCCS_OP_CODE_VCP_REQUEST = 0x01,
|
||||
MCCS_OP_CODE_VCP_REPLY = 0x02,
|
||||
MCCS_OP_CODE_VCP_SET = 0x03,
|
||||
MCCS_OP_CODE_VCP_RESET = 0x09,
|
||||
MCCS_OP_CODE_CAP_REQUEST = 0xF3,
|
||||
MCCS_OP_CODE_CAP_REPLY = 0xE3
|
||||
};
|
||||
|
||||
enum mccs_op_buff_size {
|
||||
MCCS_OP_BUFF_SIZE__WR_VCP_REQUEST = 5,
|
||||
MCCS_OP_BUFF_SIZE_RD_VCP_REQUEST = 11,
|
||||
MCCS_OP_BUFF_SIZE_WR_VCP_SET = 7,
|
||||
};
|
||||
|
||||
enum vcp_reply_mask {
|
||||
FREESYNC_SUPPORTED = 0x1
|
||||
};
|
||||
|
||||
union vcp_reply {
|
||||
struct {
|
||||
unsigned char src_addr;
|
||||
unsigned char length; /* Length is offset by MccsLengthOffs = 0x80 */
|
||||
unsigned char reply_op_code; /* Should return MCCS_OP_CODE_VCP_REPLY = 0x02 */
|
||||
unsigned char result_code; /* 00h No Error, 01h Unsupported VCP Code */
|
||||
unsigned char request_code; /* Should return mccs vcp code sent in the vcp request */
|
||||
unsigned char type_code; /* VCP type code: 00h Set parameter, 01h Momentary */
|
||||
unsigned char max_value[2]; /* 2 bytes returning max value current value */
|
||||
unsigned char present_value[2]; /* NOTE: Byte0 is MSB, Byte1 is LSB */
|
||||
unsigned char check_sum;
|
||||
} bytes;
|
||||
unsigned char raw[11];
|
||||
};
|
||||
|
||||
static u32 edid_extract_panel_id(struct edid *edid)
|
||||
{
|
||||
return (u32)edid->mfg_id[0] << 24 |
|
||||
@@ -1400,6 +1439,8 @@ static bool dm_is_freesync_pcon_whitelist(const uint32_t branch_dev_id)
|
||||
case DP_BRANCH_DEVICE_ID_0060AD:
|
||||
case DP_BRANCH_DEVICE_ID_00E04C:
|
||||
case DP_BRANCH_DEVICE_ID_90CC24:
|
||||
case DP_BRANCH_DEVICE_ID_001CF8:
|
||||
case DP_BRANCH_DEVICE_ID_001FF2:
|
||||
ret_val = true;
|
||||
break;
|
||||
default:
|
||||
@@ -1439,3 +1480,203 @@ bool dm_helpers_is_hdr_on(struct dc_context *ctx, struct dc_stream_state *stream
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mccs_operation_vcp_request(unsigned int vcp_code, struct dc_link *link,
|
||||
union vcp_reply *reply)
|
||||
{
|
||||
const unsigned char retry_interval_ms = 40;
|
||||
unsigned char retry = 5;
|
||||
struct amdgpu_dm_connector *aconnector = link->priv;
|
||||
struct i2c_adapter *ddc;
|
||||
struct i2c_msg msg = {0};
|
||||
int ret = 0;
|
||||
int idx;
|
||||
|
||||
unsigned char wr_data[MCCS_OP_BUFF_SIZE__WR_VCP_REQUEST] = {
|
||||
MCCS_SRC_ADDR, /* Byte0 - Src Addr */
|
||||
MCCS_LENGTH_OFFSET + 2, /* Byte1 - Length */
|
||||
MCCS_OP_CODE_VCP_REQUEST, /* Byte2 - MCCS Command */
|
||||
(unsigned char) vcp_code, /* Byte3 - VCP Code */
|
||||
MCCS_DEST_ADDR << 1 /* Byte4 - CheckSum */
|
||||
};
|
||||
|
||||
/* calculate checksum */
|
||||
for (idx = 0; idx < (MCCS_OP_BUFF_SIZE__WR_VCP_REQUEST - 1); idx++)
|
||||
wr_data[(MCCS_OP_BUFF_SIZE__WR_VCP_REQUEST-1)] ^= wr_data[idx];
|
||||
|
||||
if (link->aux_mode)
|
||||
ddc = &aconnector->dm_dp_aux.aux.ddc;
|
||||
else
|
||||
ddc = &aconnector->i2c->base;
|
||||
|
||||
do {
|
||||
msg.addr = MCCS_DEST_ADDR;
|
||||
msg.flags = 0;
|
||||
msg.len = MCCS_OP_BUFF_SIZE__WR_VCP_REQUEST;
|
||||
msg.buf = wr_data;
|
||||
|
||||
ret = i2c_transfer(ddc, &msg, 1);
|
||||
if (ret != 1)
|
||||
goto mccs_retry;
|
||||
|
||||
msleep(retry_interval_ms);
|
||||
|
||||
msg.addr = MCCS_DEST_ADDR;
|
||||
msg.flags = I2C_M_RD;
|
||||
msg.len = MCCS_OP_BUFF_SIZE_RD_VCP_REQUEST;
|
||||
msg.buf = reply->raw;
|
||||
|
||||
ret = i2c_transfer(ddc, &msg, 1);
|
||||
|
||||
/* sink might reply with null msg if it can't reply in time */
|
||||
if (ret == 1 && reply->bytes.length > MCCS_LENGTH_OFFSET)
|
||||
break;
|
||||
mccs_retry:
|
||||
retry--;
|
||||
msleep(retry_interval_ms);
|
||||
} while (retry);
|
||||
|
||||
if (!retry) {
|
||||
drm_dbg_driver(aconnector->base.dev,
|
||||
"%s: MCCS VCP request failed after retries", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dm_helpers_read_mccs_caps(struct dc_context *ctx, struct dc_link *link,
|
||||
struct dc_sink *sink)
|
||||
{
|
||||
bool mccs_op = false;
|
||||
struct dpcd_caps *dpcd_caps;
|
||||
struct drm_device *dev;
|
||||
uint16_t freesync_vcp_value = 0;
|
||||
union vcp_reply vcp_reply_value = {0};
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
dev = adev_to_drm(ctx->driver_context);
|
||||
|
||||
if (!link || !sink) {
|
||||
drm_dbg_driver(dev, "%s: link or sink is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
sink->mccs_caps.freesync_supported = false;
|
||||
dpcd_caps = &link->dpcd_caps;
|
||||
|
||||
if (sink->edid_caps.freesync_vcp_code != 0) {
|
||||
if (dc_is_dp_signal(link->connector_signal)) {
|
||||
if ((dpcd_caps->dpcd_rev.raw >= DPCD_REV_14) &&
|
||||
(dpcd_caps->dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) &&
|
||||
dm_is_freesync_pcon_whitelist(dpcd_caps->branch_dev_id) &&
|
||||
(dpcd_caps->adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT == true))
|
||||
mccs_op = true;
|
||||
|
||||
if ((dpcd_caps->dongle_type != DISPLAY_DONGLE_NONE &&
|
||||
dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER)) {
|
||||
if (mccs_op == false)
|
||||
drm_dbg_driver(dev, "%s: Legacy Pcon support", __func__);
|
||||
mccs_op = true;
|
||||
}
|
||||
|
||||
if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
|
||||
// Todo: Freesync over MST
|
||||
mccs_op = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dc_is_hdmi_signal(link->connector_signal)) {
|
||||
drm_dbg_driver(dev, "%s: Local HDMI sink", __func__);
|
||||
mccs_op = true;
|
||||
}
|
||||
|
||||
if (mccs_op == true) {
|
||||
// MCCS VCP request to get VCP value
|
||||
if (!mccs_operation_vcp_request(sink->edid_caps.freesync_vcp_code, link,
|
||||
&vcp_reply_value)) {
|
||||
freesync_vcp_value = vcp_reply_value.bytes.present_value[1];
|
||||
freesync_vcp_value |= (uint16_t) vcp_reply_value.bytes.present_value[0] << 8;
|
||||
}
|
||||
// If VCP Value bit 0 is 1, freesyncSupport = true
|
||||
sink->mccs_caps.freesync_supported =
|
||||
(freesync_vcp_value & FREESYNC_SUPPORTED) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mccs_operation_vcp_set(unsigned int vcp_code, struct dc_link *link, uint16_t value)
|
||||
{
|
||||
const unsigned char retry_interval_ms = 40;
|
||||
unsigned char retry = 5;
|
||||
struct amdgpu_dm_connector *aconnector = link->priv;
|
||||
struct i2c_adapter *ddc;
|
||||
struct i2c_msg msg = {0};
|
||||
int ret = 0;
|
||||
int idx;
|
||||
|
||||
unsigned char wr_data[MCCS_OP_BUFF_SIZE_WR_VCP_SET] = {
|
||||
MCCS_SRC_ADDR, /* Byte0 - Src Addr */
|
||||
MCCS_LENGTH_OFFSET + 4, /* Byte1 - Length */
|
||||
MCCS_OP_CODE_VCP_SET, /* Byte2 - MCCS Command */
|
||||
(unsigned char)vcp_code, /* Byte3 - VCP Code */
|
||||
(unsigned char)(value >> 8), /* Byte4 - Value High Byte */
|
||||
(unsigned char)(value & 0xFF), /* Byte5 - Value Low Byte */
|
||||
MCCS_DEST_ADDR << 1 /* Byte6 - CheckSum */
|
||||
};
|
||||
|
||||
/* calculate checksum */
|
||||
for (idx = 0; idx < (MCCS_OP_BUFF_SIZE_WR_VCP_SET - 1); idx++)
|
||||
wr_data[MCCS_OP_BUFF_SIZE_WR_VCP_SET - 1] ^= wr_data[idx];
|
||||
|
||||
if (link->aux_mode)
|
||||
ddc = &aconnector->dm_dp_aux.aux.ddc;
|
||||
else
|
||||
ddc = &aconnector->i2c->base;
|
||||
|
||||
do {
|
||||
msg.addr = MCCS_DEST_ADDR;
|
||||
msg.flags = 0;
|
||||
msg.len = MCCS_OP_BUFF_SIZE_WR_VCP_SET;
|
||||
msg.buf = wr_data;
|
||||
|
||||
ret = i2c_transfer(ddc, &msg, 1);
|
||||
if (ret == 1)
|
||||
break;
|
||||
|
||||
retry--;
|
||||
msleep(retry_interval_ms);
|
||||
} while (retry);
|
||||
|
||||
if (!retry)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dm_helpers_mccs_vcp_set(struct dc_context *ctx, struct dc_link *link,
|
||||
struct dc_sink *sink)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
const uint16_t enable = 0x0101;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
dev = adev_to_drm(ctx->driver_context);
|
||||
|
||||
if (!link || !sink) {
|
||||
drm_dbg_driver(dev, "%s: link or sink is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sink->mccs_caps.freesync_supported) {
|
||||
drm_dbg_driver(dev, "%s: MCCS freesync not supported on this sink", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mccs_operation_vcp_set(sink->edid_caps.freesync_vcp_code, link, enable))
|
||||
drm_dbg_driver(dev, "%s: Failed to set VCP code %d", __func__,
|
||||
sink->edid_caps.freesync_vcp_code);
|
||||
}
|
||||
|
||||
@@ -270,7 +270,6 @@ static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
|
||||
struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
|
||||
struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
int r;
|
||||
|
||||
trace_amdgpu_dm_ism_commit(dm->active_vblank_irq_count,
|
||||
vblank_enabled,
|
||||
@@ -323,16 +322,7 @@ static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
|
||||
*/
|
||||
if (!vblank_enabled && dm->active_vblank_irq_count == 0) {
|
||||
dc_post_update_surfaces_to_stream(dm->dc);
|
||||
|
||||
r = amdgpu_dpm_pause_power_profile(adev, true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "failed to set default power profile mode\n");
|
||||
|
||||
dc_allow_idle_optimizations(dm->dc, true);
|
||||
|
||||
r = amdgpu_dpm_pause_power_profile(adev, false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "failed to restore the power profile mode\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,6 +462,9 @@ void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
|
||||
/* ISM transitions must be called with mutex acquired */
|
||||
ASSERT(mutex_is_locked(&dm->dc_lock));
|
||||
|
||||
/* ISM should not run after dc is destroyed */
|
||||
ASSERT(dm->dc);
|
||||
|
||||
if (!acrtc_state) {
|
||||
trace_amdgpu_dm_ism_event(acrtc->crtc_id, "NO_STATE",
|
||||
"NO_STATE", "N/A");
|
||||
@@ -545,6 +538,8 @@ void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm)
|
||||
struct amdgpu_crtc *acrtc;
|
||||
struct amdgpu_dm_ism *ism;
|
||||
|
||||
ASSERT(mutex_is_locked(&dm->dc_lock));
|
||||
|
||||
drm_for_each_crtc(crtc, dm->ddev) {
|
||||
acrtc = to_amdgpu_crtc(crtc);
|
||||
ism = &acrtc->ism;
|
||||
|
||||
@@ -474,7 +474,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
|
||||
|
||||
if (aconnector->dc_sink) {
|
||||
amdgpu_dm_update_freesync_caps(
|
||||
connector, aconnector->drm_edid);
|
||||
connector, aconnector->drm_edid, true);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_FP)
|
||||
if (!validate_dsc_caps_on_connector(aconnector))
|
||||
|
||||
@@ -611,80 +611,6 @@ static struct clk_bw_params dcn42_bw_params = {
|
||||
|
||||
};
|
||||
|
||||
static struct wm_table ddr5_wm_table = {
|
||||
.entries = {
|
||||
{
|
||||
.wm_inst = WM_A,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.72,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_B,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.72,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_C,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.72,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_D,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.72,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct wm_table lpddr5_wm_table = {
|
||||
.entries = {
|
||||
{
|
||||
.wm_inst = WM_A,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_B,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_C,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_D,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 28.0,
|
||||
.sr_enter_plus_exit_time_us = 30.0,
|
||||
.valid = true,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct dcn42_ss_info_table dcn42_ss_info_table = {
|
||||
.ss_divider = 1000,
|
||||
.ss_percentage = {0, 0, 375, 375, 375}
|
||||
@@ -1141,10 +1067,6 @@ void dcn42_clk_mgr_construct(
|
||||
if (ctx->dc_bios->integrated_info) {
|
||||
clk_mgr->base.base.dentist_vco_freq_khz = ctx->dc_bios->integrated_info->dentist_vco_freq;
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
dcn42_bw_params.wm_table = lpddr5_wm_table;
|
||||
else
|
||||
dcn42_bw_params.wm_table = ddr5_wm_table;
|
||||
dcn42_bw_params.vram_type = ctx->dc_bios->integrated_info->memory_type;
|
||||
dcn42_bw_params.dram_channel_width_bytes = ctx->dc_bios->integrated_info->memory_type == 0x22 ? 8 : 4;
|
||||
dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 1;
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/array_size.h>
|
||||
|
||||
#include "dm_services.h"
|
||||
#include "core_types.h"
|
||||
#include "timing_generator.h"
|
||||
|
||||
@@ -5069,6 +5069,12 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->ctx->dce_version < DCE_VERSION_8_0 &&
|
||||
stream->timing.display_color_depth >= COLOR_DEPTH_101010) {
|
||||
/* DCE 6.x doesn't support 10-bit truncation or dither options. */
|
||||
option = DITHER_OPTION_DISABLE;
|
||||
}
|
||||
|
||||
if (option == DITHER_OPTION_DISABLE)
|
||||
return;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
|
||||
struct dcn_optc_reg_state;
|
||||
struct dcn_dccg_reg_state;
|
||||
|
||||
#define DC_VER "3.2.376"
|
||||
#define DC_VER "3.2.378"
|
||||
|
||||
/**
|
||||
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
|
||||
@@ -562,6 +562,7 @@ struct dc_config {
|
||||
bool frame_update_cmd_version2;
|
||||
struct spl_sharpness_range dcn_sharpness_range;
|
||||
struct spl_sharpness_range dcn_override_sharpness_range;
|
||||
bool no_native422_support;
|
||||
};
|
||||
|
||||
enum visual_confirm {
|
||||
@@ -986,7 +987,6 @@ struct link_service;
|
||||
* causing an issue or not.
|
||||
*/
|
||||
struct dc_debug_options {
|
||||
bool native422_support;
|
||||
bool disable_dsc;
|
||||
enum visual_confirm visual_confirm;
|
||||
int visual_confirm_rect_height;
|
||||
@@ -1061,9 +1061,11 @@ struct dc_debug_options {
|
||||
bool hdmi20_disable;
|
||||
bool skip_detection_link_training;
|
||||
uint32_t edid_read_retry_times;
|
||||
unsigned int force_odm_combine; //bit vector based on otg inst
|
||||
unsigned int seamless_boot_odm_combine;
|
||||
unsigned int force_odm_combine_4to1; //bit vector based on otg inst
|
||||
|
||||
uint8_t force_odm_combine; //bit vector based on otg inst
|
||||
uint8_t seamless_boot_odm_combine;
|
||||
uint8_t force_odm_combine_4to1; //bit vector based on otg inst
|
||||
|
||||
int minimum_z8_residency_time;
|
||||
int minimum_z10_residency_time;
|
||||
bool disable_z9_mpc;
|
||||
@@ -2725,6 +2727,7 @@ struct dc_sink {
|
||||
struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX];
|
||||
bool converter_disable_audio;
|
||||
|
||||
struct mccs_caps mccs_caps;
|
||||
struct scdc_caps scdc_caps;
|
||||
struct dc_sink_dsc_caps dsc_caps;
|
||||
struct dc_sink_fec_caps fec_caps;
|
||||
|
||||
@@ -52,6 +52,7 @@ struct dc_dsc_policy {
|
||||
uint32_t max_target_bpp;
|
||||
uint32_t min_target_bpp;
|
||||
bool enable_dsc_when_not_needed;
|
||||
bool ycbcr422_simple;
|
||||
};
|
||||
|
||||
struct dc_dsc_config_options {
|
||||
|
||||
Loaded 100 of 226 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user