Merge remote-tracking branch 'torvalds/master' into perf-tools-next

To pick up perf-tools fixes.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2026-01-05 10:17:53 -03:00
commit ba23adb653
409 changed files with 3147 additions and 1900 deletions

View File

@ -127,7 +127,8 @@ Barry Song <baohua@kernel.org> <Baohua.Song@csr.com>
Barry Song <baohua@kernel.org> <barry.song@analog.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
Bartosz Golaszewski <brgl@bgdev.pl> <bgolaszewski@baylibre.com>
Bartosz Golaszewski <brgl@kernel.org> <bartosz.golaszewski@linaro.org>
Bartosz Golaszewski <brgl@kernel.org> <bgolaszewski@baylibre.com>
Ben Dooks <ben-linux@fluff.org> <ben.dooks@simtec.co.uk>
Ben Dooks <ben-linux@fluff.org> <ben.dooks@sifive.com>
Ben Gardner <bgardner@wabtec.com>
@ -704,6 +705,8 @@ Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org>
Santosh Shilimkar <santosh.shilimkar@oracle.org>
Santosh Shilimkar <ssantosh@kernel.org>
Sarangdhar Joshi <spjoshi@codeaurora.org>
Saravana Kannan <saravanak@kernel.org> <skannan@codeaurora.org>
Saravana Kannan <saravanak@kernel.org> <saravanak@google.com>
Sascha Hauer <s.hauer@pengutronix.de>
Sahitya Tummala <quic_stummala@quicinc.com> <stummala@codeaurora.org>
Sathishkumar Muruganandam <quic_murugana@quicinc.com> <murugana@codeaurora.org>
@ -857,7 +860,6 @@ Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
WangYuli <wangyuli@aosc.io> <wangyl5933@chinaunicom.cn>
WangYuli <wangyuli@aosc.io> <wangyuli@deepin.org>
WangYuli <wangyuli@aosc.io> <wangyuli@uniontech.com>
Weiwen Hu <huweiwen@linux.alibaba.com> <sehuww@mail.scut.edu.cn>
WeiXiong Liao <gmpy.liaowx@gmail.com> <liaoweixiong@allwinnertech.com>
Wen Gong <quic_wgong@quicinc.com> <wgong@codeaurora.org>

View File

