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:
Carlos Llamas committed 2026-05-26 22:17:28 +00:00
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
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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)'
-11
View File
@@ -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)
+1 -1
View File
@@ -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.
*/
+1
View File
@@ -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);
+2 -2
View File
@@ -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) \
+2 -2
View File
@@ -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()
+4 -30
View File
@@ -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)
{
-20
View File
@@ -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);
+1 -1
View File
@@ -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
-1
View File
@@ -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. */
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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)
+9
View File
@@ -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. */
+1 -1
View File
@@ -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)
-49
View File
@@ -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
+1 -1
View File
@@ -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 */
+6 -6
View File
@@ -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)) {
-2
View File
@@ -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
+1
View File
@@ -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
+1 -1
View File
@@ -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.
+1 -42
View File
@@ -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
-3
View File
@@ -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[];
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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);
+1 -5
View File
@@ -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);
+2 -6
View File
@@ -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);
}
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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.
*/
-2
View File
@@ -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 */
+2 -4
View File
@@ -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,
+86 -137
View File
@@ -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);
+8
View File
@@ -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
+3
View File
@@ -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))
+7 -7
View File
@@ -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());
}
-5
View File
@@ -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 */
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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.
*/
+3
View File
@@ -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)
+1 -1
View File
@@ -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.
+2 -2
View File
@@ -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
*/
+35
View File
@@ -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)
+164
View File
@@ -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)
+37
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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);
+10 -1
View File
@@ -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
+2 -2
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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)
+13 -7
View File
@@ -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;
+5
View File
@@ -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)
+49
View File
@@ -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 = &regmap_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 = &regmap_smbus_byte_word_reg16;
else if (config->val_bits == 16 && config->reg_bits == 8 &&
i2c_check_functionality(i2c->adapter,
I2C_FUNC_SMBUS_WORD_DATA))
+7 -1
View File
@@ -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, &regmap_ram, data, config,
lock_key, lock_name);
if (IS_ERR(map)) {
kfree(data->read);
kfree(data->written);
}
return map;
}
+18 -18
View File
@@ -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;
+1 -2
View File
@@ -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");
+2 -2
View File
@@ -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();
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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)) {
+27 -9
View File
@@ -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;
+10 -10
View File
@@ -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;
}
+2
View File
@@ -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);
+78 -64
View File
@@ -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,
+33 -14
View 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;
+2 -1
View File
@@ -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);
+11 -1
View File
@@ -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;
}
+5 -2
View File
@@ -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;
}
/*
+26 -5
View File
@@ -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);
+46 -6
View File
@@ -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);
}
}
+23 -2
View File
@@ -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;
+4 -4
View File
@@ -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;
+8 -1
View File
@@ -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;
+1
View File
@@ -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)
{
+12
View File
@@ -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");
+3
View File
@@ -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
+1
View File
@@ -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);
+11
View File
@@ -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
+106 -29
View File
@@ -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;
+8 -5
View File
@@ -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;
+1
View File
@@ -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