mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-16 19:39:28 -05:00
Merge tag 'v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into pinctrl-qcom/for-next
Linux 7.2-rc1
This commit is contained in:
@@ -60,7 +60,7 @@ examples:
|
||||
clock-output-names = "main", "pll0", "pll1", "pll2",
|
||||
"pll2s", "pll2h", "z", "z2",
|
||||
"i", "m3", "b", "m1", "m2",
|
||||
"zx", "zs", "hp";
|
||||
"zx", "zs", "hp", "ztr", "zt";
|
||||
};
|
||||
|
||||
sdhi2_clk: sdhi2_clk@e615007c {
|
||||
|
||||
@@ -28,7 +28,6 @@ properties:
|
||||
|
||||
fan-supply:
|
||||
description: Phandle to the regulator that powers the fan.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/sprd,sc2730-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Unisoc SC2730 Power Management IC regulators
|
||||
|
||||
maintainers:
|
||||
- Otto Pflüger <otto.pflueger@abscue.de>
|
||||
|
||||
patternProperties:
|
||||
"^dcdc-(core|cpu|gen[0-1]|gpu|mem|memq|modem|sram)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-avdd(12|18)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vdd(18-dcxo|28)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vdd(emmccore|kpled|ldo[0-2]|sd(core|io)|sim[0-2]|usb33|wcn|wifipa)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vddcam(a0|a1|d0|d1|io|mot)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vddrf(1v25|18)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
...
|
||||
@@ -1,39 +0,0 @@
|
||||
Epson RX6110 Real Time Clock
|
||||
============================
|
||||
|
||||
The Epson RX6110 can be used with SPI or I2C busses. The kind of
|
||||
bus depends on the SPISEL pin and can not be configured via software.
|
||||
|
||||
I2C mode
|
||||
--------
|
||||
|
||||
Required properties:
|
||||
- compatible: should be: "epson,rx6110"
|
||||
- reg : the I2C address of the device for I2C
|
||||
|
||||
Example:
|
||||
|
||||
rtc: rtc@32 {
|
||||
compatible = "epson,rx6110"
|
||||
reg = <0x32>;
|
||||
};
|
||||
|
||||
SPI mode
|
||||
--------
|
||||
|
||||
Required properties:
|
||||
- compatible: should be: "epson,rx6110"
|
||||
- reg: chip select number
|
||||
- spi-cs-high: RX6110 needs chipselect high
|
||||
- spi-cpha: RX6110 works with SPI shifted clock phase
|
||||
- spi-cpol: RX6110 works with SPI inverse clock polarity
|
||||
|
||||
Example:
|
||||
|
||||
rtc: rtc@3 {
|
||||
compatible = "epson,rx6110"
|
||||
reg = <3>
|
||||
spi-cs-high;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/epson,rx6110.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Epson RX6110 Real Time Clock
|
||||
|
||||
description:
|
||||
The Epson RX6110 can be used with SPI or I2C busses. The kind of bus depends
|
||||
on the SPISEL pin and cannot be configured via software.
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: epson,rx6110
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-cs-high: true
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
dependencies:
|
||||
spi-cs-high: [ spi-cpha, spi-cpol ]
|
||||
spi-cpha: [ spi-cs-high, spi-cpol ]
|
||||
spi-cpol: [ spi-cs-high, spi-cpha ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
# I2C mode
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtc@32 {
|
||||
compatible = "epson,rx6110";
|
||||
reg = <0x32>;
|
||||
};
|
||||
};
|
||||
|
||||
# SPI mode
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtc@3 {
|
||||
compatible = "epson,rx6110";
|
||||
reg = <3>;
|
||||
spi-cs-high;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
};
|
||||
};
|
||||
@@ -31,6 +31,7 @@ properties:
|
||||
- epson,rx8025
|
||||
- isil,isl12057
|
||||
- epson,rx8130
|
||||
- epson,rx8901
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/st,m41t93.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ST M41T93 RTC and compatible
|
||||
|
||||
maintainers:
|
||||
- Akhilesh Patil <akhilesh@ee.iitb.ac.in>
|
||||
|
||||
description:
|
||||
ST M41T93 is spi based Real Time Clock (RTC) with time, date,
|
||||
alarm, watchdog, square wave clock output, 8 bit timer and
|
||||
7 bytes of user SRAM.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,m41t93
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
rtc@0 {
|
||||
compatible = "st,m41t93";
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
spi-max-frequency = <2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,6 +30,8 @@ properties:
|
||||
- aspeed,ast2500-rtc
|
||||
# ASPEED BMC ast2600 Real-time Clock
|
||||
- aspeed,ast2600-rtc
|
||||
# ASPEED BMC ast2700 Real-time Clock
|
||||
- aspeed,ast2700-rtc
|
||||
# Conexant Digicolor Real Time Clock Controller
|
||||
- cnxt,cx92755-rtc
|
||||
# I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
|
||||
|
||||
@@ -54,6 +54,12 @@ properties:
|
||||
- sophgo,sg2042-spi
|
||||
- thead,th1520-spi
|
||||
- const: snps,dw-apb-ssi
|
||||
- description: Vendor controllers which use snps,dwc-ssi-2.00a as fallback
|
||||
items:
|
||||
- enum:
|
||||
- starfive,jhb100-spi
|
||||
- const: snps,dwc-ssi-2.00a
|
||||
- const: snps,dwc-ssi-1.01a
|
||||
- description: Intel Keem Bay SPI Controller
|
||||
const: intel,keembay-ssi
|
||||
- description: Intel Mount Evans Integrated Management Complex SPI Controller
|
||||
|
||||
@@ -87,9 +87,12 @@ examples:
|
||||
amlogic,ao-secure = <&sec_AO>;
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/clock/amlogic,t7-peripherals-clkc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
temperature-sensor@20000 {
|
||||
compatible = "amlogic,t7-thermal";
|
||||
reg = <0x0 0x20000 0x0 0x50>;
|
||||
reg = <0x20000 0x50>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clkc_periphs CLKID_TS>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| arm64: | ok |
|
||||
| csky: | TODO |
|
||||
| hexagon: | TODO |
|
||||
| loongarch: | TODO |
|
||||
| loongarch: | ok |
|
||||
| m68k: | TODO |
|
||||
| microblaze: | TODO |
|
||||
| mips: | TODO |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc1
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -559,6 +559,15 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
|
||||
else
|
||||
alignment_mask = 0x7;
|
||||
offset = hw->address & alignment_mask;
|
||||
|
||||
/*
|
||||
* BAS is an 8-bit field in WCR/BCR; the shift below would
|
||||
* silently drop the high bits of ctrl.len when offset + len
|
||||
* exceeds 8, programming hardware to watch fewer bytes than
|
||||
* the user requested.
|
||||
*/
|
||||
if (((u32)hw->ctrl.len << offset) > ARM_BREAKPOINT_LEN_8)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw->address &= ~alignment_mask;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <linux/static_call.h>
|
||||
#include <linux/memory.h>
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/insn.h>
|
||||
|
||||
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
|
||||
{
|
||||
|
||||
+6
-5
@@ -1198,11 +1198,6 @@ static void __init map_mem(void)
|
||||
__map_memblock(start, end, pgprot_tagged(PAGE_KERNEL),
|
||||
flags);
|
||||
}
|
||||
|
||||
/* Map the kernel data/bss read-only in the linear map */
|
||||
__map_memblock(init_end, kernel_end, PAGE_KERNEL_RO, flags);
|
||||
flush_tlb_kernel_range((unsigned long)lm_alias(__init_end),
|
||||
(unsigned long)lm_alias(__bss_stop));
|
||||
}
|
||||
|
||||
void mark_rodata_ro(void)
|
||||
@@ -1221,6 +1216,12 @@ void mark_rodata_ro(void)
|
||||
update_mapping_prot(__pa_symbol(_text), (unsigned long)_text,
|
||||
(unsigned long)_stext - (unsigned long)_text,
|
||||
PAGE_KERNEL_RO);
|
||||
|
||||
/* Map the kernel data/bss read-only in the linear map */
|
||||
update_mapping_prot(__pa_symbol(__init_end),
|
||||
(unsigned long)lm_alias(__init_end),
|
||||
(unsigned long)__bss_stop - (unsigned long)__init_end,
|
||||
PAGE_KERNEL_RO);
|
||||
}
|
||||
|
||||
static void __init declare_vma(struct vm_struct *vma,
|
||||
|
||||
@@ -209,6 +209,7 @@ config LOONGARCH
|
||||
select SYSCTL_ARCH_UNALIGN_NO_WARN
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select SWIOTLB if 64BIT
|
||||
select THREAD_INFO_IN_TASK
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
select USER_STACKTRACE_SUPPORT
|
||||
|
||||
@@ -405,6 +405,8 @@
|
||||
i2c0: i2c@1ff48000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff48000 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <14>;
|
||||
status = "disabled";
|
||||
@@ -413,6 +415,8 @@
|
||||
i2c@1ff48800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff48800 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <15>;
|
||||
status = "disabled";
|
||||
@@ -421,6 +425,8 @@
|
||||
i2c@1ff49000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff49000 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <16>;
|
||||
status = "disabled";
|
||||
@@ -429,6 +435,8 @@
|
||||
i2c@1ff49800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff49800 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <17>;
|
||||
status = "disabled";
|
||||
@@ -437,6 +445,8 @@
|
||||
i2c@1ff4a000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff4a000 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <18>;
|
||||
status = "disabled";
|
||||
@@ -445,6 +455,8 @@
|
||||
i2c@1ff4a800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff4a800 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <19>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -311,6 +311,8 @@
|
||||
i2c2: i2c@1fe21000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe21000 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&liointc0>;
|
||||
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
@@ -319,6 +321,8 @@
|
||||
i2c3: i2c@1fe21800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe21800 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&liointc0>;
|
||||
interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -239,6 +239,8 @@
|
||||
i2c@1fe00120 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe00120 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_MISC_CLK>;
|
||||
interrupt-parent = <&liointc>;
|
||||
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
@@ -247,6 +249,8 @@
|
||||
i2c@1fe00130 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe00130 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_MISC_CLK>;
|
||||
interrupt-parent = <&liointc>;
|
||||
interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -38,6 +38,8 @@ static inline bool acpi_has_cpu_in_madt(void)
|
||||
extern struct list_head acpi_wakeup_device_list;
|
||||
extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
|
||||
|
||||
extern void acpi_add_early_pio(void);
|
||||
extern void acpi_remove_early_pio(void);
|
||||
extern int __init parse_acpi_topology(void);
|
||||
|
||||
#endif /* !CONFIG_ACPI */
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_LOONGARCH_CURRENT_H
|
||||
#define __ASM_LOONGARCH_CURRENT_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <asm/percpu.h>
|
||||
|
||||
struct task_struct;
|
||||
|
||||
DECLARE_PER_CPU(struct task_struct *, cpu_tasks);
|
||||
|
||||
register struct task_struct *current_thread_pointer __asm__("$tp");
|
||||
|
||||
static __always_inline struct task_struct *get_current(void)
|
||||
{
|
||||
return current_thread_pointer;
|
||||
}
|
||||
|
||||
#define current get_current()
|
||||
|
||||
static __always_inline void set_current(struct task_struct *task)
|
||||
{
|
||||
__this_cpu_write(cpu_tasks, task);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* __ASM_LOONGARCH_CURRENT_H */
|
||||
@@ -41,6 +41,8 @@ struct kimage_arch {
|
||||
unsigned long systable_ptr;
|
||||
};
|
||||
|
||||
struct kimage;
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
extern const struct kexec_file_ops kexec_efi_ops;
|
||||
extern const struct kexec_file_ops kexec_elf_ops;
|
||||
@@ -59,7 +61,6 @@ typedef void (*do_kexec_t)(unsigned long efi_boot,
|
||||
unsigned long start_addr,
|
||||
unsigned long first_ind_entry);
|
||||
|
||||
struct kimage;
|
||||
extern const unsigned char relocate_new_kernel[];
|
||||
extern const size_t relocate_new_kernel_size;
|
||||
extern void kexec_reboot(void);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#ifndef __ASM_PERCPU_H
|
||||
#define __ASM_PERCPU_H
|
||||
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -429,6 +429,8 @@ static inline pte_t pte_mkwrite_novma(pte_t pte)
|
||||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
if (pte_val(pte) & _PAGE_DIRTY)
|
||||
pte_val(pte) |= _PAGE_MODIFIED;
|
||||
pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pte;
|
||||
}
|
||||
@@ -535,6 +537,8 @@ static inline pmd_t pmd_mkwrite_novma(pmd_t pmd)
|
||||
|
||||
static inline pmd_t pmd_wrprotect(pmd_t pmd)
|
||||
{
|
||||
if (pmd_val(pmd) & _PAGE_DIRTY)
|
||||
pmd_val(pmd) |= _PAGE_MODIFIED;
|
||||
pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
@@ -81,8 +81,9 @@ extern int __cpu_logical_map[NR_CPUS];
|
||||
struct seq_file;
|
||||
|
||||
struct secondary_data {
|
||||
unsigned long task;
|
||||
unsigned long stack;
|
||||
unsigned long thread_info;
|
||||
unsigned long offset;
|
||||
};
|
||||
extern struct secondary_data cpuboot_data;
|
||||
|
||||
|
||||
@@ -184,6 +184,7 @@
|
||||
.cfi_rel_offset ra, PT_ERA
|
||||
.endif
|
||||
cfi_st tp, PT_R2, \docfi
|
||||
cfi_st u0, PT_R21, \docfi
|
||||
cfi_st fp, PT_R22, \docfi
|
||||
|
||||
/* Set thread_info if we're coming from user mode */
|
||||
@@ -191,10 +192,13 @@
|
||||
andi t0, t0, 0x3 /* extract pplv bit */
|
||||
beqz t0, 9f
|
||||
|
||||
LONG_LI tp, ~_THREAD_MASK
|
||||
and tp, tp, sp
|
||||
cfi_st u0, PT_R21, \docfi
|
||||
csrrd u0, PERCPU_BASE_KS
|
||||
|
||||
la_abs t1, cpu_tasks
|
||||
#ifdef CONFIG_SMP
|
||||
LONG_ADD t1, t1, u0
|
||||
#endif
|
||||
LONG_L tp, t1, 0
|
||||
9:
|
||||
#ifdef CONFIG_KGDB
|
||||
li.w t0, CSR_CRMD_WE
|
||||
|
||||
@@ -15,7 +15,6 @@ struct task_struct;
|
||||
* __switch_to - switch execution of a task
|
||||
* @prev: The task previously executed.
|
||||
* @next: The task to begin executing.
|
||||
* @next_ti: task_thread_info(next).
|
||||
* @sched_ra: __schedule return address.
|
||||
* @sched_cfa: __schedule call frame address.
|
||||
*
|
||||
@@ -23,8 +22,7 @@ struct task_struct;
|
||||
* the context of next. Returns prev.
|
||||
*/
|
||||
extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
|
||||
struct task_struct *next, struct thread_info *next_ti,
|
||||
void *sched_ra, void *sched_cfa);
|
||||
struct task_struct *next, void *sched_ra, void *sched_cfa);
|
||||
|
||||
/*
|
||||
* For newly created kernel threads switch_to() will return to
|
||||
@@ -37,7 +35,8 @@ do { \
|
||||
lose_fpu_inatomic(1, prev); \
|
||||
lose_lbt_inatomic(1, prev); \
|
||||
hw_breakpoint_thread_switch(next); \
|
||||
(last) = __switch_to(prev, next, task_thread_info(next), \
|
||||
set_current(next); \
|
||||
(last) = __switch_to(prev, next, \
|
||||
__builtin_return_address(0), __builtin_frame_address(0)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* must also be changed
|
||||
*/
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
unsigned long tp_value; /* thread pointer */
|
||||
__u32 cpu; /* current CPU */
|
||||
@@ -37,20 +36,11 @@ struct thread_info {
|
||||
*/
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.flags = _TIF_FIXADE, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
}
|
||||
|
||||
/* How to get the thread information struct from C. */
|
||||
register struct thread_info *__current_thread_info __asm__("$tp");
|
||||
|
||||
static inline struct thread_info *current_thread_info(void)
|
||||
{
|
||||
return __current_thread_info;
|
||||
}
|
||||
|
||||
register unsigned long current_stack_pointer __asm__("$sp");
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/numa.h>
|
||||
#include <asm/loongson.h>
|
||||
@@ -59,6 +60,33 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
|
||||
return ioremap_cache(phys, size);
|
||||
}
|
||||
|
||||
#define PIO_BASE (unsigned long)PCI_IOBASE
|
||||
#define PIO_SIZE ALIGN(ISA_IOSIZE, PAGE_SIZE)
|
||||
|
||||
static bool acpi_pio;
|
||||
|
||||
/* Add PIO for early access */
|
||||
void acpi_add_early_pio(void)
|
||||
{
|
||||
if (!acpi_disabled) {
|
||||
acpi_pio = true;
|
||||
vmap_page_range(PIO_BASE, PIO_BASE + PIO_SIZE,
|
||||
LOONGSON_LIO_BASE, pgprot_device(PAGE_KERNEL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove PIO for PCI register */
|
||||
void acpi_remove_early_pio(void)
|
||||
{
|
||||
if (!acpi_pio)
|
||||
return;
|
||||
|
||||
if (!acpi_disabled) {
|
||||
acpi_pio = false;
|
||||
vunmap_range(PIO_BASE, PIO_BASE + PIO_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static int set_processor_mask(u32 id, u32 pass)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ static void __used output_task_defines(void)
|
||||
{
|
||||
COMMENT("LoongArch task_struct offsets.");
|
||||
OFFSET(TASK_STATE, task_struct, __state);
|
||||
OFFSET(TASK_THREAD_INFO, task_struct, stack);
|
||||
OFFSET(TASK_STACK, task_struct, stack);
|
||||
OFFSET(TASK_FLAGS, task_struct, flags);
|
||||
OFFSET(TASK_MM, task_struct, mm);
|
||||
OFFSET(TASK_PID, task_struct, pid);
|
||||
@@ -84,7 +84,6 @@ static void __used output_task_defines(void)
|
||||
static void __used output_thread_info_defines(void)
|
||||
{
|
||||
COMMENT("LoongArch thread_info offsets.");
|
||||
OFFSET(TI_TASK, thread_info, task);
|
||||
OFFSET(TI_FLAGS, thread_info, flags);
|
||||
OFFSET(TI_TP_VALUE, thread_info, tp_value);
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
@@ -266,8 +265,9 @@ static void __used output_signal_defines(void)
|
||||
static void __used output_smpboot_defines(void)
|
||||
{
|
||||
COMMENT("Linux smp cpu boot offsets.");
|
||||
OFFSET(CPU_BOOT_TASK, secondary_data, task);
|
||||
OFFSET(CPU_BOOT_STACK, secondary_data, stack);
|
||||
OFFSET(CPU_BOOT_TINFO, secondary_data, thread_info);
|
||||
OFFSET(CPU_BOOT_OFFSET, secondary_data, offset);
|
||||
BLANK();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -67,8 +67,11 @@ SYM_CODE_START(handle_syscall)
|
||||
#endif
|
||||
|
||||
move u0, t0
|
||||
LONG_LI tp, ~_THREAD_MASK
|
||||
and tp, tp, sp
|
||||
la_abs t1, cpu_tasks
|
||||
#ifdef CONFIG_SMP
|
||||
LONG_ADD t1, t1, u0
|
||||
#endif
|
||||
LONG_L tp, t1, 0
|
||||
|
||||
move a0, sp
|
||||
bl do_syscall
|
||||
|
||||
@@ -74,10 +74,11 @@ SYM_CODE_START(kernel_entry) # kernel entry point
|
||||
/* GPR21 used for percpu base (runtime), initialized as 0 */
|
||||
move u0, zero
|
||||
|
||||
la.pcrel tp, init_thread_union
|
||||
/* Set the SP after an empty pt_regs. */
|
||||
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
|
||||
PTR_ADD sp, sp, tp
|
||||
la.pcrel tp, init_task
|
||||
la.pcrel t0, init_stack
|
||||
PTR_LI t1, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, t1
|
||||
PTR_ADDI sp, t0, -PT_SIZE
|
||||
set_saved_sp sp, t0, t1
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
@@ -86,8 +87,10 @@ SYM_CODE_START(kernel_entry) # kernel entry point
|
||||
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
/* Repoint the sp into the new kernel */
|
||||
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
|
||||
PTR_ADD sp, sp, tp
|
||||
LONG_LPTR t0, tp, TASK_STACK
|
||||
PTR_LI t1, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, t1
|
||||
PTR_ADDI sp, t0, -PT_SIZE
|
||||
set_saved_sp sp, t0, t1
|
||||
|
||||
/* Jump to the new kernel: new_pc = current_pc + random_offset */
|
||||
@@ -127,8 +130,9 @@ SYM_CODE_START(smpboot_entry)
|
||||
csrxchg t0, t1, LOONGARCH_CSR_IMPCTL1
|
||||
#endif
|
||||
la.pcrel t0, cpuboot_data
|
||||
ld.d tp, t0, CPU_BOOT_TASK
|
||||
ld.d sp, t0, CPU_BOOT_STACK
|
||||
ld.d tp, t0, CPU_BOOT_TINFO
|
||||
ld.d u0, t0, CPU_BOOT_OFFSET
|
||||
|
||||
bl start_secondary
|
||||
ASM_BUG()
|
||||
|
||||
@@ -60,6 +60,8 @@ unsigned long __stack_chk_guard __read_mostly;
|
||||
EXPORT_SYMBOL(__stack_chk_guard);
|
||||
#endif
|
||||
|
||||
DEFINE_PER_CPU(struct task_struct *, cpu_tasks);
|
||||
|
||||
/*
|
||||
* Idle related variables and functions
|
||||
*/
|
||||
|
||||
@@ -313,7 +313,7 @@ unsigned long __init relocate_kernel(void)
|
||||
reloc_offset += random_offset;
|
||||
|
||||
/* The current thread is now within the relocated kernel */
|
||||
__current_thread_info = RELOCATED_KASLR(__current_thread_info);
|
||||
current_thread_pointer = RELOCATED_KASLR(current_thread_pointer);
|
||||
|
||||
update_reloc_offset(&reloc_offset, random_offset);
|
||||
}
|
||||
|
||||
@@ -502,6 +502,8 @@ static __init int arch_reserve_pio_range(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
acpi_add_early_pio();
|
||||
|
||||
for_each_node_by_name(np, "isa") {
|
||||
struct of_range range;
|
||||
struct of_range_parser parser;
|
||||
@@ -593,6 +595,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
cpu_probe();
|
||||
unwind_init();
|
||||
set_current(current);
|
||||
|
||||
init_environ();
|
||||
efi_init();
|
||||
|
||||
@@ -400,8 +400,9 @@ void loongson_boot_secondary(int cpu, struct task_struct *idle)
|
||||
pr_info("Booting CPU#%d...\n", cpu);
|
||||
|
||||
entry = __pa_symbol((unsigned long)&smpboot_entry);
|
||||
cpuboot_data.stack = (unsigned long)__KSTK_TOS(idle);
|
||||
cpuboot_data.thread_info = (unsigned long)task_thread_info(idle);
|
||||
cpuboot_data.task = (unsigned long)idle;
|
||||
cpuboot_data.stack = (unsigned long)task_pt_regs(idle);
|
||||
cpuboot_data.offset = per_cpu_offset(cpu);
|
||||
|
||||
csr_mail_send(entry, cpu_logical_map(cpu), 0);
|
||||
|
||||
@@ -663,6 +664,7 @@ asmlinkage void start_secondary(void)
|
||||
set_my_cpu_offset(per_cpu_offset(cpu));
|
||||
|
||||
cpu_probe();
|
||||
set_current(current);
|
||||
constant_clockevent_init();
|
||||
loongson_init_secondary();
|
||||
|
||||
@@ -705,6 +707,7 @@ static void stop_this_cpu(void *dummy)
|
||||
set_cpu_online(smp_processor_id(), false);
|
||||
calculate_cpu_foreign_map();
|
||||
local_irq_disable();
|
||||
rcutree_report_cpu_dead();
|
||||
while (true);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/*
|
||||
* task_struct *__switch_to(task_struct *prev, task_struct *next,
|
||||
* struct thread_info *next_ti, void *sched_ra, void *sched_cfa)
|
||||
* void *sched_ra, void *sched_cfa)
|
||||
*/
|
||||
.align 5
|
||||
SYM_FUNC_START(__switch_to)
|
||||
@@ -24,8 +24,8 @@ SYM_FUNC_START(__switch_to)
|
||||
LONG_SPTR t1, a0, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET)
|
||||
|
||||
cpu_save_nonscratch a0
|
||||
LONG_SPTR a3, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET)
|
||||
LONG_SPTR a4, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET)
|
||||
LONG_SPTR a2, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET)
|
||||
LONG_SPTR a3, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET)
|
||||
|
||||
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
|
||||
la t7, __stack_chk_guard
|
||||
@@ -33,11 +33,12 @@ SYM_FUNC_START(__switch_to)
|
||||
LONG_SPTR t8, t7, 0
|
||||
#endif
|
||||
|
||||
move tp, a2
|
||||
move tp, a1
|
||||
cpu_restore_nonscratch a1
|
||||
|
||||
li.w t0, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, tp
|
||||
LONG_LPTR t0, a1, (TASK_STACK - TASK_STRUCT_OFFSET)
|
||||
PTR_LI t1, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, t1
|
||||
set_saved_sp t0, t1, t2
|
||||
|
||||
LONG_LPTR t1, a1, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET)
|
||||
@@ -45,6 +46,7 @@ SYM_FUNC_START(__switch_to)
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
PTR_ADDI a0, a0, -TASK_STRUCT_OFFSET
|
||||
PTR_ADDI tp, tp, -TASK_STRUCT_OFFSET
|
||||
#endif
|
||||
jr ra
|
||||
SYM_FUNC_END(__switch_to)
|
||||
|
||||
@@ -107,6 +107,12 @@ static void show_stacktrace(struct task_struct *task,
|
||||
unsigned long stackdata;
|
||||
unsigned long *sp = (unsigned long *)regs->regs[3];
|
||||
|
||||
if (!task)
|
||||
task = current;
|
||||
|
||||
if (!try_get_task_stack(task))
|
||||
return;
|
||||
|
||||
printk("%sStack :", loglvl);
|
||||
i = 0;
|
||||
while ((unsigned long) sp & (PAGE_SIZE - 1)) {
|
||||
@@ -129,6 +135,8 @@ static void show_stacktrace(struct task_struct *task,
|
||||
}
|
||||
pr_cont("\n");
|
||||
show_backtrace(task, regs, loglvl, user);
|
||||
|
||||
put_task_stack(task);
|
||||
}
|
||||
|
||||
void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
|
||||
|
||||
@@ -234,5 +234,5 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
|
||||
clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
|
||||
}
|
||||
|
||||
return __set_memory(addr, 1, set, clear);
|
||||
return __set_memory(addr, nr, set, clear);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,18 @@
|
||||
* Copyright (C) 2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <linux/memory.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include "bpf_jit.h"
|
||||
|
||||
#define LOONGARCH_MAX_REG_ARGS 8
|
||||
|
||||
#define LOONGARCH_SAVE_RA_NINSNS 1
|
||||
#define LOONGARCH_LONG_JUMP_NINSNS 5
|
||||
#define LOONGARCH_TCC_SLOT_NINSNS 1
|
||||
|
||||
#define LOONGARCH_PROLOGUE_SKIP_INSNS \
|
||||
(LOONGARCH_SAVE_RA_NINSNS + LOONGARCH_LONG_JUMP_NINSNS + LOONGARCH_TCC_SLOT_NINSNS)
|
||||
|
||||
#define LOONGARCH_LONG_JUMP_NBYTES (LOONGARCH_LONG_JUMP_NINSNS * 4)
|
||||
|
||||
#define LOONGARCH_FENTRY_NINSNS 2
|
||||
@@ -143,8 +150,13 @@ static void build_prologue(struct jit_ctx *ctx)
|
||||
stack_adjust = round_up(stack_adjust, 16);
|
||||
stack_adjust += bpf_stack_adjust;
|
||||
|
||||
/*
|
||||
* Save the original return address to a temporary register to prevent
|
||||
* it from being overwritten, then reserve space for the long jump and
|
||||
* fentry trampoline slot for dynamically patching by ftrace at runtime.
|
||||
* These instructions are bypassed during a tail call invocation.
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -253,10 +265,11 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
|
||||
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
|
||||
} else {
|
||||
/*
|
||||
* Call the next bpf prog and skip the first instruction
|
||||
* of TCC initialization.
|
||||
* Tail call to the next BPF program, passing offset in number
|
||||
* of instructions to jirl to bypass the initial setup slots.
|
||||
*/
|
||||
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7);
|
||||
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO,
|
||||
LOONGARCH_GPR_T3, LOONGARCH_PROLOGUE_SKIP_INSNS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,12 +325,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
|
||||
*/
|
||||
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off);
|
||||
emit_insn(ctx, ldd, t3, REG_TCC, 0);
|
||||
emit_insn(ctx, addid, t3, t3, 1);
|
||||
emit_insn(ctx, std, t3, REG_TCC, 0);
|
||||
emit_insn(ctx, addid, t2, LOONGARCH_GPR_ZERO, MAX_TAIL_CALL_CNT);
|
||||
if (emit_tailcall_jmp(ctx, BPF_JSGT, t3, t2, jmp_offset) < 0)
|
||||
if (emit_tailcall_jmp(ctx, BPF_JSGE, t3, t2, jmp_offset) < 0)
|
||||
goto toofar;
|
||||
|
||||
emit_insn(ctx, addid, t3, t3, 1);
|
||||
|
||||
/*
|
||||
* prog = array->ptrs[index];
|
||||
* if (!prog)
|
||||
@@ -330,6 +343,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
|
||||
if (emit_tailcall_jmp(ctx, BPF_JEQ, t2, LOONGARCH_GPR_ZERO, jmp_offset) < 0)
|
||||
goto toofar;
|
||||
|
||||
emit_insn(ctx, std, t3, REG_TCC, 0);
|
||||
|
||||
/* goto *(prog->bpf_func + 4); */
|
||||
off = offsetof(struct bpf_prog, bpf_func);
|
||||
emit_insn(ctx, ldd, t3, t2, off);
|
||||
@@ -1147,6 +1162,19 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
||||
|
||||
/* function call */
|
||||
case BPF_JMP | BPF_CALL:
|
||||
/* Implement helper call to bpf_get_current_task/_btf() inline */
|
||||
if (insn->src_reg == 0 && (insn->imm == BPF_FUNC_get_current_task ||
|
||||
insn->imm == BPF_FUNC_get_current_task_btf)) {
|
||||
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_TP);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Implement helper call to bpf_get_smp_processor_id() inline */
|
||||
if (insn->src_reg == 0 && insn->imm == BPF_FUNC_get_smp_processor_id) {
|
||||
emit_insn(ctx, ldwu, regmap[BPF_REG_0], LOONGARCH_GPR_TP, TI_CPU);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass,
|
||||
&func_addr, &func_addr_fixed);
|
||||
if (ret < 0)
|
||||
@@ -2367,3 +2395,15 @@ bool bpf_jit_supports_subprog_tailcalls(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpf_jit_inlines_helper_call(s32 imm)
|
||||
{
|
||||
switch (imm) {
|
||||
case BPF_FUNC_get_current_task:
|
||||
case BPF_FUNC_get_current_task_btf:
|
||||
case BPF_FUNC_get_smp_processor_id:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
|
||||
struct resource_entry *entry, *tmp;
|
||||
struct acpi_device *device = ci->bridge;
|
||||
|
||||
acpi_remove_early_pio();
|
||||
|
||||
status = acpi_pci_probe_root_resources(ci);
|
||||
if (status > 0) {
|
||||
acpi_evaluate_integer(device->handle, "PCIH", NULL, &pci_h);
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
|
||||
#include <asm/vdso/vdso.h>
|
||||
|
||||
#include <linux/build-salt.h>
|
||||
#include <linux/elfnote.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
ELFNOTE_START(Linux, 0, "a")
|
||||
.long LINUX_VERSION_CODE
|
||||
ELFNOTE_END
|
||||
|
||||
BUILD_SALT
|
||||
|
||||
@@ -1300,7 +1300,7 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
|
||||
args->handle, args->offset, args->size);
|
||||
|
||||
if (args->direction == SYNC_DIRECT_FROM_DEVICE)
|
||||
ret = amdxdna_hwctx_sync_debug_bo(abo->client, args->handle);
|
||||
ret = amdxdna_hwctx_sync_debug_bo(client, args->handle);
|
||||
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
@@ -208,9 +208,9 @@ static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq
|
||||
ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->id,
|
||||
priority);
|
||||
if (ret)
|
||||
return ret;
|
||||
ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
|
||||
@@ -281,10 +281,10 @@ static int ivpu_cmdq_register(struct ivpu_file_priv *file_priv, struct ivpu_cmdq
|
||||
}
|
||||
|
||||
ret = ivpu_register_db(file_priv, cmdq);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret && vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW)
|
||||
ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ivpu_cmdq_unregister(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
|
||||
|
||||
@@ -490,7 +490,7 @@ static void ipmi_bmc_gone(int iface)
|
||||
mutex_lock(&driver_data.ipmi_lock);
|
||||
list_for_each_entry_safe(iter, temp,
|
||||
&driver_data.ipmi_devices, head) {
|
||||
if (iter->ipmi_ifnum != iface) {
|
||||
if (iter->ipmi_ifnum == iface) {
|
||||
ipmi_device = iter;
|
||||
__ipmi_dev_kill(iter);
|
||||
break;
|
||||
|
||||
@@ -168,7 +168,16 @@ void acpi_ut_safe_strncpy(char *dest, char *source, acpi_size dest_size)
|
||||
{
|
||||
/* Always terminate destination string */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
strscpy_pad(dest, source, dest_size);
|
||||
#else
|
||||
/*
|
||||
* strscpy_pad() is not defined in ACPICA tools builds, so use strncpy()
|
||||
* and directly NUL-terminate the destination string in that case.
|
||||
*/
|
||||
strncpy(dest, source, dest_size);
|
||||
dest[dest_size - 1] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1143,7 +1143,7 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
|
||||
int __weak __cpuidle acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -1156,7 +1156,7 @@ int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
|
||||
*
|
||||
* Return: 0 for success or negative value for error
|
||||
*/
|
||||
static int acpi_idle_lpi_enter(struct cpuidle_device *dev,
|
||||
static int __cpuidle acpi_idle_lpi_enter(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int index)
|
||||
{
|
||||
struct acpi_processor *pr;
|
||||
|
||||
@@ -871,7 +871,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
|
||||
|
||||
/**
|
||||
* acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
|
||||
* acpi_dev_free_resource_list - Free resource from acpi_dev_get_resources().
|
||||
* @list: The head of the resource list to free.
|
||||
*/
|
||||
void acpi_dev_free_resource_list(struct list_head *list)
|
||||
@@ -991,7 +991,7 @@ static int __acpi_dev_get_resources(struct acpi_device *adev,
|
||||
*
|
||||
* The resultant struct resource objects are put on the list pointed to by
|
||||
* @list, that must be empty initially, as members of struct resource_entry
|
||||
* objects. Callers of this routine should use %acpi_dev_free_resource_list() to
|
||||
* objects. Callers of this routine should use acpi_dev_free_resource_list() to
|
||||
* free that list.
|
||||
*
|
||||
* The number of resources in the output list is returned on success, an error
|
||||
@@ -1032,7 +1032,7 @@ static int is_memory(struct acpi_resource *ares, void *not_used)
|
||||
* The resultant struct resource objects are put on the list pointed to
|
||||
* by @list, that must be empty initially, as members of struct
|
||||
* resource_entry objects. Callers of this routine should use
|
||||
* %acpi_dev_free_resource_list() to free that list.
|
||||
* acpi_dev_free_resource_list() to free that list.
|
||||
*
|
||||
* The number of resources in the output list is returned on success,
|
||||
* an error code reflecting the error condition is returned otherwise.
|
||||
|
||||
@@ -66,7 +66,7 @@ int acpi_processor_ffh_lpi_probe(unsigned int cpu)
|
||||
return acpi_cpu_init_idle(cpu);
|
||||
}
|
||||
|
||||
int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
|
||||
int __cpuidle acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
|
||||
{
|
||||
u32 state = lpi->address;
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
#ifdef CONFIG_ACPI_DEBUG
|
||||
/*
|
||||
* ACPI debug sysfs I/F, including:
|
||||
* /sys/modules/acpi/parameters/debug_layer
|
||||
* /sys/modules/acpi/parameters/debug_level
|
||||
* /sys/modules/acpi/parameters/trace_method_name
|
||||
* /sys/modules/acpi/parameters/trace_state
|
||||
* /sys/modules/acpi/parameters/trace_debug_layer
|
||||
* /sys/modules/acpi/parameters/trace_debug_level
|
||||
* /sys/module/acpi/parameters/debug_layer
|
||||
* /sys/module/acpi/parameters/debug_level
|
||||
* /sys/module/acpi/parameters/trace_method_name
|
||||
* /sys/module/acpi/parameters/trace_state
|
||||
* /sys/module/acpi/parameters/trace_debug_layer
|
||||
* /sys/module/acpi/parameters/trace_debug_level
|
||||
*/
|
||||
|
||||
struct acpi_dlayer {
|
||||
@@ -269,7 +269,7 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
|
||||
#endif /* CONFIG_ACPI_DEBUG */
|
||||
|
||||
|
||||
/* /sys/modules/acpi/parameters/aml_debug_output */
|
||||
/* /sys/module/acpi/parameters/aml_debug_output */
|
||||
|
||||
module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object,
|
||||
byte, 0644);
|
||||
|
||||
@@ -245,7 +245,7 @@ err_exit:
|
||||
if (map->cache_ops->exit) {
|
||||
dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
|
||||
map->lock(map->lock_arg);
|
||||
ret = map->cache_ops->exit(map);
|
||||
map->cache_ops->exit(map);
|
||||
map->unlock(map->lock_arg);
|
||||
}
|
||||
err_free_reg_defaults:
|
||||
|
||||
+7
-16
@@ -580,14 +580,7 @@ static const struct bus_type rbd_bus_type = {
|
||||
.bus_groups = rbd_bus_groups,
|
||||
};
|
||||
|
||||
static void rbd_root_dev_release(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct device rbd_root_dev = {
|
||||
.init_name = "rbd",
|
||||
.release = rbd_root_dev_release,
|
||||
};
|
||||
static struct device *rbd_root_dev;
|
||||
|
||||
static __printf(2, 3)
|
||||
void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
|
||||
@@ -5378,7 +5371,7 @@ static struct rbd_device *__rbd_dev_create(struct rbd_spec *spec)
|
||||
|
||||
rbd_dev->dev.bus = &rbd_bus_type;
|
||||
rbd_dev->dev.type = &rbd_device_type;
|
||||
rbd_dev->dev.parent = &rbd_root_dev;
|
||||
rbd_dev->dev.parent = rbd_root_dev;
|
||||
device_initialize(&rbd_dev->dev);
|
||||
|
||||
return rbd_dev;
|
||||
@@ -7324,15 +7317,13 @@ static int __init rbd_sysfs_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = device_register(&rbd_root_dev);
|
||||
if (ret < 0) {
|
||||
put_device(&rbd_root_dev);
|
||||
return ret;
|
||||
}
|
||||
rbd_root_dev = root_device_register("rbd");
|
||||
if (IS_ERR(rbd_root_dev))
|
||||
return PTR_ERR(rbd_root_dev);
|
||||
|
||||
ret = bus_register(&rbd_bus_type);
|
||||
if (ret < 0)
|
||||
device_unregister(&rbd_root_dev);
|
||||
root_device_unregister(rbd_root_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -7340,7 +7331,7 @@ static int __init rbd_sysfs_init(void)
|
||||
static void __exit rbd_sysfs_cleanup(void)
|
||||
{
|
||||
bus_unregister(&rbd_bus_type);
|
||||
device_unregister(&rbd_root_dev);
|
||||
root_device_unregister(rbd_root_dev);
|
||||
}
|
||||
|
||||
static int __init rbd_slab_init(void)
|
||||
|
||||
@@ -195,14 +195,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
|
||||
s->exit_latency_ns = 0;
|
||||
else
|
||||
s->exit_latency = div_u64(s->exit_latency_ns, NSEC_PER_USEC);
|
||||
|
||||
/*
|
||||
* Warn if the exit latency of a CPU idle state exceeds its
|
||||
* target residency which is assumed to never happen in cpuidle
|
||||
* in multiple places.
|
||||
*/
|
||||
if (s->exit_latency_ns > s->target_residency_ns)
|
||||
pr_warn("Idle state %d target residency too low\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -558,7 +558,7 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
|
||||
|
||||
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
struct amdgpu_device **dmabuf_adev,
|
||||
uint64_t *bo_size, void *metadata_buffer,
|
||||
uint64_t *bo_size, void **metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags, int8_t *xcp_id)
|
||||
{
|
||||
@@ -593,9 +593,24 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
*dmabuf_adev = adev;
|
||||
if (bo_size)
|
||||
*bo_size = amdgpu_bo_size(bo);
|
||||
if (metadata_buffer)
|
||||
r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size,
|
||||
metadata_size, &metadata_flags);
|
||||
if (metadata_buffer) {
|
||||
/* first get metadata_size by buffer = NULL */
|
||||
r = amdgpu_bo_get_metadata(bo, NULL, 0,
|
||||
metadata_size, NULL);
|
||||
|
||||
/* user buf_size is bigger than bo metadata_size
|
||||
* allocate a buf at kernel space and copy */
|
||||
if (*metadata_size <= buffer_size) {
|
||||
*metadata_buffer = kzalloc(*metadata_size, GFP_KERNEL);
|
||||
|
||||
if (!*metadata_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
r = amdgpu_bo_get_metadata(bo, *metadata_buffer, *metadata_size,
|
||||
NULL, &metadata_flags);
|
||||
} else
|
||||
r = -EINVAL;
|
||||
}
|
||||
if (flags) {
|
||||
*flags = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_VRAM
|
||||
|
||||
@@ -262,7 +262,7 @@ uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
|
||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
struct amdgpu_device **dmabuf_adev,
|
||||
uint64_t *bo_size, void *metadata_buffer,
|
||||
uint64_t *bo_size, void **metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags, int8_t *xcp_id);
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
|
||||
|
||||
@@ -1914,13 +1914,6 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
|
||||
mutex_lock(&mem->lock);
|
||||
|
||||
/* Unpin MMIO/DOORBELL BO's that were pinned during allocation */
|
||||
if (mem->alloc_flags &
|
||||
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||
amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
|
||||
}
|
||||
|
||||
mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
|
||||
is_imported = mem->is_imported;
|
||||
mutex_unlock(&mem->lock);
|
||||
@@ -1934,6 +1927,15 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* At this point the BO is guaranteed to be freed, so unpin the
|
||||
* MMIO/DOORBELL BOs that were pinned during allocation.
|
||||
*/
|
||||
if (mem->alloc_flags &
|
||||
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||
amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
|
||||
}
|
||||
|
||||
/* Make sure restore workers don't access the BO any more */
|
||||
mutex_lock(&process_info->lock);
|
||||
if (!list_empty(&mem->validate_list))
|
||||
|
||||
@@ -247,13 +247,17 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
|
||||
goto free_partial_kdata;
|
||||
break;
|
||||
|
||||
case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
|
||||
if (size < sizeof(struct drm_amdgpu_cs_chunk_cp_gfx_shadow))
|
||||
goto free_partial_kdata;
|
||||
break;
|
||||
|
||||
case AMDGPU_CHUNK_ID_DEPENDENCIES:
|
||||
case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
|
||||
case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
|
||||
case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
|
||||
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
|
||||
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
|
||||
case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -326,7 +326,6 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
|
||||
struct drm_file *filp, struct amdgpu_ctx *ctx)
|
||||
{
|
||||
struct amdgpu_fpriv *fpriv = filp->driver_priv;
|
||||
u32 current_stable_pstate;
|
||||
int r;
|
||||
|
||||
r = amdgpu_ctx_priority_permit(filp, priority);
|
||||
@@ -344,36 +343,21 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
|
||||
ctx->generation = amdgpu_vm_generation(mgr->adev, &fpriv->vm);
|
||||
ctx->init_priority = priority;
|
||||
ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;
|
||||
|
||||
r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (mgr->adev->pm.stable_pstate_ctx)
|
||||
ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate;
|
||||
else
|
||||
ctx->stable_pstate = current_stable_pstate;
|
||||
ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
|
||||
u32 stable_pstate)
|
||||
static int __amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
|
||||
u32 stable_pstate)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->mgr->adev;
|
||||
enum amd_dpm_forced_level level;
|
||||
struct amdgpu_ctx *current_ctx;
|
||||
u32 current_stable_pstate;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&adev->pm.stable_pstate_ctx_lock);
|
||||
if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) {
|
||||
r = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate);
|
||||
if (r || (stable_pstate == current_stable_pstate))
|
||||
goto done;
|
||||
lockdep_assert_held(&adev->pm.stable_pstate_ctx_lock);
|
||||
|
||||
switch (stable_pstate) {
|
||||
case AMDGPU_CTX_STABLE_PSTATE_NONE:
|
||||
@@ -392,17 +376,41 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
|
||||
level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
|
||||
break;
|
||||
default:
|
||||
r = -EINVAL;
|
||||
goto done;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = amdgpu_dpm_force_performance_level(adev, level);
|
||||
current_ctx = adev->pm.stable_pstate_ctx;
|
||||
if (current_ctx && current_ctx != ctx)
|
||||
return -EBUSY;
|
||||
|
||||
if (level == AMD_DPM_FORCED_LEVEL_AUTO)
|
||||
adev->pm.stable_pstate_ctx = NULL;
|
||||
else
|
||||
r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate);
|
||||
if (r || current_stable_pstate == stable_pstate)
|
||||
return r;
|
||||
|
||||
r = amdgpu_dpm_force_performance_level(adev, level);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!current_ctx) {
|
||||
adev->pm.stable_pstate_ctx = ctx;
|
||||
done:
|
||||
/*
|
||||
* Serialized by context taking ownership for the first time
|
||||
* while holding adev->pm.stable_pstate_ctx_lock).
|
||||
*/
|
||||
WRITE_ONCE(ctx->stable_pstate, current_stable_pstate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
|
||||
u32 stable_pstate)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->mgr->adev;
|
||||
int r;
|
||||
|
||||
mutex_lock(&adev->pm.stable_pstate_ctx_lock);
|
||||
r = __amdgpu_ctx_set_stable_pstate(ctx, stable_pstate);
|
||||
mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
|
||||
|
||||
return r;
|
||||
@@ -428,7 +436,12 @@ static void amdgpu_ctx_fini(struct kref *ref)
|
||||
}
|
||||
|
||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
||||
amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate);
|
||||
mutex_lock(&adev->pm.stable_pstate_ctx_lock);
|
||||
if (adev->pm.stable_pstate_ctx == ctx) {
|
||||
__amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate);
|
||||
adev->pm.stable_pstate_ctx = NULL;
|
||||
}
|
||||
mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <generated/utsrelease.h>
|
||||
#include <linux/devcoredump.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <drm/drm_exec.h>
|
||||
#include "amdgpu_dev_coredump.h"
|
||||
#include "atom.h"
|
||||
|
||||
@@ -207,28 +208,143 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
amdgpu_devcoredump_print_ibs(struct drm_printer *p,
|
||||
struct amdgpu_coredump_info *coredump,
|
||||
bool sizing_pass)
|
||||
{
|
||||
struct amdgpu_device *adev = coredump->adev;
|
||||
struct amdgpu_bo_va_mapping *mapping;
|
||||
struct amdgpu_bo *abo;
|
||||
struct drm_exec exec;
|
||||
struct amdgpu_vm *vm;
|
||||
u32 *ib_content;
|
||||
u64 va_start, offset;
|
||||
u8 *kptr;
|
||||
u32 off;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* On the sizing pass there is no VM to look up and no BO to lock; the
|
||||
* size estimate doesn't depend on whether the IB BOs are reachable.
|
||||
* Just emit the per-IB headers (the content is not written anywhere).
|
||||
*/
|
||||
if (sizing_pass) {
|
||||
for (int i = 0; i < coredump->num_ibs; i++) {
|
||||
drm_printf(p, "\nIB #%d 0x%llx %d dw\n", i,
|
||||
coredump->ibs[i].gpu_addr,
|
||||
coredump->ibs[i].ib_size_dw);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the VM root PD and every IB BO together in a single drm_exec
|
||||
* ticket. Reserving the IB BOs one by one while the root PD is held
|
||||
* would be a recursive reservation_ww_class_mutex acquire without a
|
||||
* ww_acquire_ctx, which trips lockdep and self-deadlocks for IB BOs
|
||||
* that share their dma_resv with the root PD (always-valid BOs).
|
||||
*/
|
||||
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 1 + coredump->num_ibs);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, coredump->pasid, &exec);
|
||||
if (!vm)
|
||||
goto unlock;
|
||||
|
||||
for (int i = 0; i < coredump->num_ibs; i++) {
|
||||
u64 pfn = (coredump->ibs[i].gpu_addr &
|
||||
AMDGPU_GMC_HOLE_MASK) / AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
mapping = amdgpu_vm_bo_lookup_mapping(vm, pfn);
|
||||
if (!mapping)
|
||||
continue;
|
||||
|
||||
abo = mapping->bo_va->base.bo;
|
||||
r = drm_exec_lock_obj(&exec, &abo->tbo.base);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (r)
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < coredump->num_ibs; i++) {
|
||||
bool emit_content = false;
|
||||
|
||||
ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
|
||||
GFP_KERNEL);
|
||||
if (!ib_content)
|
||||
continue;
|
||||
|
||||
va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
|
||||
mapping = amdgpu_vm_bo_lookup_mapping(vm,
|
||||
va_start / AMDGPU_GPU_PAGE_SIZE);
|
||||
if (!mapping)
|
||||
goto output_ib_content;
|
||||
|
||||
abo = mapping->bo_va->base.bo;
|
||||
offset = va_start - mapping->start * AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
|
||||
struct amdgpu_res_cursor cursor;
|
||||
|
||||
off = 0;
|
||||
|
||||
if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
|
||||
goto output_ib_content;
|
||||
|
||||
amdgpu_res_first(abo->tbo.resource, offset,
|
||||
coredump->ibs[i].ib_size_dw * 4, &cursor);
|
||||
while (cursor.remaining) {
|
||||
amdgpu_device_mm_access(adev, cursor.start / 4,
|
||||
&ib_content[off], cursor.size / 4,
|
||||
false);
|
||||
off += cursor.size;
|
||||
amdgpu_res_next(&cursor, cursor.size);
|
||||
}
|
||||
emit_content = true;
|
||||
} else {
|
||||
r = ttm_bo_kmap(&abo->tbo, 0, PFN_UP(abo->tbo.base.size),
|
||||
&abo->kmap);
|
||||
if (r)
|
||||
goto output_ib_content;
|
||||
|
||||
kptr = amdgpu_bo_kptr(abo);
|
||||
kptr += offset;
|
||||
memcpy(ib_content, kptr, coredump->ibs[i].ib_size_dw * 4);
|
||||
|
||||
amdgpu_bo_kunmap(abo);
|
||||
emit_content = true;
|
||||
}
|
||||
|
||||
output_ib_content:
|
||||
drm_printf(p, "\nIB #%d 0x%llx %d dw\n", i,
|
||||
coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
|
||||
if (emit_content) {
|
||||
for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
|
||||
drm_printf(p, "0x%08x\n", ib_content[j]);
|
||||
}
|
||||
kvfree(ib_content);
|
||||
}
|
||||
|
||||
unlock:
|
||||
drm_exec_fini(&exec);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump)
|
||||
{
|
||||
struct amdgpu_device *adev = coredump->adev;
|
||||
struct drm_printer p;
|
||||
struct drm_print_iterator iter;
|
||||
struct amdgpu_vm_fault_info *fault_info;
|
||||
struct amdgpu_bo_va_mapping *mapping;
|
||||
struct amdgpu_ip_block *ip_block;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
struct amdgpu_bo *abo, *root;
|
||||
uint64_t va_start, offset;
|
||||
struct amdgpu_ring *ring;
|
||||
struct amdgpu_vm *vm;
|
||||
u32 *ib_content;
|
||||
uint8_t *kptr;
|
||||
int ver, i, j, r;
|
||||
int ver, i, j;
|
||||
u32 ring_idx, off;
|
||||
bool sizing_pass;
|
||||
|
||||
sizing_pass = buffer == NULL;
|
||||
iter.data = buffer;
|
||||
iter.start = 0;
|
||||
iter.offset = 0;
|
||||
iter.remain = count;
|
||||
|
||||
@@ -236,7 +352,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
|
||||
|
||||
drm_printf(&p, "**** AMDGPU Device Coredump ****\n");
|
||||
drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
|
||||
drm_printf(&p, "kernel: " UTS_RELEASE "\n");
|
||||
drm_printf(&p, "kernel: %s\n", init_utsname()->release);
|
||||
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
|
||||
drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
|
||||
|
||||
@@ -342,86 +458,8 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
|
||||
else if (coredump->reset_vram_lost)
|
||||
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
|
||||
|
||||
if (coredump->num_ibs) {
|
||||
/* Don't try to lookup the VM or map the BOs when calculating the
|
||||
* size required to store the devcoredump.
|
||||
*/
|
||||
if (sizing_pass)
|
||||
vm = NULL;
|
||||
else
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
|
||||
|
||||
for (int i = 0; i < coredump->num_ibs && (sizing_pass || vm); i++) {
|
||||
ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
|
||||
GFP_KERNEL);
|
||||
if (!ib_content)
|
||||
continue;
|
||||
|
||||
/* vm=NULL can only happen when 'sizing_pass' is true. Skip to the
|
||||
* drm_printf() calls (ib_content doesn't need to be initialized
|
||||
* as its content won't be written anywhere).
|
||||
*/
|
||||
if (!vm)
|
||||
goto output_ib_content;
|
||||
|
||||
va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
|
||||
mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
|
||||
if (!mapping)
|
||||
goto free_ib_content;
|
||||
|
||||
offset = va_start - (mapping->start * AMDGPU_GPU_PAGE_SIZE);
|
||||
abo = amdgpu_bo_ref(mapping->bo_va->base.bo);
|
||||
r = amdgpu_bo_reserve(abo, false);
|
||||
if (r)
|
||||
goto free_ib_content;
|
||||
|
||||
if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
|
||||
off = 0;
|
||||
|
||||
if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
|
||||
goto unreserve_abo;
|
||||
|
||||
amdgpu_res_first(abo->tbo.resource, offset,
|
||||
coredump->ibs[i].ib_size_dw * 4,
|
||||
&cursor);
|
||||
while (cursor.remaining) {
|
||||
amdgpu_device_mm_access(adev, cursor.start / 4,
|
||||
&ib_content[off], cursor.size / 4,
|
||||
false);
|
||||
off += cursor.size;
|
||||
amdgpu_res_next(&cursor, cursor.size);
|
||||
}
|
||||
} else {
|
||||
r = ttm_bo_kmap(&abo->tbo, 0,
|
||||
PFN_UP(abo->tbo.base.size),
|
||||
&abo->kmap);
|
||||
if (r)
|
||||
goto unreserve_abo;
|
||||
|
||||
kptr = amdgpu_bo_kptr(abo);
|
||||
kptr += offset;
|
||||
memcpy(ib_content, kptr,
|
||||
coredump->ibs[i].ib_size_dw * 4);
|
||||
|
||||
amdgpu_bo_kunmap(abo);
|
||||
}
|
||||
|
||||
output_ib_content:
|
||||
drm_printf(&p, "\nIB #%d 0x%llx %d dw\n",
|
||||
i, coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
|
||||
for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
|
||||
drm_printf(&p, "0x%08x\n", ib_content[j]);
|
||||
unreserve_abo:
|
||||
if (vm)
|
||||
amdgpu_bo_unreserve(abo);
|
||||
free_ib_content:
|
||||
kvfree(ib_content);
|
||||
}
|
||||
if (vm) {
|
||||
amdgpu_bo_unreserve(root);
|
||||
amdgpu_bo_unref(&root);
|
||||
}
|
||||
}
|
||||
if (coredump->num_ibs)
|
||||
amdgpu_devcoredump_print_ibs(&p, coredump, sizing_pass);
|
||||
|
||||
return count - iter.remain;
|
||||
}
|
||||
|
||||
@@ -3043,7 +3043,7 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
|
||||
amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D3Entry);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
if (!adev->ip_blocks[i].status.valid || !adev->ip_blocks[i].status.hw)
|
||||
continue;
|
||||
/* displays are handled in phase1 */
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)
|
||||
@@ -3771,6 +3771,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
mutex_init(&adev->gfx.workload_profile_mutex);
|
||||
mutex_init(&adev->vcn.workload_profile_mutex);
|
||||
|
||||
spin_lock_init(&adev->irq.lock);
|
||||
|
||||
amdgpu_device_init_apu_flags(adev);
|
||||
|
||||
r = amdgpu_device_check_arguments(adev);
|
||||
|
||||
@@ -1094,6 +1094,11 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
|
||||
* If that number is larger than the size of the array, the ioctl must
|
||||
* be retried.
|
||||
*/
|
||||
if (!bo_va) {
|
||||
r = -ENOENT;
|
||||
goto out_exec;
|
||||
}
|
||||
|
||||
if (args->num_entries > INT_MAX / sizeof(*vm_entries)) {
|
||||
r = -EINVAL;
|
||||
goto out_exec;
|
||||
|
||||
@@ -1664,12 +1664,13 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct drm_gpu_scheduler *sched = &ring->sched;
|
||||
struct drm_sched_entity entity;
|
||||
unsigned int ib_size_dw = 16;
|
||||
static atomic_t counter;
|
||||
struct dma_fence *f;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
void *owner;
|
||||
int i, r;
|
||||
int r;
|
||||
|
||||
/* Initialize the scheduler entity */
|
||||
r = drm_sched_entity_init(&entity, DRM_SCHED_PRIORITY_NORMAL,
|
||||
@@ -1687,7 +1688,7 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
|
||||
owner = (void *)(unsigned long)atomic_inc_return(&counter);
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
|
||||
64, 0, &job,
|
||||
ib_size_dw * sizeof(uint32_t), 0, &job,
|
||||
AMDGPU_KERNEL_JOB_ID_CLEANER_SHADER);
|
||||
if (r)
|
||||
goto err;
|
||||
@@ -1697,9 +1698,8 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
|
||||
job->run_cleaner_shader = true;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
for (i = 0; i <= ring->funcs->align_mask; ++i)
|
||||
ib->ptr[i] = ring->funcs->nop;
|
||||
ib->length_dw = ring->funcs->align_mask + 1;
|
||||
memset32(ib->ptr, ring->funcs->nop, ib_size_dw);
|
||||
ib->length_dw = ib_size_dw;
|
||||
|
||||
f = amdgpu_job_submit(job);
|
||||
|
||||
|
||||
@@ -272,7 +272,20 @@ static bool amdgpu_gtt_mgr_intersects(struct ttm_resource_manager *man,
|
||||
const struct ttm_place *place,
|
||||
size_t size)
|
||||
{
|
||||
return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
|
||||
const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
|
||||
const u32 num_pages = PFN_UP(size);
|
||||
|
||||
if (!place->lpfn)
|
||||
return true;
|
||||
|
||||
if (!amdgpu_gtt_mgr_has_gart_addr(res))
|
||||
return false;
|
||||
|
||||
if (place->fpfn >= (node->start + num_pages) ||
|
||||
(place->lpfn && place->lpfn <= node->start))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,7 +303,20 @@ static bool amdgpu_gtt_mgr_compatible(struct ttm_resource_manager *man,
|
||||
const struct ttm_place *place,
|
||||
size_t size)
|
||||
{
|
||||
return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
|
||||
const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
|
||||
const u32 num_pages = PFN_UP(size);
|
||||
|
||||
if (!place->lpfn)
|
||||
return true;
|
||||
|
||||
if (!amdgpu_gtt_mgr_has_gart_addr(res))
|
||||
return false;
|
||||
|
||||
if (node->start < place->fpfn ||
|
||||
(place->lpfn && (node->start + num_pages) > place->lpfn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -309,8 +309,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
||||
unsigned int irq, flags;
|
||||
int r;
|
||||
|
||||
spin_lock_init(&adev->irq.lock);
|
||||
|
||||
/* Enable MSI if not disabled by module parameter */
|
||||
adev->irq.msi_enabled = false;
|
||||
|
||||
@@ -547,7 +545,7 @@ void amdgpu_irq_delegate(struct amdgpu_device *adev,
|
||||
unsigned int num_dw)
|
||||
{
|
||||
amdgpu_ih_ring_write(adev, &adev->irq.ih_soft, entry->iv_entry, num_dw);
|
||||
schedule_work(&adev->irq.ih_soft_work);
|
||||
queue_work(system_unbound_wq, &adev->irq.ih_soft_work);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,17 @@
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
|
||||
struct amdgpu_lockdep_dummy_locks {
|
||||
struct mutex reset_lock;
|
||||
struct mutex userq_sch_mutex;
|
||||
struct mutex userq_mutex;
|
||||
struct mutex notifier_lock;
|
||||
struct mutex vram_lock;
|
||||
struct mutex srbm_mutex;
|
||||
struct mutex grbm_idx_mutex;
|
||||
spinlock_t mmio_idx_lock;
|
||||
};
|
||||
|
||||
/* Lock class keys for associating with real driver locks */
|
||||
static struct lock_class_key amdgpu_userq_sch_mutex_key;
|
||||
static struct lock_class_key amdgpu_userq_mutex_key;
|
||||
@@ -84,72 +95,65 @@ void amdgpu_lockdep_set_class(struct amdgpu_device *adev)
|
||||
int amdgpu_lockdep_init(void)
|
||||
{
|
||||
struct amdgpu_reset_domain *reset_domain = NULL;
|
||||
struct amdgpu_reset_control reset_ctl;
|
||||
struct mutex userq_sch_mutex;
|
||||
struct mutex userq_mutex;
|
||||
struct mutex notifier_lock;
|
||||
struct mutex vram_lock;
|
||||
struct mutex srbm_mutex;
|
||||
struct mutex grbm_idx_mutex;
|
||||
spinlock_t mmio_idx_lock;
|
||||
struct amdgpu_lockdep_dummy_locks *locks;
|
||||
unsigned long flags;
|
||||
|
||||
locks = kzalloc(sizeof(*locks), GFP_KERNEL);
|
||||
if (!locks)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Initialize dummy reset domain
|
||||
*/
|
||||
reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE,
|
||||
"lockdep_test");
|
||||
if (!reset_domain)
|
||||
if (!reset_domain) {
|
||||
kfree(locks);
|
||||
return -ENOMEM;
|
||||
|
||||
}
|
||||
/* Initialize dummy locks */
|
||||
mutex_init(&userq_sch_mutex);
|
||||
mutex_init(&userq_mutex);
|
||||
mutex_init(¬ifier_lock);
|
||||
mutex_init(&vram_lock);
|
||||
mutex_init(&reset_ctl.reset_lock);
|
||||
mutex_init(&srbm_mutex);
|
||||
mutex_init(&grbm_idx_mutex);
|
||||
spin_lock_init(&mmio_idx_lock);
|
||||
mutex_init(&locks->userq_sch_mutex);
|
||||
mutex_init(&locks->userq_mutex);
|
||||
mutex_init(&locks->notifier_lock);
|
||||
mutex_init(&locks->vram_lock);
|
||||
mutex_init(&locks->reset_lock);
|
||||
mutex_init(&locks->srbm_mutex);
|
||||
mutex_init(&locks->grbm_idx_mutex);
|
||||
spin_lock_init(&locks->mmio_idx_lock);
|
||||
|
||||
/*
|
||||
* Associate dummy locks with the same class keys used for real
|
||||
* driver locks. This ensures lockdep connects the ordering learned
|
||||
* here with the actual locks used at runtime.
|
||||
*/
|
||||
lockdep_set_class(&userq_sch_mutex, &amdgpu_userq_sch_mutex_key);
|
||||
lockdep_set_class(&userq_mutex, &amdgpu_userq_mutex_key);
|
||||
lockdep_set_class(¬ifier_lock, &amdgpu_notifier_lock_key);
|
||||
lockdep_set_class(&vram_lock, &amdgpu_vram_lock_key);
|
||||
lockdep_set_class(&locks->userq_sch_mutex, &amdgpu_userq_sch_mutex_key);
|
||||
lockdep_set_class(&locks->userq_mutex, &amdgpu_userq_mutex_key);
|
||||
lockdep_set_class(&locks->notifier_lock, &amdgpu_notifier_lock_key);
|
||||
lockdep_set_class(&locks->vram_lock, &amdgpu_vram_lock_key);
|
||||
lockdep_set_class(&reset_domain->sem, &amdgpu_reset_sem_key);
|
||||
lockdep_set_class(&reset_ctl.reset_lock, &amdgpu_reset_lock_key);
|
||||
lockdep_set_class(&srbm_mutex, &amdgpu_srbm_lock_key);
|
||||
lockdep_set_class(&grbm_idx_mutex, &amdgpu_grbm_lock_key);
|
||||
lockdep_set_class(&mmio_idx_lock, &amdgpu_mmio_lock_key);
|
||||
|
||||
lockdep_set_class(&locks->reset_lock, &amdgpu_reset_lock_key);
|
||||
lockdep_set_class(&locks->srbm_mutex, &amdgpu_srbm_lock_key);
|
||||
lockdep_set_class(&locks->grbm_idx_mutex, &amdgpu_grbm_lock_key);
|
||||
lockdep_set_class(&locks->mmio_idx_lock, &amdgpu_mmio_lock_key);
|
||||
/*
|
||||
* Take locks in the correct order to train lockdep.
|
||||
* This establishes the dependency chain.
|
||||
*/
|
||||
|
||||
/* Level 1: Global userq scheduler mutex (outermost) */
|
||||
mutex_lock(&userq_sch_mutex);
|
||||
mutex_lock(&locks->userq_sch_mutex);
|
||||
|
||||
/* Level 2: Per-context userq mutex */
|
||||
mutex_lock(&userq_mutex);
|
||||
|
||||
mutex_lock(&locks->userq_mutex);
|
||||
/* Level 3: MMU notifier lock */
|
||||
mutex_lock(¬ifier_lock);
|
||||
|
||||
mutex_lock(&locks->notifier_lock);
|
||||
/* Level 4: VRAM allocator lock */
|
||||
mutex_lock(&vram_lock);
|
||||
|
||||
mutex_lock(&locks->vram_lock);
|
||||
/* Level 5: Reset domain semaphore */
|
||||
down_read(&reset_domain->sem);
|
||||
|
||||
/* Level 6: Reset control lock */
|
||||
mutex_lock(&reset_ctl.reset_lock);
|
||||
|
||||
mutex_lock(&locks->reset_lock);
|
||||
/*
|
||||
* Mark potential memory reclaim boundary.
|
||||
* GPU operations might trigger memory allocation/reclaim.
|
||||
@@ -157,36 +161,35 @@ int amdgpu_lockdep_init(void)
|
||||
fs_reclaim_acquire(GFP_KERNEL);
|
||||
|
||||
/* Level 7: SRBM register access */
|
||||
mutex_lock(&srbm_mutex);
|
||||
|
||||
mutex_lock(&locks->srbm_mutex);
|
||||
/* Level 8: GRBM index access */
|
||||
mutex_lock(&grbm_idx_mutex);
|
||||
mutex_lock(&locks->grbm_idx_mutex);
|
||||
|
||||
/* Level 9: MMIO index access (innermost lock, spinlock) */
|
||||
spin_lock_irqsave(&mmio_idx_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&locks->mmio_idx_lock, flags);
|
||||
/*
|
||||
* All locks acquired in order.
|
||||
* Lockdep has now learned the valid dependency chain.
|
||||
*/
|
||||
|
||||
/* Release in reverse order */
|
||||
spin_unlock_irqrestore(&mmio_idx_lock, flags);
|
||||
mutex_unlock(&grbm_idx_mutex);
|
||||
mutex_unlock(&srbm_mutex);
|
||||
|
||||
spin_unlock_irqrestore(&locks->mmio_idx_lock, flags);
|
||||
mutex_unlock(&locks->grbm_idx_mutex);
|
||||
mutex_unlock(&locks->srbm_mutex);
|
||||
fs_reclaim_release(GFP_KERNEL);
|
||||
|
||||
mutex_unlock(&reset_ctl.reset_lock);
|
||||
mutex_unlock(&locks->reset_lock);
|
||||
up_read(&reset_domain->sem);
|
||||
mutex_unlock(&vram_lock);
|
||||
mutex_unlock(¬ifier_lock);
|
||||
mutex_unlock(&userq_mutex);
|
||||
mutex_unlock(&userq_sch_mutex);
|
||||
|
||||
mutex_unlock(&locks->vram_lock);
|
||||
mutex_unlock(&locks->notifier_lock);
|
||||
mutex_unlock(&locks->userq_mutex);
|
||||
mutex_unlock(&locks->userq_sch_mutex);
|
||||
|
||||
/* Cleanup */
|
||||
amdgpu_reset_put_reset_domain(reset_domain);
|
||||
|
||||
kfree(locks);
|
||||
pr_info("AMDGPU: Lockdep annotations initialized (9 lock levels)\n");
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
|
||||
if (new_mem->mem_type == TTM_PL_TT ||
|
||||
new_mem->mem_type == AMDGPU_PL_PREEMPT) {
|
||||
if (old_mem && (old_mem->mem_type == TTM_PL_TT ||
|
||||
old_mem->mem_type == AMDGPU_PL_PREEMPT)) {
|
||||
r = ttm_bo_wait_ctx(bo, ctx);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem);
|
||||
if (r)
|
||||
return r;
|
||||
@@ -549,6 +558,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
ttm_bo_assign_mem(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
if ((old_mem->mem_type == TTM_PL_TT ||
|
||||
old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
|
||||
(new_mem->mem_type == TTM_PL_TT ||
|
||||
new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
|
||||
amdgpu_bo_move_notify(bo, evict, new_mem);
|
||||
ttm_resource_free(bo, &bo->resource);
|
||||
ttm_bo_assign_mem(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (old_mem->mem_type == AMDGPU_PL_GDS ||
|
||||
old_mem->mem_type == AMDGPU_PL_GWS ||
|
||||
|
||||
@@ -135,7 +135,7 @@ MODULE_FIRMWARE(FIRMWARE_VEGA12);
|
||||
MODULE_FIRMWARE(FIRMWARE_VEGA20);
|
||||
|
||||
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
|
||||
static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo);
|
||||
static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *abo);
|
||||
|
||||
static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
|
||||
uint32_t size,
|
||||
@@ -158,7 +158,7 @@ static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
|
||||
amdgpu_bo_kunmap(bo);
|
||||
amdgpu_bo_unpin(bo);
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
|
||||
amdgpu_uvd_force_into_uvd_segment(bo);
|
||||
amdgpu_uvd_force_into_vcpu_segment(bo);
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
if (r)
|
||||
goto err;
|
||||
@@ -188,6 +188,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
const struct common_firmware_header *hdr;
|
||||
unsigned int family_id;
|
||||
int i, j, r;
|
||||
u32 vcpu_bo_domain;
|
||||
|
||||
INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);
|
||||
|
||||
@@ -319,12 +320,20 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
|
||||
|
||||
/* UVD 5.0 and newer HW can use 64 bit addressing. */
|
||||
adev->uvd.address_64_bit =
|
||||
!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0);
|
||||
|
||||
vcpu_bo_domain = AMDGPU_GEM_DOMAIN_VRAM;
|
||||
if (adev->uvd.address_64_bit)
|
||||
vcpu_bo_domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
|
||||
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
|
||||
if (adev->uvd.harvest_config & (1 << j))
|
||||
continue;
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
vcpu_bo_domain,
|
||||
&adev->uvd.inst[j].vcpu_bo,
|
||||
&adev->uvd.inst[j].gpu_addr,
|
||||
&adev->uvd.inst[j].cpu_addr);
|
||||
@@ -339,10 +348,6 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
adev->uvd.filp[i] = NULL;
|
||||
}
|
||||
|
||||
/* from uvd v5.0 HW addressing capacity increased to 64 bits */
|
||||
if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))
|
||||
adev->uvd.address_64_bit = true;
|
||||
|
||||
r = amdgpu_uvd_create_msg_bo_helper(adev, 128 << 10, &adev->uvd.ib_bo);
|
||||
if (r)
|
||||
return r;
|
||||
@@ -545,6 +550,24 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
|
||||
}
|
||||
}
|
||||
|
||||
static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_bo *vcpu_bo = adev->uvd.inst[0].vcpu_bo;
|
||||
struct amdgpu_res_cursor vcpu_cur;
|
||||
|
||||
amdgpu_res_first(vcpu_bo->tbo.resource, 0,
|
||||
amdgpu_bo_size(vcpu_bo), &vcpu_cur);
|
||||
|
||||
bo->placement.num_placement = 1;
|
||||
bo->placement.placement = &bo->placements[0];
|
||||
bo->placements[0].fpfn = ALIGN_DOWN(vcpu_cur.start, SZ_256M) >> PAGE_SHIFT;
|
||||
bo->placements[0].lpfn = bo->placements[0].fpfn + (SZ_256M >> PAGE_SHIFT);
|
||||
bo->placements[0].mem_type = vcpu_bo->tbo.resource->mem_type;
|
||||
if (bo->placements[0].mem_type == TTM_PL_VRAM)
|
||||
bo->placements[0].flags |= TTM_PL_FLAG_CONTIGUOUS;
|
||||
}
|
||||
|
||||
static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
|
||||
{
|
||||
int i;
|
||||
@@ -595,13 +618,10 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
|
||||
if (!ctx->parser->adev->uvd.address_64_bit) {
|
||||
/* check if it's a message or feedback command */
|
||||
cmd = amdgpu_ib_get_value(ctx->ib, ctx->idx) >> 1;
|
||||
if (cmd == 0x0 || cmd == 0x3) {
|
||||
/* yes, force it into VRAM */
|
||||
uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM;
|
||||
|
||||
amdgpu_bo_placement_from_domain(bo, domain);
|
||||
}
|
||||
amdgpu_uvd_force_into_uvd_segment(bo);
|
||||
if (cmd == 0x0 || cmd == 0x3)
|
||||
amdgpu_uvd_force_into_vcpu_segment(bo);
|
||||
else
|
||||
amdgpu_uvd_force_into_uvd_segment(bo);
|
||||
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &tctx);
|
||||
}
|
||||
|
||||
@@ -2920,47 +2920,56 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_lock_by_pasid - return an amdgpu_vm and its root bo from a pasid, if possible.
|
||||
* amdgpu_vm_lock_by_pasid - look up a VM by PASID and lock its root PD
|
||||
* @adev: amdgpu device pointer
|
||||
* @root: root BO of the VM
|
||||
* @pasid: PASID of the VM
|
||||
* The caller needs to unreserve and unref the root bo on success.
|
||||
* @exec: drm_exec context to lock the root PD in
|
||||
*
|
||||
* Must be called from within a drm_exec_until_all_locked() loop; the caller
|
||||
* runs drm_exec_retry_on_contention() afterwards. The drm_exec context holds
|
||||
* a reference on the root BO until it is finalised.
|
||||
*
|
||||
* Return: the VM on success, or NULL if the PASID has no VM, the VM is being
|
||||
* torn down, or locking the root PD failed.
|
||||
*/
|
||||
struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo **root, u32 pasid)
|
||||
u32 pasid, struct drm_exec *exec)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
struct amdgpu_bo *root;
|
||||
struct amdgpu_vm *vm;
|
||||
int r;
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
*root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
|
||||
root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
|
||||
|
||||
if (!*root)
|
||||
if (!root)
|
||||
return NULL;
|
||||
|
||||
r = amdgpu_bo_reserve(*root, true);
|
||||
if (r)
|
||||
goto error_unref;
|
||||
r = drm_exec_lock_obj(exec, &root->tbo.base);
|
||||
if (r) {
|
||||
amdgpu_bo_unref(&root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Double check that the VM still exists */
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
if (vm && vm->root.bo != *root)
|
||||
if (vm && vm->root.bo != root)
|
||||
vm = NULL;
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
|
||||
if (!vm)
|
||||
goto error_unlock;
|
||||
if (!vm) {
|
||||
drm_exec_unlock_obj(exec, &root->tbo.base);
|
||||
amdgpu_bo_unref(&root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The drm_exec context holds its own reference on the root BO. */
|
||||
amdgpu_bo_unref(&root);
|
||||
|
||||
return vm;
|
||||
error_unlock:
|
||||
amdgpu_bo_unreserve(*root);
|
||||
|
||||
error_unref:
|
||||
amdgpu_bo_unref(root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2982,33 +2991,49 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
uint64_t ts, bool write_fault)
|
||||
{
|
||||
bool is_compute_context = false;
|
||||
struct amdgpu_bo *root;
|
||||
struct drm_exec exec;
|
||||
uint64_t value, flags;
|
||||
struct amdgpu_vm *vm;
|
||||
int r;
|
||||
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid);
|
||||
if (!vm)
|
||||
drm_exec_init(&exec, 0, 1);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, pasid, &exec);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (!vm)
|
||||
break;
|
||||
}
|
||||
if (!vm) {
|
||||
drm_exec_fini(&exec);
|
||||
return false;
|
||||
}
|
||||
|
||||
is_compute_context = vm->is_compute_context;
|
||||
|
||||
if (is_compute_context) {
|
||||
/* Unreserve root since svm_range_restore_pages might try to reserve it. */
|
||||
/* TODO: rework svm_range_restore_pages so that this isn't necessary. */
|
||||
amdgpu_bo_unreserve(root);
|
||||
/* Release the root PD lock since svm_range_restore_pages
|
||||
* might try to take it.
|
||||
* TODO: rework svm_range_restore_pages so that this isn't
|
||||
* necessary.
|
||||
*/
|
||||
drm_exec_fini(&exec);
|
||||
|
||||
if (!svm_range_restore_pages(adev, pasid, vmid,
|
||||
node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
|
||||
amdgpu_bo_unref(&root);
|
||||
node_id, addr >> PAGE_SHIFT, ts, write_fault))
|
||||
return true;
|
||||
}
|
||||
amdgpu_bo_unref(&root);
|
||||
|
||||
/* Re-acquire the VM lock, could be that the VM was freed in between. */
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid);
|
||||
if (!vm)
|
||||
drm_exec_init(&exec, 0, 1);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, pasid, &exec);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (!vm)
|
||||
break;
|
||||
}
|
||||
if (!vm) {
|
||||
drm_exec_fini(&exec);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
addr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
@@ -3032,7 +3057,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
value = 0;
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(root->tbo.base.resv, 1);
|
||||
r = dma_resv_reserve_fences(vm->root.bo->tbo.base.resv, 1);
|
||||
if (r) {
|
||||
pr_debug("failed %d to reserve fence slot\n", r);
|
||||
goto error_unlock;
|
||||
@@ -3046,12 +3071,10 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
r = amdgpu_vm_update_pdes(adev, vm, true);
|
||||
|
||||
error_unlock:
|
||||
amdgpu_bo_unreserve(root);
|
||||
drm_exec_fini(&exec);
|
||||
if (r < 0)
|
||||
dev_err(adev->dev, "Can't handle page fault (%d)\n", r);
|
||||
|
||||
amdgpu_bo_unref(&root);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -592,7 +592,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
bool write_fault);
|
||||
|
||||
struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo **root, u32 pasid);
|
||||
u32 pasid, struct drm_exec *exec);
|
||||
|
||||
void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
|
||||
|
||||
|
||||
@@ -4071,6 +4071,41 @@ err_priv_inst:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void gfx_v9_0_deactivate_kcq_hqd(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
|
||||
for (int i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
u32 tmp;
|
||||
struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
|
||||
tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||
/* disable the queue if it's active */
|
||||
if (tmp & CP_HQD_ACTIVE__ACTIVE_MASK) {
|
||||
int j;
|
||||
|
||||
WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1);
|
||||
for (j = 0; j < adev->usec_timeout; j++) {
|
||||
tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||
if (!(tmp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
if (j == AMDGPU_MAX_USEC_TIMEOUT) {
|
||||
DRM_DEBUG("comp_%u_%u_%u dequeue request failed.\n",
|
||||
ring->me, ring->pipe, ring->queue);
|
||||
/* Manual disable if dequeue request times out */
|
||||
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, 0);
|
||||
}
|
||||
WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 0);
|
||||
}
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
|
||||
}
|
||||
|
||||
static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
@@ -4095,6 +4130,10 @@ static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev) &&
|
||||
amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_MODE2)
|
||||
gfx_v9_0_deactivate_kcq_hqd(adev);
|
||||
|
||||
/* Use deinitialize sequence from CAIL when unbinding device from driver,
|
||||
* otherwise KIQ is hanging when binding back
|
||||
*/
|
||||
|
||||
@@ -790,7 +790,7 @@ static void ih_v6_1_set_interrupt_funcs(struct amdgpu_device *adev)
|
||||
const struct amdgpu_ip_block_version ih_v6_1_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_IH,
|
||||
.major = 6,
|
||||
.minor = 0,
|
||||
.minor = 1,
|
||||
.rev = 0,
|
||||
.funcs = &ih_v6_1_ip_funcs,
|
||||
};
|
||||
|
||||
@@ -1299,18 +1299,11 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
|
||||
GFP_KERNEL);
|
||||
if (!devices_arr)
|
||||
return -ENOMEM;
|
||||
devices_arr = memdup_array_user((void *)args->device_ids_array_ptr,
|
||||
args->n_devices, sizeof(*devices_arr));
|
||||
|
||||
err = copy_from_user(devices_arr,
|
||||
(void __user *)args->device_ids_array_ptr,
|
||||
args->n_devices * sizeof(*devices_arr));
|
||||
if (err != 0) {
|
||||
err = -EFAULT;
|
||||
goto copy_from_user_failed;
|
||||
}
|
||||
if (IS_ERR(devices_arr))
|
||||
return PTR_ERR(devices_arr);
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle));
|
||||
@@ -1391,7 +1384,6 @@ get_mem_obj_from_handle_failed:
|
||||
map_memory_to_gpu_failed:
|
||||
sync_memory_failed:
|
||||
mutex_unlock(&p->mutex);
|
||||
copy_from_user_failed:
|
||||
kfree(devices_arr);
|
||||
|
||||
return err;
|
||||
@@ -1416,18 +1408,11 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
|
||||
GFP_KERNEL);
|
||||
if (!devices_arr)
|
||||
return -ENOMEM;
|
||||
devices_arr = memdup_array_user((void *)args->device_ids_array_ptr,
|
||||
args->n_devices, sizeof(*devices_arr));
|
||||
|
||||
err = copy_from_user(devices_arr,
|
||||
(void __user *)args->device_ids_array_ptr,
|
||||
args->n_devices * sizeof(*devices_arr));
|
||||
if (err != 0) {
|
||||
err = -EFAULT;
|
||||
goto copy_from_user_failed;
|
||||
}
|
||||
if (IS_ERR(devices_arr))
|
||||
return PTR_ERR(devices_arr);
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle));
|
||||
@@ -1493,7 +1478,6 @@ get_mem_obj_from_handle_failed:
|
||||
unmap_memory_from_gpu_failed:
|
||||
sync_memory_failed:
|
||||
mutex_unlock(&p->mutex);
|
||||
copy_from_user_failed:
|
||||
kfree(devices_arr);
|
||||
return err;
|
||||
}
|
||||
@@ -1562,16 +1546,10 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (args->metadata_ptr) {
|
||||
metadata_buffer = kzalloc(args->metadata_size, GFP_KERNEL);
|
||||
if (!metadata_buffer)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get dmabuf info from KGD */
|
||||
r = amdgpu_amdkfd_get_dmabuf_info(dev->adev, args->dmabuf_fd,
|
||||
&dmabuf_adev, &args->size,
|
||||
metadata_buffer, args->metadata_size,
|
||||
&metadata_buffer, args->metadata_size,
|
||||
&args->metadata_size, &flags, &xcp_id);
|
||||
if (r)
|
||||
goto exit;
|
||||
@@ -1583,7 +1561,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
|
||||
args->flags = flags;
|
||||
|
||||
/* Copy metadata buffer to user mode */
|
||||
if (metadata_buffer) {
|
||||
if (metadata_buffer && args->metadata_ptr) {
|
||||
r = copy_to_user((void __user *)args->metadata_ptr,
|
||||
metadata_buffer, args->metadata_size);
|
||||
if (r != 0)
|
||||
@@ -2359,17 +2337,11 @@ static int criu_restore_devices(struct kfd_process *p,
|
||||
if (*priv_offset + (args->num_devices * sizeof(*device_privs)) > max_priv_data_size)
|
||||
return -EINVAL;
|
||||
|
||||
device_buckets = kmalloc_objs(*device_buckets, args->num_devices);
|
||||
if (!device_buckets)
|
||||
return -ENOMEM;
|
||||
device_buckets = memdup_array_user((void *)args->devices,
|
||||
args->num_devices, sizeof(*device_buckets));
|
||||
|
||||
ret = copy_from_user(device_buckets, (void __user *)args->devices,
|
||||
args->num_devices * sizeof(*device_buckets));
|
||||
if (ret) {
|
||||
pr_err("Failed to copy devices buckets from user\n");
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
if (IS_ERR(device_buckets))
|
||||
return PTR_ERR(device_buckets);
|
||||
|
||||
for (i = 0; i < args->num_devices; i++) {
|
||||
struct kfd_node *dev;
|
||||
|
||||
@@ -153,14 +153,16 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
|
||||
u32 inx;
|
||||
|
||||
mutex_lock(&kfd->doorbell_mutex);
|
||||
|
||||
inx = find_first_zero_bit(kfd->doorbell_bitmap, PAGE_SIZE / sizeof(u32));
|
||||
if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) {
|
||||
mutex_unlock(&kfd->doorbell_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__set_bit(inx, kfd->doorbell_bitmap);
|
||||
mutex_unlock(&kfd->doorbell_mutex);
|
||||
|
||||
if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
|
||||
return NULL;
|
||||
|
||||
*doorbell_off = amdgpu_doorbell_index_on_bar(kfd->adev,
|
||||
kfd->doorbells,
|
||||
inx,
|
||||
|
||||
@@ -424,7 +424,7 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
|
||||
migrate.dst = migrate.src + npages;
|
||||
scratch = (dma_addr_t *)(migrate.dst + npages);
|
||||
|
||||
kfd_smi_event_migration_start(node, p->lead_thread->pid,
|
||||
kfd_smi_event_migration_start(node, p->lead_thread,
|
||||
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
|
||||
0, node->id, prange->prefetch_loc,
|
||||
prange->preferred_loc, trigger);
|
||||
@@ -462,7 +462,7 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
|
||||
|
||||
out_free:
|
||||
kvfree(buf);
|
||||
kfd_smi_event_migration_end(node, p->lead_thread->pid,
|
||||
kfd_smi_event_migration_end(node, p->lead_thread,
|
||||
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
|
||||
0, node->id, trigger, r);
|
||||
out:
|
||||
@@ -727,7 +727,7 @@ svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
|
||||
migrate.fault_page = fault_page;
|
||||
scratch = (dma_addr_t *)(migrate.dst + npages);
|
||||
|
||||
kfd_smi_event_migration_start(node, p->lead_thread->pid,
|
||||
kfd_smi_event_migration_start(node, p->lead_thread,
|
||||
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
|
||||
node->id, 0, prange->prefetch_loc,
|
||||
prange->preferred_loc, trigger);
|
||||
@@ -766,7 +766,7 @@ svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
|
||||
|
||||
out_free:
|
||||
kvfree(buf);
|
||||
kfd_smi_event_migration_end(node, p->lead_thread->pid,
|
||||
kfd_smi_event_migration_end(node, p->lead_thread,
|
||||
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
|
||||
node->id, 0, trigger, r);
|
||||
out:
|
||||
|
||||
@@ -1175,10 +1175,12 @@ static void kfd_process_remove_sysfs(struct kfd_process *p)
|
||||
if (!p->kobj)
|
||||
return;
|
||||
|
||||
sysfs_remove_file(p->kobj, &p->attr_pasid);
|
||||
kobject_del(p->kobj_queues);
|
||||
kobject_put(p->kobj_queues);
|
||||
p->kobj_queues = NULL;
|
||||
if (p->kobj_queues) {
|
||||
sysfs_remove_file(p->kobj, &p->attr_pasid);
|
||||
kobject_del(p->kobj_queues);
|
||||
kobject_put(p->kobj_queues);
|
||||
p->kobj_queues = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < p->n_pdds; i++) {
|
||||
pdd = p->pdds[i];
|
||||
@@ -1186,17 +1188,21 @@ static void kfd_process_remove_sysfs(struct kfd_process *p)
|
||||
sysfs_remove_file(p->kobj, &pdd->attr_vram);
|
||||
sysfs_remove_file(p->kobj, &pdd->attr_sdma);
|
||||
|
||||
sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict);
|
||||
if (pdd->dev->kfd2kgd->get_cu_occupancy)
|
||||
sysfs_remove_file(pdd->kobj_stats,
|
||||
&pdd->attr_cu_occupancy);
|
||||
kobject_del(pdd->kobj_stats);
|
||||
kobject_put(pdd->kobj_stats);
|
||||
pdd->kobj_stats = NULL;
|
||||
if (pdd->kobj_stats) {
|
||||
sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict);
|
||||
if (pdd->dev->kfd2kgd->get_cu_occupancy)
|
||||
sysfs_remove_file(pdd->kobj_stats,
|
||||
&pdd->attr_cu_occupancy);
|
||||
kobject_del(pdd->kobj_stats);
|
||||
kobject_put(pdd->kobj_stats);
|
||||
pdd->kobj_stats = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for_each_set_bit(i, p->svms.bitmap_supported, p->n_pdds) {
|
||||
pdd = p->pdds[i];
|
||||
if (!pdd->kobj_counters)
|
||||
continue;
|
||||
|
||||
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_faults);
|
||||
sysfs_remove_file(pdd->kobj_counters, &pdd->attr_page_in);
|
||||
@@ -1254,6 +1260,13 @@ static void kfd_process_wq_release(struct work_struct *work)
|
||||
|
||||
kfd_debugfs_remove_process(p);
|
||||
|
||||
/*
|
||||
* Remove the proc/sysfs entries before destroying PDDs. The removal path
|
||||
* walks the PDD array and sysfs callbacks dereference PDD fields, so the
|
||||
* backing data must remain valid until sysfs removal has completed.
|
||||
*/
|
||||
kfd_process_remove_sysfs(p);
|
||||
|
||||
kfd_process_kunmap_signal_bo(p);
|
||||
kfd_process_free_outstanding_kfd_bos(p);
|
||||
svm_range_list_fini(p);
|
||||
@@ -1267,11 +1280,6 @@ static void kfd_process_wq_release(struct work_struct *work)
|
||||
|
||||
put_task_struct(p->lead_thread);
|
||||
|
||||
/* the last step is removing process entries under /sys
|
||||
* to indicate the process has been terminated.
|
||||
*/
|
||||
kfd_process_remove_sysfs(p);
|
||||
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
@@ -1969,7 +1977,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger)
|
||||
struct kfd_process_device *pdd = p->pdds[i];
|
||||
struct device *dev = pdd->dev->adev->dev;
|
||||
|
||||
kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread->pid,
|
||||
kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread,
|
||||
trigger);
|
||||
|
||||
r = pdd->dev->dqm->ops.evict_process_queues(pdd->dev->dqm,
|
||||
@@ -1999,7 +2007,7 @@ fail:
|
||||
if (n_evicted == 0)
|
||||
break;
|
||||
|
||||
kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid);
|
||||
kfd_smi_event_queue_restore(pdd->dev, p->lead_thread);
|
||||
|
||||
if (pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm,
|
||||
&pdd->qpd))
|
||||
@@ -2022,7 +2030,7 @@ int kfd_process_restore_queues(struct kfd_process *p)
|
||||
struct kfd_process_device *pdd = p->pdds[i];
|
||||
struct device *dev = pdd->dev->adev->dev;
|
||||
|
||||
kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid);
|
||||
kfd_smi_event_queue_restore(pdd->dev, p->lead_thread);
|
||||
|
||||
r = pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm,
|
||||
&pdd->qpd);
|
||||
|
||||
@@ -962,8 +962,8 @@ static void set_queue_properties_from_criu(struct queue_properties *qp,
|
||||
qp->priority = q_data->priority;
|
||||
qp->queue_address = q_data->q_address;
|
||||
qp->queue_size = q_data->q_size;
|
||||
qp->read_ptr = (uint32_t *) q_data->read_ptr_addr;
|
||||
qp->write_ptr = (uint32_t *) q_data->write_ptr_addr;
|
||||
qp->read_ptr = (void __user *)q_data->read_ptr_addr;
|
||||
qp->write_ptr = (void __user *)q_data->write_ptr_addr;
|
||||
qp->eop_ring_buffer_address = q_data->eop_ring_buffer_address;
|
||||
qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size;
|
||||
qp->ctx_save_restore_area_address = q_data->ctx_save_restore_area_address;
|
||||
@@ -1042,10 +1042,18 @@ int kfd_criu_restore_queue(struct kfd_process *p,
|
||||
memset(&qp, 0, sizeof(qp));
|
||||
set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask));
|
||||
|
||||
ret = kfd_queue_acquire_buffers(pdd, &qp);
|
||||
if (ret) {
|
||||
pr_debug("failed to acquire user queue buffers for CRIU\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
print_queue_properties(&qp);
|
||||
|
||||
ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, ctl_stack, NULL);
|
||||
if (ret) {
|
||||
kfd_queue_unref_bo_vas(pdd, &qp);
|
||||
kfd_queue_release_buffers(pdd, &qp);
|
||||
pr_err("Failed to create new queue err:%d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -195,17 +195,35 @@ static void add_event_to_kfifo(pid_t pid, struct kfd_node *dev,
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* kfd_smi_task_to_pid - Convert task to namespace-aware PID
|
||||
* @task: task_struct pointer (typically p->lead_thread)
|
||||
*
|
||||
* Returns the PID as it appears in the task's own PID namespace.
|
||||
* For containerized processes, this returns the container-local PID
|
||||
* (what getpid() returns), not the global host PID.
|
||||
*
|
||||
* Returns 0 if task is NULL.
|
||||
*/
|
||||
static inline pid_t kfd_smi_task_to_pid(struct task_struct *task)
|
||||
{
|
||||
return task ? task_tgid_nr_ns(task, task_active_pid_ns(task)) : 0;
|
||||
}
|
||||
|
||||
__printf(4, 5)
|
||||
static void kfd_smi_event_add(pid_t pid, struct kfd_node *dev,
|
||||
static void kfd_smi_event_add(struct task_struct *task, struct kfd_node *dev,
|
||||
unsigned int event, char *fmt, ...)
|
||||
{
|
||||
char fifo_in[KFD_SMI_EVENT_MSG_SIZE];
|
||||
int len;
|
||||
va_list args;
|
||||
pid_t pid;
|
||||
|
||||
if (list_empty(&dev->smi_clients))
|
||||
return;
|
||||
|
||||
pid = kfd_smi_task_to_pid(task);
|
||||
|
||||
len = snprintf(fifo_in, sizeof(fifo_in), "%x ", event);
|
||||
|
||||
va_start(args, fmt);
|
||||
@@ -234,14 +252,15 @@ void kfd_smi_event_update_gpu_reset(struct kfd_node *dev, bool post_reset,
|
||||
amdgpu_reset_get_desc(reset_context, reset_cause,
|
||||
sizeof(reset_cause));
|
||||
|
||||
kfd_smi_event_add(0, dev, event, KFD_EVENT_FMT_UPDATE_GPU_RESET(
|
||||
kfd_smi_event_add(NULL, dev, event, KFD_EVENT_FMT_UPDATE_GPU_RESET(
|
||||
dev->reset_seq_num, reset_cause));
|
||||
}
|
||||
|
||||
void kfd_smi_event_update_thermal_throttling(struct kfd_node *dev,
|
||||
uint64_t throttle_bitmask)
|
||||
{
|
||||
kfd_smi_event_add(0, dev, KFD_SMI_EVENT_THERMAL_THROTTLE, KFD_EVENT_FMT_THERMAL_THROTTLING(
|
||||
kfd_smi_event_add(NULL, dev, KFD_SMI_EVENT_THERMAL_THROTTLE,
|
||||
KFD_EVENT_FMT_THERMAL_THROTTLING(
|
||||
throttle_bitmask,
|
||||
amdgpu_dpm_get_thermal_throttling_counter(dev->adev)));
|
||||
}
|
||||
@@ -254,67 +273,67 @@ void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid)
|
||||
if (task_info) {
|
||||
/* Report VM faults from user applications, not retry from kernel */
|
||||
if (task_info->task.pid)
|
||||
kfd_smi_event_add(task_info->tgid, dev,
|
||||
KFD_SMI_EVENT_VMFAULT,
|
||||
KFD_EVENT_FMT_VMFAULT(task_info->task.pid,
|
||||
task_info->task.comm));
|
||||
kfd_smi_event_add(NULL, dev, KFD_SMI_EVENT_VMFAULT, KFD_EVENT_FMT_VMFAULT(
|
||||
task_info->task.pid, task_info->task.comm));
|
||||
amdgpu_vm_put_task_info(task_info);
|
||||
}
|
||||
}
|
||||
|
||||
void kfd_smi_event_page_fault_start(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_page_fault_start(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long address, bool write_fault,
|
||||
ktime_t ts)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_PAGE_FAULT_START,
|
||||
KFD_EVENT_FMT_PAGEFAULT_START(ktime_to_ns(ts), pid,
|
||||
address, node->id, write_fault ? 'W' : 'R'));
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_PAGE_FAULT_START,
|
||||
KFD_EVENT_FMT_PAGEFAULT_START(ktime_to_ns(ts),
|
||||
kfd_smi_task_to_pid(task), address, node->id,
|
||||
write_fault ? 'W' : 'R'));
|
||||
}
|
||||
|
||||
void kfd_smi_event_page_fault_end(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_page_fault_end(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long address, bool migration)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_PAGE_FAULT_END,
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_PAGE_FAULT_END,
|
||||
KFD_EVENT_FMT_PAGEFAULT_END(ktime_get_boottime_ns(),
|
||||
pid, address, node->id, migration ? 'M' : 'U'));
|
||||
kfd_smi_task_to_pid(task), address, node->id,
|
||||
migration ? 'M' : 'U'));
|
||||
}
|
||||
|
||||
void kfd_smi_event_migration_start(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_migration_start(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long start, unsigned long end,
|
||||
uint32_t from, uint32_t to,
|
||||
uint32_t prefetch_loc, uint32_t preferred_loc,
|
||||
uint32_t trigger)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_MIGRATE_START,
|
||||
KFD_EVENT_FMT_MIGRATE_START(
|
||||
ktime_get_boottime_ns(), pid, start, end - start,
|
||||
from, to, prefetch_loc, preferred_loc, trigger));
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_MIGRATE_START,
|
||||
KFD_EVENT_FMT_MIGRATE_START(ktime_get_boottime_ns(),
|
||||
kfd_smi_task_to_pid(task), start, end - start, from,
|
||||
to, prefetch_loc, preferred_loc, trigger));
|
||||
}
|
||||
|
||||
void kfd_smi_event_migration_end(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_migration_end(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long start, unsigned long end,
|
||||
uint32_t from, uint32_t to, uint32_t trigger,
|
||||
int error_code)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_MIGRATE_END,
|
||||
KFD_EVENT_FMT_MIGRATE_END(
|
||||
ktime_get_boottime_ns(), pid, start, end - start,
|
||||
from, to, trigger, error_code));
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_MIGRATE_END,
|
||||
KFD_EVENT_FMT_MIGRATE_END(ktime_get_boottime_ns(),
|
||||
kfd_smi_task_to_pid(task), start, end - start, from,
|
||||
to, trigger, error_code));
|
||||
}
|
||||
|
||||
void kfd_smi_event_queue_eviction(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_queue_eviction(struct kfd_node *node, struct task_struct *task,
|
||||
uint32_t trigger)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_EVICTION,
|
||||
KFD_EVENT_FMT_QUEUE_EVICTION(ktime_get_boottime_ns(), pid,
|
||||
node->id, trigger));
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_QUEUE_EVICTION,
|
||||
KFD_EVENT_FMT_QUEUE_EVICTION(ktime_get_boottime_ns(),
|
||||
kfd_smi_task_to_pid(task), node->id, trigger));
|
||||
}
|
||||
|
||||
void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid)
|
||||
void kfd_smi_event_queue_restore(struct kfd_node *node, struct task_struct *task)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_RESTORE,
|
||||
KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(), pid,
|
||||
node->id, '0'));
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_QUEUE_RESTORE,
|
||||
KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(),
|
||||
kfd_smi_task_to_pid(task), node->id, '0'));
|
||||
}
|
||||
|
||||
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
|
||||
@@ -329,21 +348,23 @@ void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
|
||||
for (i = 0; i < p->n_pdds; i++) {
|
||||
struct kfd_process_device *pdd = p->pdds[i];
|
||||
|
||||
kfd_smi_event_add(p->lead_thread->pid, pdd->dev,
|
||||
kfd_smi_event_add(p->lead_thread, pdd->dev,
|
||||
KFD_SMI_EVENT_QUEUE_RESTORE,
|
||||
KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(),
|
||||
p->lead_thread->pid, pdd->dev->id, 'R'));
|
||||
kfd_smi_task_to_pid(p->lead_thread),
|
||||
pdd->dev->id, 'R'));
|
||||
}
|
||||
kfd_unref_process(p);
|
||||
}
|
||||
|
||||
void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long address, unsigned long last,
|
||||
uint32_t trigger)
|
||||
{
|
||||
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_UNMAP_FROM_GPU,
|
||||
kfd_smi_event_add(task, node, KFD_SMI_EVENT_UNMAP_FROM_GPU,
|
||||
KFD_EVENT_FMT_UNMAP_FROM_GPU(ktime_get_boottime_ns(),
|
||||
pid, address, last - address + 1, node->id, trigger));
|
||||
kfd_smi_task_to_pid(task), address,
|
||||
last - address + 1, node->id, trigger));
|
||||
}
|
||||
|
||||
void kfd_smi_event_process(struct kfd_process_device *pdd, bool start)
|
||||
@@ -358,7 +379,7 @@ void kfd_smi_event_process(struct kfd_process_device *pdd, bool start)
|
||||
task_info = amdgpu_vm_get_task_info_vm(avm);
|
||||
|
||||
if (task_info) {
|
||||
kfd_smi_event_add(task_info->tgid, pdd->dev,
|
||||
kfd_smi_event_add(NULL, pdd->dev,
|
||||
start ? KFD_SMI_EVENT_PROCESS_START :
|
||||
KFD_SMI_EVENT_PROCESS_END,
|
||||
KFD_EVENT_FMT_PROCESS(task_info->task.pid,
|
||||
@@ -387,7 +408,7 @@ int kfd_smi_event_open(struct kfd_node *dev, uint32_t *fd)
|
||||
spin_lock_init(&client->lock);
|
||||
client->events = 0;
|
||||
client->dev = dev;
|
||||
client->pid = current->tgid;
|
||||
client->pid = kfd_smi_task_to_pid(current);
|
||||
client->suser = capable(CAP_SYS_ADMIN);
|
||||
|
||||
spin_lock(&dev->smi_lock);
|
||||
|
||||
@@ -32,25 +32,25 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_node *dev,
|
||||
uint64_t throttle_bitmask);
|
||||
void kfd_smi_event_update_gpu_reset(struct kfd_node *dev, bool post_reset,
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
void kfd_smi_event_page_fault_start(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_page_fault_start(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long address, bool write_fault,
|
||||
ktime_t ts);
|
||||
void kfd_smi_event_page_fault_end(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_page_fault_end(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long address, bool migration);
|
||||
void kfd_smi_event_migration_start(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_migration_start(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long start, unsigned long end,
|
||||
uint32_t from, uint32_t to,
|
||||
uint32_t prefetch_loc, uint32_t preferred_loc,
|
||||
uint32_t trigger);
|
||||
void kfd_smi_event_migration_end(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_migration_end(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long start, unsigned long end,
|
||||
uint32_t from, uint32_t to, uint32_t trigger,
|
||||
int error_code);
|
||||
void kfd_smi_event_queue_eviction(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_queue_eviction(struct kfd_node *node, struct task_struct *task,
|
||||
uint32_t trigger);
|
||||
void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid);
|
||||
void kfd_smi_event_queue_restore(struct kfd_node *node, struct task_struct *task);
|
||||
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm);
|
||||
void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, pid_t pid,
|
||||
void kfd_smi_event_unmap_from_gpu(struct kfd_node *node, struct task_struct *task,
|
||||
unsigned long address, unsigned long last,
|
||||
uint32_t trigger);
|
||||
void kfd_smi_event_process(struct kfd_process_device *pdd, bool start);
|
||||
|
||||
@@ -1144,7 +1144,7 @@ static int
|
||||
svm_range_split_tail(struct svm_range *prange, uint64_t new_last,
|
||||
struct list_head *insert_list, struct list_head *remap_list)
|
||||
{
|
||||
unsigned long last_align_down = ALIGN_DOWN(prange->last, 512);
|
||||
unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512);
|
||||
unsigned long start_align = ALIGN(prange->start, 512);
|
||||
bool huge_page_mapping = last_align_down > start_align;
|
||||
struct svm_range *tail = NULL;
|
||||
@@ -1168,7 +1168,7 @@ static int
|
||||
svm_range_split_head(struct svm_range *prange, uint64_t new_start,
|
||||
struct list_head *insert_list, struct list_head *remap_list)
|
||||
{
|
||||
unsigned long last_align_down = ALIGN_DOWN(prange->last, 512);
|
||||
unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512);
|
||||
unsigned long start_align = ALIGN(prange->start, 512);
|
||||
bool huge_page_mapping = last_align_down > start_align;
|
||||
struct svm_range *head = NULL;
|
||||
@@ -1181,8 +1181,8 @@ svm_range_split_head(struct svm_range *prange, uint64_t new_start,
|
||||
|
||||
list_add(&head->list, insert_list);
|
||||
|
||||
if (huge_page_mapping && head->last + 1 > start_align &&
|
||||
head->last + 1 < last_align_down && (!IS_ALIGNED(head->last, 512)))
|
||||
if (huge_page_mapping && new_start > start_align &&
|
||||
new_start < last_align_down && !IS_ALIGNED(new_start, 512))
|
||||
list_add(&head->update_list, remap_list);
|
||||
|
||||
return 0;
|
||||
@@ -1408,7 +1408,7 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfd_smi_event_unmap_from_gpu(pdd->dev, p->lead_thread->pid,
|
||||
kfd_smi_event_unmap_from_gpu(pdd->dev, p->lead_thread,
|
||||
start, last, trigger);
|
||||
|
||||
r = svm_range_unmap_from_gpu(pdd->dev->adev,
|
||||
@@ -3205,7 +3205,7 @@ retry_write_locked:
|
||||
svms, prange->start, prange->last, best_loc,
|
||||
prange->actual_loc);
|
||||
|
||||
kfd_smi_event_page_fault_start(node, p->lead_thread->pid, addr,
|
||||
kfd_smi_event_page_fault_start(node, p->lead_thread, addr,
|
||||
write_fault, timestamp);
|
||||
|
||||
/* Align migration range start and size to granularity size */
|
||||
@@ -3248,7 +3248,7 @@ retry_write_locked:
|
||||
r, svms, start, last);
|
||||
|
||||
out_migrate_fail:
|
||||
kfd_smi_event_page_fault_end(node, p->lead_thread->pid, addr,
|
||||
kfd_smi_event_page_fault_end(node, p->lead_thread, addr,
|
||||
migration);
|
||||
|
||||
out_unlock_range:
|
||||
@@ -4115,6 +4115,7 @@ exit:
|
||||
list_for_each_entry_safe(criu_svm_md, next, &svms->criu_svm_metadata_list, list) {
|
||||
pr_debug("freeing criu_svm_md[]\n\tstart: 0x%llx\n",
|
||||
criu_svm_md->data.start_addr);
|
||||
list_del(&criu_svm_md->list);
|
||||
kfree(criu_svm_md);
|
||||
}
|
||||
|
||||
|
||||
@@ -12942,13 +12942,11 @@ static bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
|
||||
struct drm_plane_state *new_plane_state, *old_plane_state;
|
||||
|
||||
drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
|
||||
new_plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
old_plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
old_plane_state = drm_atomic_get_old_plane_state(state, plane);
|
||||
|
||||
if (IS_ERR(new_plane_state) || IS_ERR(old_plane_state)) {
|
||||
drm_err(dev, "Failed to get plane state for plane %s\n", plane->name);
|
||||
return false;
|
||||
}
|
||||
if (!old_plane_state || !new_plane_state)
|
||||
continue;
|
||||
|
||||
if (old_plane_state->fb && new_plane_state->fb &&
|
||||
get_mem_type(old_plane_state->fb) != get_mem_type(new_plane_state->fb))
|
||||
|
||||
@@ -95,8 +95,11 @@ static u32 edid_extract_panel_id(struct edid *edid)
|
||||
(u32)EDID_PRODUCT_ID(edid);
|
||||
}
|
||||
|
||||
static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct dc_edid_caps *edid_caps)
|
||||
static void apply_edid_quirks(struct dc_link *link, struct edid *edid,
|
||||
struct dc_edid_caps *edid_caps)
|
||||
{
|
||||
struct amdgpu_dm_connector *aconnector = link->priv;
|
||||
struct drm_device *dev = aconnector->base.dev;
|
||||
uint32_t panel_id = edid_extract_panel_id(edid);
|
||||
|
||||
switch (panel_id) {
|
||||
@@ -126,6 +129,11 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct
|
||||
drm_dbg_driver(dev, "Disabling VSC on monitor with panel id %X\n", panel_id);
|
||||
edid_caps->panel_patch.disable_colorimetry = true;
|
||||
break;
|
||||
/* Workaround for monitors that get corrupted by the PHY SSC reduction */
|
||||
case drm_edid_encode_panel_id('D', 'E', 'L', 0x4147):
|
||||
drm_dbg_driver(dev, "Skip PHY SSC reduction on panel id %X\n", panel_id);
|
||||
link->wa_flags.skip_phy_ssc_reduction = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +155,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
|
||||
{
|
||||
struct amdgpu_dm_connector *aconnector = link->priv;
|
||||
struct drm_connector *connector = &aconnector->base;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL;
|
||||
struct cea_sad *sads;
|
||||
int sad_count = -1;
|
||||
@@ -188,7 +195,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
|
||||
edid_caps->frl_dsc_max_frl_rate, edid_caps->frl_dsc_total_chunk_kbytes);
|
||||
}
|
||||
|
||||
apply_edid_quirks(dev, edid_buf, edid_caps);
|
||||
apply_edid_quirks(link, edid_buf, edid_caps);
|
||||
|
||||
sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
|
||||
if (sad_count <= 0)
|
||||
|
||||
@@ -1859,6 +1859,7 @@ static const struct drm_plane_funcs dm_plane_funcs = {
|
||||
.atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
|
||||
.atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
|
||||
.format_mod_supported = amdgpu_dm_plane_format_mod_supported,
|
||||
.format_mod_supported_async = amdgpu_dm_plane_format_mod_supported,
|
||||
#ifdef AMD_PRIVATE_COLOR
|
||||
.atomic_set_property = dm_atomic_plane_set_property,
|
||||
.atomic_get_property = dm_atomic_plane_get_property,
|
||||
|
||||
@@ -158,7 +158,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
|
||||
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
|
||||
dcn31_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
|
||||
dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
|
||||
@@ -184,7 +183,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
|
||||
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
|
||||
dcn31_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
|
||||
dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,7 +230,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
|
||||
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
|
||||
dcn314_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
|
||||
dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
|
||||
@@ -255,7 +254,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
|
||||
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
|
||||
dcn314_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
|
||||
dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
|
||||
|
||||
@@ -419,6 +419,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
|
||||
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
|
||||
dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
|
||||
dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
|
||||
@@ -438,6 +439,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
|
||||
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
|
||||
dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
|
||||
dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
|
||||
|
||||
@@ -227,9 +227,14 @@ static int smu_v15_0_0_system_features_control(struct smu_context *smu, bool en)
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
int ret = 0;
|
||||
|
||||
if (!en && !adev->in_s0ix)
|
||||
if (!en && !adev->in_s0ix) {
|
||||
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
|
||||
|
||||
/* SMU resets BIF_FB_EN to zero, re-enable MC access on APUs with SMU V15 */
|
||||
if (!ret && adev->nbio.funcs && adev->nbio.funcs->mc_access_enable)
|
||||
adev->nbio.funcs->mc_access_enable(adev, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -3571,7 +3571,7 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
|
||||
/**
|
||||
* drm_mode_get_tile_group - get a reference to an existing tile group
|
||||
* @dev: DRM device
|
||||
* @topology: 8-bytes unique per monitor.
|
||||
* @topology_id: 9-byte unique ID per monitor.
|
||||
*
|
||||
* Use the unique bytes to get a reference to an existing tile group.
|
||||
*
|
||||
@@ -3579,14 +3579,14 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
|
||||
* tile group or NULL if not found.
|
||||
*/
|
||||
struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
|
||||
const char topology[8])
|
||||
const char topology_id[9])
|
||||
{
|
||||
struct drm_tile_group *tg;
|
||||
int id;
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
|
||||
if (!memcmp(tg->group_data, topology, 8)) {
|
||||
if (!memcmp(tg->group_data, topology_id, sizeof(tg->group_data))) {
|
||||
if (!kref_get_unless_zero(&tg->refcount))
|
||||
tg = NULL;
|
||||
mutex_unlock(&dev->mode_config.idr_mutex);
|
||||
@@ -3601,7 +3601,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
|
||||
/**
|
||||
* drm_mode_create_tile_group - create a tile group from a displayid description
|
||||
* @dev: DRM device
|
||||
* @topology: 8-bytes unique per monitor.
|
||||
* @topology_id: 9-byte unique ID per monitor.
|
||||
*
|
||||
* Create a tile group for the unique monitor, and get a unique
|
||||
* identifier for the tile group.
|
||||
@@ -3610,7 +3610,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
|
||||
* new tile group or NULL.
|
||||
*/
|
||||
struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
|
||||
const char topology[8])
|
||||
const char topology_id[9])
|
||||
{
|
||||
struct drm_tile_group *tg;
|
||||
int ret;
|
||||
@@ -3620,7 +3620,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
|
||||
return NULL;
|
||||
|
||||
kref_init(&tg->refcount);
|
||||
memcpy(tg->group_data, topology, 8);
|
||||
memcpy(tg->group_data, topology_id, sizeof(tg->group_data));
|
||||
tg->dev = dev;
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
|
||||
@@ -109,7 +109,7 @@ struct displayid_tiled_block {
|
||||
u8 topo[3];
|
||||
u8 tile_size[4];
|
||||
u8 tile_pixel_bezel[5];
|
||||
u8 topology_id[8];
|
||||
u8 topology_id[9];
|
||||
} __packed;
|
||||
|
||||
struct displayid_detailed_timings_1 {
|
||||
|
||||
@@ -7575,6 +7575,14 @@ static void drm_parse_tiled_block(struct drm_connector *connector,
|
||||
u8 num_v_tile, num_h_tile;
|
||||
struct drm_tile_group *tg;
|
||||
|
||||
/* tiled block payload per spec: cap 1 + topo 3 + size 4 + bezel 5 + id 9 = 22 */
|
||||
if (block->num_bytes < 22) {
|
||||
drm_dbg_kms(connector->dev,
|
||||
"[CONNECTOR:%d:%s] Unexpected tiled block size %u\n",
|
||||
connector->base.id, connector->name, block->num_bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
w = tile->tile_size[0] | tile->tile_size[1] << 8;
|
||||
h = tile->tile_size[2] | tile->tile_size[3] << 8;
|
||||
|
||||
|
||||
@@ -288,6 +288,12 @@ static void intel_crtc_put_color_blobs(struct intel_crtc_state *crtc_state)
|
||||
|
||||
drm_property_blob_put(crtc_state->pre_csc_lut);
|
||||
drm_property_blob_put(crtc_state->post_csc_lut);
|
||||
|
||||
crtc_state->hw.degamma_lut = NULL;
|
||||
crtc_state->hw.gamma_lut = NULL;
|
||||
crtc_state->hw.ctm = NULL;
|
||||
crtc_state->pre_csc_lut = NULL;
|
||||
crtc_state->post_csc_lut = NULL;
|
||||
}
|
||||
|
||||
void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state)
|
||||
|
||||
@@ -1256,9 +1256,22 @@ static void skl_sanitize_cdclk(struct intel_display *display)
|
||||
cdctl = intel_de_read(display, CDCLK_CTL);
|
||||
expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
|
||||
skl_cdclk_decimal(display->cdclk.hw.cdclk);
|
||||
if (cdctl == expected)
|
||||
/* All well; nothing to sanitize */
|
||||
return;
|
||||
|
||||
if (cdctl != expected) {
|
||||
cdctl &= ~CDCLK_FREQ_DECIMAL_MASK;
|
||||
cdctl |= expected & CDCLK_FREQ_DECIMAL_MASK;
|
||||
|
||||
if (cdctl != expected)
|
||||
goto sanitize;
|
||||
|
||||
drm_dbg_kms(display->drm, "Sanitizing CDCLK decimal divider (CDCLK_CTL 0x%x, expected 0x%x)\n",
|
||||
intel_de_read(display, CDCLK_CTL), expected);
|
||||
|
||||
intel_de_write(display, CDCLK_CTL, expected);
|
||||
}
|
||||
|
||||
/* All well; nothing to sanitize */
|
||||
return;
|
||||
|
||||
sanitize:
|
||||
drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
|
||||
@@ -2354,11 +2367,25 @@ static void bxt_sanitize_cdclk(struct intel_display *display)
|
||||
* (PIPE_NONE).
|
||||
*/
|
||||
cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
expected &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
|
||||
|
||||
if (cdctl == expected)
|
||||
/* All well; nothing to sanitize */
|
||||
return;
|
||||
if (cdctl != expected) {
|
||||
if (DISPLAY_VER(display) < 20) {
|
||||
cdctl &= ~CDCLK_FREQ_DECIMAL_MASK;
|
||||
cdctl |= expected & CDCLK_FREQ_DECIMAL_MASK;
|
||||
}
|
||||
|
||||
if (cdctl != expected)
|
||||
goto sanitize;
|
||||
|
||||
drm_dbg_kms(display->drm, "Sanitizing CDCLK decimal divider (CDCLK_CTL 0x%x, expected 0x%x)\n",
|
||||
intel_de_read(display, CDCLK_CTL), expected);
|
||||
|
||||
intel_de_write(display, CDCLK_CTL, expected);
|
||||
}
|
||||
|
||||
/* All well; nothing to sanitize */
|
||||
return;
|
||||
|
||||
sanitize:
|
||||
drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
|
||||
|
||||
@@ -2652,9 +2652,6 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
|
||||
/* 3. Select Thunderbolt */
|
||||
mtl_port_buf_ctl_io_selection(encoder);
|
||||
|
||||
/* 4. Enable Panel Power if PPS is required */
|
||||
intel_pps_on(intel_dp);
|
||||
|
||||
/* 5. Enable the port PLL */
|
||||
intel_ddi_enable_clock(encoder, crtc_state);
|
||||
|
||||
@@ -3708,6 +3705,14 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
|
||||
else if (display->platform.geminilake || display->platform.broxton)
|
||||
bxt_dpio_phy_set_lane_optim_mask(encoder,
|
||||
crtc_state->lane_lat_optim_mask);
|
||||
|
||||
/*
|
||||
* There is no direct connection between the PLL and PPS, however
|
||||
* enabling PPS before PLL is required to avoid PLL/DDI BUF timeouts
|
||||
* during system resume. Do that matching the Bspec order as well.
|
||||
*/
|
||||
if (DISPLAY_VER(display) >= 14)
|
||||
intel_pps_on(&dig_port->dp);
|
||||
}
|
||||
|
||||
static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
|
||||
|
||||
@@ -722,6 +722,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
|
||||
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
ret = intel_pfit_compute_config(pipe_config, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_pfit_compute_config(pipe_config, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -613,6 +613,7 @@ set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user *base,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
slot = array_index_nospec(slot, set->num_engines);
|
||||
if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) {
|
||||
drm_dbg(&i915->drm,
|
||||
"Invalid placement[%d], already occupied\n", slot);
|
||||
|
||||
@@ -331,10 +331,10 @@ nouveau_exec_ucopy(struct nouveau_exec_job_args *args,
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_pushs:
|
||||
u_free(args->push.s);
|
||||
err_free_ins:
|
||||
u_free(args->in_sync.s);
|
||||
err_free_pushs:
|
||||
u_free(args->push.s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1779,10 +1779,10 @@ nouveau_uvmm_vm_bind_ucopy(struct nouveau_uvmm_bind_job_args *args,
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_ops:
|
||||
u_free(args->op.s);
|
||||
err_free_ins:
|
||||
u_free(args->in_sync.s);
|
||||
err_free_ops:
|
||||
u_free(args->op.s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,6 +315,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
|
||||
i, us, fw);
|
||||
}
|
||||
}
|
||||
nvkm_done(acr->wpr);
|
||||
return -EINVAL;
|
||||
}
|
||||
nvkm_done(acr->wpr);
|
||||
|
||||
@@ -906,6 +906,7 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
|
||||
{
|
||||
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
|
||||
struct radeon_fence *fence;
|
||||
uint64_t cur_src_offset, cur_dst_offset;
|
||||
uint32_t cur_pages;
|
||||
uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE;
|
||||
uint32_t pitch;
|
||||
@@ -934,6 +935,10 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
|
||||
cur_pages = 8191;
|
||||
}
|
||||
num_gpu_pages -= cur_pages;
|
||||
cur_src_offset = src_offset +
|
||||
(uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
|
||||
cur_dst_offset = dst_offset +
|
||||
(uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
|
||||
|
||||
/* pages are in Y direction - height
|
||||
page width in X direction - width */
|
||||
@@ -950,13 +955,13 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
|
||||
RADEON_DP_SRC_SOURCE_MEMORY |
|
||||
RADEON_GMC_CLR_CMP_CNTL_DIS |
|
||||
RADEON_GMC_WR_MSK_DIS);
|
||||
radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10));
|
||||
radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10));
|
||||
radeon_ring_write(ring, (pitch << 22) | (cur_src_offset >> 10));
|
||||
radeon_ring_write(ring, (pitch << 22) | (cur_dst_offset >> 10));
|
||||
radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
|
||||
radeon_ring_write(ring, 0);
|
||||
radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
|
||||
radeon_ring_write(ring, num_gpu_pages);
|
||||
radeon_ring_write(ring, num_gpu_pages);
|
||||
radeon_ring_write(ring, 0);
|
||||
radeon_ring_write(ring, 0);
|
||||
radeon_ring_write(ring, cur_pages | (stride_pixels << 16));
|
||||
}
|
||||
radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));
|
||||
|
||||
@@ -50,7 +50,7 @@ struct resource *drm_sysfb_get_memory_si(struct drm_device *dev,
|
||||
int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si,
|
||||
const struct drm_format_info *format,
|
||||
unsigned int width, unsigned int height, u64 size);
|
||||
u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
|
||||
s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
|
||||
unsigned int height, unsigned int stride, u64 size);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/screen_info.h>
|
||||
|
||||
@@ -56,18 +57,24 @@ int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si
|
||||
unsigned int width, unsigned int height, u64 size)
|
||||
{
|
||||
u64 lfb_linelength = si->lfb_linelength;
|
||||
s64 stride;
|
||||
|
||||
if (!lfb_linelength)
|
||||
lfb_linelength = drm_format_info_min_pitch(format, 0, width);
|
||||
|
||||
return drm_sysfb_get_validated_int0(dev, "stride", lfb_linelength, div64_u64(size, height));
|
||||
stride = drm_sysfb_get_validated_size0(dev, "stride", lfb_linelength,
|
||||
div64_u64(size, height));
|
||||
if (stride < INT_MIN || stride > INT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return (int)stride; /* stride or negative errno code */
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfb_get_stride_si);
|
||||
|
||||
u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
|
||||
s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
|
||||
unsigned int height, unsigned int stride, u64 size)
|
||||
{
|
||||
u64 vsize = PAGE_ALIGN(height * stride);
|
||||
u64 vsize = mul_u32_u32(height, stride);
|
||||
|
||||
return drm_sysfb_get_validated_size0(dev, "visible size", vsize, size);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user