@ -281,6 +281,14 @@ The following keys are defined:
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOP`: The Zicbop extension is supported, as
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
* :c:macro:`RISCV_HWPROBE_EXT_ZILSD`: The Zilsd extension is supported as
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
* :c:macro:`RISCV_HWPROBE_EXT_ZCLSD`: The Zclsd extension is supported as
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
mistakenly classified as a bitmask rather than a value.

View File

@ -377,6 +377,20 @@ properties:
guarantee on LR/SC sequences, as ratified in commit b1d806605f87
("Updated to ratified state.") of the riscv profiles specification.
- const: zilsd
description:
The standard Zilsd extension which provides support for aligned
register-pair load and store operations in 32-bit instruction
encodings, as ratified in commit f88abf1 ("Integrating
load/store pair for RV32 with the main manual") of riscv-isa-manual.
- const: zclsd
description:
The Zclsd extension implements the compressed (16-bit) version of the
Load/Store Pair for RV32. As with Zilsd, this extension was ratified
in commit f88abf1 ("Integrating load/store pair for RV32 with the
main manual") of riscv-isa-manual.
- const: zk
description:
The standard Zk Standard Scalar cryptography extension as ratified
@ -882,6 +896,16 @@ properties:
anyOf:
- const: v
- const: zve32x
# Zclsd depends on Zilsd and Zca
- if:
contains:
anyOf:
- const: zclsd
then:
contains:
allOf:
- const: zilsd
- const: zca
allOf:
# Zcf extension does not exist on rv64
@ -899,6 +923,18 @@ allOf:
not:
contains:
const: zcf
# Zilsd extension does not exist on rv64
- if:
properties:
riscv,isa-base:
contains:
const: rv64i
then:
properties:
riscv,isa-extensions:
not:
contains:
const: zilsd
additionalProperties: true
...

View File

@ -17,6 +17,7 @@ properties:
compatible:
oneOf:
- const: allwinner,sun50i-r329-spi
- const: allwinner,sun55i-a523-spi
- const: allwinner,sun6i-a31-spi
- const: allwinner,sun8i-h3-spi
- items:
@ -35,6 +36,9 @@ properties:
- const: allwinner,sun20i-d1-spi-dbi
- const: allwinner,sun50i-r329-spi-dbi
- const: allwinner,sun50i-r329-spi
- items:
- const: allwinner,sun55i-a523-spi-dbi
- const: allwinner,sun55i-a523-spi
reg:
maxItems: 1

View File

@ -6532,7 +6532,7 @@ F: rust/kernel/cpufreq.rs
F: tools/testing/selftests/cpufreq/
CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ
M: Saravana Kannan <saravanak@google.com>
M: Saravana Kannan <saravanak@kernel.org>
L: linux-pm@vger.kernel.org
S: Maintained
F: drivers/cpufreq/virtual-cpufreq.c
@ -7170,7 +7170,7 @@ F: drivers/base/devcoredump.c
F: include/linux/devcoredump.h
DEVICE DEPENDENCY HELPER SCRIPT
M: Saravana Kannan <saravanak@google.com>
M: Saravana Kannan <saravanak@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: scripts/dev-needs.sh
@ -13959,6 +13959,7 @@ S: Maintained
F: Documentation/admin-guide/mm/kho.rst
F: Documentation/core-api/kho/*
F: include/linux/kexec_handover.h
F: include/linux/kho/
F: kernel/liveupdate/kexec_handover*
F: lib/test_kho.c
F: tools/testing/selftests/kho/
@ -14637,6 +14638,7 @@ S: Maintained
F: Documentation/core-api/liveupdate.rst
F: Documentation/mm/memfd_preservation.rst
F: Documentation/userspace-api/liveupdate.rst
F: include/linux/kho/abi/
F: include/linux/liveupdate.h
F: include/linux/liveupdate/
F: include/uapi/linux/liveupdate.h
@ -16426,6 +16428,7 @@ MEMORY HOT(UN)PLUG
M: David Hildenbrand <david@kernel.org>
M: Oscar Salvador <osalvador@suse.de>
L: linux-mm@kvack.org
L: linux-cxl@vger.kernel.org
S: Maintained
F: Documentation/admin-guide/mm/memory-hotplug.rst
F: Documentation/core-api/memory-hotplug.rst
@ -16751,6 +16754,7 @@ F: tools/testing/selftests/mm/transhuge-stress.c
MEMORY MANAGEMENT - USERFAULTFD
M: Andrew Morton <akpm@linux-foundation.org>
M: Mike Rapoport <rppt@kernel.org>
R: Peter Xu <peterx@redhat.com>
L: linux-mm@kvack.org
S: Maintained
@ -19543,7 +19547,7 @@ F: include/linux/oa_tc6.h
OPEN FIRMWARE AND FLATTENED DEVICE TREE
M: Rob Herring <robh@kernel.org>
M: Saravana Kannan <saravanak@google.com>
M: Saravana Kannan <saravanak@kernel.org>
L: devicetree@vger.kernel.org
S: Maintained
Q: http://patchwork.kernel.org/project/devicetree/list/
@ -21345,7 +21349,7 @@ F: Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
F: drivers/net/wwan/qcom_bam_dmux.c
QUALCOMM BLUETOOTH DRIVER
M: Bartosz Golaszewski <brgl@bgdev.pl>
M: Bartosz Golaszewski <brgl@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/bluetooth/btqca.[ch]
@ -24571,7 +24575,7 @@ F: drivers/tty/vcc.c
F: include/linux/sunserialcore.h
SPARSE CHECKER
M: "Luc Van Oostenryck" <luc.vanoostenryck@gmail.com>
M: Chris Li <sparse@chrisli.org>
L: linux-sparse@vger.kernel.org
S: Maintained
W: https://sparse.docs.kernel.org/
@ -27920,6 +27924,7 @@ F: drivers/regulator/
F: rust/kernel/regulator.rs
F: include/dt-bindings/regulator/
F: include/linux/regulator/
F: include/uapi/regulator/
K: regulator_get_optional
VOLTAGE AND CURRENT REGULATOR IRQ HELPERS

View File

@ -2,7 +2,7 @@
VERSION = 6
PATCHLEVEL = 19
SUBLEVEL = 0
EXTRAVERSION = -rc2
EXTRAVERSION = -rc4
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@ -94,6 +94,12 @@
#define CPUCFG2_LSPW BIT(21)
#define CPUCFG2_LAM BIT(22)
#define CPUCFG2_PTW BIT(24)
#define CPUCFG2_FRECIPE BIT(25)
#define CPUCFG2_DIV32 BIT(26)
#define CPUCFG2_LAM_BH BIT(27)
#define CPUCFG2_LAMCAS BIT(28)
#define CPUCFG2_LLACQ_SCREL BIT(29)
#define CPUCFG2_SCQ BIT(30)
#define LOONGARCH_CPUCFG3 0x3
#define CPUCFG3_CCDMA BIT(0)
@ -108,6 +114,7 @@
#define CPUCFG3_SPW_HG_HF BIT(11)
#define CPUCFG3_RVA BIT(12)
#define CPUCFG3_RVAMAX GENMASK(16, 13)
#define CPUCFG3_DBAR_HINTS BIT(17)
#define CPUCFG3_ALDORDER_CAP BIT(18) /* All address load ordered, capability */
#define CPUCFG3_ASTORDER_CAP BIT(19) /* All address store ordered, capability */
#define CPUCFG3_ALDORDER_STA BIT(20) /* All address load ordered, status */

View File

@ -42,6 +42,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
.align 12
SYM_CODE_START(kernel_entry) # kernel entry point
UNWIND_HINT_END_OF_STACK
SETUP_TWINS
SETUP_MODES t0
@ -113,6 +114,7 @@ SYM_CODE_END(kernel_entry)
* function after setting up the stack and tp registers.
*/
SYM_CODE_START(smpboot_entry)
UNWIND_HINT_END_OF_STACK
SETUP_TWINS
SETUP_MODES t0
@ -142,5 +144,3 @@ SYM_CODE_START(smpboot_entry)
SYM_CODE_END(smpboot_entry)
#endif /* CONFIG_SMP */
SYM_ENTRY(kernel_entry_end, SYM_L_GLOBAL, SYM_A_NONE)

View File

@ -94,7 +94,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
* at the callsite, so there is no need to restore the T series regs.
*/
ftrace_common_return:
PTR_L ra, sp, PT_R1
PTR_L a0, sp, PT_R4
PTR_L a1, sp, PT_R5
PTR_L a2, sp, PT_R6
@ -104,12 +103,17 @@ ftrace_common_return:
PTR_L a6, sp, PT_R10
PTR_L a7, sp, PT_R11
PTR_L fp, sp, PT_R22
PTR_L t0, sp, PT_ERA
PTR_L t1, sp, PT_R13
PTR_ADDI sp, sp, PT_SIZE
bnez t1, .Ldirect
PTR_L ra, sp, PT_R1
PTR_L t0, sp, PT_ERA
PTR_ADDI sp, sp, PT_SIZE
jr t0
.Ldirect:
PTR_L t0, sp, PT_R1
PTR_L ra, sp, PT_ERA
PTR_ADDI sp, sp, PT_SIZE
jr t1
SYM_CODE_END(ftrace_common)
@ -161,6 +165,8 @@ SYM_CODE_END(return_to_handler)
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
SYM_CODE_START(ftrace_stub_direct_tramp)
UNWIND_HINT_UNDEFINED
jr t0
move t1, ra
move ra, t0
jr t1
SYM_CODE_END(ftrace_stub_direct_tramp)
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */

View File

@ -535,10 +535,15 @@ asmlinkage void noinstr do_fpe(struct pt_regs *regs, unsigned long fcsr)
asmlinkage void noinstr do_ade(struct pt_regs *regs)
{
irqentry_state_t state = irqentry_enter(regs);
unsigned int esubcode = FIELD_GET(CSR_ESTAT_ESUBCODE, regs->csr_estat);
if ((esubcode == EXSUBCODE_ADEM) && fixup_exception(regs))
goto out;
die_if_kernel("Kernel ade access", regs);
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)regs->csr_badvaddr);
out:
irqentry_exit(regs, state);
}

View File

@ -348,24 +348,10 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
}
EXPORT_SYMBOL_GPL(unwind_start);
static bool is_entry_func(unsigned long addr)
{
extern u32 kernel_entry;
extern u32 kernel_entry_end;
return addr >= (unsigned long)&kernel_entry && addr < (unsigned long)&kernel_entry_end;
}
static inline unsigned long bt_address(unsigned long ra)
{
extern unsigned long eentry;
if (__kernel_text_address(ra))
return ra;
if (__module_text_address(ra))
return ra;
if (ra >= eentry && ra < eentry + EXCCODE_INT_END * VECSIZE) {
unsigned long func;
unsigned long type = (ra - eentry) / VECSIZE;
@ -383,10 +369,13 @@ static inline unsigned long bt_address(unsigned long ra)
break;
}
return func + offset;
ra = func + offset;
}
return ra;
if (__kernel_text_address(ra))
return ra;
return 0;
}
bool unwind_next_frame(struct unwind_state *state)
@ -402,9 +391,6 @@ bool unwind_next_frame(struct unwind_state *state)
/* Don't let modules unload while we're reading their ORC data. */
guard(rcu)();
if (is_entry_func(state->pc))
goto end;
orc = orc_find(state->pc);
if (!orc) {
/*
@ -512,9 +498,6 @@ bool unwind_next_frame(struct unwind_state *state)
goto err;
}
if (!__kernel_text_address(state->pc))
goto err;
return true;
err:

View File

@ -160,8 +160,8 @@ void cpu_cache_init(void)
static const pgprot_t protection_map[16] = {
[VM_NONE] = __pgprot(_CACHE_CC | _PAGE_USER |
_PAGE_PROTNONE | _PAGE_NO_EXEC |
_PAGE_NO_READ),
_PAGE_NO_EXEC | _PAGE_NO_READ |
(_PAGE_PROTNONE ? : _PAGE_PRESENT)),
[VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
_PAGE_USER | _PAGE_PRESENT |
_PAGE_NO_EXEC),
@ -180,8 +180,8 @@ static const pgprot_t protection_map[16] = {
[VM_EXEC | VM_WRITE | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
_PAGE_USER | _PAGE_PRESENT),
[VM_SHARED] = __pgprot(_CACHE_CC | _PAGE_USER |
_PAGE_PROTNONE | _PAGE_NO_EXEC |
_PAGE_NO_READ),
_PAGE_NO_EXEC | _PAGE_NO_READ |
(_PAGE_PROTNONE ? : _PAGE_PRESENT)),
[VM_SHARED | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
_PAGE_USER | _PAGE_PRESENT |
_PAGE_NO_EXEC),

View File

@ -139,6 +139,7 @@ static void build_prologue(struct jit_ctx *ctx)
stack_adjust = round_up(stack_adjust, 16);
stack_adjust += bpf_stack_adjust;
move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA);
/* Reserve space for the move_imm + jirl instruction */
for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++)
emit_insn(ctx, nop);
@ -238,7 +239,7 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
* Call the next bpf prog and skip the first instruction
* of TCC initialization.
*/
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 6);
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7);
}
}
@ -280,6 +281,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
* goto out;
*/
tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0];
emit_zext_32(ctx, a2, true);
off = offsetof(struct bpf_array, map.max_entries);
emit_insn(ctx, ldwu, t1, a1, off);
/* bgeu $a2, $t1, jmp_offset */
@ -950,6 +953,22 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off);
}
if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
const struct btf_func_model *m;
int i;
m = bpf_jit_find_kfunc_model(ctx->prog, insn);
if (!m)
return -EINVAL;
for (i = 0; i < m->nr_args; i++) {
u8 reg = regmap[BPF_REG_1 + i];
bool sign = m->arg_flags[i] & BTF_FMODEL_SIGNED_ARG;
emit_abi_ext(ctx, reg, m->arg_size[i], sign);
}
}
move_addr(ctx, t1, func_addr);
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0);
@ -1265,7 +1284,7 @@ static int emit_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
return 0;
}
return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO, (u64)target);
return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_RA : LOONGARCH_GPR_ZERO, (u64)target);
}
static int emit_call(struct jit_ctx *ctx, u64 addr)
@ -1290,15 +1309,30 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
{
int ret;
bool is_call;
unsigned long size = 0;
unsigned long offset = 0;
void *image = NULL;
char namebuf[KSYM_NAME_LEN];
u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
/* Only poking bpf text is supported. Since kernel function entry
* is set up by ftrace, we rely on ftrace to poke kernel functions.
*/
if (!is_bpf_text_address((unsigned long)ip))
if (!__bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf))
return -ENOTSUPP;
image = ip - offset;
/* zero offset means we're poking bpf prog entry */
if (offset == 0) {
/* skip to the nop instruction in bpf prog entry:
* move t0, ra
* nop
*/
ip = image + LOONGARCH_INSN_SIZE;
}
is_call = old_t == BPF_MOD_CALL;
ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call);
if (ret)
@ -1622,14 +1656,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
/* To traced function */
/* Ftrace jump skips 2 NOP instructions */
if (is_kernel_text((unsigned long)orig_call))
if (is_kernel_text((unsigned long)orig_call) ||
is_module_text_address((unsigned long)orig_call))
orig_call += LOONGARCH_FENTRY_NBYTES;
/* Direct jump skips 5 NOP instructions */
else if (is_bpf_text_address((unsigned long)orig_call))
orig_call += LOONGARCH_BPF_FENTRY_NBYTES;
/* Module tracing not supported - cause kernel lockups */
else if (is_module_text_address((unsigned long)orig_call))
return -ENOTSUPP;
if (flags & BPF_TRAMP_F_CALL_ORIG) {
move_addr(ctx, LOONGARCH_GPR_A0, (const u64)im);
@ -1722,12 +1754,16 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
emit_insn(ctx, ldd, LOONGARCH_GPR_FP, LOONGARCH_GPR_SP, 0);
emit_insn(ctx, addid, LOONGARCH_GPR_SP, LOONGARCH_GPR_SP, 16);
if (flags & BPF_TRAMP_F_SKIP_FRAME)
if (flags & BPF_TRAMP_F_SKIP_FRAME) {
/* return to parent function */
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
else
/* return to traced function */
move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0);
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T0, 0);
} else {
/* return to traced function */
move_reg(ctx, LOONGARCH_GPR_T1, LOONGARCH_GPR_RA);
move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0);
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T1, 0);
}
}
ret = ctx->idx;

View File

@ -88,6 +88,32 @@ static inline void emit_sext_32(struct jit_ctx *ctx, enum loongarch_gpr reg, boo
emit_insn(ctx, addiw, reg, reg, 0);
}
/* Emit proper extension according to ABI requirements.
* Note that it requires a value of size `size` already resides in register `reg`.
*/
static inline void emit_abi_ext(struct jit_ctx *ctx, int reg, u8 size, bool sign)
{
/* ABI requires unsigned char/short to be zero-extended */
if (!sign && (size == 1 || size == 2))
return;
switch (size) {
case 1:
emit_insn(ctx, extwb, reg, reg);
break;
case 2:
emit_insn(ctx, extwh, reg, reg);
break;
case 4:
emit_insn(ctx, addiw, reg, reg, 0);
break;
case 8:
break;
default:
pr_warn("bpf_jit: invalid size %d for extension\n", size);
}
}
static inline void move_addr(struct jit_ctx *ctx, enum loongarch_gpr rd, u64 addr)
{
u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;

View File

@ -90,7 +90,7 @@ static inline void __hard_EE_RI_disable(void)
if (IS_ENABLED(CONFIG_BOOKE))
wrtee(0);
else if (IS_ENABLED(CONFIG_PPC_8xx))
wrtspr(SPRN_NRI);
wrtspr_sync(SPRN_NRI);
else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64))
__mtmsrd(0, 1);
else

View File

@ -1400,6 +1400,7 @@ static inline void mtmsr_isync(unsigned long val)
: "r" ((unsigned long)(v)) \
: "memory")
#define wrtspr(rn) asm volatile("mtspr " __stringify(rn) ",2" : : : "memory")
#define wrtspr_sync(rn) asm volatile("mtspr " __stringify(rn) ",2; sync" : : : "memory")
static inline void wrtee(unsigned long val)
{

View File

@ -20,6 +20,7 @@
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/udbg.h>
#include <asm/setup.h>
#define NO_SCROLL
@ -463,7 +464,7 @@ static noinline void draw_byte(unsigned char c, long locX, long locY)
{
unsigned char *base = calc_base(locX << 3, locY << 4);
unsigned int font_index = c * 16;
const unsigned char *font = font_sun_8x16.data + font_index;
const unsigned char *font = PTRRELOC(font_sun_8x16.data) + font_index;
int rb = dispDeviceRowBytes;
rmci_maybe_on();

View File

@ -101,17 +101,6 @@ SYM_FUNC_END(__kuep_unlock)
.endm
#endif
.macro clr_ri trash
#ifndef CONFIG_BOOKE
#ifdef CONFIG_PPC_8xx
mtspr SPRN_NRI, \trash
#else
li \trash, MSR_KERNEL & ~MSR_RI
mtmsr \trash
#endif
#endif
.endm
.globl transfer_to_syscall
transfer_to_syscall:
stw r3, ORIG_GPR3(r1)
@ -160,7 +149,6 @@ ret_from_syscall:
cmpwi r3,0
REST_GPR(3, r1)
syscall_exit_finish:
clr_ri r4
mtspr SPRN_SRR0,r7
mtspr SPRN_SRR1,r8
@ -237,7 +225,6 @@ fast_exception_return:
/* Clear the exception marker on the stack to avoid confusing stacktrace */
li r10, 0
stw r10, 8(r11)
clr_ri r10
mtspr SPRN_SRR1,r9
mtspr SPRN_SRR0,r12
REST_GPR(9, r11)
@ -270,7 +257,6 @@ interrupt_return:
.Lfast_user_interrupt_return:
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
clr_ri r4
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r12
@ -313,7 +299,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
cmpwi cr1,r3,0
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
clr_ri r4
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r12

View File

@ -38,7 +38,7 @@ static inline bool exit_must_hard_disable(void)
#else
static inline bool exit_must_hard_disable(void)
{
return false;
return true;
}
#endif
@ -443,6 +443,9 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
if (unlikely(stack_store))
__hard_EE_RI_disable();
#else
} else {
__hard_EE_RI_disable();
#endif /* CONFIG_PPC64 */
}

View File

@ -202,6 +202,23 @@ static void kexec_prepare_cpus_wait(int wait_state)
mb();
}
/*
* The add_cpu() call in wake_offline_cpus() can fail as cpu_bootable()
* returns false for CPUs that fail the cpu_smt_thread_allowed() check
* or non primary threads if SMT is disabled. Re-enable SMT and set the
* number of SMT threads to threads per core.
*/
static void kexec_smt_reenable(void)
{
#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
lock_device_hotplug();
cpu_smt_num_threads = threads_per_core;
cpu_smt_control = CPU_SMT_ENABLED;
unlock_device_hotplug();
#endif
}
/*
* We need to make sure each present CPU is online. The next kernel will scan
* the device tree and assume primary threads are online and query secondary
@ -216,6 +233,8 @@ static void wake_offline_cpus(void)
{
int cpu = 0;
kexec_smt_reenable();
for_each_present_cpu(cpu) {
if (!cpu_online(cpu)) {
printk(KERN_INFO "kexec: Waking offline cpu %d.\n",

View File

@ -1171,8 +1171,9 @@ static void __init pnv_arch300_idle_init(void)
u64 max_residency_ns = 0;
int i;
/* stop is not really architected, we only have p9,p10 drivers */
if (!pvr_version_is(PVR_POWER10) && !pvr_version_is(PVR_POWER9))
/* stop is not really architected, we only have p9,p10 and p11 drivers */
if (!pvr_version_is(PVR_POWER9) && !pvr_version_is(PVR_POWER10) &&
!pvr_version_is(PVR_POWER11))
return;
/*
@ -1189,8 +1190,8 @@ static void __init pnv_arch300_idle_init(void)
struct pnv_idle_states_t *state = &pnv_idle_states[i];
u64 psscr_rl = state->psscr_val & PSSCR_RL_MASK;
/* No deep loss driver implemented for POWER10 yet */
if (pvr_version_is(PVR_POWER10) &&
/* No deep loss driver implemented for POWER10 and POWER11 yet */
if ((pvr_version_is(PVR_POWER10) || pvr_version_is(PVR_POWER11)) &&
state->flags & (OPAL_PM_TIMEBASE_STOP|OPAL_PM_LOSE_FULL_CONTEXT))
continue;

View File

@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
set -e
set -o pipefail
# To debug, uncomment the following line
# set -x

View File

@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
set -e
set -o pipefail
# To debug, uncomment the following line
# set -x

View File

@ -203,7 +203,7 @@ ATOMIC_OPS(xor, xor, i)
" add %[rc], %[p], %[a]\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
" fence rw, rw\n" \
RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: [a]"r" (_a), [u]"r" (_u) \
@ -242,7 +242,7 @@ static __always_inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a,
" addi %[rc], %[p], 1\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
" fence rw, rw\n" \
RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: \
@ -268,7 +268,7 @@ static __always_inline bool arch_atomic_inc_unless_negative(atomic_t *v)
" addi %[rc], %[p], -1\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
" fence rw, rw\n" \
RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: \
@ -294,7 +294,7 @@ static __always_inline bool arch_atomic_dec_unless_positive(atomic_t *v)
" bltz %[rc], 1f\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
" fence rw, rw\n" \
RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: \

View File

@ -108,6 +108,8 @@
#define RISCV_ISA_EXT_ZICBOP 99
#define RISCV_ISA_EXT_SVRSW60T59B 100
#define RISCV_ISA_EXT_ZALASR 101
#define RISCV_ISA_EXT_ZILSD 102
#define RISCV_ISA_EXT_ZCLSD 103
#define RISCV_ISA_EXT_XLINUXENVCFG 127

View File

@ -660,7 +660,13 @@ extern int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long a
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, pte_t *ptep)
{
pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
#ifdef CONFIG_SMP
pte_t pte = __pte(xchg(&ptep->pte, 0));
#else
pte_t pte = *ptep;
set_pte(ptep, __pte(0));
#endif
page_table_check_pte_clear(mm, pte);
@ -997,7 +1003,13 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
unsigned long address, pmd_t *pmdp)
{
pmd_t pmd = __pmd(atomic_long_xchg((atomic_long_t *)pmdp, 0));
#ifdef CONFIG_SMP
pmd_t pmd = __pmd(xchg(&pmdp->pmd, 0));
#else
pmd_t pmd = *pmdp;
pmd_clear(pmdp);
#endif
page_table_check_pmd_clear(mm, pmd);

View File

@ -37,6 +37,7 @@ enum sbi_ext_id {
SBI_EXT_NACL = 0x4E41434C,
SBI_EXT_FWFT = 0x46574654,
SBI_EXT_MPXY = 0x4D505859,
SBI_EXT_DBTR = 0x44425452,
/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@ -505,6 +506,34 @@ enum sbi_mpxy_rpmi_attribute_id {
#define SBI_MPXY_CHAN_CAP_SEND_WITHOUT_RESP BIT(4)
#define SBI_MPXY_CHAN_CAP_GET_NOTIFICATIONS BIT(5)
/* SBI debug triggers function IDs */
enum sbi_ext_dbtr_fid {
SBI_EXT_DBTR_NUM_TRIGGERS = 0,
SBI_EXT_DBTR_SETUP_SHMEM,
SBI_EXT_DBTR_TRIG_READ,
SBI_EXT_DBTR_TRIG_INSTALL,
SBI_EXT_DBTR_TRIG_UPDATE,
SBI_EXT_DBTR_TRIG_UNINSTALL,
SBI_EXT_DBTR_TRIG_ENABLE,
SBI_EXT_DBTR_TRIG_DISABLE,
};
struct sbi_dbtr_data_msg {
unsigned long tstate;
unsigned long tdata1;
unsigned long tdata2;
unsigned long tdata3;
};
struct sbi_dbtr_id_msg {
unsigned long idx;
};
union sbi_dbtr_shmem_entry {
struct sbi_dbtr_data_msg data;
struct sbi_dbtr_id_msg id;
};
/* SBI spec version fields */
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24

View File

@ -424,6 +424,9 @@ static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
#define riscv_v_thread_free(tsk) do {} while (0)
#define riscv_v_setup_ctx_cache() do {} while (0)
#define riscv_v_thread_alloc(tsk) do {} while (0)
#define get_cpu_vector_context() do {} while (0)
#define put_cpu_vector_context() do {} while (0)
#define riscv_v_vstate_set_restore(task, regs) do {} while (0)
#endif /* CONFIG_RISCV_ISA_V */

View File

@ -84,6 +84,9 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_EXT_ZABHA (1ULL << 58)
#define RISCV_HWPROBE_EXT_ZALASR (1ULL << 59)
#define RISCV_HWPROBE_EXT_ZICBOP (1ULL << 60)
#define RISCV_HWPROBE_EXT_ZILSD (1ULL << 61)
#define RISCV_HWPROBE_EXT_ZCLSD (1ULL << 62)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)

View File

@ -242,6 +242,28 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data,
return -EPROBE_DEFER;
}
static int riscv_ext_zilsd_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
if (IS_ENABLED(CONFIG_64BIT))
return -EINVAL;
return 0;
}
static int riscv_ext_zclsd_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
if (IS_ENABLED(CONFIG_64BIT))
return -EINVAL;
if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZILSD) &&
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZCA))
return 0;
return -EPROBE_DEFER;
}
static int riscv_vector_f_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
@ -484,6 +506,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA_VALIDATE(zcd, RISCV_ISA_EXT_ZCD, riscv_ext_zcd_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zcf, RISCV_ISA_EXT_ZCF, riscv_ext_zcf_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zcmop, RISCV_ISA_EXT_ZCMOP, riscv_ext_zca_depends),
__RISCV_ISA_EXT_DATA_VALIDATE(zclsd, RISCV_ISA_EXT_ZCLSD, riscv_ext_zclsd_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zilsd, RISCV_ISA_EXT_ZILSD, riscv_ext_zilsd_validate),
__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
__RISCV_ISA_EXT_DATA(zbc, RISCV_ISA_EXT_ZBC),

View File

@ -68,18 +68,19 @@ static long save_fp_state(struct pt_regs *regs,
#define restore_fp_state(task, regs) (0)
#endif
#ifdef CONFIG_RISCV_ISA_V
static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
static long save_v_state(struct pt_regs *regs, void __user *sc_vec)
{
struct __riscv_ctx_hdr __user *hdr;
struct __sc_riscv_v_state __user *state;
void __user *datap;
long err;
hdr = *sc_vec;
/* Place state to the user's signal context space after the hdr */
state = (struct __sc_riscv_v_state __user *)(hdr + 1);
if (!IS_ENABLED(CONFIG_RISCV_ISA_V) ||
!((has_vector() || has_xtheadvector()) &&
riscv_v_vstate_query(regs)))
return 0;
/* Place state to the user's signal context space */
state = (struct __sc_riscv_v_state __user *)sc_vec;
/* Point datap right after the end of __sc_riscv_v_state */
datap = state + 1;
@ -97,15 +98,11 @@ static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
err |= __put_user((__force void *)datap, &state->v_state.datap);
/* Copy the whole vector content to user space datap. */
err |= __copy_to_user(datap, current->thread.vstate.datap, riscv_v_vsize);
/* Copy magic to the user space after saving all vector conetext */
err |= __put_user(RISCV_V_MAGIC, &hdr->magic);
err |= __put_user(riscv_v_sc_size, &hdr->size);
if (unlikely(err))
return err;
return -EFAULT;
/* Only progress the sv_vec if everything has done successfully */
*sc_vec += riscv_v_sc_size;
return 0;
/* Only return the size if everything has done successfully */
return riscv_v_sc_size;
}
/*
@ -142,10 +139,20 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
*/
return copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize);
}
#else
#define save_v_state(task, regs) (0)
#define __restore_v_state(task, regs) (0)
#endif
struct arch_ext_priv {
__u32 magic;
long (*save)(struct pt_regs *regs, void __user *sc_vec);
};
struct arch_ext_priv arch_ext_list[] = {
{
.magic = RISCV_V_MAGIC,
.save = &save_v_state,
},
};
const size_t nr_arch_exts = ARRAY_SIZE(arch_ext_list);
static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
@ -270,7 +277,8 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
{
struct sigcontext __user *sc = &frame->uc.uc_mcontext;
struct __riscv_ctx_hdr __user *sc_ext_ptr = &sc->sc_extdesc.hdr;
long err;
struct arch_ext_priv *arch_ext;
long err, i, ext_size;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
@ -278,8 +286,20 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
if (has_fpu())
err |= save_fp_state(regs, &sc->sc_fpregs);
/* Save the vector state. */
if ((has_vector() || has_xtheadvector()) && riscv_v_vstate_query(regs))
err |= save_v_state(regs, (void __user **)&sc_ext_ptr);
for (i = 0; i < nr_arch_exts; i++) {
arch_ext = &arch_ext_list[i];
if (!arch_ext->save)
continue;
ext_size = arch_ext->save(regs, sc_ext_ptr + 1);
if (ext_size <= 0) {
err |= ext_size;
} else {
err |= __put_user(arch_ext->magic, &sc_ext_ptr->magic);
err |= __put_user(ext_size, &sc_ext_ptr->size);
sc_ext_ptr = (void *)sc_ext_ptr + ext_size;
}
}
/* Write zero to fp-reserved space and check it on restore_sigcontext */
err |= __put_user(0, &sc->sc_extdesc.reserved);
/* And put END __riscv_ctx_hdr at the end. */

View File

@ -121,6 +121,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZBS);
EXT_KEY(ZCA);
EXT_KEY(ZCB);
EXT_KEY(ZCLSD);
EXT_KEY(ZCMOP);
EXT_KEY(ZICBOM);
EXT_KEY(ZICBOP);
@ -130,6 +131,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZIHINTNTL);
EXT_KEY(ZIHINTPAUSE);
EXT_KEY(ZIHPM);
EXT_KEY(ZILSD);
EXT_KEY(ZIMOP);
EXT_KEY(ZKND);
EXT_KEY(ZKNE);

View File

@ -258,7 +258,7 @@ static bool cpu_has_entrysign(void)
if (fam == 0x1a) {
if (model <= 0x2f ||
(0x40 <= model && model <= 0x4f) ||
(0x60 <= model && model <= 0x6f))
(0x60 <= model && model <= 0x7f))
return true;
}

View File

@ -380,7 +380,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
blkg_rwstat_add_aux(&to->merged, &from->merged);
blkg_rwstat_add_aux(&to->service_time, &from->service_time);
blkg_rwstat_add_aux(&to->wait_time, &from->wait_time);
bfq_stat_add_aux(&from->time, &from->time);
bfq_stat_add_aux(&to->time, &from->time);
bfq_stat_add_aux(&to->avg_queue_size_sum, &from->avg_queue_size_sum);
bfq_stat_add_aux(&to->avg_queue_size_samples,
&from->avg_queue_size_samples);

View File

@ -984,7 +984,7 @@ struct bfq_group_data {
* unused for the root group. Used to know whether there
* are groups with more than one active @bfq_entity
* (see the comments to the function
* bfq_bfqq_may_idle()).
* bfq_better_to_idle()).
* @rq_pos_tree: rbtree sorted by next_request position, used when
* determining if two or more queues have interleaving
* requests (see bfq_find_close_cooperator()).

View File

@ -3721,7 +3721,7 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
struct blk_mq_hw_ctx, cpuhp_online);
int ret = 0;
if (blk_mq_hctx_has_online_cpu(hctx, cpu))
if (!hctx->nr_ctx || blk_mq_hctx_has_online_cpu(hctx, cpu))
return 0;
/*

View File

@ -50,6 +50,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
struct aead_request *subreq = aead_request_ctx(req);
crypto_completion_t compl;
bool unaligned_info;
void *data;
u8 *info;
unsigned int ivsize = 8;
@ -68,8 +69,9 @@ static int seqiv_aead_encrypt(struct aead_request *req)
memcpy_sglist(req->dst, req->src,
req->assoclen + req->cryptlen);
if (unlikely(!IS_ALIGNED((unsigned long)info,
crypto_aead_alignmask(geniv) + 1))) {
unaligned_info = !IS_ALIGNED((unsigned long)info,
crypto_aead_alignmask(geniv) + 1);
if (unlikely(unaligned_info)) {
info = kmemdup(req->iv, ivsize, req->base.flags &
CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
GFP_ATOMIC);
@ -89,7 +91,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
err = crypto_aead_encrypt(subreq);
if (unlikely(info != req->iv))
if (unlikely(unaligned_info))
seqiv_aead_encrypt_complete2(req, err);
return err;
}

View File

@ -112,7 +112,7 @@ struct rnbd_clt_dev {
struct rnbd_queue *hw_queues;
u32 device_id;
/* local Idr index - used to track minor number allocations. */
u32 clt_device_id;
int clt_device_id;
struct mutex lock;
enum rnbd_clt_dev_state dev_state;
refcount_t refcount;

View File

@ -237,6 +237,7 @@ struct ublk_device {
bool canceling;
pid_t ublksrv_tgid;
struct delayed_work exit_work;
struct work_struct partition_scan_work;
struct ublk_queue *queues[];
};
@ -254,6 +255,20 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
u16 q_id, u16 tag, struct ublk_io *io, size_t offset);
static inline unsigned int ublk_req_build_flags(struct request *req);
static void ublk_partition_scan_work(struct work_struct *work)
{
struct ublk_device *ub =
container_of(work, struct ublk_device, partition_scan_work);
if (WARN_ON_ONCE(!test_and_clear_bit(GD_SUPPRESS_PART_SCAN,
&ub->ub_disk->state)))
return;
mutex_lock(&ub->ub_disk->open_mutex);
bdev_disk_changed(ub->ub_disk, false);
mutex_unlock(&ub->ub_disk->open_mutex);
}
static inline struct ublksrv_io_desc *
ublk_get_iod(const struct ublk_queue *ubq, unsigned tag)
{
@ -1607,8 +1622,7 @@ static bool ublk_check_and_reset_active_ref(struct ublk_device *ub)
{
int i, j;
if (!(ub->dev_info.flags & (UBLK_F_SUPPORT_ZERO_COPY |
UBLK_F_AUTO_BUF_REG)))
if (!ublk_dev_need_req_ref(ub))
return false;
for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
@ -2027,6 +2041,7 @@ static void ublk_stop_dev(struct ublk_device *ub)
mutex_lock(&ub->mutex);
ublk_stop_dev_unlocked(ub);
mutex_unlock(&ub->mutex);
flush_work(&ub->partition_scan_work);
ublk_cancel_dev(ub);
}
@ -2955,9 +2970,17 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
ublk_apply_params(ub);
/* don't probe partitions if any daemon task is un-trusted */
if (ub->unprivileged_daemons)
set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
/*
* Suppress partition scan to avoid potential IO hang.
*
* If ublk server error occurs during partition scan, the IO may
* wait while holding ub->mutex, which can deadlock with other
* operations that need the mutex. Defer partition scan to async
* work.
* For unprivileged daemons, keep GD_SUPPRESS_PART_SCAN set
* permanently.
*/
set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
ublk_get_device(ub);
ub->dev_info.state = UBLK_S_DEV_LIVE;
@ -2974,6 +2997,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
set_bit(UB_STATE_USED, &ub->state);
/* Schedule async partition scan for trusted daemons */
if (!ub->unprivileged_daemons)
schedule_work(&ub->partition_scan_work);
out_put_cdev:
if (ret) {
ublk_detach_disk(ub);
@ -3139,6 +3166,7 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
mutex_init(&ub->mutex);
spin_lock_init(&ub->lock);
mutex_init(&ub->cancel_mutex);
INIT_WORK(&ub->partition_scan_work, ublk_partition_scan_work);
ret = ublk_alloc_dev_number(ub, header->dev_id);
if (ret < 0)

View File

@ -4052,7 +4052,7 @@ static int btusb_probe(struct usb_interface *intf,
return -ENODEV;
}
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -4075,8 +4075,10 @@ static int btusb_probe(struct usb_interface *intf,
}
}
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
kfree(data);
return -ENODEV;
}
if (id->driver_info & BTUSB_AMP) {
data->cmdreq_type = USB_TYPE_CLASS | 0x01;
@ -4131,8 +4133,10 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_acl = hci_recv_frame;
hdev = hci_alloc_dev_priv(priv_size);
if (!hdev)
if (!hdev) {
kfree(data);
return -ENOMEM;
}
hdev->bus = HCI_USB;
hci_set_drvdata(hdev, data);
@ -4406,6 +4410,7 @@ static int btusb_probe(struct usb_interface *intf,
if (data->reset_gpio)
gpiod_put(data->reset_gpio);
hci_free_dev(hdev);
kfree(data);
return err;
}
@ -4454,6 +4459,7 @@ static void btusb_disconnect(struct usb_interface *intf)
}
hci_free_dev(hdev);
kfree(data);
}
#ifdef CONFIG_PM

View File

@ -991,7 +991,7 @@ static void qm_get_complete_eqe_num(struct hisi_qm *qm)
return;
poll_data = &qm->poll_data[cqn];
while (QM_EQE_PHASE(dw0) != qm->status.eqc_phase) {
do {
poll_data->qp_finish_id[eqe_num] = dw0 & QM_EQE_CQN_MASK;
eqe_num++;
@ -1004,11 +1004,10 @@ static void qm_get_complete_eqe_num(struct hisi_qm *qm)
qm->status.eq_head++;
}
if (eqe_num == (eq_depth >> 1) - 1)
break;
dw0 = le32_to_cpu(eqe->dw0);
}
if (QM_EQE_PHASE(dw0) != qm->status.eqc_phase)
break;
} while (eqe_num < (eq_depth >> 1) - 1);
poll_data->eqe_num = eqe_num;
queue_work(qm->wq, &poll_data->work);

View File

@ -36,6 +36,8 @@
static char driver_name[] = KBUILD_MODNAME;
#define RCV_BUFFER_SIZE (16 * 1024)
/* this is the physical layout of a PCL, its size is 128 bytes */
struct pcl {
__le32 next;
@ -517,16 +519,14 @@ remove_card(struct pci_dev *dev)
lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
lynx->rcv_pcl, lynx->rcv_pcl_bus);
dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE, lynx->rcv_buffer,
lynx->rcv_buffer_bus);
dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
pci_disable_device(dev);
lynx_put(lynx);
}
#define RCV_BUFFER_SIZE (16 * 1024)
static int
add_card(struct pci_dev *dev, const struct pci_device_id *unused)
{
@ -680,7 +680,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
lynx->rcv_pcl, lynx->rcv_pcl_bus);
if (lynx->rcv_buffer)
dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE,
dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);

View File

@ -73,6 +73,7 @@ struct mm_struct efi_mm = {
MMAP_LOCK_INITIALIZER(efi_mm)
.page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
.user_ns = &init_user_ns,
.cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0},
#ifdef CONFIG_SCHED_MM_CID
.mm_cid.lock = __RAW_SPIN_LOCK_UNLOCKED(efi_mm.mm_cid.lock),

View File

@ -513,15 +513,15 @@ efi_status_t efi_setup_graphics(struct screen_info *si, struct edid_info *edid)
status = efi_bs_call(handle_protocol, handle, &EFI_EDID_ACTIVE_PROTOCOL_GUID,
(void **)&active_edid);
if (status == EFI_SUCCESS) {
gop_size_of_edid = active_edid->size_of_edid;
gop_edid = active_edid->edid;
gop_size_of_edid = efi_table_attr(active_edid, size_of_edid);
gop_edid = efi_table_attr(active_edid, edid);
} else {
status = efi_bs_call(handle_protocol, handle,
&EFI_EDID_DISCOVERED_PROTOCOL_GUID,
(void **)&discovered_edid);
if (status == EFI_SUCCESS) {
gop_size_of_edid = discovered_edid->size_of_edid;
gop_edid = discovered_edid->edid;
gop_size_of_edid = efi_table_attr(discovered_edid, size_of_edid);
gop_edid = efi_table_attr(discovered_edid, edid);
}
}

View File

@ -96,7 +96,8 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj
/**
* drm_gem_shmem_init - Initialize an allocated object.
* @dev: DRM device
* @obj: The allocated shmem GEM object.
* @shmem: The allocated shmem GEM object.
* @size: Buffer size in bytes
*
* Returns:
* 0 on success, or a negative error code on failure.
@ -895,4 +896,4 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_no_map);
MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
MODULE_IMPORT_NS("DMA_BUF");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL");

View File

@ -3,6 +3,7 @@
* Copyright © 2024-2025 Intel Corporation
*/
#include <linux/dma-fence.h>
#include <linux/dma-mapping.h>
#include <linux/migrate.h>
#include <linux/pagemap.h>
@ -408,10 +409,14 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
drm_pagemap_get_devmem_page(page, zdd);
}
err = ops->copy_to_devmem(pages, pagemap_addr, npages);
err = ops->copy_to_devmem(pages, pagemap_addr, npages,
devmem_allocation->pre_migrate_fence);
if (err)
goto err_finalize;
dma_fence_put(devmem_allocation->pre_migrate_fence);
devmem_allocation->pre_migrate_fence = NULL;
/* Upon success bind devmem allocation to range and zdd */
devmem_allocation->timeslice_expiration = get_jiffies_64() +
msecs_to_jiffies(timeslice_ms);
@ -596,7 +601,7 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation)
for (i = 0; i < npages; ++i)
pages[i] = migrate_pfn_to_page(src[i]);
err = ops->copy_to_ram(pages, pagemap_addr, npages);
err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
if (err)
goto err_finalize;
@ -732,7 +737,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
for (i = 0; i < npages; ++i)
pages[i] = migrate_pfn_to_page(migrate.src[i]);
err = ops->copy_to_ram(pages, pagemap_addr, npages);
err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
if (err)
goto err_finalize;
@ -813,11 +818,14 @@ EXPORT_SYMBOL_GPL(drm_pagemap_pagemap_ops_get);
* @ops: Pointer to the operations structure for GPU SVM device memory
* @dpagemap: The struct drm_pagemap we're allocating from.
* @size: Size of device memory allocation
* @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
* (May be NULL).
*/
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
struct device *dev, struct mm_struct *mm,
const struct drm_pagemap_devmem_ops *ops,
struct drm_pagemap *dpagemap, size_t size)
struct drm_pagemap *dpagemap, size_t size,
struct dma_fence *pre_migrate_fence)
{
init_completion(&devmem_allocation->detached);
devmem_allocation->dev = dev;
@ -825,6 +833,7 @@ void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
devmem_allocation->ops = ops;
devmem_allocation->dpagemap = dpagemap;
devmem_allocation->size = size;
devmem_allocation->pre_migrate_fence = pre_migrate_fence;
}
EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);

View File

@ -951,13 +951,13 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
vma = eb_lookup_vma(eb, eb->exec[i].handle);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
goto err;
return err;
}
err = eb_validate_vma(eb, &eb->exec[i], vma);
if (unlikely(err)) {
i915_vma_put(vma);
goto err;
return err;
}
err = eb_add_vma(eb, &current_batch, i, vma);
@ -966,19 +966,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
if (i915_gem_object_is_userptr(vma->obj)) {
err = i915_gem_object_userptr_submit_init(vma->obj);
if (err) {
if (i + 1 < eb->buffer_count) {
/*
* Execbuffer code expects last vma entry to be NULL,
* since we already initialized this entry,
* set the next value to NULL or we mess up
* cleanup handling.
*/
eb->vma[i + 1].vma = NULL;
}
if (err)
return err;
}
eb->vma[i].flags |= __EXEC_OBJECT_USERPTR_INIT;
eb->args->flags |= __EXEC_USERPTR_USED;
@ -986,10 +975,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
}
return 0;
err:
eb->vma[i].vma = NULL;
return err;
}
static int eb_lock_vmas(struct i915_execbuffer *eb)
@ -3375,7 +3360,8 @@ i915_gem_do_execbuffer(struct drm_device *dev,
eb.exec = exec;
eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1);
eb.vma[0].vma = NULL;
memset(eb.vma, 0, (args->buffer_count + 1) * sizeof(struct eb_vma));
eb.batch_pool = NULL;
eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
@ -3584,7 +3570,18 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
if (err)
return err;
/* Allocate extra slots for use by the command parser */
/*
* Allocate extra slots for use by the command parser.
*
* Note that this allocation handles two different arrays (the
* exec2_list array, and the eventual eb.vma array introduced in
* i915_gem_do_execbuffer()), that reside in virtually contiguous
* memory. Also note that the allocation intentionally doesn't fill the
* area with zeros, because the exec2_list part doesn't need to be, as
* it's immediately overwritten by user data a few lines below.
* However, the eb.vma part is explicitly zeroed later in
* i915_gem_do_execbuffer().
*/
exec2_list = kvmalloc_array(count + 2, eb_element_size(),
__GFP_NOWARN | GFP_KERNEL);
if (exec2_list == NULL) {

View File

@ -28,6 +28,16 @@ static void pvr_gem_object_free(struct drm_gem_object *obj)
drm_gem_shmem_object_free(obj);
}
static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags)
{
struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(obj);
if (pvr_obj->flags & DRM_PVR_BO_PM_FW_PROTECT)
return ERR_PTR(-EPERM);
return drm_gem_prime_export(obj, flags);
}
static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *vma)
{
struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(gem_obj);
@ -42,6 +52,7 @@ static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *v
static const struct drm_gem_object_funcs pvr_gem_object_funcs = {
.free = pvr_gem_object_free,
.print_info = drm_gem_shmem_object_print_info,
.export = pvr_gem_export,
.pin = drm_gem_shmem_object_pin,
.unpin = drm_gem_shmem_object_unpin,
.get_sg_table = drm_gem_shmem_object_get_sg_table,

View File

@ -1376,7 +1376,6 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
REG_A6XX_UCHE_MODE_CNTL,
REG_A6XX_RB_NC_MODE_CNTL,
REG_A6XX_RB_CMP_DBG_ECO_CNTL,
REG_A7XX_GRAS_NC_MODE_CNTL,
REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE,
REG_A6XX_UCHE_GBIF_GX_CONFIG,
REG_A6XX_UCHE_CLIENT_PF,
@ -1392,6 +1391,7 @@ static const u32 a750_ifpc_reglist_regs[] = {
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
REG_A6XX_RBBM_PERFCTR_CNTL,
REG_A6XX_TPL1_NC_MODE_CNTL,
REG_A6XX_SP_NC_MODE_CNTL,
REG_A6XX_CP_DBG_ECO_CNTL,
@ -1448,6 +1448,12 @@ static const u32 a750_ifpc_reglist_regs[] = {
DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist);
static const struct adreno_reglist_pipe a7xx_dyn_pwrup_reglist_regs[] = {
{ REG_A7XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
};
DECLARE_ADRENO_REGLIST_PIPE_LIST(a7xx_dyn_pwrup_reglist);
static const struct adreno_info a7xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
@ -1491,6 +1497,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a730_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
.dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_cgc_mode = 0x00020000,
},
@ -1513,6 +1520,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
.dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7020100,
.gmu_cgc_mode = 0x00020202,
@ -1547,6 +1555,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
.dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.ifpc_reglist = &a750_ifpc_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7050001,
@ -1589,6 +1598,7 @@ static const struct adreno_info a7xx_gpus[] = {
.a6xx = &(const struct a6xx_info) {
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
.dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.ifpc_reglist = &a750_ifpc_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7090100,
@ -1623,6 +1633,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
.dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x70f0000,
.gmu_cgc_mode = 0x00020222,

View File

@ -849,9 +849,16 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
min_acc_len_64b << 3 |
hbb_lo << 1 | ubwc_mode);
if (adreno_is_a7xx(adreno_gpu))
gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL,
FIELD_PREP(GENMASK(8, 5), hbb_lo));
if (adreno_is_a7xx(adreno_gpu)) {
for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_BV; pipe_id++) {
gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id));
gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL,
FIELD_PREP(GENMASK(8, 5), hbb_lo));
}
gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
}
gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL,
min_acc_len_64b << 23 | hbb_lo << 21);
@ -865,23 +872,27 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
const struct adreno_reglist_list *reglist;
const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
void *ptr = a6xx_gpu->pwrup_reglist_ptr;
struct cpu_gpu_lock *lock = ptr;
u32 *dest = (u32 *)&lock->regs[0];
u32 dyn_pwrup_reglist_count = 0;
int i;
lock->gpu_req = lock->cpu_req = lock->turn = 0;
reglist = adreno_gpu->info->a6xx->ifpc_reglist;
lock->ifpc_list_len = reglist->count;
if (reglist) {
lock->ifpc_list_len = reglist->count;
/*
* For each entry in each of the lists, write the offset and the current
* register value into the GPU buffer
*/
for (i = 0; i < reglist->count; i++) {
*dest++ = reglist->regs[i];
*dest++ = gpu_read(gpu, reglist->regs[i]);
/*
* For each entry in each of the lists, write the offset and the current
* register value into the GPU buffer
*/
for (i = 0; i < reglist->count; i++) {
*dest++ = reglist->regs[i];
*dest++ = gpu_read(gpu, reglist->regs[i]);
}
}
reglist = adreno_gpu->info->a6xx->pwrup_reglist;
@ -907,7 +918,24 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
* (<aperture, shifted 12 bits> <address> <data>), and the length is
* stored as number for triplets in dynamic_list_len.
*/
lock->dynamic_list_len = 0;
dyn_pwrup_reglist = adreno_gpu->info->a6xx->dyn_pwrup_reglist;
if (dyn_pwrup_reglist) {
for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_BV; pipe_id++) {
gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id));
for (i = 0; i < dyn_pwrup_reglist->count; i++) {
if ((dyn_pwrup_reglist->regs[i].pipe & BIT(pipe_id)) == 0)
continue;
*dest++ = A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id);
*dest++ = dyn_pwrup_reglist->regs[i].offset;
*dest++ = gpu_read(gpu, dyn_pwrup_reglist->regs[i].offset);
dyn_pwrup_reglist_count++;
}
}
gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
}
lock->dynamic_list_len = dyn_pwrup_reglist_count;
}
static int a7xx_preempt_start(struct msm_gpu *gpu)

View File

@ -45,6 +45,7 @@ struct a6xx_info {
const struct adreno_reglist *hwcg;
const struct adreno_protect *protect;
const struct adreno_reglist_list *pwrup_reglist;
const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
const struct adreno_reglist_list *ifpc_reglist;
const struct adreno_reglist *gbif_cx;
const struct adreno_reglist_pipe *nonctxt_reglist;

View File

@ -454,11 +454,11 @@ void a6xx_preempt_init(struct msm_gpu *gpu)
gpu->vm, &a6xx_gpu->preempt_postamble_bo,
&a6xx_gpu->preempt_postamble_iova);
preempt_prepare_postamble(a6xx_gpu);
if (IS_ERR(a6xx_gpu->preempt_postamble_ptr))
goto fail;
preempt_prepare_postamble(a6xx_gpu);
timer_setup(&a6xx_gpu->preempt_timer, a6xx_preempt_timer, 0);
return;

View File

@ -188,6 +188,19 @@ static const struct adreno_reglist_list name = { \
.count = ARRAY_SIZE(name ## _regs), \
};
struct adreno_reglist_pipe_list {
/** @reg: List of register **/
const struct adreno_reglist_pipe *regs;
/** @count: Number of registers in the list **/
u32 count;
};
#define DECLARE_ADRENO_REGLIST_PIPE_LIST(name) \
static const struct adreno_reglist_pipe_list name = { \
.regs = name ## _regs, \
.count = ARRAY_SIZE(name ## _regs), \
};
struct adreno_gpu {
struct msm_gpu base;
const struct adreno_info *info;

View File

@ -200,7 +200,7 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc,
struct dpu_crtc_state *crtc_state)
{
struct dpu_crtc_mixer *m;
u32 crcs[CRTC_QUAD_MIXERS];
u32 crcs[CRTC_DUAL_MIXERS];
int rc = 0;
int i;
@ -1328,7 +1328,6 @@ static struct msm_display_topology dpu_crtc_get_topology(
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct msm_display_topology topology = {0};
struct drm_encoder *drm_enc;
u32 num_rt_intf;
drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
@ -1342,14 +1341,11 @@ static struct msm_display_topology dpu_crtc_get_topology(
* Dual display
* 2 LM, 2 INTF ( Split display using 2 interfaces)
*
* If DSC is enabled, try to use 4:4:2 topology if there is enough
* resource. Otherwise, use 2:2:2 topology.
*
* Single display
* 1 LM, 1 INTF
* 2 LM, 1 INTF (stream merge to support high resolution interfaces)
*
* If DSC is enabled, use 2:2:1 topology
* If DSC is enabled, use 2 LMs for 2:2:1 topology
*
* Add dspps to the reservation requirements if ctm is requested
*
@ -1361,23 +1357,14 @@ static struct msm_display_topology dpu_crtc_get_topology(
* (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
*/
num_rt_intf = topology.num_intf;
if (topology.cwb_enabled)
num_rt_intf--;
if (topology.num_dsc) {
if (dpu_kms->catalog->dsc_count >= num_rt_intf * 2)
topology.num_dsc = num_rt_intf * 2;
else
topology.num_dsc = num_rt_intf;
topology.num_lm = topology.num_dsc;
} else if (num_rt_intf == 2) {
if (topology.num_intf == 2 && !topology.cwb_enabled)
topology.num_lm = 2;
} else if (dpu_kms->catalog->caps->has_3d_merge) {
else if (topology.num_dsc == 2)
topology.num_lm = 2;
else if (dpu_kms->catalog->caps->has_3d_merge)
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
} else {
else
topology.num_lm = 1;
}
if (crtc_state->ctm)
topology.num_dspp = topology.num_lm;
@ -1620,17 +1607,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
return 0;
}
/**
* dpu_crtc_get_num_lm - Get mixer number in this CRTC pipeline
* @state: Pointer to drm crtc state object
*/
unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state)
{
struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
return cstate->num_mixers;
}
#ifdef CONFIG_DEBUG_FS
static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
{

View File

@ -210,7 +210,7 @@ struct dpu_crtc_state {
bool bw_control;
bool bw_split_vote;
struct drm_rect lm_bounds[CRTC_QUAD_MIXERS];
struct drm_rect lm_bounds[CRTC_DUAL_MIXERS];
uint64_t input_fence_timeout_ns;
@ -218,10 +218,10 @@ struct dpu_crtc_state {
/* HW Resources reserved for the crtc */
u32 num_mixers;
struct dpu_crtc_mixer mixers[CRTC_QUAD_MIXERS];
struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS];
u32 num_ctls;
struct dpu_hw_ctl *hw_ctls[CRTC_QUAD_MIXERS];
struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS];
enum dpu_crtc_crc_source crc_source;
int crc_frame_skip_count;
@ -267,6 +267,4 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type(
void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event);
unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state);
#endif /* _DPU_CRTC_H_ */

View File

@ -55,7 +55,7 @@
#define MAX_PHYS_ENCODERS_PER_VIRTUAL \
(MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES)
#define MAX_CHANNELS_PER_ENC 4
#define MAX_CHANNELS_PER_ENC 2
#define MAX_CWB_PER_ENC 2
#define IDLE_SHORT_TIMEOUT 1
@ -661,6 +661,7 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
struct msm_drm_private *priv = dpu_enc->base.dev->dev_private;
struct msm_display_info *disp_info = &dpu_enc->disp_info;
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
struct drm_connector *connector;
struct drm_connector_state *conn_state;
struct drm_framebuffer *fb;
@ -674,12 +675,22 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
dsc = dpu_encoder_get_dsc_config(drm_enc);
/*
* Set DSC number as 1 to mark the enabled status, will be adjusted
* in dpu_crtc_get_topology()
*/
if (dsc)
topology->num_dsc = 1;
/* We only support 2 DSC mode (with 2 LM and 1 INTF) */
if (dsc) {
/*
* Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces
* when Display Stream Compression (DSC) is enabled,
* and when enough DSC blocks are available.
* This is power-optimal and can drive up to (including) 4k
* screens.
*/
WARN(topology->num_intf > 2,
"DSC topology cannot support more than 2 interfaces\n");
if (topology->num_intf >= 2 || dpu_kms->catalog->dsc_count >= 2)
topology->num_dsc = 2;
else
topology->num_dsc = 1;
}
connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
if (!connector)
@ -2169,8 +2180,8 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
{
int i, num_lm;
struct dpu_global_state *global_state;
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_mixer *hw_mixer[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[2];
struct dpu_hw_mixer *hw_mixer[2];
struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
/* reset all mixers for this encoder */

View File

@ -302,7 +302,7 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
/* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
(dpu_cstate->num_mixers != 1) &&
dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
!dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;

View File

@ -247,14 +247,12 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
if (hw_cdm)
intf_cfg.cdm = hw_cdm->idx;
if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode)
phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
mode_3d);
if (hw_pp && hw_pp->merge_3d && hw_pp->merge_3d->ops.setup_3d_mode)
hw_pp->merge_3d->ops.setup_3d_mode(hw_pp->merge_3d, mode_3d);
/* setup which pp blk will connect to this wb */
if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk)
phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb,
phys_enc->hw_pp->idx);
if (hw_pp && hw_wb->ops.bind_pingpong_blk)
hw_wb->ops.bind_pingpong_blk(hw_wb, hw_pp->idx);
phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
} else if (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg) {

View File

@ -24,7 +24,7 @@
#define DPU_MAX_IMG_WIDTH 0x3fff
#define DPU_MAX_IMG_HEIGHT 0x3fff
#define CRTC_QUAD_MIXERS 4
#define CRTC_DUAL_MIXERS 2
#define MAX_XIN_COUNT 16

View File

@ -89,13 +89,13 @@ enum dpu_hw_cdwn_op_mode_method_h_v {
*/
struct dpu_hw_cdm_ops {
/**
* Enable the CDM module
* @enable: Enable the CDM module
* @cdm Pointer to chroma down context
*/
int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
/**
* Enable/disable the connection with pingpong
* @bind_pingpong_blk: Enable/disable the connection with pingpong
* @cdm Pointer to chroma down context
* @pp pingpong block id.
*/

View File

@ -12,9 +12,9 @@
#include "dpu_hw_sspp.h"
/**
* dpu_ctl_mode_sel: Interface mode selection
* DPU_CTL_MODE_SEL_VID: Video mode interface
* DPU_CTL_MODE_SEL_CMD: Command mode interface
* enum dpu_ctl_mode_sel: Interface mode selection
* @DPU_CTL_MODE_SEL_VID: Video mode interface
* @DPU_CTL_MODE_SEL_CMD: Command mode interface
*/
enum dpu_ctl_mode_sel {
DPU_CTL_MODE_SEL_VID = 0,
@ -37,6 +37,7 @@ struct dpu_hw_stage_cfg {
* struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface
* @intf : Interface id
* @intf_master: Master interface id in the dual pipe topology
* @wb: Writeback mode
* @mode_3d: 3d mux configuration
* @merge_3d: 3d merge block used
* @intf_mode_sel: Interface mode, cmd / vid
@ -64,21 +65,21 @@ struct dpu_hw_intf_cfg {
*/
struct dpu_hw_ctl_ops {
/**
* kickoff hw operation for Sw controlled interfaces
* @trigger_start: kickoff hw operation for Sw controlled interfaces
* DSI cmd mode and WB interface are SW controlled
* @ctx : ctl path ctx pointer
*/
void (*trigger_start)(struct dpu_hw_ctl *ctx);
/**
* check if the ctl is started
* @is_started: check if the ctl is started
* @ctx : ctl path ctx pointer
* @Return: true if started, false if stopped
*/
bool (*is_started)(struct dpu_hw_ctl *ctx);
/**
* kickoff prepare is in progress hw operation for sw
* @trigger_pending: kickoff prepare is in progress hw operation for sw
* controlled interfaces: DSI cmd mode and WB interface
* are SW controlled
* @ctx : ctl path ctx pointer
@ -86,7 +87,7 @@ struct dpu_hw_ctl_ops {
void (*trigger_pending)(struct dpu_hw_ctl *ctx);
/**
* Clear the value of the cached pending_flush_mask
* @clear_pending_flush: Clear the value of the cached pending_flush_mask
* No effect on hardware.
* Required to be implemented.
* @ctx : ctl path ctx pointer
@ -94,14 +95,15 @@ struct dpu_hw_ctl_ops {
void (*clear_pending_flush)(struct dpu_hw_ctl *ctx);
/**
* Query the value of the cached pending_flush_mask
* @get_pending_flush: Query the value of the cached pending_flush_mask
* No effect on hardware
* @ctx : ctl path ctx pointer
*/
u32 (*get_pending_flush)(struct dpu_hw_ctl *ctx);
/**
* OR in the given flushbits to the cached pending_flush_mask
* @update_pending_flush: OR in the given flushbits to the cached
* pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @flushbits : module flushmask
@ -110,7 +112,8 @@ struct dpu_hw_ctl_ops {
u32 flushbits);
/**
* OR in the given flushbits to the cached pending_(wb_)flush_mask
* @update_pending_flush_wb: OR in the given flushbits to the
* cached pending_(wb_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : writeback block index
@ -119,7 +122,8 @@ struct dpu_hw_ctl_ops {
enum dpu_wb blk);
/**
* OR in the given flushbits to the cached pending_(cwb_)flush_mask
* @update_pending_flush_cwb: OR in the given flushbits to the
* cached pending_(cwb_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : concurrent writeback block index
@ -128,7 +132,8 @@ struct dpu_hw_ctl_ops {
enum dpu_cwb blk);
/**
* OR in the given flushbits to the cached pending_(intf_)flush_mask
* @update_pending_flush_intf: OR in the given flushbits to the
* cached pending_(intf_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@ -137,7 +142,8 @@ struct dpu_hw_ctl_ops {
enum dpu_intf blk);
/**
* OR in the given flushbits to the cached pending_(periph_)flush_mask
* @update_pending_flush_periph: OR in the given flushbits to the
* cached pending_(periph_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@ -146,7 +152,8 @@ struct dpu_hw_ctl_ops {
enum dpu_intf blk);
/**
* OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
* @update_pending_flush_merge_3d: OR in the given flushbits to the
* cached pending_(merge_3d_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@ -155,7 +162,8 @@ struct dpu_hw_ctl_ops {
enum dpu_merge_3d blk);
/**
* OR in the given flushbits to the cached pending_flush_mask
* @update_pending_flush_sspp: OR in the given flushbits to the
* cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : SSPP block index
@ -164,7 +172,8 @@ struct dpu_hw_ctl_ops {
enum dpu_sspp blk);
/**
* OR in the given flushbits to the cached pending_flush_mask
* @update_pending_flush_mixer: OR in the given flushbits to the
* cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : LM block index
@ -173,7 +182,8 @@ struct dpu_hw_ctl_ops {
enum dpu_lm blk);
/**
* OR in the given flushbits to the cached pending_flush_mask
* @update_pending_flush_dspp: OR in the given flushbits to the
* cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : DSPP block index
@ -183,7 +193,8 @@ struct dpu_hw_ctl_ops {
enum dpu_dspp blk, u32 dspp_sub_blk);
/**
* OR in the given flushbits to the cached pending_(dsc_)flush_mask
* @update_pending_flush_dsc: OR in the given flushbits to the
* cached pending_(dsc_)flush_mask.
* No effect on hardware
* @ctx: ctl path ctx pointer
* @blk: interface block index
@ -192,7 +203,8 @@ struct dpu_hw_ctl_ops {
enum dpu_dsc blk);
/**
* OR in the given flushbits to the cached pending_(cdm_)flush_mask
* @update_pending_flush_cdm: OR in the given flushbits to the
* cached pending_(cdm_)flush_mask.
* No effect on hardware
* @ctx: ctl path ctx pointer
* @cdm_num: idx of cdm to be flushed
@ -200,20 +212,20 @@ struct dpu_hw_ctl_ops {
void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num);
/**
* Write the value of the pending_flush_mask to hardware
* @trigger_flush: Write the value of the pending_flush_mask to hardware
* @ctx : ctl path ctx pointer
*/
void (*trigger_flush)(struct dpu_hw_ctl *ctx);
/**
* Read the value of the flush register
* @get_flush_register: Read the value of the flush register
* @ctx : ctl path ctx pointer
* @Return: value of the ctl flush register.
*/
u32 (*get_flush_register)(struct dpu_hw_ctl *ctx);
/**
* Setup ctl_path interface config
* @setup_intf_cfg: Setup ctl_path interface config
* @ctx
* @cfg : interface config structure pointer
*/
@ -221,17 +233,20 @@ struct dpu_hw_ctl_ops {
struct dpu_hw_intf_cfg *cfg);
/**
* reset ctl_path interface config
* @reset_intf_cfg: reset ctl_path interface config
* @ctx : ctl path ctx pointer
* @cfg : interface config structure pointer
*/
void (*reset_intf_cfg)(struct dpu_hw_ctl *ctx,
struct dpu_hw_intf_cfg *cfg);
/**
* @reset: reset function for this ctl type
*/
int (*reset)(struct dpu_hw_ctl *c);
/*
* wait_reset_status - checks ctl reset status
/**
* @wait_reset_status: checks ctl reset status
* @ctx : ctl path ctx pointer
*
* This function checks the ctl reset status bit.
@ -242,13 +257,13 @@ struct dpu_hw_ctl_ops {
int (*wait_reset_status)(struct dpu_hw_ctl *ctx);
/**
* Set all blend stages to disabled
* @clear_all_blendstages: Set all blend stages to disabled
* @ctx : ctl path ctx pointer
*/
void (*clear_all_blendstages)(struct dpu_hw_ctl *ctx);
/**
* Configure layer mixer to pipe configuration
* @setup_blendstage: Configure layer mixer to pipe configuration
* @ctx : ctl path ctx pointer
* @lm : layer mixer enumeration
* @cfg : blend stage configuration
@ -256,11 +271,16 @@ struct dpu_hw_ctl_ops {
void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
/**
* @set_active_fetch_pipes: Set active pipes attached to this CTL
* @ctx: ctl path ctx pointer
* @active_pipes: bitmap of enum dpu_sspp
*/
void (*set_active_fetch_pipes)(struct dpu_hw_ctl *ctx,
unsigned long *fetch_active);
/**
* Set active pipes attached to this CTL
* @set_active_pipes: Set active pipes attached to this CTL
* @ctx: ctl path ctx pointer
* @active_pipes: bitmap of enum dpu_sspp
*/
@ -268,13 +288,12 @@ struct dpu_hw_ctl_ops {
unsigned long *active_pipes);
/**
* Set active layer mixers attached to this CTL
* @set_active_lms: Set active layer mixers attached to this CTL
* @ctx: ctl path ctx pointer
* @active_lms: bitmap of enum dpu_lm
*/
void (*set_active_lms)(struct dpu_hw_ctl *ctx,
unsigned long *active_lms);
};
/**
@ -289,6 +308,9 @@ struct dpu_hw_ctl_ops {
* @pending_intf_flush_mask: pending INTF flush
* @pending_wb_flush_mask: pending WB flush
* @pending_cwb_flush_mask: pending CWB flush
* @pending_periph_flush_mask: pending PERIPH flush
* @pending_merge_3d_flush_mask: pending MERGE 3D flush
* @pending_dspp_flush_mask: pending DSPP flush
* @pending_dsc_flush_mask: pending DSC flush
* @pending_cdm_flush_mask: pending CDM flush
* @mdss_ver: MDSS revision information
@ -320,7 +342,7 @@ struct dpu_hw_ctl {
};
/**
* dpu_hw_ctl - convert base object dpu_hw_base to container
* to_dpu_hw_ctl - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/

View File

@ -28,7 +28,6 @@ struct dpu_hw_cwb_setup_cfg {
};
/**
*
* struct dpu_hw_cwb_ops : Interface to the cwb hw driver functions
* @config_cwb: configure CWB mux
*/
@ -54,7 +53,7 @@ struct dpu_hw_cwb {
};
/**
* dpu_hw_cwb - convert base object dpu_hw_base to container
* to_dpu_hw_cwb - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/

View File

@ -21,13 +21,13 @@ struct dpu_hw_dsc;
*/
struct dpu_hw_dsc_ops {
/**
* dsc_disable - disable dsc
* @dsc_disable: disable dsc
* @hw_dsc: Pointer to dsc context
*/
void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
/**
* dsc_config - configures dsc encoder
* @dsc_config: configures dsc encoder
* @hw_dsc: Pointer to dsc context
* @dsc: panel dsc parameters
* @mode: dsc topology mode to be set
@ -39,13 +39,17 @@ struct dpu_hw_dsc_ops {
u32 initial_lines);
/**
* dsc_config_thresh - programs panel thresholds
* @dsc_config_thresh: programs panel thresholds
* @hw_dsc: Pointer to dsc context
* @dsc: panel dsc parameters
*/
void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
struct drm_dsc_config *dsc);
/**
* @dsc_bind_pingpong_blk: binds pixel output from a DSC block
* to a pingpong block
*/
void (*dsc_bind_pingpong_blk)(struct dpu_hw_dsc *hw_dsc,
enum dpu_pingpong pp);
};

View File

@ -22,7 +22,7 @@ struct dpu_hw_pcc_coeff {
};
/**
* struct dpu_hw_pcc - pcc feature structure
* struct dpu_hw_pcc_cfg - pcc feature structure
* @r: red coefficients.
* @g: green coefficients.
* @b: blue coefficients.
@ -40,7 +40,7 @@ struct dpu_hw_pcc_cfg {
*/
struct dpu_hw_dspp_ops {
/**
* setup_pcc - setup dspp pcc
* @setup_pcc: setup_pcc - setup dspp pcc
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
@ -69,7 +69,7 @@ struct dpu_hw_dspp {
};
/**
* dpu_hw_dspp - convert base object dpu_hw_base to container
* to_dpu_hw_dspp - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/

View File

@ -57,11 +57,11 @@ struct dpu_hw_intf_cmd_mode_cfg {
/**
* struct dpu_hw_intf_ops : Interface to the interface Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @ setup_timing_gen : programs the timing engine
* @ setup_prog_fetch : enables/disables the programmable fetch logic
* @ enable_timing: enable/disable timing engine
* @ get_status: returns if timing engine is enabled or not
* @ get_line_count: reads current vertical line counter
* @setup_timing_gen : programs the timing engine
* @setup_prg_fetch : enables/disables the programmable fetch logic
* @enable_timing: enable/disable timing engine
* @get_status: returns if timing engine is enabled or not
* @get_line_count: reads current vertical line counter
* @bind_pingpong_blk: enable/disable the connection with pingpong which will
* feed pixels to this interface
* @setup_misr: enable/disable MISR
@ -70,12 +70,9 @@ struct dpu_hw_intf_cmd_mode_cfg {
* pointer and programs the tear check configuration
* @disable_tearcheck: Disables tearcheck block
* @connect_external_te: Read, modify, write to either set or clear listening to external TE
* Return: 1 if TE was originally connected, 0 if not, or -ERROR
* @get_vsync_info: Provides the programmed and current line_count
* @setup_autorefresh: Configure and enable the autorefresh config
* @get_autorefresh: Retrieve autorefresh config from hardware
* Return: 0 on success, -ETIMEDOUT on timeout
* Returns 1 if TE was originally connected, 0 if not, or -ERROR
* @vsync_sel: Select vsync signal for tear-effect configuration
* @disable_autorefresh: Disable autorefresh if enabled
* @program_intf_cmd_cfg: Program the DPU to interface datapath for command mode
*/
struct dpu_hw_intf_ops {
@ -109,9 +106,6 @@ struct dpu_hw_intf_ops {
void (*vsync_sel)(struct dpu_hw_intf *intf, enum dpu_vsync_source vsync_source);
/**
* Disable autorefresh if enabled
*/
void (*disable_autorefresh)(struct dpu_hw_intf *intf, uint32_t encoder_id, u16 vdisplay);
void (*program_intf_cmd_cfg)(struct dpu_hw_intf *intf,

View File

@ -25,39 +25,38 @@ struct dpu_hw_color3_cfg {
};
/**
*
* struct dpu_hw_lm_ops : Interface to the mixer Hw driver functions
* Assumption is these functions will be called after clocks are enabled
*/
struct dpu_hw_lm_ops {
/*
* Sets up mixer output width and height
/**
* @setup_mixer_out: Sets up mixer output width and height
* and border color if enabled
*/
void (*setup_mixer_out)(struct dpu_hw_mixer *ctx,
struct dpu_hw_mixer_cfg *cfg);
/*
* Alpha blending configuration
/**
* @setup_blend_config: Alpha blending configuration
* for the specified stage
*/
void (*setup_blend_config)(struct dpu_hw_mixer *ctx, uint32_t stage,
uint32_t fg_alpha, uint32_t bg_alpha, uint32_t blend_op);
/*
* Alpha color component selection from either fg or bg
/**
* @setup_alpha_out: Alpha color component selection from either fg or bg
*/
void (*setup_alpha_out)(struct dpu_hw_mixer *ctx, uint32_t mixer_op);
/**
* Clear layer mixer to pipe configuration
* @clear_all_blendstages: Clear layer mixer to pipe configuration
* @ctx : mixer ctx pointer
* Returns: 0 on success or -error
*/
int (*clear_all_blendstages)(struct dpu_hw_mixer *ctx);
/**
* Configure layer mixer to pipe configuration
* @setup_blendstage: Configure layer mixer to pipe configuration
* @ctx : mixer ctx pointer
* @lm : layer mixer enumeration
* @stage_cfg : blend stage configuration
@ -67,19 +66,19 @@ struct dpu_hw_lm_ops {
struct dpu_hw_stage_cfg *stage_cfg);
/**
* setup_border_color : enable/disable border color
* @setup_border_color : enable/disable border color
*/
void (*setup_border_color)(struct dpu_hw_mixer *ctx,
struct dpu_mdss_color *color,
u8 border_en);
/**
* setup_misr: Enable/disable MISR
* @setup_misr: Enable/disable MISR
*/
void (*setup_misr)(struct dpu_hw_mixer *ctx);
/**
* collect_misr: Read MISR signature
* @collect_misr: Read MISR signature
*/
int (*collect_misr)(struct dpu_hw_mixer *ctx, u32 *misr_value);
};

View File

@ -34,7 +34,7 @@
#define DPU_MAX_PLANES 4
#endif
#define STAGES_PER_PLANE 2
#define STAGES_PER_PLANE 1
#define PIPES_PER_STAGE 2
#define PIPES_PER_PLANE (PIPES_PER_STAGE * STAGES_PER_PLANE)
#ifndef DPU_MAX_DE_CURVES

View File

@ -12,7 +12,6 @@
struct dpu_hw_merge_3d;
/**
*
* struct dpu_hw_merge_3d_ops : Interface to the merge_3d Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @setup_3d_mode : enable 3D merge

View File

@ -34,7 +34,6 @@ struct dpu_hw_dither_cfg {
};
/**
*
* struct dpu_hw_pingpong_ops : Interface to the pingpong Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @enable_tearcheck: program and enable tear check block
@ -44,51 +43,52 @@ struct dpu_hw_dither_cfg {
*/
struct dpu_hw_pingpong_ops {
/**
* enables vysnc generation and sets up init value of
* @enable_tearcheck: enables vysnc generation and sets up init value of
* read pointer and programs the tear check cofiguration
*/
int (*enable_tearcheck)(struct dpu_hw_pingpong *pp,
struct dpu_hw_tear_check *cfg);
/**
* disables tear check block
* @disable_tearcheck: disables tear check block
*/
int (*disable_tearcheck)(struct dpu_hw_pingpong *pp);
/**
* read, modify, write to either set or clear listening to external TE
* @connect_external_te: read, modify, write to either set or clear
* listening to external TE
* @Return: 1 if TE was originally connected, 0 if not, or -ERROR
*/
int (*connect_external_te)(struct dpu_hw_pingpong *pp,
bool enable_external_te);
/**
* Obtain current vertical line counter
* @get_line_count: Obtain current vertical line counter
*/
u32 (*get_line_count)(struct dpu_hw_pingpong *pp);
/**
* Disable autorefresh if enabled
* @disable_autorefresh: Disable autorefresh if enabled
*/
void (*disable_autorefresh)(struct dpu_hw_pingpong *pp, uint32_t encoder_id, u16 vdisplay);
/**
* Setup dither matix for pingpong block
* @setup_dither: Setup dither matix for pingpong block
*/
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
/**
* Enable DSC
* @enable_dsc: Enable DSC
*/
int (*enable_dsc)(struct dpu_hw_pingpong *pp);
/**
* Disable DSC
* @disable_dsc: Disable DSC
*/
void (*disable_dsc)(struct dpu_hw_pingpong *pp);
/**
* Setup DSC
* @setup_dsc: Setup DSC
*/
int (*setup_dsc)(struct dpu_hw_pingpong *pp);
};

View File

@ -14,7 +14,7 @@ struct dpu_hw_sspp;
#define DPU_SSPP_MAX_PITCH_SIZE 0xffff
/**
/*
* Flags
*/
#define DPU_SSPP_FLIP_LR BIT(0)
@ -23,7 +23,7 @@ struct dpu_hw_sspp;
#define DPU_SSPP_ROT_90 BIT(3)
#define DPU_SSPP_SOLID_FILL BIT(4)
/**
/*
* Component indices
*/
enum {
@ -36,9 +36,10 @@ enum {
};
/**
* DPU_SSPP_RECT_SOLO - multirect disabled
* DPU_SSPP_RECT_0 - rect0 of a multirect pipe
* DPU_SSPP_RECT_1 - rect1 of a multirect pipe
* enum dpu_sspp_multirect_index - multirect mode
* @DPU_SSPP_RECT_SOLO: multirect disabled
* @DPU_SSPP_RECT_0: rect0 of a multirect pipe
* @DPU_SSPP_RECT_1: rect1 of a multirect pipe
*
* Note: HW supports multirect with either RECT0 or
* RECT1. Considering no benefit of such configs over
@ -143,7 +144,7 @@ struct dpu_hw_pixel_ext {
* struct dpu_sw_pipe_cfg : software pipe configuration
* @src_rect: src ROI, caller takes into account the different operations
* such as decimation, flip etc to program this field
* @dest_rect: destination ROI.
* @dst_rect: destination ROI.
* @rotation: simplified drm rotation hint
*/
struct dpu_sw_pipe_cfg {
@ -165,8 +166,8 @@ struct dpu_hw_pipe_ts_cfg {
/**
* struct dpu_sw_pipe - software pipe description
* @sspp: backing SSPP pipe
* @index: index of the rectangle of SSPP
* @mode: parallel or time multiplex multirect mode
* @multirect_index: index of the rectangle of SSPP
* @multirect_mode: parallel or time multiplex multirect mode
*/
struct dpu_sw_pipe {
struct dpu_hw_sspp *sspp;
@ -181,7 +182,7 @@ struct dpu_sw_pipe {
*/
struct dpu_hw_sspp_ops {
/**
* setup_format - setup pixel format cropping rectangle, flip
* @setup_format: setup pixel format cropping rectangle, flip
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
* @flags: Extra flags for format config
@ -190,7 +191,7 @@ struct dpu_hw_sspp_ops {
const struct msm_format *fmt, u32 flags);
/**
* setup_rects - setup pipe ROI rectangles
* @setup_rects: setup pipe ROI rectangles
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
*/
@ -198,7 +199,7 @@ struct dpu_hw_sspp_ops {
struct dpu_sw_pipe_cfg *cfg);
/**
* setup_pe - setup pipe pixel extension
* @setup_pe: setup pipe pixel extension
* @ctx: Pointer to pipe context
* @pe_ext: Pointer to pixel ext settings
*/
@ -206,7 +207,7 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_pixel_ext *pe_ext);
/**
* setup_sourceaddress - setup pipe source addresses
* @setup_sourceaddress: setup pipe source addresses
* @pipe: Pointer to software pipe context
* @layout: format layout information for programming buffer to hardware
*/
@ -214,14 +215,14 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_fmt_layout *layout);
/**
* setup_csc - setup color space coversion
* @setup_csc: setup color space coversion
* @ctx: Pointer to pipe context
* @data: Pointer to config structure
*/
void (*setup_csc)(struct dpu_hw_sspp *ctx, const struct dpu_csc_cfg *data);
/**
* setup_solidfill - enable/disable colorfill
* @setup_solidfill: enable/disable colorfill
* @pipe: Pointer to software pipe context
* @const_color: Fill color value
* @flags: Pipe flags
@ -229,23 +230,22 @@ struct dpu_hw_sspp_ops {
void (*setup_solidfill)(struct dpu_sw_pipe *pipe, u32 color);
/**
* setup_multirect - setup multirect configuration
* @setup_multirect: setup multirect configuration
* @pipe: Pointer to software pipe context
*/
void (*setup_multirect)(struct dpu_sw_pipe *pipe);
/**
* setup_sharpening - setup sharpening
* @setup_sharpening: setup sharpening
* @ctx: Pointer to pipe context
* @cfg: Pointer to config structure
*/
void (*setup_sharpening)(struct dpu_hw_sspp *ctx,
struct dpu_hw_sharp_cfg *cfg);
/**
* setup_qos_lut - setup QoS LUTs
* @setup_qos_lut: setup QoS LUTs
* @ctx: Pointer to pipe context
* @cfg: LUT configuration
*/
@ -253,7 +253,7 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_qos_cfg *cfg);
/**
* setup_qos_ctrl - setup QoS control
* @setup_qos_ctrl: setup QoS control
* @ctx: Pointer to pipe context
* @danger_safe_en: flags controlling enabling of danger/safe QoS/LUT
*/
@ -261,7 +261,7 @@ struct dpu_hw_sspp_ops {
bool danger_safe_en);
/**
* setup_clk_force_ctrl - setup clock force control
* @setup_clk_force_ctrl: setup clock force control
* @ctx: Pointer to pipe context
* @enable: enable clock force if true
*/
@ -269,7 +269,7 @@ struct dpu_hw_sspp_ops {
bool enable);
/**
* setup_histogram - setup histograms
* @setup_histogram: setup histograms
* @ctx: Pointer to pipe context
* @cfg: Pointer to histogram configuration
*/
@ -277,7 +277,7 @@ struct dpu_hw_sspp_ops {
void *cfg);
/**
* setup_scaler - setup scaler
* @setup_scaler: setup scaler
* @scaler3_cfg: Pointer to scaler configuration
* @format: pixel format parameters
*/
@ -286,7 +286,7 @@ struct dpu_hw_sspp_ops {
const struct msm_format *format);
/**
* setup_cdp - setup client driven prefetch
* @setup_cdp: setup client driven prefetch
* @pipe: Pointer to software pipe context
* @fmt: format used by the sw pipe
* @enable: whether the CDP should be enabled for this pipe
@ -303,6 +303,7 @@ struct dpu_hw_sspp_ops {
* @ubwc: UBWC configuration data
* @idx: pipe index
* @cap: pointer to layer_cfg
* @mdss_ver: MDSS version info to use for feature checks
* @ops: pointer to operations possible for this pipe
*/
struct dpu_hw_sspp {

View File

@ -77,12 +77,11 @@ enum dpu_dp_phy_sel {
/**
* struct dpu_hw_mdp_ops - interface to the MDP TOP Hw driver functions
* Assumption is these functions will be called after clocks are enabled.
* @setup_split_pipe : Programs the pipe control registers
* @setup_pp_split : Programs the pp split control registers
* @setup_traffic_shaper : programs traffic shaper control
*/
struct dpu_hw_mdp_ops {
/** setup_split_pipe() : Registers are not double buffered, thisk
/**
* @setup_split_pipe : Programs the pipe control registers.
* Registers are not double buffered, this
* function should be called before timing control enable
* @mdp : mdp top context driver
* @cfg : upper and lower part of pipe configuration
@ -91,7 +90,7 @@ struct dpu_hw_mdp_ops {
struct split_pipe_cfg *p);
/**
* setup_traffic_shaper() : Setup traffic shaper control
* @setup_traffic_shaper : programs traffic shaper control.
* @mdp : mdp top context driver
* @cfg : traffic shaper configuration
*/
@ -99,7 +98,7 @@ struct dpu_hw_mdp_ops {
struct traffic_shaper_cfg *cfg);
/**
* setup_clk_force_ctrl - set clock force control
* @setup_clk_force_ctrl: set clock force control
* @mdp: mdp top context driver
* @clk_ctrl: clock to be controlled
* @enable: force on enable
@ -109,7 +108,7 @@ struct dpu_hw_mdp_ops {
enum dpu_clk_ctrl_type clk_ctrl, bool enable);
/**
* get_danger_status - get danger status
* @get_danger_status: get danger status
* @mdp: mdp top context driver
* @status: Pointer to danger safe status
*/
@ -117,7 +116,7 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
* setup_vsync_source - setup vsync source configuration details
* @setup_vsync_source: setup vsync source configuration details
* @mdp: mdp top context driver
* @cfg: vsync source selection configuration
*/
@ -125,7 +124,7 @@ struct dpu_hw_mdp_ops {
struct dpu_vsync_source_cfg *cfg);
/**
* get_safe_status - get safe status
* @get_safe_status: get safe status
* @mdp: mdp top context driver
* @status: Pointer to danger safe status
*/
@ -133,14 +132,14 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
* dp_phy_intf_sel - configure intf to phy mapping
* @dp_phy_intf_sel: configure intf to phy mapping
* @mdp: mdp top context driver
* @phys: list of phys the DP interfaces should be connected to. 0 disables the INTF.
*/
void (*dp_phy_intf_sel)(struct dpu_hw_mdp *mdp, enum dpu_dp_phy_sel phys[2]);
/**
* intf_audio_select - select the external interface for audio
* @intf_audio_select: select the external interface for audio
* @mdp: mdp top context driver
*/
void (*intf_audio_select)(struct dpu_hw_mdp *mdp);

View File

@ -17,7 +17,7 @@ struct dpu_hw_vbif;
*/
struct dpu_hw_vbif_ops {
/**
* set_limit_conf - set transaction limit config
* @set_limit_conf: set transaction limit config
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @rd: true for read limit; false for write limit
@ -27,7 +27,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool rd, u32 limit);
/**
* get_limit_conf - get transaction limit config
* @get_limit_conf: get transaction limit config
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @rd: true for read limit; false for write limit
@ -37,7 +37,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool rd);
/**
* set_halt_ctrl - set halt control
* @set_halt_ctrl: set halt control
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @enable: halt control enable
@ -46,7 +46,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool enable);
/**
* get_halt_ctrl - get halt control
* @get_halt_ctrl: get halt control
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @return: halt control enable
@ -55,7 +55,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id);
/**
* set_qos_remap - set QoS priority remap
* @set_qos_remap: set QoS priority remap
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @level: priority level
@ -65,7 +65,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, u32 level, u32 remap_level);
/**
* set_mem_type - set memory type
* @set_mem_type: set memory type
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @value: memory type value
@ -74,7 +74,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, u32 value);
/**
* clear_errors - clear any vbif errors
* @clear_errors: clear any vbif errors
* This function clears any detected pending/source errors
* on the VBIF interface, and optionally returns the detected
* error mask(s).
@ -86,7 +86,7 @@ struct dpu_hw_vbif_ops {
u32 *pnd_errors, u32 *src_errors);
/**
* set_write_gather_en - set write_gather enable
* @set_write_gather_en: set write_gather enable
* @vbif: vbif context driver
* @xin_id: client interface identifier
*/

View File

@ -22,11 +22,11 @@ struct dpu_hw_wb_cfg {
};
/**
*
* struct dpu_hw_wb_ops : Interface to the wb hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @setup_outaddress: setup output address from the writeback job
* @setup_outformat: setup output format of writeback block from writeback job
* @setup_roi: setup ROI (Region of Interest) parameters
* @setup_qos_lut: setup qos LUT for writeback block based on input
* @setup_cdp: setup chroma down prefetch block for writeback block
* @setup_clk_force_ctrl: setup clock force control
@ -61,7 +61,7 @@ struct dpu_hw_wb_ops {
* struct dpu_hw_wb : WB driver object
* @hw: block hardware details
* @idx: hardware index number within type
* @wb_hw_caps: hardware capabilities
* @caps: hardware capabilities
* @ops: function pointers
*/
struct dpu_hw_wb {

View File

@ -826,12 +826,8 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
struct dpu_sw_pipe_cfg *pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg;
struct dpu_sw_pipe_cfg init_pipe_cfg;
struct drm_rect fb_rect = { 0 };
const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
uint32_t max_linewidth;
u32 num_lm;
int stage_id, num_stages;
min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
max_scale = MAX_DOWNSCALE_RATIO << 16;
@ -854,10 +850,13 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
return -EINVAL;
}
num_lm = dpu_crtc_get_num_lm(crtc_state);
/* move the assignment here, to ease handling to another pairs later */
pipe_cfg = &pstate->pipe_cfg[0];
r_pipe_cfg = &pstate->pipe_cfg[1];
/* state->src is 16.16, src_rect is not */
drm_rect_fp_to_int(&init_pipe_cfg.src_rect, &new_plane_state->src);
drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
pipe_cfg->dst_rect = new_plane_state->dst;
fb_rect.x2 = new_plane_state->fb->width;
fb_rect.y2 = new_plane_state->fb->height;
@ -882,94 +881,35 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
max_linewidth = pdpu->catalog->caps->max_linewidth;
drm_rect_rotate(&init_pipe_cfg.src_rect,
drm_rect_rotate(&pipe_cfg->src_rect,
new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
/*
* We have 1 mixer pair cfg for 1:1:1 and 2:2:1 topology, 2 mixer pair
* configs for left and right half screen in case of 4:4:2 topology.
* But we may have 2 rect to split wide plane that exceeds limit with 1
* config for 2:2:1. So need to handle both wide plane splitting, and
* two halves of screen splitting for quad-pipe case. Check dest
* rectangle left/right clipping first, then check wide rectangle
* splitting in every half next.
*/
num_stages = (num_lm + 1) / 2;
/* iterate mixer configs for this plane, to separate left/right with the id */
for (stage_id = 0; stage_id < num_stages; stage_id++) {
struct drm_rect mixer_rect = {
.x1 = stage_id * mode->hdisplay / num_stages,
.y1 = 0,
.x2 = (stage_id + 1) * mode->hdisplay / num_stages,
.y2 = mode->vdisplay
};
int cfg_idx = stage_id * PIPES_PER_STAGE;
pipe_cfg = &pstate->pipe_cfg[cfg_idx];
r_pipe_cfg = &pstate->pipe_cfg[cfg_idx + 1];
drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
pipe_cfg->dst_rect = new_plane_state->dst;
DPU_DEBUG_PLANE(pdpu, "checking src " DRM_RECT_FMT
" vs clip window " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_cfg->src_rect),
DRM_RECT_ARG(&mixer_rect));
/*
* If this plane does not fall into mixer rect, check next
* mixer rect.
*/
if (!drm_rect_clip_scaled(&pipe_cfg->src_rect,
&pipe_cfg->dst_rect,
&mixer_rect)) {
memset(pipe_cfg, 0, 2 * sizeof(struct dpu_sw_pipe_cfg));
continue;
if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
_dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {
if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
return -E2BIG;
}
pipe_cfg->dst_rect.x1 -= mixer_rect.x1;
pipe_cfg->dst_rect.x2 -= mixer_rect.x1;
DPU_DEBUG_PLANE(pdpu, "Got clip src:" DRM_RECT_FMT " dst: " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_cfg->src_rect), DRM_RECT_ARG(&pipe_cfg->dst_rect));
/* Split wide rect into 2 rect */
if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
_dpu_plane_calc_clk(mode, pipe_cfg) > max_mdp_clk_rate) {
if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
return -E2BIG;
}
memcpy(r_pipe_cfg, pipe_cfg, sizeof(struct dpu_sw_pipe_cfg));
pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
DPU_DEBUG_PLANE(pdpu, "Split wide plane into:"
DRM_RECT_FMT " and " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_cfg->src_rect),
DRM_RECT_ARG(&r_pipe_cfg->src_rect));
} else {
memset(r_pipe_cfg, 0, sizeof(struct dpu_sw_pipe_cfg));
}
drm_rect_rotate_inv(&pipe_cfg->src_rect,
new_plane_state->fb->width,
new_plane_state->fb->height,
new_plane_state->rotation);
if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
new_plane_state->fb->width,
new_plane_state->fb->height,
new_plane_state->rotation);
*r_pipe_cfg = *pipe_cfg;
pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
} else {
memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg));
}
drm_rect_rotate_inv(&pipe_cfg->src_rect,
new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
return 0;
@ -1045,17 +985,20 @@ static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
drm_atomic_get_new_plane_state(state, plane);
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
struct dpu_sw_pipe *pipe;
struct dpu_sw_pipe_cfg *pipe_cfg;
int ret = 0, i;
struct dpu_sw_pipe *pipe = &pstate->pipe[0];
struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
int ret = 0;
for (i = 0; i < PIPES_PER_PLANE; i++) {
pipe = &pstate->pipe[i];
pipe_cfg = &pstate->pipe_cfg[i];
if (!drm_rect_width(&pipe_cfg->src_rect))
continue;
DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i);
ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
&crtc_state->adjusted_mode,
new_plane_state);
if (ret)
return ret;
if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) {
ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg,
&crtc_state->adjusted_mode,
new_plane_state);
if (ret)

View File

@ -24,7 +24,7 @@ enum msm_format_flags {
#define MSM_FORMAT_FLAG_UNPACK_TIGHT BIT(MSM_FORMAT_FLAG_UNPACK_TIGHT_BIT)
#define MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB BIT(MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB_BIT)
/**
/*
* DPU HW,Component order color map
*/
enum {
@ -37,6 +37,10 @@ enum {
/**
* struct msm_format: defines the format configuration
* @pixel_format: format fourcc
* @bpc_g_y: element bit widths: BPC for G or Y
* @bpc_b_cb: element bit widths: BPC for B or Cb
* @bpc_r_cr: element bit widths: BPC for R or Cr
* @bpc_a: element bit widths: BPC for the alpha channel
* @element: element color ordering
* @fetch_type: how the color components are packed in pixel format
* @chroma_sample: chroma sub-samplng type

View File

@ -12,7 +12,7 @@
#if defined(CONFIG_DEBUG_FS)
/**
* msm_dp_debug_get() - configure and get the DisplayPlot debug module data
* msm_dp_debug_init() - configure and get the DisplayPlot debug module data
*
* @dev: device instance of the caller
* @panel: instance of panel module

View File

@ -18,6 +18,7 @@
/**
* msm_dp_bridge_detect - callback to determine if connector is connected
* @bridge: Pointer to drm bridge structure
* @connector: Pointer to drm connector structure
* Returns: Bridge's 'is connected' status
*/
static enum drm_connector_status

View File

@ -80,11 +80,11 @@ struct msm_dp_link {
};
/**
* mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
* msm_dp_link_bit_depth_to_bpp() - convert test bit depth to bpp
* @tbd: test bit depth
*
* Returns the bits per pixel (bpp) to be used corresponding to the
* git bit depth value. This function assumes that bit depth has
* Returns: the bits per pixel (bpp) to be used corresponding to the
* bit depth value. This function assumes that bit depth has
* already been validated.
*/
static inline u32 msm_dp_link_bit_depth_to_bpp(u32 tbd)
@ -120,7 +120,8 @@ bool msm_dp_link_send_edid_checksum(struct msm_dp_link *msm_dp_link, u8 checksum
/**
* msm_dp_link_get() - get the functionalities of dp test module
*
* @dev: kernel device structure
* @aux: DisplayPort AUX channel
*
* return: a pointer to msm_dp_link struct
*/

View File

@ -63,9 +63,9 @@ void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel);
/**
* is_link_rate_valid() - validates the link rate
* @lane_rate: link rate requested by the sink
* @bw_code: link rate requested by the sink
*
* Returns true if the requested link rate is supported.
* Returns: true if the requested link rate is supported.
*/
static inline bool is_link_rate_valid(u32 bw_code)
{
@ -76,10 +76,10 @@ static inline bool is_link_rate_valid(u32 bw_code)
}
/**
* msm_dp_link_is_lane_count_valid() - validates the lane count
* is_lane_count_valid() - validates the lane count
* @lane_count: lane count requested by the sink
*
* Returns true if the requested lane count is supported.
* Returns: true if the requested lane count is supported.
*/
static inline bool is_lane_count_valid(u32 lane_count)
{

View File

@ -16,34 +16,29 @@
* incrementing fence seqno at the end of each submit
*/
struct msm_fence_context {
/** @dev: the drm device */
struct drm_device *dev;
/** name: human readable name for fence timeline */
/** @name: human readable name for fence timeline */
char name[32];
/** context: see dma_fence_context_alloc() */
/** @context: see dma_fence_context_alloc() */
unsigned context;
/** index: similar to context, but local to msm_fence_context's */
/** @index: similar to context, but local to msm_fence_context's */
unsigned index;
/**
* last_fence:
*
* @last_fence:
* Last assigned fence, incremented each time a fence is created
* on this fence context. If last_fence == completed_fence,
* there is no remaining pending work
*/
uint32_t last_fence;
/**
* completed_fence:
*
* @completed_fence:
* The last completed fence, updated from the CPU after interrupt
* from GPU
*/
uint32_t completed_fence;
/**
* fenceptr:
*
* @fenceptr:
* The address that the GPU directly writes with completed fence
* seqno. This can be ahead of completed_fence. We can peek at
* this to see if a fence has already signaled but the CPU hasn't
@ -51,6 +46,9 @@ struct msm_fence_context {
*/
volatile uint32_t *fenceptr;
/**
* @spinlock: fence context spinlock
*/
spinlock_t spinlock;
/*
@ -59,18 +57,22 @@ struct msm_fence_context {
* don't queue, so maybe that is ok
*/
/** next_deadline: Time of next deadline */
/** @next_deadline: Time of next deadline */
ktime_t next_deadline;
/**
* next_deadline_fence:
*
* @next_deadline_fence:
* Fence value for next pending deadline. The deadline timer is
* canceled when this fence is signaled.
*/
uint32_t next_deadline_fence;
/**
* @deadline_timer: tracks nearest deadline of a fence timeline and
* expires just before it.
*/
struct hrtimer deadline_timer;
/**
* @deadline_work: work to do after deadline_timer expires
*/
struct kthread_work deadline_work;
};

View File

@ -65,7 +65,7 @@ struct msm_vm_unmap_op {
};
/**
* struct msm_vma_op - A MAP or UNMAP operation
* struct msm_vm_op - A MAP or UNMAP operation
*/
struct msm_vm_op {
/** @op: The operation type */
@ -798,6 +798,9 @@ static const struct drm_sched_backend_ops msm_vm_bind_ops = {
* synchronous operations are supported. In a user managed VM, userspace
* handles virtual address allocation, and both async and sync operations
* are supported.
*
* Returns: pointer to the created &struct drm_gpuvm on success
* or an ERR_PTR(-errno) on failure.
*/
struct drm_gpuvm *
msm_gem_vm_create(struct drm_device *drm, struct msm_mmu *mmu, const char *name,

View File

@ -116,15 +116,12 @@ struct msm_gpu_fault_info {
* struct msm_gpu_devfreq - devfreq related state
*/
struct msm_gpu_devfreq {
/** devfreq: devfreq instance */
/** @devfreq: devfreq instance */
struct devfreq *devfreq;
/** lock: lock for "suspended", "busy_cycles", and "time" */
/** @lock: lock for "suspended", "busy_cycles", and "time" */
struct mutex lock;
/**
* idle_freq:
*
* @idle_freq:
* Shadow frequency used while the GPU is idle. From the PoV of
* the devfreq governor, we are continuing to sample busyness and
* adjust frequency while the GPU is idle, but we use this shadow
@ -132,43 +129,34 @@ struct msm_gpu_devfreq {
* it is inactive.
*/
unsigned long idle_freq;
/**
* boost_constraint:
*
* @boost_freq:
* A PM QoS constraint to boost min freq for a period of time
* until the boost expires.
*/
struct dev_pm_qos_request boost_freq;
/**
* busy_cycles: Last busy counter value, for calculating elapsed busy
* @busy_cycles: Last busy counter value, for calculating elapsed busy
* cycles since last sampling period.
*/
u64 busy_cycles;
/** time: Time of last sampling period. */
/** @time: Time of last sampling period. */
ktime_t time;
/** idle_time: Time of last transition to idle: */
/** @idle_time: Time of last transition to idle. */
ktime_t idle_time;
/**
* idle_work:
*
* @idle_work:
* Used to delay clamping to idle freq on active->idle transition.
*/
struct msm_hrtimer_work idle_work;
/**
* boost_work:
*
* @boost_work:
* Used to reset the boost_constraint after the boost period has
* elapsed
*/
struct msm_hrtimer_work boost_work;
/** suspended: tracks if we're suspended */
/** @suspended: tracks if we're suspended */
bool suspended;
};
@ -358,57 +346,43 @@ struct msm_gpu_perfcntr {
struct msm_context {
/** @queuelock: synchronizes access to submitqueues list */
rwlock_t queuelock;
/** @submitqueues: list of &msm_gpu_submitqueue created by userspace */
struct list_head submitqueues;
/**
* @queueid:
*
* Counter incremented each time a submitqueue is created, used to
* assign &msm_gpu_submitqueue.id
*/
int queueid;
/**
* @closed: The device file associated with this context has been closed.
*
* Once the device is closed, any submits that have not been written
* to the ring buffer are no-op'd.
*/
bool closed;
/**
* @userspace_managed_vm:
*
* Has userspace opted-in to userspace managed VM (ie. VM_BIND) via
* MSM_PARAM_EN_VM_BIND?
*/
bool userspace_managed_vm;
/**
* @vm:
*
* The per-process GPU address-space. Do not access directly, use
* msm_context_vm().
*/
struct drm_gpuvm *vm;
/** @kref: the reference count */
/** @ref: the reference count */
struct kref ref;
/**
* @seqno:
*
* A unique per-process sequence number. Used to detect context
* switches, without relying on keeping a, potentially dangling,
* pointer to the previous context.
*/
int seqno;
/**
* @sysprof:
*
* The value of MSM_PARAM_SYSPROF set by userspace. This is
* intended to be used by system profiling tools like Mesa's
* pps-producer (perfetto), and restricted to CAP_SYS_ADMIN.
@ -423,40 +397,32 @@ struct msm_context {
* file is closed.
*/
int sysprof;
/**
* @comm: Overridden task comm, see MSM_PARAM_COMM
*
* Accessed under msm_gpu::lock
*/
char *comm;
/**
* @cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE
*
* Accessed under msm_gpu::lock
*/
char *cmdline;
/**
* @elapsed:
*
* @elapsed_ns:
* The total (cumulative) elapsed time GPU was busy with rendering
* from this context in ns.
*/
uint64_t elapsed_ns;
/**
* @cycles:
*
* The total (cumulative) GPU cycles elapsed attributed to this
* context.
*/
uint64_t cycles;
/**
* @entities:
*
* Table of per-priority-level sched entities used by submitqueues
* associated with this &drm_file. Because some userspace apps
* make assumptions about rendering from multiple gl contexts
@ -466,10 +432,8 @@ struct msm_context {
* level.
*/
struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
/**
* @ctx_mem:
*
* Total amount of memory of GEM buffers with handles attached for
* this context.
*/
@ -479,7 +443,7 @@ struct msm_context {
struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx);
/**
* msm_context_is_vm_bind() - has userspace opted in to VM_BIND?
* msm_context_is_vmbind() - has userspace opted in to VM_BIND?
*
* @ctx: the drm_file context
*
@ -487,6 +451,8 @@ struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx
* do sparse binding including having multiple, potentially partial,
* mappings in the VM. Therefore certain legacy uabi (ie. GET_IOVA,
* SET_IOVA) are rejected because they don't have a sensible meaning.
*
* Returns: %true if userspace is managing the VM, %false otherwise.
*/
static inline bool
msm_context_is_vmbind(struct msm_context *ctx)
@ -518,6 +484,8 @@ msm_context_is_vmbind(struct msm_context *ctx)
* This allows generations without preemption (nr_rings==1) to have some
* amount of prioritization, and provides more priority levels for gens
* that do have preemption.
*
* Returns: %0 on success, %-errno on error.
*/
static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
unsigned *ring_nr, enum drm_sched_priority *sched_prio)
@ -541,7 +509,7 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
}
/**
* struct msm_gpu_submitqueues - Userspace created context.
* struct msm_gpu_submitqueue - Userspace created context.
*
* A submitqueue is associated with a gl context or vk queue (or equiv)
* in userspace.

View File

@ -364,7 +364,7 @@ msm_iommu_pagetable_prealloc_cleanup(struct msm_mmu *mmu, struct msm_mmu_preallo
}
/**
* alloc_pt() - Custom page table allocator
* msm_iommu_pagetable_alloc_pt() - Custom page table allocator
* @cookie: Cookie passed at page table allocation time.
* @size: Size of the page table. This size should be fixed,
* and determined at creation time based on the granule size.
@ -416,7 +416,7 @@ msm_iommu_pagetable_alloc_pt(void *cookie, size_t size, gfp_t gfp)
/**
* free_pt() - Custom page table free function
* msm_iommu_pagetable_free_pt() - Custom page table free function
* @cookie: Cookie passed at page table allocation time.
* @data: Page table to free.
* @size: Size of the page table. This size should be fixed,

View File

@ -65,13 +65,13 @@ static int refill_buf(struct msm_perf_state *perf)
if ((perf->cnt++ % 32) == 0) {
/* Header line: */
n = snprintf(ptr, rem, "%%BUSY");
n = scnprintf(ptr, rem, "%%BUSY");
ptr += n;
rem -= n;
for (i = 0; i < gpu->num_perfcntrs; i++) {
const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
n = snprintf(ptr, rem, "\t%s", perfcntr->name);
n = scnprintf(ptr, rem, "\t%s", perfcntr->name);
ptr += n;
rem -= n;
}
@ -93,21 +93,21 @@ static int refill_buf(struct msm_perf_state *perf)
return ret;
val = totaltime ? 1000 * activetime / totaltime : 0;
n = snprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
n = scnprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
ptr += n;
rem -= n;
for (i = 0; i < ret; i++) {
/* cycle counters (I think).. convert to MHz.. */
val = cntrs[i] / 10000;
n = snprintf(ptr, rem, "\t%5d.%02d",
n = scnprintf(ptr, rem, "\t%5d.%02d",
val / 100, val % 100);
ptr += n;
rem -= n;
}
}
n = snprintf(ptr, rem, "\n");
n = scnprintf(ptr, rem, "\n");
ptr += n;
rem -= n;

View File

@ -152,8 +152,21 @@ static inline struct nv50_head_atom *
nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(statec))
return (void *)statec;
return nv50_head_atom(statec);
}
static inline struct nv50_head_atom *
nv50_head_atom_get_new(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_crtc_state *statec = drm_atomic_get_new_crtc_state(state, crtc);
if (!statec)
return NULL;
return nv50_head_atom(statec);
}

View File

@ -583,7 +583,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
asyw->image.offset[0] = nvbo->offset;
if (wndw->func->prepare) {
asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
asyh = nv50_head_atom_get_new(asyw->state.state, asyw->state.crtc);
if (IS_ERR(asyh))
return PTR_ERR(asyh);

View File

@ -104,7 +104,9 @@ static void g2h_fence_cancel(struct g2h_fence *g2h_fence)
{
g2h_fence->cancel = true;
g2h_fence->fail = true;
g2h_fence->done = true;
/* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
WRITE_ONCE(g2h_fence->done, true);
}
static bool g2h_fence_needs_alloc(struct g2h_fence *g2h_fence)
@ -1203,10 +1205,13 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len,
return ret;
}
ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ);
/* READ_ONCEs pairs with WRITE_ONCEs in parse_g2h_response
* and g2h_fence_cancel.
*/
ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ);
if (!ret) {
LNL_FLUSH_WORK(&ct->g2h_worker);
if (g2h_fence.done) {
if (READ_ONCE(g2h_fence.done)) {
xe_gt_warn(gt, "G2H fence %u, action %04x, done\n",
g2h_fence.seqno, action[0]);
ret = 1;
@ -1454,7 +1459,8 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len)
g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
g2h_fence->done = true;
/* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
WRITE_ONCE(g2h_fence->done, true);
smp_mb();
wake_up_all(&ct->g2h_fence_wq);

View File

@ -2062,6 +2062,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
unsigned long sram_offset,
struct drm_pagemap_addr *sram_addr,
u64 vram_addr,
struct dma_fence *deps,
const enum xe_migrate_copy_dir dir)
{
struct xe_gt *gt = m->tile->primary_gt;
@ -2150,6 +2151,14 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
xe_sched_job_add_migrate_flush(job, MI_INVALIDATE_TLB);
if (deps && !dma_fence_is_signaled(deps)) {
dma_fence_get(deps);
err = drm_sched_job_add_dependency(&job->drm, deps);
if (err)
dma_fence_wait(deps, false);
err = 0;
}
mutex_lock(&m->job_mutex);
xe_sched_job_arm(job);
fence = dma_fence_get(&job->drm.s_fence->finished);
@ -2175,6 +2184,8 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
* @npages: Number of pages to migrate.
* @src_addr: Array of DMA information (source of migrate)
* @dst_addr: Device physical address of VRAM (destination of migrate)
* @deps: struct dma_fence representing the dependencies that need
* to be signaled before migration.
*
* Copy from an array dma addresses to a VRAM device physical address
*
@ -2184,10 +2195,11 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
unsigned long npages,
struct drm_pagemap_addr *src_addr,
u64 dst_addr)
u64 dst_addr,
struct dma_fence *deps)
{
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, src_addr, dst_addr,
XE_MIGRATE_COPY_TO_VRAM);
deps, XE_MIGRATE_COPY_TO_VRAM);
}
/**
@ -2196,6 +2208,8 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
* @npages: Number of pages to migrate.
* @src_addr: Device physical address of VRAM (source of migrate)
* @dst_addr: Array of DMA information (destination of migrate)
* @deps: struct dma_fence representing the dependencies that need
* to be signaled before migration.
*
* Copy from a VRAM device physical address to an array dma addresses
*
@ -2205,10 +2219,11 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
unsigned long npages,
u64 src_addr,
struct drm_pagemap_addr *dst_addr)
struct drm_pagemap_addr *dst_addr,
struct dma_fence *deps)
{
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, dst_addr, src_addr,
XE_MIGRATE_COPY_TO_SRAM);
deps, XE_MIGRATE_COPY_TO_SRAM);
}
static void xe_migrate_dma_unmap(struct xe_device *xe,
@ -2384,7 +2399,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
__fence = xe_migrate_vram(m, current_bytes,
(unsigned long)buf & ~PAGE_MASK,
&pagemap_addr[current_page],
vram_addr, write ?
vram_addr, NULL, write ?
XE_MIGRATE_COPY_TO_VRAM :
XE_MIGRATE_COPY_TO_SRAM);
if (IS_ERR(__fence)) {

View File

@ -116,12 +116,14 @@ int xe_migrate_init(struct xe_migrate *m);
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
unsigned long npages,
struct drm_pagemap_addr *src_addr,
u64 dst_addr);
u64 dst_addr,
struct dma_fence *deps);
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
unsigned long npages,
u64 src_addr,
struct drm_pagemap_addr *dst_addr);
struct drm_pagemap_addr *dst_addr,
struct dma_fence *deps);
struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
struct xe_bo *src_bo,

View File

@ -476,7 +476,8 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt,
static int xe_svm_copy(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
unsigned long npages, const enum xe_svm_copy_dir dir)
unsigned long npages, const enum xe_svm_copy_dir dir,
struct dma_fence *pre_migrate_fence)
{
struct xe_vram_region *vr = NULL;
struct xe_gt *gt = NULL;
@ -565,7 +566,8 @@ static int xe_svm_copy(struct page **pages,
__fence = xe_migrate_from_vram(vr->migrate,
i - pos + incr,
vram_addr,
&pagemap_addr[pos]);
&pagemap_addr[pos],
pre_migrate_fence);
} else {
vm_dbg(&xe->drm,
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%ld",
@ -574,13 +576,14 @@ static int xe_svm_copy(struct page **pages,
__fence = xe_migrate_to_vram(vr->migrate,
i - pos + incr,
&pagemap_addr[pos],
vram_addr);
vram_addr,
pre_migrate_fence);
}
if (IS_ERR(__fence)) {
err = PTR_ERR(__fence);
goto err_out;
}
pre_migrate_fence = NULL;
dma_fence_put(fence);
fence = __fence;
}
@ -603,20 +606,22 @@ static int xe_svm_copy(struct page **pages,
vram_addr, (u64)pagemap_addr[pos].addr, 1);
__fence = xe_migrate_from_vram(vr->migrate, 1,
vram_addr,
&pagemap_addr[pos]);
&pagemap_addr[pos],
pre_migrate_fence);
} else {
vm_dbg(&xe->drm,
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%d",
(u64)pagemap_addr[pos].addr, vram_addr, 1);
__fence = xe_migrate_to_vram(vr->migrate, 1,
&pagemap_addr[pos],
vram_addr);
vram_addr,
pre_migrate_fence);
}
if (IS_ERR(__fence)) {
err = PTR_ERR(__fence);
goto err_out;
}
pre_migrate_fence = NULL;
dma_fence_put(fence);
fence = __fence;
}
@ -629,6 +634,8 @@ static int xe_svm_copy(struct page **pages,
dma_fence_wait(fence, false);
dma_fence_put(fence);
}
if (pre_migrate_fence)
dma_fence_wait(pre_migrate_fence, false);
/*
* XXX: We can't derive the GT here (or anywhere in this functions, but
@ -645,16 +652,20 @@ static int xe_svm_copy(struct page **pages,
static int xe_svm_copy_to_devmem(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
unsigned long npages)
unsigned long npages,
struct dma_fence *pre_migrate_fence)
{
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM);
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM,
pre_migrate_fence);
}
static int xe_svm_copy_to_ram(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
unsigned long npages)
unsigned long npages,
struct dma_fence *pre_migrate_fence)
{
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM);
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM,
pre_migrate_fence);
}
static struct xe_bo *to_xe_bo(struct drm_pagemap_devmem *devmem_allocation)
@ -667,6 +678,7 @@ static void xe_svm_devmem_release(struct drm_pagemap_devmem *devmem_allocation)
struct xe_bo *bo = to_xe_bo(devmem_allocation);
struct xe_device *xe = xe_bo_device(bo);
dma_fence_put(devmem_allocation->pre_migrate_fence);
xe_bo_put_async(bo);
xe_pm_runtime_put(xe);
}
@ -861,6 +873,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
unsigned long timeslice_ms)
{
struct xe_vram_region *vr = container_of(dpagemap, typeof(*vr), dpagemap);
struct dma_fence *pre_migrate_fence = NULL;
struct xe_device *xe = vr->xe;
struct device *dev = xe->drm.dev;
struct drm_buddy_block *block;
@ -887,8 +900,20 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
break;
}
/* Ensure that any clearing or async eviction will complete before migration. */
if (!dma_resv_test_signaled(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL)) {
err = dma_resv_get_singleton(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
&pre_migrate_fence);
if (err)
dma_resv_wait_timeout(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
false, MAX_SCHEDULE_TIMEOUT);
else if (pre_migrate_fence)
dma_fence_enable_sw_signaling(pre_migrate_fence);
}
drm_pagemap_devmem_init(&bo->devmem_allocation, dev, mm,
&dpagemap_devmem_ops, dpagemap, end - start);
&dpagemap_devmem_ops, dpagemap, end - start,
pre_migrate_fence);
blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks;
list_for_each_entry(block, blocks, link)
@ -941,7 +966,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
xe_assert(vm->xe, IS_DGFX(vm->xe));
if (xe_svm_range_in_vram(range)) {
drm_info(&vm->xe->drm, "Range is already in VRAM\n");
drm_dbg(&vm->xe->drm, "Range is already in VRAM\n");
return false;
}

View File

@ -80,37 +80,25 @@ static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
.min = sizeof(struct rdma_nla_ls_gid)},
};
static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
static void ib_nl_process_ip_rsep(const struct nlmsghdr *nlh)
{
struct nlattr *tb[LS_NLA_TYPE_MAX] = {};
union ib_gid gid;
struct addr_req *req;
int found = 0;
int ret;
if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)
return false;
return;
ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_addr_policy, NULL);
if (ret)
return false;
return;
return true;
}
static void ib_nl_process_good_ip_rsep(const struct nlmsghdr *nlh)
{
const struct nlattr *head, *curr;
union ib_gid gid;
struct addr_req *req;
int len, rem;
int found = 0;
head = (const struct nlattr *)nlmsg_data(nlh);
len = nlmsg_len(nlh);
nla_for_each_attr(curr, head, len, rem) {
if (curr->nla_type == LS_NLA_TYPE_DGID)
memcpy(&gid, nla_data(curr), nla_len(curr));
}
if (!tb[LS_NLA_TYPE_DGID])
return;
memcpy(&gid, nla_data(tb[LS_NLA_TYPE_DGID]), sizeof(gid));
spin_lock_bh(&lock);
list_for_each_entry(req, &req_list, list) {
@ -137,8 +125,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
!(NETLINK_CB(skb).sk))
return -EPERM;
if (ib_nl_is_good_ip_resp(nlh))
ib_nl_process_good_ip_rsep(nlh);
ib_nl_process_ip_rsep(nlh);
return 0;
}

View File

@ -2009,6 +2009,7 @@ static void destroy_mc(struct rdma_id_private *id_priv,
ib_sa_free_multicast(mc->sa_mc);
if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
struct rdma_cm_event *event = &mc->iboe_join.event;
struct rdma_dev_addr *dev_addr =
&id_priv->id.route.addr.dev_addr;
struct net_device *ndev = NULL;
@ -2031,6 +2032,8 @@ static void destroy_mc(struct rdma_id_private *id_priv,
dev_put(ndev);
cancel_work_sync(&mc->iboe_join.work);
if (event->event == RDMA_CM_EVENT_MULTICAST_JOIN)
rdma_destroy_ah_attr(&event->param.ud.ah_attr);
}
kfree(mc);
}

View File

@ -2881,8 +2881,10 @@ int ib_del_sub_device_and_put(struct ib_device *sub)
{
struct ib_device *parent = sub->parent;
if (!parent)
if (!parent) {
ib_device_put(sub);
return -EOPNOTSUPP;
}
mutex_lock(&parent->subdev_lock);
list_del(&sub->subdev_list);

View File

@ -738,7 +738,7 @@ int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
(struct in6_addr *)dgid);
return 0;
} else if (net_type == RDMA_NETWORK_IPV6 ||
net_type == RDMA_NETWORK_IB || RDMA_NETWORK_ROCE_V1) {
net_type == RDMA_NETWORK_IB || net_type == RDMA_NETWORK_ROCE_V1) {
*dgid = hdr->ibgrh.dgid;
*sgid = hdr->ibgrh.sgid;
return 0;

View File

@ -89,6 +89,9 @@ enum bnxt_re_hw_stats {
BNXT_RE_RES_SRQ_LOAD_ERR,
BNXT_RE_RES_TX_PCI_ERR,
BNXT_RE_RES_RX_PCI_ERR,
BNXT_RE_REQ_CQE_ERROR,
BNXT_RE_RESP_CQE_ERROR,
BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_OUT_OF_SEQ_ERR,
BNXT_RE_TX_ATOMIC_REQ,
BNXT_RE_TX_READ_REQ,
@ -110,9 +113,6 @@ enum bnxt_re_hw_stats {
BNXT_RE_TX_CNP,
BNXT_RE_RX_CNP,
BNXT_RE_RX_ECN,
BNXT_RE_REQ_CQE_ERROR,
BNXT_RE_RESP_CQE_ERROR,
BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_NUM_EXT_COUNTERS
};

View File

@ -2919,14 +2919,9 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC;
}
switch (wr->send_flags) {
case IB_SEND_IP_CSUM:
if (wr->send_flags & IB_SEND_IP_CSUM)
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM;
break;
default:
break;
}
fallthrough;
case IB_WR_SEND_WITH_INV:
rc = bnxt_re_build_send_wqe(qp, wr, &wqe);

View File

@ -1112,7 +1112,7 @@ static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt)
creq_db->dbinfo.flags = 0;
creq_db->reg.bar_id = RCFW_COMM_CONS_PCI_BAR_REGION;
creq_db->reg.bar_base = pci_resource_start(pdev, creq_db->reg.bar_id);
if (!creq_db->reg.bar_id)
if (!creq_db->reg.bar_base)
dev_err(&pdev->dev,
"QPLIB: CREQ BAR region %d resc start is 0!",
creq_db->reg.bar_id);

View File

@ -64,9 +64,7 @@ static void __free_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,
for (i = 0; i < pbl->pg_count; i++) {
if (pbl->pg_arr[i])
dma_free_coherent(&pdev->dev, pbl->pg_size,
(void *)((unsigned long)
pbl->pg_arr[i] &
PAGE_MASK),
pbl->pg_arr[i],
pbl->pg_map_arr[i]);
else
dev_warn(&pdev->dev,
@ -237,7 +235,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
if (npbl % BIT(MAX_PDL_LVL_SHIFT))
npde++;
/* Alloc PDE pages */
sginfo.pgsize = npde * pg_size;
sginfo.pgsize = npde * ROCE_PG_SIZE_4K;
sginfo.npages = 1;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
if (rc)
@ -245,7 +243,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
/* Alloc PBL pages */
sginfo.npages = npbl;
sginfo.pgsize = PAGE_SIZE;
sginfo.pgsize = ROCE_PG_SIZE_4K;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo);
if (rc)
goto fail;

View File

@ -1320,13 +1320,9 @@ static int umem_to_page_list(struct efa_dev *dev,
u32 hp_cnt,
u8 hp_shift)
{
u32 pages_in_hp = BIT(hp_shift - PAGE_SHIFT);
struct ib_block_iter biter;
unsigned int hp_idx = 0;
ibdev_dbg(&dev->ibdev, "hp_cnt[%u], pages_in_hp[%u]\n",
hp_cnt, pages_in_hp);
rdma_umem_for_each_dma_block(umem, &biter, BIT(hp_shift))
page_list[hp_idx++] = rdma_block_iter_dma_address(&biter);

View File

@ -251,7 +251,7 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
void *ptr)
{
struct neighbour *neigh = ptr;
struct net_device *real_dev, *netdev = (struct net_device *)neigh->dev;
struct net_device *real_dev, *netdev;
struct irdma_device *iwdev;
struct ib_device *ibdev;
__be32 *p;
@ -260,6 +260,7 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
switch (event) {
case NETEVENT_NEIGH_UPDATE:
netdev = neigh->dev;
real_dev = rdma_vlan_dev_real_dev(netdev);
if (!real_dev)
real_dev = netdev;

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