Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Cross-merge networking fixes after downstream PR (net-7.3-rc8).

No conflicts. Adjacent changes:

drivers/net/ethernet/microchip/lan865x/lan865x.c
  2a3f6d2a9a ("microchip: lan865x: move setting of netops to fix crash")
  15358c2c3d ("net: ethernet: oa_tc6: return ERR_PTR from oa_tc6_init()")

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-10-15 09:20:09 -07:00
commit f5e575a787
238 changed files with 8275 additions and 984 deletions

View File

@ -77,6 +77,7 @@ properties:
- mscc,ocelot-spi
- mscc,jaguar2-spi
- sophgo,sg2042-spi
- syna,sl2610-spi
- thead,th1520-spi
- ultrarisc,dp1000-spi
- const: snps,dw-apb-ssi

View File

@ -32,12 +32,12 @@ of set. They can be reparented to the place where the bottom of
stack is attached to a mount that will survive. NOTE: doing that
will violate a constraint on having no more than one mount with
the same parent/mountpoint pair; however, the caller (umount_tree())
will immediately remedy that - it may keep unmounted element attached
to parent, but only if the parent itself is unmounted. Since all
conflicts created by reparenting have common parent *not* in the
set and one side of the conflict (bottom of the stack of overmounts)
is in the set, it will be resolved. However, we rely upon umount_tree()
doing that pretty much immediately after the call of propagate_umount().
will immediately remedy that - it detaches every element of the set
from its parent. Since all conflicts created by reparenting have
common parent *not* in the set and one side of the conflict (bottom
of the stack of overmounts) is in the set, it will be resolved.
However, we rely upon umount_tree() doing that pretty much immediately
after the call of propagate_umount().
Algorithm is based on two statements:
1) for any set S, there is a maximal non-shifting subset of S

View File

@ -564,8 +564,8 @@ f) Unmount semantics
where 'A' is a mount mounted on mount 'B' at dentry 'b'.
If mount 'B' is shared, then all most-recently-mounted mounts at dentry
'b' on mounts that receive propagation from mount 'B' and does not have
sub-mounts within them are unmounted.
'b' on mounts that receive propagation from mount 'B' are unmounted as
well, if every mount below them is also unmounted.
Example: Let's say 'B1', 'B2', 'B3' are shared mounts that propagate to
each other.
@ -584,10 +584,18 @@ f) Unmount semantics
So all 'C1', 'C2' and 'C3' should be unmounted.
If any of 'C2' or 'C3' has some child mounts, then that mount is not
unmounted, but all other mounts are unmounted. However if 'C1' is told
to be unmounted and 'C1' has some sub-mounts, the umount operation is
failed entirely.
If any of 'C2' or 'C3' has a child mount that cannot be unmounted
then that mount is not unmounted. But all other mounts are unmounted.
A child mount that is itself unmounted by the same unmount
propagation does not keep its parent mounted. However if 'C1' is
supposed to be unmounted and 'C1' has some sub-mounts, the unmount
fails.
A lazy umount (MNT_DETACH) takes a whole tree. Every mount of the
tree then propagates its unmount from its own parent as described
above, so the mounts that receive propagation lose the corresponding
trees as well. Documentation/filesystems/propagate_umount.txt has the
precise rules, including the ones for locked mounts.
g) Clone Namespace

View File

@ -8172,7 +8172,6 @@ F: drivers/gpu/drm/tiny/hx8357d.c
DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE
M: Dexuan Cui <decui@microsoft.com>
M: Long Li <longli@microsoft.com>
M: Saurabh Sengar <ssengar@linux.microsoft.com>
L: linux-hyperv@vger.kernel.org
L: dri-devel@lists.freedesktop.org
@ -12163,11 +12162,9 @@ S: Maintained
F: drivers/media/i2c/hi847.c
Hyper-V/Azure CORE AND DRIVERS
M: "K. Y. Srinivasan" <kys@microsoft.com>
M: Haiyang Zhang <haiyangz@microsoft.com>
M: Wei Liu <wei.liu@kernel.org>
M: Dexuan Cui <decui@microsoft.com>
M: Long Li <longli@microsoft.com>
L: linux-hyperv@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
@ -18831,6 +18828,7 @@ F: drivers/net/ethernet/nebula-matrix/
NETCONSOLE
M: Breno Leitao <leitao@debian.org>
R: Gustavo Luiz Duarte <gustavold@gmail.com>
S: Maintained
F: Documentation/networking/netconsole.rst
F: drivers/net/netconsole.c

View File

@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 3
SUBLEVEL = 0
EXTRAVERSION = -rc6
EXTRAVERSION = -rc7
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@ -421,8 +421,9 @@
mov x2, xzr
mrs x1, id_aa64dfr0_el1
ubfx x1, x1, #ID_AA64DFR0_EL1_PMUVer_SHIFT, #4
cmp x1, #ID_AA64DFR0_EL1_PMUVer_V3P9
b.lt .Lskip_pmuv3p9_\@
cmp x1, #ID_AA64DFR0_EL1_PMUVer_IMP_DEF
ccmp x1, #ID_AA64DFR0_EL1_PMUVer_V3P9, #8, ne
b.lt .Lskip_pmuv3p9_\@ // Skip if < PMUv3p9 or IMP_DEF
orr x0, x0, #HDFGRTR2_EL2_nPMICNTR_EL0
orr x0, x0, #HDFGRTR2_EL2_nPMICFILTR_EL0

View File

@ -25,6 +25,9 @@ KASAN_SANITIZE_stacktrace.o := n
KCOV_INSTRUMENT_entry-common.o := n
KCOV_INSTRUMENT_idle.o := n
# Softirq stack switching can run outside interrupt context.
KCOV_INSTRUMENT_irq.o := n
# Object file lists.
obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
entry-common.o process.o ptrace.o \

View File

@ -27,7 +27,7 @@ static inline __sum16 csum_fold(__wsum sum)
"add %0, %0, r8\n"
"nor %0, %0, %0\n"
: "=r" (sum)
: "r" (sum << 16), "0" (sum)
: "r" ((__force u32)sum << 16), "0" (sum)
: "r8");
return (__force __sum16) sum;
}

View File

@ -453,9 +453,10 @@ config SMP
config NR_CPUS
int "Maximum number of CPUs (2-512)"
depends on SMP
range 2 512 if !RISCV_SBI_V01
range 2 32 if RISCV_SBI_V01 && 32BIT
range 2 512 if !RISCV_SBI_V01 && 64BIT
range 2 128 if !RISCV_SBI_V01 && 32BIT
range 2 64 if RISCV_SBI_V01 && 64BIT
range 2 32 if RISCV_SBI_V01 && 32BIT
default "32" if 32BIT
default "64" if RISCV_SBI_V01 && 64BIT
default "256" if !RISCV_SBI_V01 && 64BIT

View File

@ -46,7 +46,7 @@ config ERRATA_MIPS_P8700_PAUSE_OPCODE
config ERRATA_SIFIVE
bool "SiFive errata"
depends on RISCV_ALTERNATIVE
depends on RISCV_ALTERNATIVE && 64BIT
help
All SiFive errata Kconfig depend on this Kconfig. Disabling
this Kconfig will disable all SiFive errata. Please say "Y"
@ -96,6 +96,20 @@ config ERRATA_STARFIVE_JH7100
Say "Y" if you want to support the BeagleV Starlight and/or
StarFive VisionFive V1 boards.
config ERRATA_SIFIVE_MAL_9092
bool "Apply SiFive HLV/HLVX/HSV fence errata"
depends on ERRATA_SIFIVE && 64BIT
default y
help
This will apply the SiFive MAL-9092 errata to add fence.rw
instructions around all HLV/HLVX/HSV instructions.
Note: HSTATUS.HU is cleared during KVM initialization. If future
changes enable HSTATUS.HU to allow hypervisor instructions in
U-mode, additional errata handling may be required.
If you don't know what to do here, say "Y".
config ERRATA_THEAD
bool "T-HEAD errata"
depends on RISCV_ALTERNATIVE
@ -146,6 +160,7 @@ config ERRATA_THEAD_PMU
config ERRATA_THEAD_GHOSTWRITE
bool "Apply T-Head Ghostwrite errata"
depends on ERRATA_THEAD && RISCV_ISA_XTHEADVECTOR
select RISCV_ALTERNATIVE_EARLY
default y
help
The T-Head C9xx cores have a vulnerability in the xtheadvector

View File

@ -34,6 +34,7 @@ config ARCH_RENESAS
config ARCH_SIFIVE
bool "SiFive SoCs"
select ERRATA_SIFIVE
depends on 64BIT
help
This enables support for SiFive SoC platform hardware.

View File

@ -51,6 +51,22 @@ static bool errata_cip_1200_check_func(unsigned long arch_id, unsigned long imp
return true;
}
static bool errata_mal_9092_check_func(unsigned long arch_id, unsigned long impid)
{
/*
* Affected cores:
* Architecture ID: 0x8000000000000109
* Implementation ID: 0x19251031, 0x19251217, 0x19260320
*/
if (arch_id != 0x8000000000000109)
return false;
if (impid != 0x19251031 && impid != 0x19251217 && impid != 0x19260320)
return false;
return true;
}
static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = {
{
.name = "cip-453",
@ -60,6 +76,10 @@ static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = {
.name = "cip-1200",
.check_func = errata_cip_1200_check_func
},
{
.name = "mal-9092",
.check_func = errata_mal_9092_check_func
},
};
static u32 __init_or_module sifive_errata_probe(unsigned long archid,

View File

@ -40,6 +40,8 @@ extern u32 thead_vlenb_of;
void __init riscv_user_isa_enable(void);
void riscv_clear_hypervisor_csr(void);
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
.name = #_name, \
.property = #_name, \

View File

@ -11,7 +11,8 @@
#ifdef CONFIG_ERRATA_SIFIVE
#define ERRATA_SIFIVE_CIP_453 0
#define ERRATA_SIFIVE_CIP_1200 1
#define ERRATA_SIFIVE_NUMBER 2
#define ERRATA_SIFIVE_MAL_9092 2
#define ERRATA_SIFIVE_NUMBER 3
#endif
#ifdef CONFIG_ERRATA_THEAD

View File

@ -40,6 +40,7 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
if (!access_ok(uaddr, sizeof(u32)))
return -EFAULT;
uaddr = untagged_addr(uaddr);
switch (op) {
case FUTEX_OP_SET:
@ -82,6 +83,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
if (!access_ok(uaddr, sizeof(u32)))
return -EFAULT;
uaddr = untagged_addr(uaddr);
__enable_user_access();
__asm__ __volatile__ (

View File

@ -192,18 +192,28 @@
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(49), \
__RD(0), RS1(gaddr), RS2(vmid))
#define ALT_SIFIVE_MAL_9092_FENCE \
ALTERNATIVE("nop", "fence rw, rw", SIFIVE_VENDOR_ID, \
ERRATA_SIFIVE_MAL_9092, CONFIG_ERRATA_SIFIVE_MAL_9092)
#define HLVX_HU(dest, addr) \
ALT_SIFIVE_MAL_9092_FENCE "\n" \
INSN_R(OPCODE_SYSTEM, FUNC3(4), FUNC7(50), \
RD(dest), RS1(addr), __RS2(3))
RD(dest), RS1(addr), __RS2(3)) "\n" \
ALT_SIFIVE_MAL_9092_FENCE
#define HLV_W(dest, addr) \
ALT_SIFIVE_MAL_9092_FENCE "\n" \
INSN_R(OPCODE_SYSTEM, FUNC3(4), FUNC7(52), \
RD(dest), RS1(addr), __RS2(0))
RD(dest), RS1(addr), __RS2(0)) "\n" \
ALT_SIFIVE_MAL_9092_FENCE
#ifdef CONFIG_64BIT
#define HLV_D(dest, addr) \
ALT_SIFIVE_MAL_9092_FENCE "\n" \
INSN_R(OPCODE_SYSTEM, FUNC3(4), FUNC7(54), \
RD(dest), RS1(addr), __RS2(0))
RD(dest), RS1(addr), __RS2(0)) "\n" \
ALT_SIFIVE_MAL_9092_FENCE
#else
#define HLV_D(dest, addr) \
__ASM_STR(.error "hlv.d requires 64-bit support")

View File

