ASoC: tegra: Support auxiliary devices

Svyatoslav Ryhel <clamor95@gmail.com> says:

Add support for auxiliary devices, such as amplifiers, sound-muxes or dsp,
to be added to the sound card.

Link: https://patch.msgid.link/20261013180253.477605-1-clamor95@gmail.com
This commit is contained in:
Mark Brown 2026-10-13 19:25:00 +01:00
commit bce34abda5
No known key found for this signature in database
GPG Key ID: 2FEF73B0B3D03889
396 changed files with 10812 additions and 1760 deletions

View File

@ -101,6 +101,7 @@ Andy Chiu <andybnac@gmail.com> <andy.chiu@sifive.com>
Andy Chiu <andybnac@gmail.com> <taochiu@synology.com>
Andy Shevchenko <andy@kernel.org> <andy@smile.org.ua>
Andy Shevchenko <andy@kernel.org> <ext-andriy.shevchenko@nokia.com>
Andy Yan <andyshrk@163.com> <andy.yan@rock-chips.com>
Anilkumar Kolli <quic_akolli@quicinc.com> <akolli@codeaurora.org>
Anirudh Ghayal <quic_aghayal@quicinc.com> <aghayal@codeaurora.org>
Antoine Tenart <atenart@kernel.org> <antoine.tenart@bootlin.com>
@ -461,7 +462,8 @@ Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
John Crispin <john@phrozen.org> <blogic@openwrt.org>
John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
John Garry <john.g.garry@oracle.com> <john.garry@huawei.com>
John Garry <john.garry@linux.dev> <john.garry@huawei.com>
John Garry <john.garry@linux.dev> <john.g.garry@oracle.com>
John Keeping <john@keeping.me.uk> <john@metanate.com>
John Moon <john@jmoon.dev> <quic_johmoo@quicinc.com>
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
@ -486,6 +488,7 @@ Juha Yrjola <juha.yrjola@nokia.com>
Juha Yrjola <juha.yrjola@solidboot.com>
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
Justin Iurman <justin.iurman@gmail.com> <justin.iurman@uliege.be>
Imre Kaloz <kaloz@kernel.org> <kaloz@openwrt.org>
Ira Weiny <iweiny@kernel.org> <ira.weiny@intel.com>
Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com>
Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org>

View File

@ -172,7 +172,8 @@ When mounting an ext4 filesystem, the following option are accepted:
data=journal
All data are committed into the journal prior to being written into the
main file system. Enabling this mode will disable delayed allocation
and O_DIRECT support.
and O_DIRECT support. This feature is deprecated and support
will be removed in January 2028.
data=ordered (*)
All data are forced directly out to the main file system prior to its
@ -418,7 +419,8 @@ There are 3 different data modes:
consistent state. This mode is the slowest except when data needs to be read
from and written to disk at the same time where it outperforms all others
modes. Enabling this mode will disable delayed allocation and O_DIRECT
support.
support. The data=journal feature is deprecated and support will be
removed in January 2028.
/proc entries
=============

View File

@ -48,6 +48,11 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of audio codec
nvidia,aux-devs:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: List of phandles pointing to auxiliary devices,
such as amplifiers or dsp, to be added to the sound card.
nvidia,spkr-en-gpios:
maxItems: 1
description: The GPIO that enables the speakers

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

@ -77,7 +77,7 @@ Functions
strp_done is called to release any resources held by the stream
parser instance. This must be called after the stream processor
has been stopped.
has been stopped. The socket lock must not be held.
::

View File

@ -3020,7 +3020,7 @@ F: arch/arm/boot/dts/ti/omap/omap3-igep*
ARM/INTEL IXP4XX ARM ARCHITECTURE
M: Linus Walleij <linusw@kernel.org>
M: Imre Kaloz <kaloz@openwrt.org>
M: Imre Kaloz <kaloz@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
@ -9876,7 +9876,7 @@ L: linux-ext4@vger.kernel.org
S: Maintained
W: http://ext4.wiki.kernel.org
Q: http://patchwork.ozlabs.org/project/linux-ext4/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev
F: Documentation/filesystems/ext4/
F: fs/ext4/
F: include/trace/events/ext4.h

View File

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

View File