@ -4,6 +4,7 @@
#ifdef __ASSEMBLER__
#include <asm/asm-offsets.h>
#include <asm/csr.h>
#ifdef CONFIG_SHADOW_CALL_STACK
@ -22,9 +23,17 @@
REG_L gp, TASK_TI_SCS_SP(tp)
.endm
/* Load task_scs_sp(current) to gp, but only if tp has changed. */
.macro scs_load_current_if_task_changed prev
beq \prev, tp, _skip_scs
/*
* Load task_scs_sp(current) to gp, but only when the trap came from U-mode.
* The source privilege level is taken from the saved sstatus.SPP bit (written
* by hardware on trap entry), not by comparing tp. tp is a user-writable
* register, so gating the shadow call stack reload on it let a user task that
* set tp == &current skip the reload and run the kernel with an attacker
* controlled gp (the shadow call stack pointer).
*/
.macro scs_load_current_if_from_user status, tmp
andi \tmp, \status, SR_SPP
bnez \tmp, _skip_scs
scs_load_current
_skip_scs:
.endm
@ -42,7 +51,7 @@
.endm
.macro scs_load_current
.endm
.macro scs_load_current_if_task_changed prev
.macro scs_load_current_if_from_user status, tmp
.endm
.macro scs_save_current
.endm

View File

@ -137,8 +137,8 @@ static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest)
"csrr %0, " __stringify(CSR_VSTART) "\n\t"
"csrr %1, " __stringify(CSR_VTYPE) "\n\t"
"csrr %2, " __stringify(CSR_VL) "\n\t"
: "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl),
"=r" (dest->vcsr) : :);
: "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl)
: :);
if (has_xtheadvector()) {
unsigned long status;
@ -230,7 +230,7 @@ static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to,
"add %1, %1, %0\n\t"
"vse8.v v24, (%1)\n\t"
".option pop\n\t"
: "=&r" (vl) : "r" (datap) : "memory");
: "=&r" (vl), "+r" (datap) : : "memory");
}
riscv_v_disable();
}
@ -266,7 +266,7 @@ static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_
"add %1, %1, %0\n\t"
"vle8.v v24, (%1)\n\t"
".option pop\n\t"
: "=&r" (vl) : "r" (datap) : "memory");
: "=&r" (vl), "+r" (datap) : : "memory");
}
__vstate_csr_restore(restore_from);
riscv_v_disable();

View File

@ -1,3 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#define RISCV_HWPROBE_VENDOR_EXT_XMIPSEXECTL BIT(0)
#include <linux/const.h>
#define RISCV_HWPROBE_VENDOR_EXT_XMIPSEXECTL _BITULL(0)

View File

@ -1233,6 +1233,18 @@ void __init riscv_user_isa_enable(void)
pr_warn("Zicbop disabled as it is unavailable on some harts\n");
}
void riscv_clear_hypervisor_csr(void)
{
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_H))
return;
/*
* Clear HSTATUS.HU to restrict hypervisor instructions to HS-mode.
* This prevents user-mode from executing HLV/HSV instructions.
*/
csr_clear(CSR_HSTATUS, HSTATUS_HU);
}
#ifdef CONFIG_RISCV_ALTERNATIVE
/*
* Alternative patch sites consider 48 bits when determining when to patch

View File

@ -208,7 +208,7 @@ SYM_CODE_START(handle_exception)
load_global_pointer
/* Load the kernel shadow call stack pointer if coming from userspace */
scs_load_current_if_task_changed s5
scs_load_current_if_from_user s1, s5
#ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
move a0, sp

View File

@ -48,7 +48,7 @@ static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
if (!IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
return addr;
phys = __pa_symbol(addr);
} else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) {
} else if (IS_ENABLED(CONFIG_EXECMEM)) {
struct page *page = vmalloc_to_page(addr);
BUG_ON(!page);

View File

@ -230,6 +230,7 @@ static int riscv_vr_set(struct task_struct *target,
return -ENODATA;
/* Copy rest of the vstate except datap */
memset(&ptrace_vstate, 0, sizeof(ptrace_vstate));
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
sizeof(struct __riscv_v_regset_state));
if (unlikely(ret))
@ -299,6 +300,9 @@ static int riscv_cfi_get(struct task_struct *target,
struct user_cfi_state user_cfi;
struct pt_regs *regs;
if (!is_user_lpad_enabled() && !is_user_shstk_enabled())
return -EINVAL;
memset(&user_cfi, 0, sizeof(user_cfi));
regs = task_pt_regs(target);
@ -337,8 +341,12 @@ static int riscv_cfi_set(struct task_struct *target,
struct user_cfi_state user_cfi;
struct pt_regs *regs;
if (!is_user_lpad_enabled() && !is_user_shstk_enabled())
return -EINVAL;
regs = task_pt_regs(target);
memset(&user_cfi, 0, sizeof(user_cfi));
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_cfi, 0, -1);
if (ret)
return ret;

View File

@ -366,6 +366,8 @@ void __init setup_arch(char **cmdline_p)
if (!IS_ENABLED(CONFIG_RISCV_ISA_ZBB) || !riscv_isa_extension_available(NULL, ZBB))
static_branch_disable(&efficient_ffs_key);
riscv_clear_hypervisor_csr();
}
bool arch_cpu_is_hotpluggable(int cpu)

View File

@ -244,6 +244,8 @@ asmlinkage __visible void smp_callin(void)
numa_add_cpu(curr_cpuid);
riscv_clear_hypervisor_csr();
pr_debug("CPU%u: Booted secondary hartid %lu\n", curr_cpuid,
cpuid_to_hartid_map(curr_cpuid));

View File

@ -43,6 +43,8 @@ void suspend_save_csrs(struct suspend_context *context)
void suspend_restore_csrs(struct suspend_context *context)
{
riscv_clear_hypervisor_csr();
csr_write(CSR_SCRATCH, 0);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_XLINUXENVCFG))
csr_write(CSR_ENVCFG, context->envcfg);

View File

@ -87,9 +87,25 @@ strnlen_zbb:
* Aligned boundary. Use the address of the last valid byte
* (s + count - 1) to avoid loading a word past the count
* boundary in the loop below. count == 0 is handled above.
*
* Saturate the boundary when s + count would wrap around (very
* large counts, e.g. SIZE_MAX passed by FORTIFY strcat/strlcat
* with a destination whose size is unknown at compile time).
* Without this, the wrapped boundary lands before s and the
* pre-loop guard below always exits, returning a truncated
* length.
*
* Clamping the increment to ~s (== SIZE_MAX - s) keeps the
* computation branchless and wrap-free:
*
* s + min(count - 1, ~s) == saturating_add(s, count - 1)
*
* Saturating makes the scan equivalent to strlen().
*/
add t4, a0, a1
addi t4, t4, -1
addi t4, a1, -1 /* count - 1 */
not t1, a0 /* SIZE_MAX - s */
minu t4, t4, t1 /* clamp, so s + t4 can never wrap */
add t4, a0, t4 /* saturated s + count - 1 */
andi t4, t4, -SZREG
/* Get the first word. */

View File

@ -68,8 +68,8 @@ ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
addr = regs_get_gpr(regs, reg_addr * sizeof(unsigned long));
offset = addr & 0x7UL;
addr &= ~0x7UL;
offset = addr & (sizeof(data) - 1);
addr &= ~(sizeof(data) - 1);
data = *(unsigned long *)addr >> (offset * 8);

View File

@ -426,7 +426,7 @@ static void __init hv_stimer_setup_percpu_clockev(void)
int ret;
/*
* Continue afters errors in setting up stimer clockevents
* Continue after errors in setting up stimer clockevents
* as we can run with the LAPIC timer as a fallback.
*/
ret = hv_stimer_alloc(false);
@ -434,7 +434,7 @@ static void __init hv_stimer_setup_percpu_clockev(void)
pr_warn("stimer setup failed with error %d\n", ret);
/*
* Still register the LAPIC timer to allows users
* Still register the LAPIC timer to allow users
* to switch to LAPIC timer via /sys, if they want to.
*/
if (old_setup_percpu_clockev)
@ -727,7 +727,8 @@ int hv_apicid_to_vp_index(u32 apic_id)
input->partition_id = HV_PARTITION_ID_SELF;
input->apic_ids[0] = apic_id;
output = *this_cpu_ptr(hyperv_pcpu_output_arg);
/* Treat input as having 2 APIC IDs so output is 64-bit aligned */
output = (void *)input + struct_size(input, apic_ids, 2);
control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_INDEX_FROM_APIC_ID;
status = hv_do_hypercall(control, input, output);

View File

@ -477,6 +477,8 @@
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */
#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */
#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */
#define X86_FEATURE_TLBSYNC_SFW_NO (20*32+ 4) /* TLBI Erratum #1718 fixed in microcode */
#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* The memory form of VERW mitigates TSA */
#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */
@ -587,4 +589,5 @@
#define X86_BUG_TSA X86_BUG( 1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */
#define X86_BUG_VMSCAPE X86_BUG( 1*32+10) /* "vmscape" CPU is affected by VMSCAPE attacks from guests */
#define X86_BUG_SEAMRET_INVD_VMCS X86_BUG( 1*32+11) /* "seamret_invd_vmcs" SEAMRET from P-SEAMLDR clears the current VMCS */
#define X86_BUG_TLBI X86_BUG( 1*32+12) /* "tlbi" AMD TLBI Erratum #1718 */
#endif /* _ASM_X86_CPUFEATURES_H */

View File

@ -110,6 +110,12 @@ static inline void __tlbsync(void)
/* TLBSYNC: supported in binutils >= 0.36. */
asm volatile(".byte 0x0f, 0x01, 0xff" ::: "memory");
if (!static_cpu_has_bug(X86_BUG_TLBI))
return;
/* TLBSYNC: supported in binutils >= 0.36. */
asm volatile(".byte 0x0f, 0x01, 0xff" ::: "memory");
}
#else
/* Some compilers (I'm looking at you clang!) simply can't do DCE */

View File

@ -1049,6 +1049,10 @@ static void init_amd_zen5(struct cpuinfo_x86 *c)
msr_clear_bit(MSR_AMD64_CPUID_FN_7, 18);
pr_emerg_once("RDSEED32 is broken. Disabling the corresponding CPUID bit.\n");
}
if (cpu_has(c, X86_FEATURE_INVLPGB) &&
!cpu_has(c, X86_FEATURE_TLBSYNC_SFW_NO))
set_cpu_bug(c, X86_BUG_TLBI);
}
static void init_amd(struct cpuinfo_x86 *c)

View File

@ -265,11 +265,39 @@ noinstr u32 kvm_read_and_reset_apf_flags(void)
}
EXPORT_SYMBOL_FOR_KVM(kvm_read_and_reset_apf_flags);
static __always_inline bool kvm_apf_reason_pending(void)
{
return __this_cpu_read(async_pf_enabled) &&
__this_cpu_read(apf_reason.flags);
}
noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token)
{
u32 flags = kvm_read_and_reset_apf_flags();
irqentry_state_t state;
u32 flags;
if (!kvm_apf_reason_pending())
return false;
/*
* The guest does not enable KVM_ASYNC_PF_SEND_ALWAYS, so the host
* delivers async #PF only to user mode (or as a #PF VM-exit, which KVM
* reads itself). A #PF from kernel mode can still arrive between that
* delivery and the read of the reason flags, inside an NMI that
* interrupted it, for instance perf reading user memory for a call
* chain. Such a fault is not async, so leave the async PF flags
* untouched for the outer handler. Outside NMI context, on the other
* hand, async PF flags on a kernel-mode fault mean the host is broken.
*/
if (!user_mode(regs)) {
if (likely(in_nmi()))
return false;
state = irqentry_enter(regs);
instrumentation_begin();
panic("Host injected async #PF in kernel mode\n");
}
flags = kvm_read_and_reset_apf_flags();
if (!flags)
return false;
@ -285,8 +313,6 @@ noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token)
panic("Host injected async #PF in interrupt disabled region\n");
if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) {
if (unlikely(!(user_mode(regs))))
panic("Host injected async #PF in kernel mode\n");
/* Page is swapped out by the host. */
kvm_async_pf_task_wait_schedule(token);
} else {

View File

@ -275,8 +275,18 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_pagewalk *w,
unsigned pte_access, unsigned pte_pkey,
u64 access)
{
/* strip nested paging fault error codes */
unsigned int pfec = access;
/*
* Of the error codes that do not contribute to the index in
* fmt->permissions, PK and SS are not supported by shadow paging
* and also not provided to EPT violations, but SS *is* included
* in the NPT exit code. RSVD faults are handled elsewhere.
*/
unsigned int pfec = access & ~PFERR_SS_MASK;
if (WARN_ON_ONCE(pfec & ~(PFERR_PRESENT_MASK | PFERR_WRITE_MASK |
PFERR_USER_MASK | PFERR_FETCH_MASK)))
pfec &= (PFERR_PRESENT_MASK | PFERR_WRITE_MASK |
PFERR_USER_MASK | PFERR_FETCH_MASK);
unsigned long rflags = kvm_x86_call(get_rflags)(vcpu);
/*
@ -301,8 +311,6 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_pagewalk *w,
kvm_mmu_refresh_passthrough_bits(vcpu, w);
fault = (fmt->permissions[index] >> pte_access) & 1;
WARN_ON_ONCE(pfec & (PFERR_PK_MASK | PFERR_SS_MASK | PFERR_RSVD_MASK));
if (unlikely(fmt->pkru_mask)) {
u32 pkru_bits, offset;

View File

@ -328,7 +328,6 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
int offset;
u64 walk_nx_mask = 0;
const int write_fault = access & PFERR_WRITE_MASK;
const int user_fault = access & PFERR_USER_MASK;
const int fetch_fault = access & PFERR_FETCH_MASK;
/*
* Note! Track the error_code that's common to legacy shadow paging
@ -486,7 +485,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
return 1;
error:
errcode |= write_fault | user_fault;
errcode |= access & (PFERR_WRITE_MASK | PFERR_USER_MASK | PFERR_SS_MASK);
if (fetch_fault && has_pferr_fetch(w))
errcode |= PFERR_FETCH_MASK;

View File

@ -395,6 +395,11 @@ static phys_addr_t avic_get_backing_page_address(struct vcpu_svm *svm)
return __sme_set(__pa(svm->vcpu.arch.apic->regs));
}
static bool avic_is_addressable_vcpu(struct kvm_vcpu *vcpu)
{
return vcpu->vcpu_id <= __avic_get_max_physical_id(vcpu->kvm, NULL);
}
void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb)
{
struct kvm_svm *kvm_svm = to_kvm_svm(svm->vcpu.kvm);
@ -412,7 +417,6 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb)
static int avic_init_backing_page(struct kvm_vcpu *vcpu)
{
u32 max_id = x2avic_enabled ? x2avic_max_physical_id : AVIC_MAX_PHYSICAL_ID;
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
struct vcpu_svm *svm = to_svm(vcpu);
u32 id = vcpu->vcpu_id;
@ -425,7 +429,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
* avic_vcpu_load() expects to be called if and only if the vCPU has
* fully initialized AVIC.
*/
if (id > max_id) {
if (!avic_is_addressable_vcpu(vcpu)) {
kvm_set_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG);
vcpu->arch.apic->apicv_active = false;
return 0;
@ -885,6 +889,14 @@ int avic_init_vcpu(struct vcpu_svm *svm)
return ret;
}
void avic_vcpu_free(struct kvm_vcpu *vcpu)
{
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
if (kvm_svm->avic_physical_id_table && avic_is_addressable_vcpu(vcpu))
WRITE_ONCE(kvm_svm->avic_physical_id_table[vcpu->vcpu_id], 0);
}
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu)
{
avic_handle_dfr_update(vcpu);
@ -1045,8 +1057,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
if (WARN_ON(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
return;
if (WARN_ON_ONCE(vcpu->vcpu_id * sizeof(entry) >=
PAGE_SIZE << avic_get_physical_id_table_order(vcpu->kvm)))
if (WARN_ON_ONCE(!avic_is_addressable_vcpu(vcpu)))
return;
/*
@ -1108,8 +1119,7 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action)
lockdep_assert_preemption_disabled();
if (WARN_ON_ONCE(vcpu->vcpu_id * sizeof(entry) >=
PAGE_SIZE << avic_get_physical_id_table_order(vcpu->kvm)))
if (WARN_ON_ONCE(!avic_is_addressable_vcpu(vcpu)))
return;
/*

View File

@ -2421,7 +2421,7 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
void *dst_vaddr = kmap_local_pfn(pfn);
memcpy(src_vaddr, dst_vaddr, PAGE_SIZE);
set_page_dirty(src_page);
set_page_dirty_lock(src_page);
kunmap_local(dst_vaddr);
kunmap_local(src_vaddr);

View File

@ -1328,7 +1328,7 @@ static int svm_vcpu_create(struct kvm_vcpu *vcpu)
svm->msrpm = svm_vcpu_alloc_msrpm();
if (!svm->msrpm) {
err = -ENOMEM;
goto error_free_sev;
goto error_free_avic;
}
svm->x2avic_msrs_intercepted = true;
@ -1342,6 +1342,8 @@ static int svm_vcpu_create(struct kvm_vcpu *vcpu)
return 0;
error_free_avic:
avic_vcpu_free(vcpu);
error_free_sev:
sev_free_vcpu(vcpu);
error_free_vmcb_page:
@ -1356,6 +1358,8 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
WARN_ON_ONCE(!list_empty(&svm->ir_list));
avic_vcpu_free(vcpu);
svm_leave_nested(vcpu);
svm_free_nested(svm);

View File

@ -955,6 +955,7 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb);
int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu);
int avic_unaccelerated_access_interception(struct kvm_vcpu *vcpu);
int avic_init_vcpu(struct vcpu_svm *svm);
void avic_vcpu_free(struct kvm_vcpu *vcpu);
void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
void avic_vcpu_put(struct kvm_vcpu *vcpu);
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);

View File

@ -3770,8 +3770,10 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
vmentry_fail_vmexit:
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
if (!from_vmentry)
if (!from_vmentry) {
nested_ept_uninit_mmu_context(vcpu);
return NVMX_VMENTRY_VMEXIT;
}
nested_put_vmcs12_pages(vcpu);

View File

@ -250,7 +250,7 @@ static inline bool is_noncanonical_invlpg_address(u64 la, struct kvm_vcpu *vcpu)
static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
gva_t gva, gfn_t gfn, unsigned access)
{
u64 gen = kvm_memslots(vcpu->kvm)->generation;
u64 gen = kvm_vcpu_memslots(vcpu)->generation;
if (unlikely(gen & KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS))
return;
@ -267,7 +267,7 @@ static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
static inline bool vcpu_match_mmio_gen(struct kvm_vcpu *vcpu)
{
return vcpu->arch.mmio_gen == kvm_memslots(vcpu->kvm)->generation;
return vcpu->arch.mmio_gen == kvm_vcpu_memslots(vcpu)->generation;
}
/*

View File

@ -800,6 +800,27 @@ static void zloop_cmd_workfn(struct work_struct *work)
current->flags = orig_flags;
}
static void zloop_fill_zero_rq(struct request *rq, unsigned int zero_from)
{
struct req_iterator iter;
struct bio_vec bv;
unsigned int pos = 0;
unsigned int end, off;
rq_for_each_segment(bv, rq, iter) {
end = pos + bv.bv_len;
if (end > zero_from) {
if (pos < zero_from)
off = zero_from - pos;
else
off = 0;
memzero_page(bv.bv_page, bv.bv_offset + off,
bv.bv_len - off);
}
pos = end;
}
}
static void zloop_complete_rq(struct request *rq)
{
struct zloop_cmd *cmd = blk_mq_rq_to_pdu(rq);
@ -814,13 +835,9 @@ static void zloop_complete_rq(struct request *rq)
pr_err("Zone %u: failed read sector %llu, %llu sectors\n",
zone_no, cmd->sector, cmd->nr_sectors);
if (cmd->ret >= 0 && cmd->ret != blk_rq_bytes(rq)) {
/* short read */
struct bio *bio;
__rq_for_each_bio(bio, rq)
zero_fill_bio(bio);
}
/* Short read. Zero out the unread tail beyond cmd->ret. */
if (cmd->ret >= 0 && cmd->ret != blk_rq_bytes(rq))
zloop_fill_zero_rq(rq, cmd->ret);
break;
case REQ_OP_WRITE:
case REQ_OP_ZONE_APPEND:

View File

@ -2796,13 +2796,13 @@ static inline void decode_bus_error(int node_id, struct mce *m)
* the instance_id. For example, instance_id=0xYXXXXX where Y is the channel
* number.
*
* For DRAM ECC errors, the Chip Select number is given in bits [2:0] of
* For DRAM ECC errors, the Chip Select number is given in bits [1:0] of
* the MCA_SYND[ErrorInformation] field.
*/
static void umc_get_err_info(struct mce *m, struct err_info *err)
{
err->channel = (m->ipid & GENMASK(31, 0)) >> 20;
err->csrow = m->synd & 0x7;
err->csrow = m->synd & 0x3;
}
static void decode_umc_error(int node_id, struct mce *m)

View File

@ -598,14 +598,18 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
/* first get metadata_size by buffer = NULL */
r = amdgpu_bo_get_metadata(bo, NULL, 0,
metadata_size, NULL);
if (r)
goto out_put;
/* user buf_size is bigger than bo metadata_size
* allocate a buf at kernel space and copy */
if (*metadata_size <= buffer_size) {
*metadata_buffer = kzalloc(*metadata_size, GFP_KERNEL);
if (!*metadata_buffer)
return -ENOMEM;
if (!*metadata_buffer) {
r = -ENOMEM;
goto out_put;
}
r = amdgpu_bo_get_metadata(bo, *metadata_buffer, *metadata_size,
NULL, &metadata_flags);

View File

@ -121,6 +121,20 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
*pos &= (1UL << 22) - 1;
if (size > PAGE_SIZE)
return -EINVAL;
/*
* Access the user buffer only while none of the locks below are held:
* a fault takes mmap_lock, and grbm_idx_mutex and srbm_mutex nest
* inside it.
*/
u32 *data __free(kfree) = kmalloc(size, GFP_KERNEL);
if (!data)
return -ENOMEM;
if (!read && copy_from_user(data, buf, size))
return -EFAULT;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@ -152,28 +166,16 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
mutex_lock(&adev->pm.mutex);
while (size) {
uint32_t value;
if (read) {
value = RREG32(*pos >> 2);
r = put_user(value, (uint32_t *)buf);
} else {
r = get_user(value, (uint32_t *)buf);
if (!r)
amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0);
}
if (r) {
result = r;
goto end;
}
if (read)
data[result >> 2] = RREG32(*pos >> 2);
else
amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, data[result >> 2], 0);
result += 4;
buf += 4;
*pos += 4;
size -= 4;
}
end:
if (use_bank) {
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
@ -188,6 +190,10 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev);
if (read && copy_to_user(buf, data, result))
return -EFAULT;
return result;
}
@ -238,11 +244,24 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
struct amdgpu_device *adev = rd->adev;
ssize_t result = 0;
int r;
uint32_t value;
if (size & 0x3 || offset & 0x3)
return -EINVAL;
if (size > PAGE_SIZE)
return -EINVAL;
/*
* Access the user buffer only while none of the locks below are held:
* a fault takes mmap_lock, and grbm_idx_mutex and srbm_mutex nest
* inside it.
*/
u32 *data __free(kfree) = kmalloc(size, GFP_KERNEL);
if (!data)
return -ENOMEM;
if (write_en && copy_from_user(data, buf, size))
return -EFAULT;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@ -281,24 +300,16 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
mutex_lock(&adev->pm.mutex);
while (size) {
if (!write_en) {
value = RREG32(offset >> 2);
r = put_user(value, (uint32_t *)buf);
} else {
r = get_user(value, (uint32_t *)buf);
if (!r)
amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value, rd->id.xcc_id);
}
if (r) {
result = r;
goto end;
}
if (!write_en)
data[result >> 2] = RREG32(offset >> 2);
else
amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, data[result >> 2],
rd->id.xcc_id);
offset += 4;
size -= 4;
result += 4;
buf += 4;
}
end:
if (rd->id.use_grbm) {
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, rd->id.xcc_id);
mutex_unlock(&adev->grbm_idx_mutex);
@ -317,6 +328,10 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev);
if (!write_en && copy_to_user(buf, data, result))
return -EFAULT;
return result;
}

View File