@ -1602,7 +1602,7 @@ esdhc0_clksync_pins: iic5-sdhc-clk-pins {
};
dspi2_miso_mosi_pins: iic5-spi3-pins {
pinctrl-single,bits = <0x3 (0x2 << 9) (0x7 << 9)>;
pinctrl-single,bits = <0x0 (0x3 << 9) (0x7 << 9)>;
};
i2c5_pins: iic6-i2c-pins {
@ -1622,7 +1622,7 @@ fspi_data74_pins: xspi1-data74-pins {
};
gpio1_31_28_pins: xspi1-data74-gpio-pins {
pinctrl-single,bits = <0x0 0x1 (0x7 << 15)>;
pinctrl-single,bits = <0x0 (0x1 << 15) (0x7 << 15)>;
};
fspi_data30_pins: xspi1-data30-pins {
@ -1630,7 +1630,7 @@ fspi_data30_pins: xspi1-data30-pins {
};
gpio1_27_24_pins: xspi1-data30-gpio-pins {
pinctrl-single,bits = <0x0 0x1 (0x7 << 18)>;
pinctrl-single,bits = <0x0 (0x1 << 18) (0x7 << 18)>;
};
fspi_dqs_sck_cs10_pins: xspi1-base-pins {
@ -1638,7 +1638,7 @@ fspi_dqs_sck_cs10_pins: xspi1-base-pins {
};
gpio1_23_20_pins: xspi1-base-gpio-pins {
pinctrl-single,bits = <0x0 0x1 (0x7 << 21)>;
pinctrl-single,bits = <0x0 (0x1 << 21) (0x7 << 21)>;
};
esdhc0_cmd_data30_clk_vsel_pins: sdhc1-base-sdhc-vsel-pins {
@ -1687,12 +1687,19 @@ i2c6_i2c7_pins: iic8-iic7-i2c-pins {
};
/* RCWSR14 */
/*
* IIC1_PMUX is a single bit at RCWSR14[10], but bit-per-mux
* uses the mask for the field to clear before applying the
* value.
* So bits 11 and 12, which are reserved, are written as 0
* on every mux switch, it is harmless.
*/
i2c0_pins: iic1-i2c-pins {
pinctrl-single,bits = <0x8 0x0 (0x1 << 10)>;
pinctrl-single,bits = <0x8 0x0 (0x7 << 10)>;
};
gpio0_3_2_pins: iic1-gpio-pins {
pinctrl-single,bits = <0x8 (0x1 << 10) (0x1 << 10)>;
pinctrl-single,bits = <0x8 (0x1 << 10) (0x7 << 10)>;
};
};

View File

@ -511,6 +511,7 @@ &usdhc2 {
pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
vmmc-supply = <&reg_usdhc2_vmmc>;
vqmmc-supply = <&ldo5>;
bus-width = <4>;
status = "okay";
};

View File

@ -863,11 +863,11 @@ spkr_01_sd_n_active: spkr-01-sd-n-active-state {
};
&lpass_vamacro {
pinctrl-0 = <&dmic01_default>, <&dmic23_default>;
pinctrl-0 = <&dmic01_default>;
pinctrl-names = "default";
vdd-micb-supply = <&vreg_l1b_1p8>;
qcom,dmic-sample-rate = <4800000>;
qcom,dmic-sample-rate = <2400000>;
};
&mdss {

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

@ -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

@ -209,6 +209,7 @@ static int raw_verify_header(
if ((vheader->flags & VIRTIO_NET_HDR_F_DATA_VALID) > 0)
return 1;
skb_set_network_header(skb, ETH_HLEN);
virtio_net_hdr_to_skb(skb, vheader, virtio_legacy_is_little_endian());
return 0;
}

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

@ -62,14 +62,50 @@ static void braille_write(u16 *buf)
{
static u16 lastwrite[WIDTH];
unsigned char data[1 + 1 + 2*WIDTH + 2 + 1], csum = 0, *c;
struct nbcon_write_context wctxt = { };
unsigned long flags;
u16 out;
int i;
if (!braille_co)
return;
/*
* Braille console is not registered in console_list. Instead, it
* is integrated with VT and shows what appears on the graphical
* console under console_lock(). From this POV it is a legacy
* console. But it calls serial console driver which might be
* converted to the NBCON API. It is similar to
* nbcon_legacy_emit_next_record() except that we should try
* harder to get the lock. Otherwise, the Braille device won't show
* everything what is displayed on the terminal.
*
* In short, simulate the original locking using NBCON API.
*/
if (braille_co->flags & CON_NBCON) {
if (panic_on_this_cpu()) {
/*
* This should be good enough in practice. Most/all
* serial console drivers have the atomic callback.
*/
if (!braille_co->write_atomic)
return;
local_irq_save(flags);
/* NBCON API strictly requires the ownership. */
if (!nbcon_braille_try_acquire(braille_co, &wctxt)) {
local_irq_restore(flags);
return;
}
} else {
braille_co->device_lock(braille_co, &flags);
while (!nbcon_braille_try_acquire(braille_co, &wctxt))
cpu_relax();
}
}
if (!memcmp(lastwrite, buf, WIDTH * sizeof(*buf)))
return;
goto unlock_nbcon;
memcpy(lastwrite, buf, WIDTH * sizeof(*buf));
#define SOH 1
@ -102,7 +138,24 @@ static void braille_write(u16 *buf)
*c++ = csum;
*c++ = ETX;
braille_co->write(braille_co, data, c - data);
if (braille_co->flags & CON_NBCON) {
nbcon_write_context_set_buf(&wctxt, (char *)data, c - data);
if (panic_on_this_cpu())
braille_co->write_atomic(braille_co, &wctxt);
else
braille_co->write_thread(braille_co, &wctxt);
} else {
braille_co->write(braille_co, data, c - data);
}
unlock_nbcon:
if (braille_co->flags & CON_NBCON) {
nbcon_braille_release(&wctxt);
if (panic_on_this_cpu())
local_irq_restore(flags);
else
braille_co->device_unlock(braille_co, flags);
}
}
/* Follow the VC cursor*/

View File

@ -3059,10 +3059,15 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
qc->dev->sdev->locked = 0;
if (cmd->result)
ata_scsi_qc_done(qc, false, 0);
else
ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION);
/*
* Report CHECK CONDITION unless the command was terminated
* with a host byte set. Only set the status byte, so that the
* SCSI midlayer internal byte, which scsi_check_sense() may
* have set from the sense data, is preserved.
*/
if (get_host_byte(cmd) == DID_OK)
set_status_byte(cmd, SAM_STAT_CHECK_CONDITION);
ata_scsi_qc_done(qc, false, 0);
goto schedule_deferred;
}

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

@ -401,7 +401,7 @@ static int btintel_pcie_send_sync(struct btintel_pcie_data *data,
tfd_index = data->ia.tr_hia[BTINTEL_PCIE_TXQ_NUM];
if (tfd_index > txq->count)
if (tfd_index >= txq->count)
return -ERANGE;
if (skb->len > BTINTEL_PCIE_BUFFER_SIZE - BTINTEL_PCIE_HCI_TYPE_LEN) {
@ -1777,7 +1777,7 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id)
static int btintel_pcie_setup_irq(struct btintel_pcie_data *data)
{
int err;
int num_irqs, i;
int num_irqs, i, j;
for (i = 0; i < BTINTEL_PCIE_MSIX_VEC_MAX; i++)
data->msix_entries[i].entry = i;
@ -1806,6 +1806,10 @@ static int btintel_pcie_setup_irq(struct btintel_pcie_data *data)
KBUILD_MODNAME,
msix_entry);
if (err) {
for (j = 0; j < i; j++)
devm_free_irq(&data->pdev->dev,
data->msix_entries[j].vector,
&data->msix_entries[j]);
pci_free_irq_vectors(data->pdev);
data->alloc_vecs = 0;
return err;
@ -1877,6 +1881,13 @@ static int btintel_pcie_config_pcie(struct pci_dev *pdev,
if (IS_ERR(data->base_addr))
return PTR_ERR(data->base_addr);
/* Do shared hardware reset to ensure a clean start before
* configuring interrupts.
*/
err = btintel_pcie_reset_bt(data);
if (err)
return err;
err = btintel_pcie_setup_irq(data);
if (err)
return err;
@ -3138,7 +3149,7 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
struct msix_entry *msix_entry;
msix_entry = &data->msix_entries[i];
free_irq(msix_entry->vector, msix_entry);
devm_free_irq(&pdev->dev, msix_entry->vector, msix_entry);
}
pci_free_irq_vectors(pdev);

View File

@ -503,7 +503,7 @@ static int mmap_zero_prepare(struct vm_area_desc *desc)
#ifndef CONFIG_MMU
return -ENOSYS;
#endif
if (vma_desc_test(desc, VMA_SHARED_BIT))
if (vma_desc_test(desc, VMA_MAYSHARE_BIT))
return shmem_zero_setup_desc(desc);
/*

View File

@ -3010,8 +3010,6 @@ static const u32 gcc_eliza_critical_cbcrs[] = {
0x26034, /* GCC_CAMERA_XO_CLK */
0x27004, /* GCC_DISP_AHB_CLK */
0x71004, /* GCC_GPU_CFG_AHB_CLK */
0x52010, /* GCC_PCIE_RSCC_CFG_AHB_CLK */
0x52010, /* GCC_PCIE_RSCC_XO_CLK */
0x32004, /* GCC_VIDEO_AHB_CLK */
0x32038, /* GCC_VIDEO_XO_CLK */
};
@ -3045,6 +3043,10 @@ static const struct regmap_config gcc_eliza_regmap_config = {
static void clk_eliza_regs_configure(struct device *dev, struct regmap *regmap)
{
/* Keep clocks always enabled */
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); /* GCC_PCIE_RSCC_CFG_AHB_CLK */
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); /* GCC_PCIE_RSCC_XO_CLK */
/* FORCE_MEM_CORE_ON for ufs phy ice core and gcc ufs phy axi clocks */
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_axi_clk, true);

View File

@ -3692,8 +3692,6 @@ static const u32 gcc_hawi_critical_cbcrs[] = {
0x67084, /* GCC_PCIE_1_RSC_CORE_CLK */
0x43014, /* GCC_PCIE_LINK_XO_CLK */
0x6b088, /* GCC_PCIE_RSC_CORE_CLK */
0x52010, /* GCC_PCIE_RSCC_CFG_AHB_CLK */
0x52010, /* GCC_PCIE_RSCC_XO_CLK */
0x32004, /* GCC_VIDEO_AHB_CLK */
0x32028, /* GCC_VIDEO_XO_CLK */
};
@ -3763,6 +3761,10 @@ static const struct regmap_config gcc_hawi_regmap_config = {
static void clk_hawi_regs_configure(struct device *dev, struct regmap *regmap)
{
/* Keep clocks always enabled */
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); /* GCC_PCIE_RSCC_CFG_AHB_CLK */
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); /* GCC_PCIE_RSCC_XO_CLK */
/* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
}

View File

@ -3464,8 +3464,6 @@ static const u32 gcc_kaanapali_critical_cbcrs[] = {
0x9f004, /* GCC_EVA_AHB_CLK */
0x9f024, /* GCC_EVA_XO_CLK */
0x71004, /* GCC_GPU_CFG_AHB_CLK */
0x52010, /* GCC_PCIE_RSCC_CFG_AHB_CLK */
0x52010, /* GCC_PCIE_RSCC_XO_CLK */
0x32004, /* GCC_VIDEO_AHB_CLK */
0x32040, /* GCC_VIDEO_XO_CLK */
};
@ -3480,6 +3478,10 @@ static const struct regmap_config gcc_kaanapali_regmap_config = {
static void clk_kaanapali_regs_configure(struct device *dev, struct regmap *regmap)
{
/* Keep clocks always enabled */
regmap_update_bits(regmap, 0x52010, BIT(20), BIT(20)); /* GCC_PCIE_RSCC_CFG_AHB_CLK */
regmap_update_bits(regmap, 0x52010, BIT(21), BIT(21)); /* GCC_PCIE_RSCC_XO_CLK */
/* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
}

View File

@ -510,7 +510,7 @@ static struct gdsc gpu_cc_cx_gdsc = {
.name = "gpu_cc_cx_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
.flags = RETAIN_FF_ENABLE | VOTABLE,
};
static struct clk_regmap *gpu_cc_glymur_clocks[] = {

View File

@ -380,7 +380,7 @@ static struct gdsc gpu_cc_cx_gdsc = {
.name = "gpu_cc_cx_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
.flags = RETAIN_FF_ENABLE | VOTABLE,
};
static struct clk_regmap *gpu_cc_kaanapali_clocks[] = {

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

@ -199,6 +199,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
index = ida_alloc(&ida_index, GFP_KERNEL);
if (index < 0)
return index;
exar_gpio->index = index;
ret = devm_add_action_or_reset(dev, exar_devm_ida_free, exar_gpio);
if (ret)
@ -214,7 +215,6 @@ static int gpio_exar_probe(struct platform_device *pdev)
exar_gpio->gpio_chip.set = exar_set_value;
exar_gpio->gpio_chip.base = -1;
exar_gpio->gpio_chip.ngpio = ngpios;
exar_gpio->index = index;
exar_gpio->first_pin = first_pin;
ret = devm_gpiochip_add_data(dev, &exar_gpio->gpio_chip, exar_gpio);

View File

@ -10,6 +10,7 @@
#include <linux/cleanup.h>
#include <linux/gpio/driver.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
@ -24,6 +25,7 @@ struct mpsse_priv {
raw_spinlock_t irq_spin; /* protects worker list */
atomic_t irq_type[16]; /* pin -> edge detection type */
atomic_t irq_enabled;
atomic_t dying; /* no new workers after disconnect */
int id;
u8 gpio_outputs[2]; /* Output states for GPIOs [L, H] */
@ -46,6 +48,7 @@ struct mpsse_worker {
atomic_t cancelled;
struct list_head list; /* linked list */
struct list_head destroy; /* teardown linked list */
struct rcu_head rcu; /* deferred free for dying path */
};
struct bulk_desc {
@ -525,10 +528,24 @@ static void gpio_mpsse_irq_enable(struct irq_data *irqd)
worker->priv = priv;
INIT_LIST_HEAD(&worker->list);
INIT_WORK(&worker->work, gpio_mpsse_poll);
schedule_work(&worker->work);
scoped_guard(raw_spinlock_irqsave, &priv->irq_spin)
scoped_guard(raw_spinlock_irqsave, &priv->irq_spin) {
if (atomic_read(&priv->dying)) {
/*
* Cannot kfree() here: this callback
* runs with the IRQ descriptor's raw
* spinlock held and kfree() may sleep
* on PREEMPT_RT. The worker is not
* yet published, so the deferred free
* is unobservable.
*/
kfree_rcu(worker, rcu);
return;
}
list_add(&worker->list, &priv->workers);
schedule_work(&worker->work);
}
}
}
@ -704,6 +721,9 @@ static void gpio_mpsse_disconnect(struct usb_interface *intf)
{
struct mpsse_priv *priv = usb_get_intfdata(intf);
scoped_guard(raw_spinlock_irqsave, &priv->irq_spin)
atomic_set(&priv->dying, 1);
/*
* Lock prevents double-free of worker from here and the teardown
* step at the beginning of gpio_mpsse_poll

View File

@ -271,14 +271,7 @@ static void xgpio_save_regs(struct xgpio_instance *chip)
static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
{
int ret;
ret = pm_runtime_get_sync(chip->parent);
/*
* If the device is already active pm_runtime_get() will return 1 on
* success, but gpio_request still needs to return 0.
*/
return ret < 0 ? ret : 0;
return pm_runtime_resume_and_get(chip->parent);
}
static void xgpio_free(struct gpio_chip *chip, unsigned int offset)

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

@ -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

@ -2894,8 +2894,13 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
}
}
if (*ivmode && !strcmp(*ivmode, "lmk"))
if (*ivmode && !strcmp(*ivmode, "lmk")) {
if (crypt_integrity_aead(cc)) {
ti->error = "AEAD transforms not supported for LMK";
return -EINVAL;
}
cc->tfms_count = 64;
}
if (*ivmode && !strcmp(*ivmode, "essiv")) {
if (!*ivopts) {

View File

@ -180,6 +180,7 @@ struct dm_integrity_c {
struct dm_bufio_client *bufio;
struct workqueue_struct *metadata_wq;
struct superblock *sb;
struct superblock *sb_copy;
unsigned int journal_pages;
unsigned int n_bitmap_blocks;
@ -2721,7 +2722,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w)
outgoing_data = dio->integrity_payload + PAGE_SIZE;
while (dio->bio_details.bi_iter.bi_size) {
char digest[HASH_MAX_DIGESTSIZE];
char digest[MAX_T(size_t, HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
int r;
struct bio_integrity_payload *bip;
struct bio_vec bv;
@ -2788,7 +2789,7 @@ static inline bool dm_integrity_check(struct dm_integrity_c *ic, struct dm_integ
unsigned pos = 0;
while (dio->bio_details.bi_iter.bi_size) {
char digest[HASH_MAX_DIGESTSIZE];
char digest[MAX_T(size_t, HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
struct bio_vec bv = bio_iter_iovec(bio, dio->bio_details.bi_iter);
char *mem = integrity_kmap(ic, bv.bv_page);
integrity_sector_checksum(ic, &dio->ahash_req, dio->bio_details.bi_iter.bi_sector, mem, bv.bv_offset, digest);
@ -3858,6 +3859,35 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
ic->journal_uptodate = true;
}
/*
* The superblock is re-read from the device on every resume, so that we pick
* up the flags and the recalculate position. The geometry described by the
* superblock must not change though - the in-memory structures (and the
* journal in particular) were sized according to the superblock that was
* validated in the constructor. Reject a superblock that was modified behind
* our back.
*
* Only the fields that the driver never rewrites may be tested here. In
* particular, "version" is recalculated by sb_set_version on every superblock
* write and it depends on SB_FLAG_RECALCULATING and SB_FLAG_DIRTY_BITMAP, and
* SB_FLAG_DISCARD_KEYED may be set by dm_integrity_resume itself.
*/
static bool superblock_changed(struct dm_integrity_c *ic)
{
const __le32 immutable_flags = cpu_to_le32(SB_FLAG_HAVE_JOURNAL_MAC |
SB_FLAG_FIXED_PADDING |
SB_FLAG_FIXED_HMAC |
SB_FLAG_INLINE);
return memcmp(ic->sb->magic, ic->sb_copy->magic, sizeof(ic->sb->magic)) != 0 ||
ic->sb->log2_interleave_sectors != ic->sb_copy->log2_interleave_sectors ||
ic->sb->integrity_tag_size != ic->sb_copy->integrity_tag_size ||
ic->sb->journal_sections != ic->sb_copy->journal_sections ||
ic->sb->log2_sectors_per_block != ic->sb_copy->log2_sectors_per_block ||
((ic->sb->flags ^ ic->sb_copy->flags) & immutable_flags) != 0 ||
memcmp(ic->sb->salt, ic->sb_copy->salt, SALT_SIZE) != 0;
}
static void dm_integrity_resume(struct dm_target *ti)
{
struct dm_integrity_c *ic = ti->private;
@ -3876,6 +3906,18 @@ static void dm_integrity_resume(struct dm_target *ti)
if (r)
dm_integrity_io_error(ic, "reading superblock", r);
if (unlikely(superblock_changed(ic))) {
/*
* Restore the superblock that we validated in the constructor,
* so that the rest of the driver doesn't operate on values
* that don't match the in-memory structures.
*/
memcpy(ic->sb, ic->sb_copy, sizeof(struct superblock));
DMERR("The superblock was changed while the device was suspended");
dm_integrity_io_error(ic, "superblock check", -EINVAL);
goto skip_writes;
}
if (ic->mode == 'R')
goto skip_writes;
@ -5427,6 +5469,13 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv
ic->just_formatted = true;
}
ic->sb_copy = kmemdup(ic->sb, sizeof(struct superblock), GFP_KERNEL);
if (!ic->sb_copy) {
ti->error = "Cannot allocate superblock copy";
r = -ENOMEM;
goto bad;
}
if (!ic->meta_dev && ic->mode != 'I') {
r = dm_set_target_max_io_len(ti, 1U << ic->sb->log2_interleave_sectors);
if (r)
@ -5525,6 +5574,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
kvfree(ic->journal_tree);
if (ic->sb)
free_pages_exact(ic->sb, SB_SECTORS << SECTOR_SHIFT);
kfree(ic->sb_copy);
if (ic->internal_shash)
crypto_free_shash(ic->internal_shash);

View File

@ -656,10 +656,16 @@ static void *get_result_buffer(struct dm_ioctl *param, size_t param_size,
{
param->data_start = align_ptr(param + 1) - (void *) param;
if (param->data_start < param_size)
if (param->data_start < param_size) {
*len = param_size - param->data_start;
else
} else {
/*
* The buffer can be as small as offsetof(*param, data), which
* is less than sizeof(*param), so don't run off the end of it.
*/
*len = 0;
param->data_start = param_size;
}
return ((void *) param) + param->data_start;
}
@ -1267,6 +1273,7 @@ static int do_resume(struct dm_ioctl *param)
/* Do we need to load a new map ? */
if (new_map) {
sector_t old_size, new_size;
blk_mode_t new_map_mode;
dm_ima_context_table_op(md, ima_context, DM_IMA_TABLE_SAVE);
/* Suspend if it isn't already suspended */
@ -1299,6 +1306,7 @@ static int do_resume(struct dm_ioctl *param)
}
}
new_map_mode = dm_table_get_mode(new_map);
old_size = dm_get_size(md);
old_map = dm_swap_table(md, new_map);
if (IS_ERR(old_map)) {
@ -1314,7 +1322,7 @@ static int do_resume(struct dm_ioctl *param)
if (old_size && new_size && old_size != new_size)
need_resize_uevent = true;
if (dm_table_get_mode(new_map) & BLK_OPEN_WRITE)
if (new_map_mode & BLK_OPEN_WRITE)
set_disk_ro(dm_disk(md), 0);
else
set_disk_ro(dm_disk(md), 1);

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