@ -1080,20 +1080,17 @@ void amdgpu_gmc_init_vga_resv_regions(struct amdgpu_device *adev)
case CHIP_RENOIR:
adev->mman.keep_stolen_vga_memory = true;
break;
case CHIP_POLARIS10:
case CHIP_POLARIS11:
case CHIP_POLARIS12:
/* MacBookPros with switchable graphics put VRAM at 0 when
* the iGPU is enabled which results in cursor issues if
* the cursor ends up at 0. Reserve vram at 0 in that case.
*/
if (adev->gmc.vram_start == 0)
adev->mman.keep_stolen_vga_memory = true;
break;
default:
adev->mman.keep_stolen_vga_memory = false;
break;
}
/* MacBookPros with switchable graphics put VRAM at 0 when
* the iGPU is enabled which results in cursor issues if
* the cursor ends up at 0. Reserve vram at 0 in that case.
*/
if ((adev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
(adev->gmc.vram_start == 0))
adev->mman.keep_stolen_vga_memory = true;
if (amdgpu_sriov_vf(adev) ||
!amdgpu_device_has_display_hardware(adev)) {

View File

@ -30,6 +30,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_vblank.h>
#include "amdgpu_uvd.h"
#include "amdgpu_vce.h"
#include "atom.h"
@ -1660,6 +1661,9 @@ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc)
DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
if (!down_read_trylock(&adev->reset_domain->sem))
return drm_crtc_vblank_count(crtc);
/* The hw increments its frame counter at start of vsync, not at start
* of vblank, as is required by DRM core vblank counter handling.
@ -1705,6 +1709,7 @@ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc)
DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
}
up_read(&adev->reset_domain->sem);
return count;
}

View File

@ -472,6 +472,7 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
u64 doorbell_index;
struct drm_gem_object *gobj;
struct amdgpu_userq_obj *db_obj = db_info->db_obj;
struct amdgpu_bo *abo;
int r, db_size;
gobj = drm_gem_object_lookup(filp, db_info->doorbell_handle);
@ -480,7 +481,17 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
return -EINVAL;
}
db_obj->obj = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
/*
* Pinning a regular BO into the doorbell domain would discard its
* contents, possibly those of a buffer shared by another client.
*/
abo = gem_to_amdgpu_bo(gobj);
if (!(abo->preferred_domains & AMDGPU_GEM_DOMAIN_DOORBELL)) {
drm_gem_object_put(gobj);
return -EINVAL;
}
db_obj->obj = amdgpu_bo_ref(abo);
drm_gem_object_put(gobj);
r = amdgpu_bo_reserve(db_obj->obj, true);

View File

@ -361,8 +361,7 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
compute_mqd = memdup_user(u64_to_user_ptr(mqd_user->mqd), mqd_user->mqd_size);
if (IS_ERR(compute_mqd)) {
DRM_ERROR("Failed to read user MQD\n");
r = -ENOMEM;
r = PTR_ERR(compute_mqd);
goto free_mqd;
}
@ -406,8 +405,7 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
mqd_gfx_v11 = memdup_user(u64_to_user_ptr(mqd_user->mqd), mqd_user->mqd_size);
if (IS_ERR(mqd_gfx_v11)) {
DRM_ERROR("Failed to read user MQD\n");
r = -ENOMEM;
r = PTR_ERR(mqd_gfx_v11);
goto free_mqd;
}
@ -451,8 +449,7 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
mqd_sdma_v11 = memdup_user(u64_to_user_ptr(mqd_user->mqd), mqd_user->mqd_size);
if (IS_ERR(mqd_sdma_v11)) {
DRM_ERROR("Failed to read sdma user MQD\n");
r = -ENOMEM;
r = PTR_ERR(mqd_sdma_v11);
goto free_mqd;
}

View File

@ -572,12 +572,32 @@ static int allocate_doorbell(struct qcm_process_device *qpd,
* we need the physical sdma engine id in order to get the
* correct doorbell offset.
*/
uint32_t valid_id = idx_offset[qpd->dqm->dev->node_id *
get_num_all_sdma_engines(qpd->dqm) +
q->properties.sdma_engine_id]
+ (q->properties.sdma_queue_id & 1)
* KFD_QUEUE_DOORBELL_MIRROR_OFFSET
+ (q->properties.sdma_queue_id >> 1);
u32 engine_base = idx_offset[dev->node_id *
get_num_all_sdma_engines(qpd->dqm) +
q->properties.sdma_engine_id];
u32 valid_id;
/*
* With the aqua_vanjaram doorbell layout, a shader doorbell
* write whose 32-byte block starts in the previous engine's
* range rings that engine instead. Engine ranges are 10
* indices apart (sdma_doorbell_range = 20 dwords, halved for
* 8-byte doorbells, in aqua_vanjaram_doorbell_index_init()),
* which puts odd engines 2 indices into a shared block.
* Aligning costs at most 2 indices, and 8 queues per engine use
* only 4 of the 10, so the aligned base stays in range. The
* 512-index mirror offset keeps the alignment.
*/
if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3) ||
KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 4) ||
KFD_GC_VERSION(dev) == IP_VERSION(9, 5, 0))
engine_base = ALIGN(engine_base,
KFD_SDMA_SHADER_DOORBELL_GRANULARITY);
valid_id = engine_base +
(q->properties.sdma_queue_id & 1) *
KFD_QUEUE_DOORBELL_MIRROR_OFFSET +
(q->properties.sdma_queue_id >> 1);
if (restore_id && *restore_id != valid_id)
return -EINVAL;

View File

@ -133,6 +133,13 @@
*/
#define KFD_QUEUE_DOORBELL_MIRROR_OFFSET 512
/*
* On GC 9.4.3, 9.4.4 and 9.5.0, doorbell writes issued from shaders are
* routed to an SDMA engine at 32-byte granularity, i.e. 4 indices with the
* 8-byte SDMA doorbells used on SOC15.
*/
#define KFD_SDMA_SHADER_DOORBELL_GRANULARITY 4
/**
* enum kfd_ioctl_flags - KFD ioctl flags
* Various flags that can be set in &amdkfd_ioctl_desc.flags to control how

View File

@ -3708,6 +3708,13 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_display_manager *dm,
struct amdgpu_dm_connector *aconn =
(struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
if (!acrtc_state->base.async_flip) {
amdgpu_dm_psr_set_event(dm, acrtc_state->stream, false,
psr_event_immediate_flip, false);
amdgpu_dm_replay_set_event(dm, acrtc_state->stream, false,
replay_event_immediate_flip, false);
}
/* Decrement skip count when SR is enabled and we're doing fast updates. */
if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
(psr->psr_feature_enabled || pr->replay_feature_enabled)) {
@ -4118,6 +4125,18 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
}
mutex_lock(&dm->dc_lock);
/*
* Tearing (immediate) flips cannot work with panel self-refresh
* features. The event is cleared by
* amdgpu_dm_enable_self_refresh() once async flips stop.
*/
if (immediate_flip) {
dc_exit_ips_for_hw_access(dm->dc);
amdgpu_dm_psr_set_event(dm, acrtc_state->stream, true,
psr_event_immediate_flip, true);
amdgpu_dm_replay_set_event(dm, acrtc_state->stream, true,
replay_event_immediate_flip, true);
}
update_planes_and_stream_adapter(dm->dc,
acrtc_state->update_type,
planes_count,

View File

@ -1012,10 +1012,15 @@ decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode,
const struct drm_display_mode *native_mode,
bool scale_enabled)
{
/* Inserted modes copy the native sync; a sink mode with equal totals may not */
if (scale_enabled || (
native_mode->clock == drm_mode->clock &&
native_mode->htotal == drm_mode->htotal &&
native_mode->vtotal == drm_mode->vtotal)) {
native_mode->vtotal == drm_mode->vtotal &&
native_mode->hsync_start == drm_mode->hsync_start &&
native_mode->hsync_end == drm_mode->hsync_end &&
native_mode->vsync_start == drm_mode->vsync_start &&
native_mode->vsync_end == drm_mode->vsync_end)) {
if (native_mode->crtc_clock)
copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
} else {

View File

@ -112,25 +112,7 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
static const uint32_t alpha_formats[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_RGBA8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_ABGR2101010,
DRM_FORMAT_ARGB16161616,
DRM_FORMAT_ABGR16161616,
DRM_FORMAT_ARGB16161616F,
};
uint32_t format = plane_state->fb->format->format;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(alpha_formats); ++i) {
if (format == alpha_formats[i]) {
*per_pixel_alpha = true;
break;
}
}
*per_pixel_alpha = plane_state->fb->format->has_alpha;
if (*per_pixel_alpha && plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE)
*pre_multiplied_alpha = false;

View File

@ -1572,6 +1572,46 @@ static void dm_test_decide_crtc_timing_no_crtc_clock(struct kunit *test)
KUNIT_EXPECT_EQ(test, drm_mode.crtc_hdisplay, 0);
}
static void dm_test_decide_crtc_timing_sink_mode_same_totals(struct kunit *test)
{
struct drm_display_mode native_mode = {
DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016, 4104,
4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) };
struct drm_display_mode drm_mode = {
DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184, 4272,
4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) };
drm_mode_set_crtcinfo(&native_mode, 0);
drm_mode_set_crtcinfo(&drm_mode, 0);
decide_crtc_timing_for_drm_display_mode(&drm_mode, &native_mode, false);
KUNIT_EXPECT_EQ(test, drm_mode.crtc_hdisplay, 4096);
KUNIT_EXPECT_EQ(test, drm_mode.crtc_hsync_start, 4184);
}
static void dm_test_decide_crtc_timing_inserted_mode(struct kunit *test)
{
struct drm_display_mode native_mode = {
DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016, 4104,
4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) };
struct drm_display_mode drm_mode;
drm_mode_set_crtcinfo(&native_mode, 0);
drm_mode = native_mode;
drm_mode.hdisplay = 1920;
drm_mode.vdisplay = 1080;
drm_mode_set_crtcinfo(&drm_mode, 0);
decide_crtc_timing_for_drm_display_mode(&drm_mode, &native_mode, false);
KUNIT_EXPECT_EQ(test, drm_mode.crtc_hdisplay, 3840);
KUNIT_EXPECT_EQ(test, drm_mode.crtc_vdisplay, 2160);
}
/* Tests for amdgpu_dm_connector_funcs_reset() */
static const struct drm_connector_funcs dm_test_connector_funcs = {
@ -5635,6 +5675,8 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
KUNIT_CASE(dm_test_decide_crtc_timing_matching_mode),
KUNIT_CASE(dm_test_decide_crtc_timing_no_copy),
KUNIT_CASE(dm_test_decide_crtc_timing_no_crtc_clock),
KUNIT_CASE(dm_test_decide_crtc_timing_sink_mode_same_totals),
KUNIT_CASE(dm_test_decide_crtc_timing_inserted_mode),
/* amdgpu_dm_connector_funcs_reset */
KUNIT_CASE(dm_test_funcs_reset_sets_defaults),
KUNIT_CASE(dm_test_funcs_reset_edp_abm_level),

View File

@ -189,13 +189,12 @@ static int aspeed_gfx_load(struct drm_device *drm)
}
reset_control_deassert(priv->rst);
priv->clk = devm_clk_get(drm->dev, NULL);
priv->clk = devm_clk_get_enabled(drm->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev,
"missing or invalid clk device tree entry");
"failed to get and enable clock\n");
return PTR_ERR(priv->clk);
}
clk_prepare_enable(priv->clk);
/* Sanitize control registers */
writel(0, priv->base + CRT_CTRL1);

View File

@ -135,8 +135,8 @@ static int th1520_dw_hdmi_probe(struct platform_device *pdev)
plat_data->priv_data = hdmi;
hdmi->dw_hdmi = dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi))
return PTR_ERR(hdmi);
if (IS_ERR(hdmi->dw_hdmi))
return PTR_ERR(hdmi->dw_hdmi);
platform_set_drvdata(pdev, hdmi);
@ -145,9 +145,9 @@ static int th1520_dw_hdmi_probe(struct platform_device *pdev)
static void th1520_dw_hdmi_remove(struct platform_device *pdev)
{
struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
struct th1520_hdmi *hdmi = platform_get_drvdata(pdev);
dw_hdmi_remove(hdmi);
dw_hdmi_remove(hdmi->dw_hdmi);
}
static const struct of_device_id th1520_dw_hdmi_of_table[] = {

View File

@ -4634,7 +4634,9 @@ static int dp_aux_backlight_update_status(struct backlight_device *bd)
if (!backlight_is_blank(bd)) {
if (!bl->enabled) {
drm_edp_backlight_enable(bl->aux, &bl->info, brightness);
ret = drm_edp_backlight_enable(bl->aux, &bl->info, brightness);
if (ret)
return ret;
bl->enabled = true;
return 0;
}

View File

@ -454,8 +454,10 @@ void drm_bridge_add(struct drm_bridge *bridge)
* in bridge_lingering_list. Remove it or bridge_lingering_list will be
* corrupted when adding this bridge to bridge_list below.
*/
mutex_lock(&bridge_lock);
if (!list_empty(&bridge->list))
list_del_init(&bridge->list);
mutex_unlock(&bridge_lock);
mutex_init(&bridge->hpd_state_mutex);
mutex_init(&bridge->hpd_mutex);
@ -593,8 +595,10 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
if (!bridge->container)
DRM_WARN("DRM bridge corrupted or not allocated by devm_drm_bridge_alloc()\n");
if (list_empty(&bridge->list))
DRM_WARN("Missing drm_bridge_add() before attach\n");
scoped_guard(mutex, &bridge_lock) {
if (list_empty(&bridge->list))
DRM_WARN("Missing drm_bridge_add() before attach\n");
}
drm_bridge_get(bridge);

View File

@ -1724,10 +1724,10 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
ret = drm_fb_helper_single_fb_probe(fb_helper);
if (ret < 0) {
if (ret == -EAGAIN) {
fb_helper->deferred_setup = true;
/* modesets are probed but fb_helper->fb isn't; defer restore too */
fb_helper->deferred_setup = true;
if (ret == -EAGAIN)
ret = 0;
}
mutex_unlock(&fb_helper->lock);
goto err_drm_fb_helper_release_info;

View File

@ -507,6 +507,7 @@ int gud_plane_atomic_check(struct drm_plane *plane,
for_each_new_connector_in_state(state, connector, connector_state, i) {
if (connector_state->crtc)
break;
connector_state = NULL;
}
/*

View File

@ -1766,6 +1766,7 @@ static int eb_reinit_userptr(struct i915_execbuffer *eb)
static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb)
{
const unsigned int count = eb->buffer_count;
bool have_copy = false;
struct eb_vma *ev;
int err = 0;
@ -1868,7 +1869,6 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb)
out:
if (have_copy) {
const unsigned int count = eb->buffer_count;
unsigned int i;
for (i = 0; i < count; i++) {

View File

@ -1904,7 +1904,8 @@ static void rps_work(struct work_struct *work)
out:
spin_lock_irq(gt->irq_lock);
gen6_gt_pm_unmask_irq(gt, rps->pm_events);
if (intel_rps_is_active(rps))
gen6_gt_pm_unmask_irq(gt, rps->pm_events);
spin_unlock_irq(gt->irq_lock);
}

View File

@ -2337,7 +2337,7 @@ void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx)
* @ctx: MMU context associated with owning VM context.
* @sgt: Scatter gather table containing pages pinned for use by this context.
* @device_addr: Virtual device address at the start of the requested mapping.
* @sgt_offset: Start offset of the requested device-virtual memory mapping.
* @sgt_offset: Offset into @sgt of the start of the requested mapping.
* @size: Size in bytes of the requested device-virtual memory mapping. For an
* unmapping, this should be zero so that no page tables are allocated.
*
@ -2350,7 +2350,6 @@ struct pvr_mmu_op_context *
pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt,
u64 device_addr, u64 sgt_offset, u64 size)
{
u64 start_addr = device_addr + sgt_offset;
int err;
struct pvr_mmu_op_context *op_ctx = kzalloc_obj(*op_ctx);
@ -2365,18 +2364,18 @@ pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt,
if (size) {
/*
* The number of page table objects we need to prealloc is
* indicated by the mapping size, start address and the sizes
* of the areas mapped per PT or PD. The range calculation is
* identical to that for the index into a table for a device
* address, so we reuse those functions here.
* The page tables needed are set by the device-virtual range
* being mapped: one level 1 table per 1GiB region and one
* level 0 table per 2MiB region the range touches. Tables that
* already exist are not consumed, so this is an upper bound.
*/
const u32 l1_start_idx = pvr_page_table_l2_idx(start_addr);
const u32 l1_end_idx = pvr_page_table_l2_idx(start_addr + size);
const u32 l1_count = l1_end_idx - l1_start_idx + 1;
const u32 l0_start_idx = pvr_page_table_l1_idx(start_addr);
const u32 l0_end_idx = pvr_page_table_l1_idx(start_addr + size);
const u32 l0_count = l0_end_idx - l0_start_idx + 1;
const u64 last_addr = device_addr + size - 1;
const u64 l1_count =
(last_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) -
(device_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) + 1;
const u64 l0_count =
(last_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) -
(device_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) + 1;
/*
* Alloc and push page table entries until we have enough of

View File

@ -418,6 +418,8 @@ pvr_vm_gpuva_unmap(struct drm_gpuva_op *op, void *op_ctx)
static int
pvr_vm_gpuva_remap(struct drm_gpuva_op *op, void *op_ctx)
{
/* The split parts belong to the object of the mapping being split. */
struct drm_gpuvm_bo *vm_bo = op->remap.unmap->va->vm_bo;
struct pvr_vm_bind_op *ctx = op_ctx;
u64 va_start = 0, va_range = 0;
int err;
@ -433,14 +435,12 @@ pvr_vm_gpuva_remap(struct drm_gpuva_op *op, void *op_ctx)
drm_gpuva_remap(&ctx->prev_va->base, &ctx->next_va->base, &op->remap);
if (op->remap.prev) {
pvr_gem_object_get(gem_to_pvr_gem(ctx->prev_va->base.gem.obj));
drm_gpuva_link(&ctx->prev_va->base, ctx->gpuvm_bo);
drm_gpuva_link(&ctx->prev_va->base, vm_bo);
ctx->prev_va = NULL;
}
if (op->remap.next) {
pvr_gem_object_get(gem_to_pvr_gem(ctx->next_va->base.gem.obj));
drm_gpuva_link(&ctx->next_va->base, ctx->gpuvm_bo);
drm_gpuva_link(&ctx->next_va->base, vm_bo);
ctx->next_va = NULL;
}

View File

@ -488,7 +488,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
goto done;
break;
case NV_DEVICE_INFO_V0_TURING:
if (engine != NV_DEVICE_HOST_RUNLIST_ENGINES_NVDEC) {
if (engine == NV_DEVICE_HOST_RUNLIST_ENGINES_GR) {
ret = nvif_object_ctor(&chan->chan->user, "abi16CeWar",
0, TURING_DMA_COPY_A, NULL, 0,
&chan->ce);

View File

@ -201,7 +201,7 @@ nvkm_udevice_gcx_ready(struct nvkm_udevice *udev, void *data, u32 size)
} *args = data;
int ret = -ENOSYS;
if (!gsp) {
if (!gsp || !gsp->rm) {
args->v0.ready = NV_DEVICE_GC6_READY | NV_DEVICE_GCOFF_READY;
return 0;
}

View File

@ -3674,6 +3674,9 @@ int panthor_group_create(struct panthor_file *pfile,
hweight64(group_args->tiler_core_mask) < group_args->max_tiler_cores)
return -EINVAL;
if (group_args->queues.count > sched->cs_slot_count)
return -EINVAL;
group = kzalloc_obj(*group);
if (!group)
return -ENOMEM;

View File

@ -204,7 +204,7 @@ static struct list_head *vc4_get_cache_list_for_size(struct drm_device *dev,
struct list_head *new_list;
uint32_t i;
new_list = kmalloc_objs(struct list_head, new_size);
new_list = kvmalloc_objs(struct list_head, new_size);
if (!new_list)
return NULL;
@ -224,7 +224,7 @@ static struct list_head *vc4_get_cache_list_for_size(struct drm_device *dev,
for (i = vc4->bo_cache.size_list_size; i < new_size; i++)
INIT_LIST_HEAD(&new_list[i]);
kfree(vc4->bo_cache.size_list);
kvfree(vc4->bo_cache.size_list);
vc4->bo_cache.size_list = new_list;
vc4->bo_cache.size_list_size = new_size;
}
@ -1052,6 +1052,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
cancel_work_sync(&vc4->bo_cache.time_work);
vc4_bo_cache_purge(dev);
kvfree(vc4->bo_cache.size_list);
for (i = 0; i < vc4->num_labels; i++) {
if (vc4->bo_labels[i].num_allocated) {

View File

@ -360,8 +360,11 @@ static int vc4_drm_bind(struct device *dev)
}
ret = aperture_remove_all_conflicting_devices(driver->name);
if (ret)
if (ret) {
if (firmware)
rpi_firmware_put(firmware);
goto err;
}
if (firmware) {
ret = rpi_firmware_property(firmware,

View File

@ -1051,7 +1051,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane,
/* vc4_v3d.c */
extern struct platform_driver vc4_v3d_driver;
extern const struct of_device_id vc4_v3d_dt_match[];
int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);
int vc4_v3d_get_bin_slot(struct vc4_dev *vc4, long timeout);
int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used);
void vc4_v3d_bin_bo_put(struct vc4_dev *vc4);
int vc4_v3d_pm_get(struct vc4_dev *vc4);

View File

@ -877,11 +877,17 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
drm_gem_object_put(&bo->base.base);
}
/* Free up the allocation of any bin slots we used. */
/* Free up the allocation of any bin slots we used. Jobs that ran to
* completion had their slots released in vc4_irq_finish_render_job().
* Only jobs that never completed still have slots to be released here.
*/
spin_lock_irqsave(&vc4->job_lock, irqflags);
vc4->bin_alloc_used &= ~exec->bin_slots;
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
/* Let anyone waiting on the binner pool retry. */
wake_up_all(&vc4->job_wait_queue);
/* Release the reference on the binner BO if needed. */
if (exec->bin_bo_used)
vc4_v3d_bin_bo_put(vc4);

View File

@ -74,7 +74,7 @@ vc4_overflow_mem_work(struct work_struct *work)
bo = vc4->bin_bo;
bin_bo_slot = vc4_v3d_get_bin_slot(vc4);
bin_bo_slot = vc4_v3d_get_bin_slot(vc4, msecs_to_jiffies(500));
if (bin_bo_slot < 0) {
drm_err(&vc4->base, "Couldn't allocate binner overflow mem\n");
goto complete;
@ -165,6 +165,10 @@ vc4_irq_finish_render_job(struct drm_device *dev)
trace_vc4_rcl_end_irq(dev, exec->seqno);
vc4->finished_seqno++;
vc4->bin_alloc_used &= ~exec->bin_slots;
exec->bin_slots = 0;
list_move_tail(&exec->head, &vc4->job_done_list);
nextbin = vc4_first_bin_job(vc4);
@ -276,7 +280,7 @@ vc4_irq_disable(struct drm_device *dev)
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
/* Finish any interrupt handler still in flight. */
synchronize_irq(vc4->irq);
disable_irq(vc4->irq);
cancel_work_sync(&vc4->overflow_mem_work);
}
@ -284,7 +288,6 @@ vc4_irq_disable(struct drm_device *dev)
int vc4_irq_install(struct drm_device *dev, int irq)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
int ret;
if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4))
return -ENODEV;
@ -298,19 +301,8 @@ int vc4_irq_install(struct drm_device *dev, int irq)
init_waitqueue_head(&vc4->job_wait_queue);
INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
/* Clear any pending interrupts someone might have left around
* for us.
*/
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
ret = devm_request_irq(dev->dev, irq, vc4_irq, 0,
dev_name(dev->dev), dev);
if (ret)
return ret;
vc4_irq_enable(dev);
return 0;
return devm_request_irq(dev->dev, irq, vc4_irq, IRQF_NO_AUTOEN,
dev_name(dev->dev), dev);
}
void vc4_irq_uninstall(struct drm_device *dev)

View File

@ -9,6 +9,7 @@
#include <linux/component.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/timer.h>
#include <drm/drm_print.h>
@ -172,46 +173,42 @@ static void vc4_v3d_init_hw(struct drm_device *dev)
V3D_WRITE(V3D_VPMBASE, 0);
}
int vc4_v3d_get_bin_slot(struct vc4_dev *vc4)
static int bin_slot_try_alloc(struct vc4_dev *vc4)
{
struct drm_device *dev = &vc4->base;
unsigned long irqflags;
int slot;
uint64_t seqno = 0;
struct vc4_exec_info *exec;
if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4))
return -ENODEV;
guard(spinlock_irqsave)(&vc4->job_lock);
try_again:
spin_lock_irqsave(&vc4->job_lock, irqflags);
slot = ffs(~vc4->bin_alloc_used);
if (slot != 0) {
/* Switch from ffs() bit index to a 0-based index. */
slot--;
vc4->bin_alloc_used |= BIT(slot);
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
return slot;
} else {
slot = -ENOMEM;
}
/* Couldn't find an open slot. Wait for render to complete
* and try again.
*/
exec = vc4_last_render_job(vc4);
if (exec)
seqno = exec->seqno;
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
return slot;
}
if (seqno) {
int ret = vc4_wait_for_seqno(dev, seqno, ~0ull, true);
int vc4_v3d_get_bin_slot(struct vc4_dev *vc4, long timeout)
{
int slot;
long ret;
if (ret == 0)
goto try_again;
if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4))
return -ENODEV;
/* If the pool is full, wait for a job to release its slots. */
ret = wait_event_interruptible_timeout(vc4->job_wait_queue,
(slot = bin_slot_try_alloc(vc4)) >= 0,
timeout);
if (ret < 0)
return ret;
}
if (ret == 0)
return -ENOMEM;
return -ENOMEM;
return slot;
}
/*
@ -396,6 +393,7 @@ static int vc4_v3d_runtime_resume(struct device *dev)
vc4_v3d_init_hw(&vc4->base);
vc4_irq_enable(&vc4->base);
enable_irq(vc4->irq);
return 0;
}
@ -452,6 +450,12 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
return ret;
vc4->irq = ret;
ret = vc4_irq_install(drm, vc4->irq);
if (ret) {
drm_err(drm, "Failed to install IRQ handler\n");
return ret;
}
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
@ -473,12 +477,6 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
V3D_WRITE(V3D_BPOA, 0);
V3D_WRITE(V3D_BPOS, 0);
ret = vc4_irq_install(drm, vc4->irq);
if (ret) {
drm_err(drm, "Failed to install IRQ handler\n");
goto err_put_runtime_pm;
}
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
pm_runtime_put_autosuspend(dev);
@ -497,8 +495,15 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
struct drm_device *drm = data;
struct vc4_dev *vc4 = to_vc4_dev(drm);
/* A straggler vc4_reset() re-enables the interrupt. */
timer_shutdown_sync(&vc4->hangcheck.timer);
cancel_work_sync(&vc4->hangcheck.reset_work);
vc4_irq_uninstall(drm);
/* Flush rather than cancel, so queued completions release their jobs. */
flush_work(&vc4->job_done_work);
/* Disable the binner's overflow memory address, so the next
* driver probe (if any) doesn't try to reuse our old
* allocation.

View File

@ -402,7 +402,7 @@ validate_tile_binning_config(VALIDATE_ARGS)
return -EINVAL;
}
bin_slot = vc4_v3d_get_bin_slot(vc4);
bin_slot = vc4_v3d_get_bin_slot(vc4, MAX_SCHEDULE_TIMEOUT);
if (bin_slot < 0) {
if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) {
drm_err(dev, "Failed to allocate binner memory: %d\n",

View File

@ -324,6 +324,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
unsigned long kmap_num;
SVGA3dCopyBox *box;
u32 box_count;
u64 src_extent;
void *virtual;
bool is_iomem;
struct vmw_dma_cmd {
@ -335,6 +336,8 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
vmw_surface_get_desc(VMW_CURSOR_SNOOP_FORMAT);
const u32 image_pitch = VMW_CURSOR_SNOOP_WIDTH * desc->pitchBytesPerBlock;
BUILD_BUG_ON(sizeof(*srf->snooper.image) != desc->pitchBytesPerBlock);
cmd = container_of(header, struct vmw_dma_cmd, header);
/* No snooper installed, nothing to copy */
@ -372,8 +375,19 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
return;
}
if (box->w == 0 || box->h == 0)
return;
src_extent = (u64)(box->h - 1) * cmd->dma.guest.pitch +
(u64)box->w * desc->pitchBytesPerBlock;
if (src_extent > bo->base.size) {
DRM_ERROR("Cursor snoop source of %llu bytes exceeds the %zu byte buffer\n",
src_extent, bo->base.size);
return;
}
kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
kmap_num = (VMW_CURSOR_SNOOP_HEIGHT * image_pitch) >> PAGE_SHIFT;
kmap_num = PFN_UP(src_extent);
ret = ttm_bo_reserve(bo, true, false, NULL);
if (unlikely(ret != 0)) {
@ -387,14 +401,16 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
virtual = ttm_kmap_obj_virtual(&map, &is_iomem);
if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) {
if (box->w == VMW_CURSOR_SNOOP_WIDTH &&
box->h == VMW_CURSOR_SNOOP_HEIGHT &&
cmd->dma.guest.pitch == image_pitch) {
memcpy(srf->snooper.image, virtual,
VMW_CURSOR_SNOOP_HEIGHT * image_pitch);
} else {
/* Image is unsigned pointer. */
/* The destination stride is in pixels. */
for (i = 0; i < box->h; i++)
memcpy(srf->snooper.image + i * image_pitch,
virtual + i * cmd->dma.guest.pitch,
memcpy(srf->snooper.image + i * VMW_CURSOR_SNOOP_WIDTH,
virtual + (size_t)i * cmd->dma.guest.pitch,
box->w * desc->pitchBytesPerBlock);
}
srf->snooper.id++;

View File

@ -20,10 +20,18 @@
#include <drm/drm_rect.h>
#include <drm/drm_sysfs.h>
#include <drm/drm_edid.h>
#include <drm/drm_blend.h>
void vmw_du_init(struct vmw_display_unit *du)
{
vmw_vkms_crtc_init(&du->crtc);
drm_plane_create_blend_mode_property(&du->primary,
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI));
// Check that the cursor plane was actually initialized
if (du->crtc.cursor == &du->cursor.base)
drm_plane_create_blend_mode_property(&du->cursor.base,
BIT(DRM_MODE_BLEND_PREMULTI));
}
void vmw_du_cleanup(struct vmw_display_unit *du)

View File

@ -356,7 +356,7 @@ static struct i915_vma *__xe_pin_fb_vma(struct drm_gem_object *obj, bool is_dpt,
drm_exec_retry_on_contention(&exec);
xe_validation_retry_on_oom(&ctx, &ret);
if (!ret)
ttm_bo_pin(&bo->ttm);
xe_bo_pin_account(bo);
}
if (ret)
goto err;
@ -373,7 +373,7 @@ static struct i915_vma *__xe_pin_fb_vma(struct drm_gem_object *obj, bool is_dpt,
err_unpin:
ttm_bo_reserve(&bo->ttm, false, false, NULL);
ttm_bo_unpin(&bo->ttm);
xe_bo_unpin_account(bo);
ttm_bo_unreserve(&bo->ttm);
err:
kfree(vma);
@ -393,7 +393,7 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma)
xe_ggtt_node_remove(vma->node, false);
ttm_bo_reserve(&vma->bo->ttm, false, false, NULL);
ttm_bo_unpin(&vma->bo->ttm);
xe_bo_unpin_account(vma->bo);
ttm_bo_unreserve(&vma->bo->ttm);
kfree(vma);
}

View File

@ -455,6 +455,100 @@ static void xe_ttm_tt_account_subtract(struct xe_device *xe, struct ttm_tt *tt)
xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0);
}
static bool xe_ttm_bo_is_imported(struct ttm_buffer_object *tbo)
{
dma_resv_assert_held(tbo->base.resv);
return tbo->ttm &&
(tbo->ttm->page_flags & (TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE)) ==
TTM_TT_FLAG_EXTERNAL;
}
/*
* Account @bo's pages as pinned for the shrinker. Removes @bo's pages
* from the shrinker's shrinkable / purgeable counts on the transition
* from unpinned to pinned. Must be called with @bo's dma-resv held,
* after &ttm_buffer_object.pin_count has been incremented by
* ttm_bo_pin(). Safe to call unconditionally regardless of which pin
* path (kernel, external, framebuffer, backup object, ...) is pinning
* @bo, since it only acts on the true 0->1 pin_count transition.
*
* Imported bos (xe_ttm_bo_is_imported()) are excluded: for those,
* xe_ttm_tt_populate() never actually populates the tt or calls
* xe_ttm_tt_account_add(), but TTM core's ttm_tt_populate() still
* unconditionally marks the tt as populated on driver-hook success.
* Relying on ttm_tt_is_populated() for these would subtract pages that
* were never added, underflowing the shrinker's counts.
*/
static void xe_bo_account_pin(struct xe_bo *bo)
{
struct xe_device *xe = xe_bo_device(bo);
if (bo->ttm.pin_count == 1 && bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm) &&
!xe_ttm_bo_is_imported(&bo->ttm))
xe_ttm_tt_account_subtract(xe, bo->ttm.ttm);
}
/*
* Counterpart to xe_bo_account_pin(). Must be called with @bo's dma-resv
* held, before &ttm_buffer_object.pin_count is decremented by
* ttm_bo_unpin(), so that the check against the true 1->0 transition sees
* the pin count that is about to be released. See xe_bo_account_pin() for
* why imported bos are excluded.
*
* On the true last unpin, also removes @bo from whichever pinned-bo list
* (external or kernel_bo_present) it may currently be linked on, since a
* bo's final unpin can happen through a pin path (e.g. framebuffer,
* backup object) that has no notion of, or ownership over, that list.
* This is safe and list-agnostic: list_del_init() only needs the node
* itself, not knowledge of which list it is threaded through, and is a
* no-op if @bo is not linked.
*/
static void xe_bo_account_unpin(struct xe_bo *bo)
{
struct xe_device *xe = xe_bo_device(bo);
bool last_unpin = bo->ttm.pin_count == 1;
if (last_unpin && !list_empty(&bo->pinned_link)) {
spin_lock(&xe->pinned.lock);
list_del_init(&bo->pinned_link);
spin_unlock(&xe->pinned.lock);
}
if (last_unpin && bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm) &&
!xe_ttm_bo_is_imported(&bo->ttm))
xe_ttm_tt_account_add(xe, bo->ttm.ttm);
}
/**
* xe_bo_pin_account() - Pin a bo and account its pages for the shrinker
* @bo: The buffer object to pin.
*
* Pins @bo via ttm_bo_pin() and updates the shrinker's shrinkable /
* purgeable page accounting to match. Must be called with @bo's dma-resv
* held. Safe to call regardless of which pin path (kernel, external,
* framebuffer, backup object, ...) is pinning @bo.
*/
void xe_bo_pin_account(struct xe_bo *bo)
{
ttm_bo_pin(&bo->ttm);
xe_bo_account_pin(bo);
}
/**
* xe_bo_unpin_account() - Unpin a bo and account its pages for the shrinker
* @bo: The buffer object to unpin.
*
* Counterpart to xe_bo_pin_account(). Updates the shrinker's shrinkable /
* purgeable page accounting to match, then unpins @bo via ttm_bo_unpin().
* Must be called with @bo's dma-resv held.
*/
void xe_bo_unpin_account(struct xe_bo *bo)
{
xe_bo_account_unpin(bo);
ttm_bo_unpin(&bo->ttm);
}
static void update_global_total_pages(struct ttm_device *ttm_dev,
long num_pages)
{
@ -1389,7 +1483,8 @@ int xe_bo_notifier_prepare_pinned(struct xe_bo *bo)
}
backup->parent_obj = xe_bo_get(bo); /* Released by bo_destroy */
ttm_bo_pin(&backup->ttm);
/* Note: XE_BO_FLAG_SYSTEM resolves to XE_PL_TT so already populated. */
xe_bo_pin_account(backup);
bo->backup_obj = backup;
}
@ -1409,7 +1504,7 @@ int xe_bo_notifier_unprepare_pinned(struct xe_bo *bo)
{
xe_bo_lock(bo, false);
if (bo->backup_obj) {
ttm_bo_unpin(&bo->backup_obj->ttm);
xe_bo_unpin_account(bo->backup_obj);
xe_bo_put(bo->backup_obj);
bo->backup_obj = NULL;
}
@ -1620,7 +1715,7 @@ int xe_bo_restore_pinned(struct xe_bo *bo)
xe_bo_vunmap(backup);
if (!bo->backup_obj) {
if (xe_bo_is_pinned(backup))
ttm_bo_unpin(&backup->ttm);
xe_bo_unpin_account(backup);
xe_bo_put(backup);
}
out_unlock_bo:
@ -2012,15 +2107,6 @@ static vm_fault_t xe_err_to_fault_t(int err)
return VM_FAULT_SIGBUS;
}
static bool xe_ttm_bo_is_imported(struct ttm_buffer_object *tbo)
{
dma_resv_assert_held(tbo->base.resv);
return tbo->ttm &&
(tbo->ttm->page_flags & (TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE)) ==
TTM_TT_FLAG_EXTERNAL;
}
static vm_fault_t xe_bo_cpu_fault_fastpath(struct vm_fault *vmf, struct xe_device *xe,
struct xe_bo *bo, bool needs_rpm)
{
@ -3141,12 +3227,13 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res)
int xe_bo_pin_external(struct xe_bo *bo, bool in_place, struct drm_exec *exec)
{
struct xe_device *xe = xe_bo_device(bo);
bool first_pin = !xe_bo_is_pinned(bo);
int err;
xe_assert(xe, !bo->vm);
xe_assert(xe, xe_bo_is_user(bo));
if (!xe_bo_is_pinned(bo)) {
if (first_pin) {
if (!in_place) {
err = xe_bo_validate(bo, NULL, false, exec);
if (err)
@ -3158,9 +3245,7 @@ int xe_bo_pin_external(struct xe_bo *bo, bool in_place, struct drm_exec *exec)
spin_unlock(&xe->pinned.lock);
}
ttm_bo_pin(&bo->ttm);
if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm))
xe_ttm_tt_account_subtract(xe, bo->ttm.ttm);
xe_bo_pin_account(bo);
/*
* FIXME: If we always use the reserve / unreserve functions for locking
@ -3216,9 +3301,7 @@ int xe_bo_pin(struct xe_bo *bo, struct drm_exec *exec)
spin_unlock(&xe->pinned.lock);
}
ttm_bo_pin(&bo->ttm);
if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm))
xe_ttm_tt_account_subtract(xe, bo->ttm.ttm);
xe_bo_pin_account(bo);
/*
* FIXME: If we always use the reserve / unreserve functions for locking
@ -3247,14 +3330,7 @@ void xe_bo_unpin_external(struct xe_bo *bo)
xe_assert(xe, xe_bo_is_pinned(bo));
xe_assert(xe, xe_bo_is_user(bo));
spin_lock(&xe->pinned.lock);
if (bo->ttm.pin_count == 1 && !list_empty(&bo->pinned_link))
list_del_init(&bo->pinned_link);
spin_unlock(&xe->pinned.lock);
ttm_bo_unpin(&bo->ttm);
if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm))
xe_ttm_tt_account_add(xe, bo->ttm.ttm);
xe_bo_unpin_account(bo);
/*
* FIXME: If we always use the reserve / unreserve functions for locking
@ -3272,21 +3348,16 @@ void xe_bo_unpin(struct xe_bo *bo)
xe_assert(xe, xe_bo_is_pinned(bo));
if (mem_type_is_vram(place->mem_type) || bo->flags & XE_BO_FLAG_GGTT) {
spin_lock(&xe->pinned.lock);
xe_assert(xe, !list_empty(&bo->pinned_link));
list_del_init(&bo->pinned_link);
spin_unlock(&xe->pinned.lock);
if (bo->backup_obj) {
if (xe_bo_is_pinned(bo->backup_obj))
ttm_bo_unpin(&bo->backup_obj->ttm);
xe_bo_unpin_account(bo->backup_obj);
xe_bo_put(bo->backup_obj);
bo->backup_obj = NULL;
}
}
ttm_bo_unpin(&bo->ttm);
if (bo->ttm.ttm && ttm_tt_is_populated(bo->ttm.ttm))
xe_ttm_tt_account_add(xe, bo->ttm.ttm);
xe_bo_unpin_account(bo);
}
/**

View File

@ -229,6 +229,8 @@ int xe_bo_pin_external(struct xe_bo *bo, bool in_place, struct drm_exec *exec);
int xe_bo_pin(struct xe_bo *bo, struct drm_exec *exec);
void xe_bo_unpin_external(struct xe_bo *bo);
void xe_bo_unpin(struct xe_bo *bo);
void xe_bo_pin_account(struct xe_bo *bo);
void xe_bo_unpin_account(struct xe_bo *bo);
int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict,
struct drm_exec *exec);

View File

@ -324,12 +324,15 @@ static void xe_i2c_remove(void *data)
xe_i2c_irq_reset(xe);
xe_amc_exit(i2c);
/* Stop the notifier from arming the client work before teardown. */
bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
cancel_work_sync(&i2c->work);
for (i = 0; i < XE_I2C_MAX_CLIENTS; i++) {
i2c_unregister_device(i2c->client[i]);
i2c->client[i] = NULL;
}
bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
xe_i2c_unregister_adapter(i2c);
xe->i2c = NULL;
}

View File

@ -1099,8 +1099,7 @@ static void xe_lrc_finish(struct xe_lrc *lrc)
#define CONTEXT_ACTIVE XE_LRC_CTX_TIMESTAMP_ACTIVE
static ssize_t setup_utilization_wa(struct xe_lrc *lrc,
struct xe_hw_engine *hwe,
u32 *batch,
size_t max_len)
u32 *batch, size_t max_len, bool indirect)
{
u32 *cmd = batch;
@ -1131,19 +1130,25 @@ static ssize_t setup_utilization_wa(struct xe_lrc *lrc,
}
static ssize_t setup_timestamp_wa(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
u32 *batch, size_t max_len)
u32 *batch, size_t max_len, bool indirect)
{
const u32 ts_addr = __xe_lrc_ctx_timestamp_ggtt_addr(lrc);
u32 *cmd = batch;
if (!XE_GT_WA(lrc->gt, 16010904313) ||
!(hwe->class == XE_ENGINE_CLASS_RENDER ||
hwe->class == XE_ENGINE_CLASS_COMPUTE ||
hwe->class == XE_ENGINE_CLASS_COPY ||
if (!XE_GT_WA(lrc->gt, 16010904313))
return 0;
if (!indirect &&
!(hwe->class == XE_ENGINE_CLASS_COPY ||
hwe->class == XE_ENGINE_CLASS_VIDEO_DECODE ||
hwe->class == XE_ENGINE_CLASS_VIDEO_ENHANCE))
return 0;
if (indirect &&
!(hwe->class == XE_ENGINE_CLASS_RENDER ||
hwe->class == XE_ENGINE_CLASS_COMPUTE))
return 0;
if (xe_gt_WARN_ON(lrc->gt, max_len < 12))
return -ENOSPC;
@ -1169,7 +1174,8 @@ static ssize_t setup_timestamp_wa(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
static ssize_t setup_configfs_post_ctx_restore_bb(struct xe_lrc *lrc,
struct xe_hw_engine *hwe,
u32 *batch, size_t max_len)
u32 *batch, size_t max_len,
bool indirect)
{
struct xe_device *xe = gt_to_xe(lrc->gt);
const u32 *user_batch;
@ -1198,7 +1204,8 @@ static ssize_t setup_configfs_post_ctx_restore_bb(struct xe_lrc *lrc,
static ssize_t setup_configfs_mid_ctx_restore_bb(struct xe_lrc *lrc,
struct xe_hw_engine *hwe,
u32 *batch, size_t max_len)
u32 *batch, size_t max_len,
bool indirect)
{
struct xe_device *xe = gt_to_xe(lrc->gt);
const u32 *user_batch;
@ -1227,7 +1234,8 @@ static ssize_t setup_configfs_mid_ctx_restore_bb(struct xe_lrc *lrc,
static ssize_t setup_invalidate_state_cache_wa(struct xe_lrc *lrc,
struct xe_hw_engine *hwe,
u32 *batch, size_t max_len)
u32 *batch, size_t max_len,
bool indirect)
{
u32 *cmd = batch;
@ -1247,7 +1255,8 @@ static ssize_t setup_invalidate_state_cache_wa(struct xe_lrc *lrc,
static ssize_t setup_invalidate_auxccs_wa(struct xe_lrc *lrc,
struct xe_hw_engine *hwe,
u32 *batch, size_t max_len)
u32 *batch, size_t max_len,
bool indirect)
{
struct xe_gt *gt = lrc->gt;
u32 *(*emit)(struct xe_gt *gt, u32 *cmd) =
@ -1264,7 +1273,7 @@ static ssize_t setup_invalidate_auxccs_wa(struct xe_lrc *lrc,
struct bo_setup {
ssize_t (*setup)(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
u32 *batch, size_t max_size);
u32 *batch, size_t max_size, bool indirect);
};
struct bo_setup_state {
@ -1273,6 +1282,7 @@ struct bo_setup_state {
struct xe_hw_engine *hwe;
size_t max_size;
size_t reserve_dw;
bool indirect;
unsigned int offset;
const struct bo_setup *funcs;
unsigned int num_funcs;
@ -1298,7 +1308,8 @@ static int setup_bo(struct bo_setup_state *state)
for (size_t i = 0; i < state->num_funcs; i++) {
ssize_t len = state->funcs[i].setup(state->lrc, state->hwe,
state->ptr, remain);
state->ptr, remain,
state->indirect);
remain -= len;
@ -1404,6 +1415,7 @@ setup_indirect_ctx(struct xe_lrc *lrc, struct xe_hw_engine *hwe)
struct bo_setup_state state = {
.lrc = lrc,
.hwe = hwe,
.indirect = true,
.max_size = (63 * 64) /* max 63 cachelines */,
.buffer = NULL,
.offset = __xe_lrc_indirect_ctx_offset(lrc),

View File

@ -320,6 +320,7 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)
return (u64)udw << 32 | ldw;
}
#define __XE_MMIO_WAIT_MAX_BACKOFF_100MS (100 * USEC_PER_MSEC)
static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val,
u32 timeout_us, u32 *out_val, bool atomic, bool expect_match)
{
@ -350,10 +351,10 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
wait = ktime_us_delta(end, cur);
if (atomic)
udelay(wait);
udelay(min_t(s64, wait, (MAX_UDELAY_MS * 1000)));
else
usleep_range(wait, wait << 1);
wait <<= 1;
wait = min_t(s64, wait << 1, __XE_MMIO_WAIT_MAX_BACKOFF_100MS);
}
if (ret != 0) {

View File

@ -19,20 +19,20 @@
#include "xe_sysctrl_mailbox_types.h"
struct xe_sysctrl_mailbox_msg_hdr {
__le32 data;
} __packed;
u32 data;
};
#define XE_SYSCTRL_HDR_GROUP_ID(hdr) \
FIELD_GET(SYSCTRL_HDR_GROUP_ID_MASK, le32_to_cpu((hdr)->data))
FIELD_GET(SYSCTRL_HDR_GROUP_ID_MASK, (hdr)->data)
#define XE_SYSCTRL_HDR_COMMAND(hdr) \
FIELD_GET(SYSCTRL_HDR_COMMAND_MASK, le32_to_cpu((hdr)->data))
FIELD_GET(SYSCTRL_HDR_COMMAND_MASK, (hdr)->data)
#define XE_SYSCTRL_HDR_IS_RESPONSE(hdr) \
FIELD_GET(SYSCTRL_HDR_IS_RESPONSE, le32_to_cpu((hdr)->data))
FIELD_GET(SYSCTRL_HDR_IS_RESPONSE, (hdr)->data)
#define XE_SYSCTRL_HDR_RESULT(hdr) \
FIELD_GET(SYSCTRL_HDR_RESULT_MASK, le32_to_cpu((hdr)->data))
FIELD_GET(SYSCTRL_HDR_RESULT_MASK, (hdr)->data)
static bool sysctrl_wait_bit_clear(struct xe_sysctrl *sc, u32 bit_mask,
unsigned int timeout_ms)
@ -126,8 +126,8 @@ static int sysctrl_prepare_command(struct xe_device *xe,
return -ENOMEM;
hdr = (struct xe_sysctrl_mailbox_msg_hdr *)buffer;
hdr->data = cpu_to_le32(FIELD_PREP(SYSCTRL_HDR_GROUP_ID_MASK, group_id) |
FIELD_PREP(SYSCTRL_HDR_COMMAND_MASK, command));
hdr->data = FIELD_PREP(SYSCTRL_HDR_GROUP_ID_MASK, group_id) |
FIELD_PREP(SYSCTRL_HDR_COMMAND_MASK, command);
if (data_in && data_in_len)
memcpy(buffer + sizeof(*hdr), data_in, data_in_len);

View File

@ -79,7 +79,7 @@ static inline u32 hv_ring_gpadl_send_hvpgoffset(u32 offset)
* therefore leaving a (PAGE_SIZE - HV_HYP_PAGE_SIZE) gap.
*
* And to calculate the effective send offset in gpadl, we need to
* substract this gap.
* subtract this gap.
*/
return (offset - (PAGE_SIZE - HV_HYP_PAGE_SIZE)) >> HV_HYP_PAGE_SHIFT;
}

View File

@ -752,13 +752,14 @@ static void init_vp_index(struct vmbus_channel *channel)
u32 i, ncpu = num_online_cpus();
cpumask_var_t available_mask;
struct cpumask *allocated_mask;
const struct cpumask *node_mask;
const struct cpumask *hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
u32 target_cpu;
int numa_node;
if (!perf_chn ||
!alloc_cpumask_var(&available_mask, GFP_KERNEL) ||
cpumask_empty(hk_mask)) {
!cpumask_intersects(hk_mask, cpu_online_mask)) {
/*
* If the channel is not a performance critical
* channel, bind it to VMBUS_CONNECT_CPU.
@ -780,14 +781,19 @@ static void init_vp_index(struct vmbus_channel *channel)
next_numa_node_id = 0;
continue;
}
if (cpumask_empty(cpumask_of_node(numa_node)))
/*
* Try next NUMA node if current NUMA node has no CPU
* or doesn't contain any housekeeping CPU.
*/
node_mask = cpumask_of_node(numa_node);
if (!cpumask_intersects(node_mask, hk_mask))
continue;
break;
}
allocated_mask = &hv_context.hv_numa_map[numa_node];
retry:
cpumask_xor(available_mask, allocated_mask, cpumask_of_node(numa_node));
cpumask_xor(available_mask, allocated_mask, node_mask);
cpumask_and(available_mask, available_mask, hk_mask);
if (cpumask_empty(available_mask)) {

View File

@ -346,7 +346,6 @@ int vmbus_connect(void)
cleanup:
pr_err("Unable to connect to host\n");
vmbus_connection.conn_state = DISCONNECTED;
vmbus_disconnect();
kfree(msginfo);

View File

@ -819,6 +819,9 @@ static vm_fault_t mshv_vtl_fault(struct vm_fault *vmf)
return VM_FAULT_NOPAGE;
}
if (!page)
return VM_FAULT_SIGBUS;
get_page(page);
vmf->page = page;

View File

@ -2923,23 +2923,19 @@ static void hv_crash_handler(struct pt_regs *regs)
static int hv_synic_suspend(void *data)
{
/*
* When we reach here, all the non-boot CPUs have been offlined.
* If we're in a legacy configuration where stimer Direct Mode is
* not enabled, the stimers on the non-boot CPUs have been unbound
* in hv_synic_cleanup() -> hv_stimer_legacy_cleanup() ->
* hv_stimer_cleanup() -> clockevents_unbind_device().
* When we reach here, all the non-boot CPUs have been offlined,
* and their stimers have been cleaned up by the cpuhp teardown
* callback hv_stimer_cleanup().
*
* hv_synic_suspend() only runs on CPU0 with interrupts disabled.
* Here we do not call hv_stimer_legacy_cleanup() on CPU0 because:
* 1) it's unnecessary as interrupts remain disabled between
* syscore_suspend() and syscore_resume(): see create_image() and
* The stimer on CPU0 is not explicitly cleaned up here because:
* 1) it's harmless as interrupts remain disabled between
* syscore_suspend() and syscore_resume(), so the stimer cannot
* fire during this window: see create_image() and
* resume_target_kernel()
* 2) the stimer on CPU0 is automatically disabled later by
* syscore_suspend() -> timekeeping_suspend() -> tick_suspend() -> ...
* -> clockevents_shutdown() -> ... -> hv_ce_shutdown()
* 3) a warning would be triggered if we call
* clockevents_unbind_device(), which may sleep, in an
* interrupts-disabled context.
*/
hv_hyp_synic_disable_regs(0);
@ -3043,7 +3039,6 @@ static void __exit vmbus_exit(void)
hv_remove_kexec_handler();
hv_remove_crash_handler();
vmbus_connection.conn_state = DISCONNECTED;
hv_stimer_global_cleanup();
vmbus_disconnect();
if (vmbus_irq == -1)

View File

@ -1003,13 +1003,14 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
ret = gi2c->dev_data->set_rate(&gi2c->se, gi2c->clk_freq_out);
if (ret)
return ret;
goto out_pm;
if (gi2c->gpi_mode)
ret = geni_i2c_gpi_xfer(gi2c, msgs, num);
else
ret = geni_i2c_fifo_xfer(gi2c, msgs, num);
out_pm:
pm_runtime_put_autosuspend(gi2c->se.dev);
gi2c->cur = NULL;
gi2c->err = 0;

View File

@ -302,6 +302,8 @@ static const struct xpad_device {
{ 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 },
{ 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 },
{ 0x1a86, 0xe310, "Legion Go S", 0, XTYPE_XBOX360 },
{ 0x1b1c, 0x2b1f, "Corsair Novablade Pro (Wired)", 0, XTYPE_XBOX360 },
{ 0x1b1c, 0x2b2b, "Corsair Novablade Pro (2.4 GHz Receiver)", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
@ -379,6 +381,7 @@ static const struct xpad_device {
{ 0x2993, 0x2001, "TECNO Pocket Go", 0, XTYPE_XBOX360 },
{ 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
{ 0x2dc8, 0x200f, "8BitDo Ultimate 3-mode Controller for Xbox", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
{ 0x2dc8, 0x201e, "8BitDo Pro 2 Wired Controller for Xbox", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
{ 0x2dc8, 0x3106, "8BitDo Ultimate Wireless / Pro 2 Wired Controller", 0, XTYPE_XBOX360 },
{ 0x2dc8, 0x3109, "8BitDo Ultimate Wireless Bluetooth", 0, XTYPE_XBOX360 },
{ 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 },
@ -545,6 +548,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */
XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */
XPAD_XBOX360_VENDOR(0x1a86), /* Nanjing Qinheng Microelectronics (WCH) */
XPAD_XBOX360_VENDOR(0x1b1c), /* Corsair controllers */
XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */
XPAD_XBOX360_VENDOR(0x1ee9), /* ZOTAC Technology Limited */
XPAD_XBOX360_VENDOR(0x20bc), /* BETOP wireless dongles */

View File

@ -672,8 +672,7 @@ static ssize_t ati_remote2_show_channel_mask(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct usb_device *udev = to_usb_device(dev);
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
struct usb_interface *intf = to_usb_interface(dev);
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
return sprintf(buf, "0x%04x\n", ar2->channel_mask);
@ -683,8 +682,7 @@ static ssize_t ati_remote2_store_channel_mask(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
struct usb_interface *intf = to_usb_interface(dev);
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
unsigned int mask;
int r;
@ -720,8 +718,7 @@ static ssize_t ati_remote2_show_mode_mask(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct usb_device *udev = to_usb_device(dev);
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
struct usb_interface *intf = to_usb_interface(dev);
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
return sprintf(buf, "0x%02x\n", ar2->mode_mask);
@ -731,8 +728,7 @@ static ssize_t ati_remote2_store_mode_mask(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
struct usb_interface *intf = to_usb_interface(dev);
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
unsigned int mask;
int err;

View File

@ -1228,9 +1228,9 @@ dma_addr_t iommu_dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
* If both the physical buffer start address and size are page aligned,
* we don't need to use a bounce page.
*/
if (dev_use_swiotlb(dev, size, dir) &&
if (!(attrs & DMA_ATTR_MMIO) && dev_use_swiotlb(dev, size, dir) &&
iova_unaligned(iovad, phys, size)) {
if (attrs & (DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT))
if (attrs & DMA_ATTR_REQUIRE_COHERENT)
return DMA_MAPPING_ERROR;
phys = iommu_dma_map_swiotlb(dev, phys, size, dir, attrs);

View File

@ -2416,7 +2416,7 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
if (video_is_registered(&v4l2->radio_dev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->radio_dev));
vb2_video_unregister_device(&v4l2->radio_dev);
video_unregister_device(&v4l2->radio_dev);
}
if (video_is_registered(&v4l2->vbi_dev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
@ -3082,7 +3082,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
dev_info(&dev->intf->dev,
"V4L2 device %s deregistered\n",
video_device_node_name(&v4l2->radio_dev));
vb2_video_unregister_device(&v4l2->radio_dev);
video_unregister_device(&v4l2->radio_dev);
}
if (video_is_registered(&v4l2->vbi_dev)) {
dev_info(&dev->intf->dev,

View File

@ -370,9 +370,7 @@ int memstick_set_rw_addr(struct memstick_dev *card)
{
card->next_request = h_memstick_set_rw_addr;
memstick_new_req(card->host);
if (!wait_for_completion_timeout(&card->mrq_complete,
msecs_to_jiffies(500)))
card->current_mrq.error = -ETIMEDOUT;
wait_for_completion(&card->mrq_complete);
return card->current_mrq.error;
}
@ -405,9 +403,7 @@ static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
card->next_request = h_memstick_read_dev_id;
memstick_new_req(host);
if (!wait_for_completion_timeout(&card->mrq_complete,
msecs_to_jiffies(500)))
card->current_mrq.error = -ETIMEDOUT;
wait_for_completion(&card->mrq_complete);
if (card->current_mrq.error)
goto err_out;

View File

@ -27,7 +27,6 @@ struct rtsx_usb_ms {
struct memstick_host *msh;
struct memstick_request *req;
struct mutex host_mutex;
struct work_struct handle_req;
struct delayed_work poll_card;
@ -514,6 +513,13 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work)
struct memstick_host *msh = host->msh;
int rc;
/* Fail requests after eject so their waiters are released. */
if (host->eject) {
while (!memstick_next_req(msh, &host->req))
host->req->error = -ENOMEDIUM;
return;
}
if (!host->req) {
pm_runtime_get_sync(ms_dev(host));
do {
@ -547,8 +553,7 @@ static void rtsx_usb_ms_request(struct memstick_host *msh)
dev_dbg(ms_dev(host), "--> %s\n", __func__);
if (!host->eject)
schedule_work(&host->handle_req);
schedule_work(&host->handle_req);
}
static int rtsx_usb_ms_set_param(struct memstick_host *msh,
@ -781,7 +786,6 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev)
host->power_mode = MEMSTICK_POWER_OFF;
platform_set_drvdata(pdev, host);
mutex_init(&host->host_mutex);
INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req);
INIT_DELAYED_WORK(&host->poll_card, rtsx_usb_ms_poll_card);
@ -812,27 +816,12 @@ static void rtsx_usb_ms_drv_remove(struct platform_device *pdev)
{
struct rtsx_usb_ms *host = platform_get_drvdata(pdev);
struct memstick_host *msh = host->msh;
int err;
host->eject = true;
msh->removing = true;
cancel_work_sync(&host->handle_req);
flush_work(&host->handle_req);
cancel_delayed_work_sync(&host->poll_card);
mutex_lock(&host->host_mutex);
if (host->req) {
dev_dbg(ms_dev(host),
"%s: Controller removed during transfer\n",
dev_name(&msh->dev));
host->req->error = -ENOMEDIUM;
do {
err = memstick_next_req(msh, &host->req);
if (!err)
host->req->error = -ENOMEDIUM;
} while (!err);
}
mutex_unlock(&host->host_mutex);
/* Balance possible unbalanced usage count
* e.g. unconditional module removal
*/
@ -841,6 +830,8 @@ static void rtsx_usb_ms_drv_remove(struct platform_device *pdev)
pm_runtime_disable(ms_dev(host));
memstick_remove_host(msh);
/* No card, no new requests; wait for the last failed one to finish. */
cancel_work_sync(&host->handle_req);
dev_dbg(ms_dev(host),
": Realtek USB Memstick controller has been removed\n");
memstick_free_host(msh);

View File

@ -295,9 +295,12 @@ static void octeon_mmc_remove(struct platform_device *pdev)
u64 dma_cfg;
int i;
for (i = 0; i < CAVIUM_MAX_MMC; i++)
for (i = 0; i < CAVIUM_MAX_MMC; i++) {
if (host->slot[i])
cvm_mmc_of_slot_remove(host->slot[i]);
if (host->slot_pdev[i])
of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
}
dma_cfg = readq(host->dma_base + MIO_EMM_DMA_CFG(host));
dma_cfg &= ~MIO_EMM_DMA_CFG_EN;

View File

@ -173,9 +173,12 @@ static void thunder_mmc_remove(struct pci_dev *pdev)
u64 dma_cfg;
int i;
for (i = 0; i < CAVIUM_MAX_MMC; i++)
for (i = 0; i < CAVIUM_MAX_MMC; i++) {
if (host->slot[i])
cvm_mmc_of_slot_remove(host->slot[i]);
if (host->slot_pdev[i])
of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
}
dma_cfg = readq(host->dma_base + MIO_EMM_DMA_CFG(host));
dma_cfg &= ~MIO_EMM_DMA_CFG_EN;

View File

@ -3216,6 +3216,7 @@ static void msdc_drv_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
mmc_remove_host(mmc);
cancel_delayed_work_sync(&host->req_timeout);
msdc_deinit_hw(host);
msdc_gate_clock(host);

View File

@ -890,6 +890,10 @@ static void sdhci_sprd_remove(struct platform_device *pdev)
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
sdhci_remove_host(host, 0);
clk_disable_unprepare(sprd_host->clk_sdio);

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