Merge remote-tracking branch 'drm/drm-next' into drm-misc-next-fixes

Seems we missed one drm-misc-next pull-request in drm-misc-next-fixes.
This is required to pull in 5d156a9c3d ("drm/bridge: Pass down
connector to drm bridge detect hook") and update its docs.

Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
This commit is contained in:
Maarten Lankhorst 2025-08-04 09:32:44 +02:00
commit 220994d61c
465 changed files with 13288 additions and 4019 deletions

View File

@ -19,6 +19,8 @@ properties:
- const: samsung,atna33xc20
- items:
- enum:
# Samsung 13" 3K (2880×1920 pixels) eDP AMOLED panel
- samsung,atna30dw01
# Samsung 14" WQXGA+ (2880×1800 pixels) eDP AMOLED panel
- samsung,atna40yk20
# Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel

View File

@ -58,12 +58,6 @@ properties:
power-domains:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
required:
- compatible
- clocks

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/sitronix,st7567.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sitronix ST7567 Display Controller
maintainers:
- Javier Martinez Canillas <javierm@redhat.com>
description:
Sitronix ST7567 is a driver and controller for monochrome
dot matrix LCD panels.
allOf:
- $ref: panel/panel-common.yaml#
properties:
compatible:
const: sitronix,st7567
reg:
maxItems: 1
width-mm: true
height-mm: true
panel-timing: true
required:
- compatible
- reg
- width-mm
- height-mm
- panel-timing
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
display@3f {
compatible = "sitronix,st7567";
reg = <0x3f>;
width-mm = <37>;
height-mm = <27>;
panel-timing {
hactive = <128>;
vactive = <64>;
hback-porch = <0>;
vback-porch = <0>;
clock-frequency = <0>;
hfront-porch = <0>;
hsync-len = <0>;
vfront-porch = <0>;
vsync-len = <0>;
};
};
};

View File

@ -447,7 +447,7 @@ hang is usually the most critical one which can result in consequential hangs or
complete wedging.
Task information
---------------
----------------
The information about which application (if any) was involved in the device
wedging is useful for userspace if they want to notify the user about what
@ -460,8 +460,8 @@ event string.
The reliability of this information is driver and hardware specific, and should
be taken with a caution regarding it's precision. To have a big picture of what
really happened, the devcoredump file provides should have much more detailed
information about the device state and about the event.
really happened, the devcoredump file provides much more detailed information
about the device state and about the event.
Consumer prerequisites
----------------------

View File

@ -0,0 +1,61 @@
.. SPDX-License-Identifier: GPL-2.0
==================================
Device Initialization (devinit)
==================================
The devinit process is complex and subject to change. This document provides a high-level
overview using the Ampere GPU family as an example. The goal is to provide a conceptual
overview of the process to aid in understanding the corresponding kernel code.
Device initialization (devinit) is a crucial sequence of register read/write operations
that occur after a GPU reset. The devinit sequence is essential for properly configuring
the GPU hardware before it can be used.
The devinit engine is an interpreter program that typically runs on the PMU (Power Management
Unit) microcontroller of the GPU. This interpreter executes a "script" of initialization
commands. The devinit engine itself is part of the VBIOS ROM in the same ROM image as the
FWSEC (Firmware Security) image (see fwsec.rst and vbios.rst) and it runs before the
nova-core driver is even loaded. On an Ampere GPU, the devinit ucode is separate from the
FWSEC ucode. It is launched by FWSEC, which runs on the GSP in 'heavy-secure' mode, while
devinit runs on the PMU in 'light-secure' mode.
Key Functions of devinit
------------------------
devinit performs several critical tasks:
1. Programming VRAM memory controller timings
2. Power sequencing
3. Clock and PLL (Phase-Locked Loop) configuration
4. Thermal management
Low-level Firmware Initialization Flow
--------------------------------------
Upon reset, several microcontrollers on the GPU (such as PMU, SEC2, GSP, etc.) run GPU
firmware (gfw) code to set up the GPU and its core parameters. Most of the GPU is
considered unusable until this initialization process completes.
These low-level GPU firmware components are typically:
1. Located in the VBIOS ROM in the same ROM partition (see vbios.rst and fwsec.rst).
2. Executed in sequence on different microcontrollers:
- The devinit engine typically but not necessarily runs on the PMU.
- On an Ampere GPU, the FWSEC typically runs on the GSP (GPU System Processor) in
heavy-secure mode.
Before the driver can proceed with further initialization, it must wait for a signal
indicating that core initialization is complete (known as GFW_BOOT). This signal is
asserted by the FWSEC running on the GSP in heavy-secure mode.
Runtime Considerations
----------------------
It's important to note that the devinit sequence also needs to run during suspend/resume
operations at runtime, not just during initial boot, as it is critical to power management.
Security and Access Control
---------------------------
The initialization process involves careful privilege management. For example, before
accessing certain completion status registers, the driver must check privilege level
masks. Some registers are only accessible after secure firmware (FWSEC) lowers the
privilege level to allow CPU (LS/low-secure) access. This is the case, for example,
when receiving the GFW_BOOT signal.

View File

@ -0,0 +1,158 @@
.. SPDX-License-Identifier: GPL-2.0
==============================
Falcon (FAst Logic Controller)
==============================
The following sections describe the Falcon core and the ucode running on it.
The descriptions are based on the Ampere GPU or earlier designs; however, they
should mostly apply to future designs as well, but everything is subject to
change. The overview provided here is mainly tailored towards understanding the
interactions of nova-core driver with the Falcon.
NVIDIA GPUs embed small RISC-like microcontrollers called Falcon cores, which
handle secure firmware tasks, initialization, and power management. Modern
NVIDIA GPUs may have multiple such Falcon instances (e.g., GSP (the GPU system
processor) and SEC2 (the security engine)) and also may integrate a RISC-V core.
This core is capable of running both RISC-V and Falcon code.
The code running on the Falcon cores is also called 'ucode', and will be
referred to as such in the following sections.
Falcons have separate instruction and data memories (IMEM/DMEM) and provide a
small DMA engine (via the FBIF - "Frame Buffer Interface") to load code from
system memory. The nova-core driver must reset and configure the Falcon, load
its firmware via DMA, and start its CPU.
Falcon security levels
======================
Falcons can run in Non-secure (NS), Light Secure (LS), or Heavy Secure (HS)
modes.
Heavy Secured (HS) also known as Privilege Level 3 (PL3)
--------------------------------------------------------
HS ucode is the most trusted code and has access to pretty much everything on
the chip. The HS binary includes a signature in it which is verified at boot.
This signature verification is done by the hardware itself, thus establishing a
root of trust. For example, the FWSEC-FRTS command (see fwsec.rst) runs on the
GSP in HS mode. FRTS, which involves setting up and loading content into the WPR
(Write Protect Region), has to be done by the HS ucode and cannot be done by the
host CPU or LS ucode.
Light Secured (LS or PL2) and Non Secured (NS or PL0)
-----------------------------------------------------
These modes are less secure than HS. Like HS, the LS or NS ucode binary also
typically includes a signature in it. To load firmware in LS or NS mode onto a
Falcon, another Falcon needs to be running in HS mode, which also establishes the
root of trust. For example, in the case of an Ampere GPU, the CPU runs the "Booter"
ucode in HS mode on the SEC2 Falcon, which then authenticates and runs the
run-time GSP binary (GSP-RM) in LS mode on the GSP Falcon. Similarly, as an
example, after reset on an Ampere, FWSEC runs on the GSP which then loads the
devinit engine onto the PMU in LS mode.
Root of trust establishment
---------------------------
To establish a root of trust, the code running on a Falcon must be immutable and
hardwired into a read-only memory (ROM). This follows industry norms for
verification of firmware. This code is called the Boot ROM (BROM). The nova-core
driver on the CPU communicates with Falcon's Boot ROM through various Falcon
registers prefixed with "BROM" (see regs.rs).
After nova-core driver reads the necessary ucode from VBIOS, it programs the
BROM and DMA registers to trigger the Falcon to load the HS ucode from the system
memory into the Falcon's IMEM/DMEM. Once the HS ucode is loaded, it is verified
by the Falcon's Boot ROM.
Once the verified HS code is running on a Falcon, it can verify and load other
LS/NS ucode binaries onto other Falcons and start them. The process of signature
verification is the same as HS; just in this case, the hardware (BROM) doesn't
compute the signature, but the HS ucode does.
The root of trust is therefore established as follows:
Hardware (Boot ROM running on the Falcon) -> HS ucode -> LS/NS ucode.
On an Ampere GPU, for example, the boot verification flow is:
Hardware (Boot ROM running on the SEC2) ->
HS ucode (Booter running on the SEC2) ->
LS ucode (GSP-RM running on the GSP)
.. note::
While the CPU can load HS ucode onto a Falcon microcontroller and have it
verified by the hardware and run, the CPU itself typically does not load
LS or NS ucode and run it. Loading of LS or NS ucode is done mainly by the
HS ucode. For example, on an Ampere GPU, after the Booter ucode runs on the
SEC2 in HS mode and loads the GSP-RM binary onto the GSP, it needs to run
the "SEC2-RTOS" ucode at runtime. This presents a problem: there is no
component to load the SEC2-RTOS ucode onto the SEC2. The CPU cannot load
LS code, and GSP-RM must run in LS mode. To overcome this, the GSP is
temporarily made to run HS ucode (which is itself loaded by the CPU via
the nova-core driver using a "GSP-provided sequencer") which then loads
the SEC2-RTOS ucode onto the SEC2 in LS mode. The GSP then resumes
running its own GSP-RM LS ucode.
Falcon memory subsystem and DMA engine
======================================
Falcons have separate instruction and data memories (IMEM/DMEM)
and contains a small DMA engine called FBDMA (Framebuffer DMA) which does
DMA transfers to/from the IMEM/DMEM memory inside the Falcon via the FBIF
(Framebuffer Interface), to external memory.
DMA transfers are possible from the Falcon's memory to both the system memory
and the framebuffer memory (VRAM).
To perform a DMA via the FBDMA, the FBIF is configured to decide how the memory
is accessed (also known as aperture type). In the nova-core driver, this is
determined by the `FalconFbifTarget` enum.
The IO-PMP block (Input/Output Physical Memory Protection) unit in the Falcon
controls access by the FBDMA to the external memory.
Conceptual diagram (not exact) of the Falcon and its memory subsystem is as follows::
External Memory (Framebuffer / System DRAM)
^ |
| |
| v
+-----------------------------------------------------+
| | |
| +---------------+ | |
| | FBIF |-------+ | FALCON
| | (FrameBuffer | Memory Interface | PROCESSOR
| | InterFace) | |
| | Apertures | |
| | Configures | |
| | mem access | |
| +-------^-------+ |
| | |
| | FBDMA uses configured FBIF apertures |
| | to access External Memory
| |
| +-------v--------+ +---------------+
| | FBDMA | cfg | RISC |
| | (FrameBuffer |<---->| CORE |----->. Direct Core Access
| | DMA Engine) | | | |
| | - Master dev. | | (can run both | |
| +-------^--------+ | Falcon and | |
| | cfg--->| RISC-V code) | |
| | / | | |
| | | +---------------+ | +------------+
| | | | | BROM |
| | | <--->| (Boot ROM) |
| | / | +------------+
| | v |
| +---------------+ |
| | IO-PMP | Controls access by FBDMA |
| | (IO Physical | and other IO Masters |
| | Memory Protect) |
| +-------^-------+ |
| | |
| | Protected Access Path for FBDMA |
| v |
| +---------------------------------------+ |
| | Memory | |
| | +---------------+ +------------+ | |
| | | IMEM | | DMEM | |<-----+
| | | (Instruction | | (Data | |
| | | Memory) | | Memory) | |
| | +---------------+ +------------+ |
| +---------------------------------------+
+-----------------------------------------------------+

View File

@ -0,0 +1,181 @@
.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
=========================
FWSEC (Firmware Security)
=========================
This document briefly/conceptually describes the FWSEC (Firmware Security) image
and its role in the GPU boot sequence. As such, this information is subject to
change in the future and is only current as of the Ampere GPU family. However,
hopefully the concepts described will be useful for understanding the kernel code
that deals with it. All the information is derived from publicly available
sources such as public drivers and documentation.
The role of FWSEC is to provide a secure boot process. It runs in
'Heavy-secure' mode, and performs firmware verification after a GPU reset
before loading various ucode images onto other microcontrollers on the GPU,
such as the PMU and GSP.
FWSEC itself is an application stored in the VBIOS ROM in the FWSEC partition of
ROM (see vbios.rst for more details). It contains different commands like FRTS
(Firmware Runtime Services) and SB (Secure Booting other microcontrollers after
reset and loading them with other non-FWSEC ucode). The kernel driver only needs
to perform FRTS, since Secure Boot (SB) has already completed by the time the driver
is loaded.
The FRTS command carves out the WPR2 region (Write protected region) which contains
data required for power management. Once setup, only HS mode ucode can access it
(see falcon.rst for privilege levels).
The FWSEC image is located in the VBIOS ROM in the partition of the ROM that contains
various ucode images (also known as applications) -- one of them being FWSEC. For how
it is extracted, see vbios.rst and the vbios.rs source code.
The Falcon data for each ucode images (including the FWSEC image) is a combination
of headers, data sections (DMEM) and instruction code sections (IMEM). All these
ucode images are stored in the same ROM partition and the PMU table is used to look
up the application to load it based on its application ID (see vbios.rs).
For the nova-core driver, the FWSEC contains an 'application interface' called
DMEMMAPPER. This interface is used to execute the 'FWSEC-FRTS' command, among others.
For Ampere, FWSEC is running on the GSP in Heavy-secure mode and runs FRTS.
FWSEC Memory Layout
-------------------
The memory layout of the FWSEC image is as follows::
+---------------------------------------------------------------+
| FWSEC ROM image (type 0xE0) |
| |
| +---------------------------------+ |
| | PMU Falcon Ucode Table | |
| | (PmuLookupTable) | |
| | +-------------------------+ | |
| | | Table Header | | |
| | | - version: 0x01 | | |
| | | - header_size: 6 | | |
| | | - entry_size: 6 | | |
| | | - entry_count: N | | |
| | | - desc_version:3(unused)| | |
| | +-------------------------+ | |
| | ... | |
| | +-------------------------+ | |
| | | Entry for FWSEC (0x85) | | |
| | | (PmuLookupTableEntry) | | |
| | | - app_id: 0x85 (FWSEC) |----|----+ |
| | | - target_id: 0x01 (PMU) | | | |
| | | - data: offset ---------|----|----|---+ look up FWSEC |
| | +-------------------------+ | | | |
| +---------------------------------+ | | |
| | | |
| | | |
| +---------------------------------+ | | |
| | FWSEC Ucode Component |<---+ | |
| | (aka Falcon data) | | |
| | +-------------------------+ | | |
| | | FalconUCodeDescV3 |<---|--------+ |
| | | - hdr | | |
| | | - stored_size | | |
| | | - pkc_data_offset | | |
| | | - interface_offset -----|----|----------------+ |
| | | - imem_phys_base | | | |
| | | - imem_load_size | | | |
| | | - imem_virt_base | | | |
| | | - dmem_phys_base | | | |
| | | - dmem_load_size | | | |
| | | - engine_id_mask | | | |
| | | - ucode_id | | | |
| | | - signature_count | | look up sig | |
| | | - signature_versions --------------+ | |
| | +-------------------------+ | | | |
| | (no gap) | | | |
| | +-------------------------+ | | | |
| | | Signatures Section |<---|-----+ | |
| | | (384 bytes per sig) | | | |
| | | - RSA-3K Signature 1 | | | |
| | | - RSA-3K Signature 2 | | | |
| | | ... | | | |
| | +-------------------------+ | | |
| | | | |
| | +-------------------------+ | | |
| | | IMEM Section (Code) | | | |
| | | | | | |
| | | Contains instruction | | | |
| | | code etc. | | | |
| | +-------------------------+ | | |
| | | | |
| | +-------------------------+ | | |
| | | DMEM Section (Data) | | | |
| | | | | | |
| | | +---------------------+ | | | |
| | | | Application | |<---|----------------+ |
| | | | Interface Table | | | |
| | | | (FalconAppifHdrV1) | | | |
| | | | Header: | | | |
| | | | - version: 0x01 | | | |
| | | | - header_size: 4 | | | |
| | | | - entry_size: 8 | | | |
| | | | - entry_count: N | | | |
| | | | | | | |
| | | | Entries: | | | |
| | | | +-----------------+ | | | |
| | | | | DEVINIT (ID 1) | | | | |
| | | | | - id: 0x01 | | | | |
| | | | | - dmemOffset X -|-|-|----+ |
| | | | +-----------------+ | | | |
| | | | +-----------------+ | | | |
| | | | | DMEMMAPPER(ID 4)| | | | |
| | | | | - id: 0x04 | | | | Used only for DevInit |
| | | | | (NVFW_FALCON_ | | | | application (not FWSEC) |
| | | | | APPIF_ID_DMEMMAPPER) | |
| | | | | - dmemOffset Y -|-|-|----|-----+ |
| | | | +-----------------+ | | | | |
| | | +---------------------+ | | | |
| | | | | | |
| | | +---------------------+ | | | |
| | | | DEVINIT Engine |<|----+ | Used by FWSEC |
| | | | Interface | | | | app. |
| | | +---------------------+ | | | |
| | | | | | |
| | | +---------------------+ | | | |
| | | | DMEM Mapper (ID 4) |<|----+-----+ |
| | | | (FalconAppifDmemmapperV3) | |
| | | | - signature: "DMAP" | | | |
| | | | - version: 0x0003 | | | |
| | | | - Size: 64 bytes | | | |
| | | | - cmd_in_buffer_off | |----|------------+ |
| | | | - cmd_in_buffer_size| | | | |
| | | | - cmd_out_buffer_off| |----|------------|-----+ |
| | | | - cmd_out_buffer_sz | | | | | |
| | | | - init_cmd | | | | | |
| | | | - features | | | | | |
| | | | - cmd_mask0/1 | | | | | |
| | | +---------------------+ | | | | |
| | | | | | | |
| | | +---------------------+ | | | | |
| | | | Command Input Buffer|<|----|------------+ | |
| | | | - Command data | | | | |
| | | | - Arguments | | | | |
| | | +---------------------+ | | | |
| | | | | | |
| | | +---------------------+ | | | |
| | | | Command Output |<|----|------------------+ |
| | | | Buffer | | | |
| | | | - Results | | | |
| | | | - Status | | | |
| | | +---------------------+ | | |
| | +-------------------------+ | |
| +---------------------------------+ |
| |
+---------------------------------------------------------------+
.. note::
This is using an GA-102 Ampere GPU as an example and could vary for future GPUs.
.. note::
The FWSEC image also plays a role in memory scrubbing (ECC initialization) and VPR
(Video Protected Region) initialization as well. Before the nova-core driver is even
loaded, the FWSEC image is running on the GSP in heavy-secure mode. After the devinit
sequence completes, it does VRAM memory scrubbing (ECC initialization). On consumer
GPUs, it scrubs only part of memory and then initiates 'async scrubbing'. Before this
async scrubbing completes, the unscrubbed VRAM cannot be used for allocation (thus DRM
memory allocators need to wait for this scrubbing to complete).

View File

@ -14,14 +14,17 @@ Tasks may have the following fields:
- ``Contact``: The person that can be contacted for further information about
the task.
A task might have `[ABCD]` code after its name. This code can be used to grep
into the code for `TODO` entries related to it.
Enablement (Rust)
=================
Tasks that are not directly related to nova-core, but are preconditions in terms
of required APIs.
FromPrimitive API
-----------------
FromPrimitive API [FPRI]
------------------------
Sometimes the need arises to convert a number to a value of an enum or a
structure.
@ -41,8 +44,27 @@ automatically generates the corresponding mappings between a value and a number.
| Complexity: Beginner
| Link: https://docs.rs/num/latest/num/trait.FromPrimitive.html
Generic register abstraction
----------------------------
Conversion from byte slices for types implementing FromBytes [TRSM]
-------------------------------------------------------------------
We retrieve several structures from byte streams coming from the BIOS or loaded
firmware. At the moment converting the bytes slice into the proper type require
an inelegant `unsafe` operation; this will go away once `FromBytes` implements
a proper `from_bytes` method.
| Complexity: Beginner
CoherentAllocation improvements [COHA]
--------------------------------------
`CoherentAllocation` needs a safe way to write into the allocation, and to
obtain slices within the allocation.
| Complexity: Beginner
| Contact: Abdiel Janulgue
Generic register abstraction [REGA]
-----------------------------------
Work out how register constants and structures can be automatically generated
through generalized macros.
@ -102,16 +124,40 @@ Usage:
let boot0 = Boot0::read(&bar);
pr_info!("Revision: {}\n", boot0.revision());
Note: a work-in-progress implementation currently resides in
A work-in-progress implementation currently resides in
`drivers/gpu/nova-core/regs/macros.rs` and is used in nova-core. It would be
nice to improve it (possibly using proc macros) and move it to the `kernel`
crate so it can be used by other components as well.
Features desired before this happens:
* Relative register with build-time base address validation,
* Arrays of registers with build-time index validation,
* Make I/O optional I/O (for field values that are not registers),
* Support other sizes than `u32`,
* Allow visibility control for registers and individual fields,
* Use Rust slice syntax to express fields ranges.
| Complexity: Advanced
| Contact: Alexandre Courbot
Delay / Sleep abstractions
--------------------------
Numerical operations [NUMM]
---------------------------
Nova uses integer operations that are not part of the standard library (or not
implemented in an optimized way for the kernel). These include:
- Aligning up and down to a power of two,
- The "Find Last Set Bit" (`fls` function of the C part of the kernel)
operation.
A `num` core kernel module is being designed to provide these operations.
| Complexity: Intermediate
| Contact: Alexandre Courbot
Delay / Sleep abstractions [DLAY]
---------------------------------
Rust abstractions for the kernel's delay() and sleep() functions.
@ -159,18 +205,6 @@ mailing list yet.
| Complexity: Intermediate
| Contact: Abdiel Janulgue
ELF utils
---------
Rust implementation of ELF header representation to retrieve section header
tables, names, and data from an ELF-formatted images.
There is preceding work from Abdiel Janulgue, which hasn't made it to the
mailing list yet.
| Complexity: Beginner
| Contact: Abdiel Janulgue
PCI MISC APIs
-------------
@ -179,12 +213,11 @@ capability, MSI API abstractions.
| Complexity: Beginner
Auxiliary bus abstractions
--------------------------
XArray bindings [XARR]
----------------------
Rust abstraction for the auxiliary bus APIs.
This is needed to connect nova-core to the nova-drm driver.
We need bindings for `xa_alloc`/`xa_alloc_cyclic` in order to generate the
auxiliary device IDs.
| Complexity: Intermediate
@ -216,15 +249,6 @@ Build the radix3 page table to map the firmware.
| Complexity: Intermediate
| Contact: Abdiel Janulgue
vBIOS support
-------------
Parse the vBIOS and probe the structures required for driver initialization.
| Contact: Dave Airlie
| Reference: Vec extensions
| Complexity: Intermediate
Initial Devinit support
-----------------------
@ -234,23 +258,6 @@ configuration.
| Contact: Dave Airlie
| Complexity: Beginner
Boot Falcon controller
----------------------
Infrastructure to load and execute falcon (sec2) firmware images; handle the
GSP falcon processor and fwsec loading.
| Complexity: Advanced
| Contact: Dave Airlie
GPU Timer support
-----------------
Support for the GPU's internal timer peripheral.
| Complexity: Beginner
| Contact: Dave Airlie
MMU / PT management
-------------------

View File

@ -0,0 +1,181 @@
.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
==========
VBIOS
==========
This document describes the layout of the VBIOS image which is a series of concatenated
images in the ROM of the GPU. The VBIOS is mirrored onto the BAR 0 space and is read
by both Boot ROM firmware (also known as IFR or init-from-rom firmware) on the GPU to
bootstrap various microcontrollers (PMU, SEC, GSP) with critical initialization before
the driver loads, as well as by the nova-core driver in the kernel to boot the GSP.
The format of the images in the ROM follow the "BIOS Specification" part of the
PCI specification, with Nvidia-specific extensions. The ROM images of type FwSec
are the ones that contain Falcon ucode and what we are mainly looking for.
As an example, the following are the different image types that can be found in the
VBIOS of an Ampere GA102 GPU which is supported by the nova-core driver.
- PciAt Image (Type 0x00) - This is the standard PCI BIOS image, whose name
likely comes from the "IBM PC/AT" architecture.
- EFI Image (Type 0x03) - This is the EFI BIOS image. It contains the UEFI GOP
driver that is used to display UEFI graphics output.
- First FwSec Image (Type 0xE0) - The first FwSec image (Secure Firmware)
- Second FwSec Image (Type 0xE0) - The second FwSec image (Secure Firmware)
contains various microcodes (also known as an applications) that do a range
of different functions. The FWSEC ucode is run in heavy-secure mode and
typically runs directly on the GSP (it could be running on a different
designated processor in future generations but as of Ampere, it is the GSP).
This firmware then loads other firmware ucodes onto the PMU and SEC2
microcontrollers for gfw initialization after GPU reset and before the driver
loads (see devinit.rst). The DEVINIT ucode is itself another ucode that is
stored in this ROM partition.
Once located, the Falcon ucodes have "Application Interfaces" in their data
memory (DMEM). For FWSEC, the application interface we use for FWSEC is the
"DMEM mapper" interface which is configured to run the "FRTS" command. This
command carves out the WPR2 (Write-Protected Region) in VRAM. It then places
important power-management data, called 'FRTS', into this region. The WPR2
region is only accessible to heavy-secure ucode.
.. note::
It is not clear why FwSec has 2 different partitions in the ROM, but they both
are of type 0xE0 and can be identified as such. This could be subject to change
in future generations.
VBIOS ROM Layout
----------------
The VBIOS layout is roughly a series of concatenated images laid out as follows::
+----------------------------------------------------------------------------+
| VBIOS (Starting at ROM_OFFSET: 0x300000) |
+----------------------------------------------------------------------------+
| +-----------------------------------------------+ |
| | PciAt Image (Type 0x00) | |
| +-----------------------------------------------+ |
| | +-------------------+ | |
| | | ROM Header | | |
| | | (Signature 0xAA55)| | |
| | +-------------------+ | |
| | | rom header's pci_data_struct_offset | |
| | | points to the PCIR structure | |
| | V | |
| | +-------------------+ | |
| | | PCIR Structure | | |
| | | (Signature "PCIR")| | |
| | | last_image: 0x80 | | |
| | | image_len: size | | |
| | | in 512-byte units | | |
| | +-------------------+ | |
| | | | |
| | | NPDE immediately follows PCIR | |
| | V | |
| | +-------------------+ | |
| | | NPDE Structure | | |
| | | (Signature "NPDE")| | |
| | | last_image: 0x00 | | |
| | +-------------------+ | |
| | | |
| | +-------------------+ | |
| | | BIT Header | (Signature scanning | |
| | | (Signature "BIT") | provides the location | |
| | +-------------------+ of the BIT table) | |
| | | header is | |
| | | followed by a table of tokens | |
| | V one of which is for falcon data. | |
| | +-------------------+ | |
| | | BIT Tokens | | |
| | | ______________ | | |
| | | | Falcon Data | | | |
| | | | Token (0x70)|---+------------>------------+--+ |
| | | +-------------+ | falcon_data_ptr() | | |
| | +-------------------+ | V |
| +-----------------------------------------------+ | |
| (no gap between images) | |
| +-----------------------------------------------+ | |
| | EFI Image (Type 0x03) | | |
| +-----------------------------------------------+ | |
| | Contains the UEFI GOP driver (Graphics Output)| | |
| | +-------------------+ | | |
| | | ROM Header | | | |
| | +-------------------+ | | |
| | | PCIR Structure | | | |
| | +-------------------+ | | |
| | | NPDE Structure | | | |
| | +-------------------+ | | |
| | | Image data | | | |
| | +-------------------+ | | |
| +-----------------------------------------------+ | |
| (no gap between images) | |
| +-----------------------------------------------+ | |
| | First FwSec Image (Type 0xE0) | | |
| +-----------------------------------------------+ | |
| | +-------------------+ | | |
| | | ROM Header | | | |
| | +-------------------+ | | |
| | | PCIR Structure | | | |
| | +-------------------+ | | |
| | | NPDE Structure | | | |
| | +-------------------+ | | |
| | | Image data | | | |
| | +-------------------+ | | |
| +-----------------------------------------------+ | |
| (no gap between images) | |
| +-----------------------------------------------+ | |
| | Second FwSec Image (Type 0xE0) | | |
| +-----------------------------------------------+ | |
| | +-------------------+ | | |
| | | ROM Header | | | |
| | +-------------------+ | | |
| | | PCIR Structure | | | |
| | +-------------------+ | | |
| | | NPDE Structure | | | |
| | +-------------------+ | | |
| | | | |
| | +-------------------+ | | |
| | | PMU Lookup Table | <- falcon_data_offset <----+ |
| | | +-------------+ | pmu_lookup_table | |
| | | | Entry 0x85 | | | |
| | | | FWSEC_PROD | | | |
| | | +-------------+ | | |
| | +-------------------+ | |
| | | | |
| | | points to | |
| | V | |
| | +-------------------+ | |
| | | FalconUCodeDescV3 | <- falcon_ucode_offset | |
| | | (FWSEC Firmware) | fwsec_header() | |
| | +-------------------+ | |
| | | immediately followed by... | |
| | V | |
| | +----------------------------+ | |
| | | Signatures + FWSEC Ucode | | |
| | | fwsec_sigs(), fwsec_ucode()| | |
| | +----------------------------+ | |
| +-----------------------------------------------+ |
| |
+----------------------------------------------------------------------------+
.. note::
This diagram is created based on an GA-102 Ampere GPU as an example and could
vary for future or other GPUs.
.. note::
For more explanations of acronyms, see the detailed descriptions in `vbios.rs`.
Falcon data Lookup
------------------
A key part of the VBIOS extraction code (vbios.rs) is to find the location of the
Falcon data in the VBIOS which contains the PMU lookup table. This lookup table is
used to find the required Falcon ucode based on an application ID.
The location of the PMU lookup table is found by scanning the BIT (`BIOS Information Table`_)
tokens for a token with the id `BIT_TOKEN_ID_FALCON_DATA` (0x70) which indicates the
offset of the same from the start of the VBIOS image. Unfortunately, the offset
does not account for the EFI image located between the PciAt and FwSec images.
The `vbios.rs` code compensates for this with appropriate arithmetic.
.. _`BIOS Information Table`: https://download.nvidia.com/open-gpu-doc/BIOS-Information-Table/1/BIOS-Information-Table.html

View File

@ -28,3 +28,7 @@ vGPU manager VFIO driver and the nova-drm driver.
core/guidelines
core/todo
core/vbios
core/devinit
core/fwsec
core/falcon

View File

@ -73,15 +73,21 @@ Overview of baseline design
.. kernel-doc:: drivers/gpu/drm/drm_gpusvm.c
:doc: Locking
.. kernel-doc:: drivers/gpu/drm/drm_gpusvm.c
:doc: Migration
.. kernel-doc:: drivers/gpu/drm/drm_gpusvm.c
:doc: Partial Unmapping of Ranges
.. kernel-doc:: drivers/gpu/drm/drm_gpusvm.c
:doc: Examples
Overview of drm_pagemap design
==============================
.. kernel-doc:: drivers/gpu/drm/drm_pagemap.c
:doc: Overview
.. kernel-doc:: drivers/gpu/drm/drm_pagemap.c
:doc: Migration
Possible future design features
===============================

View File

@ -7720,6 +7720,7 @@ F: include/uapi/drm/nouveau_drm.h
CORE DRIVER FOR NVIDIA GPUS [RUST]
M: Danilo Krummrich <dakr@kernel.org>
M: Alexandre Courbot <acourbot@nvidia.com>
L: nouveau@lists.freedesktop.org
S: Supported
Q: https://patchwork.freedesktop.org/project/nouveau/
@ -7835,6 +7836,7 @@ F: drivers/gpu/drm/sitronix/st7586.c
DRM DRIVER FOR SITRONIX ST7571 PANELS
M: Marcus Folkesson <marcus.folkesson@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/display/sitronix,st7567.yaml
F: Documentation/devicetree/bindings/display/sitronix,st7571.yaml
F: drivers/gpu/drm/sitronix/st7571-i2c.c
@ -12089,6 +12091,13 @@ L: linux-kernel@vger.kernel.org
S: Supported
F: arch/x86/include/asm/intel-family.h
INTEL DISCRETE GRAPHICS NVM MTD DRIVER
M: Alexander Usyskin <alexander.usyskin@intel.com>
L: linux-mtd@lists.infradead.org
S: Supported
F: drivers/mtd/devices/mtd_intel_dg.c
F: include/linux/intel_dg_nvm_aux.h
INTEL DRM DISPLAY FOR XE AND I915 DRIVERS
M: Jani Nikula <jani.nikula@linux.intel.com>
M: Rodrigo Vivi <rodrigo.vivi@intel.com>

View File

@ -361,7 +361,7 @@ aie2_sched_job_timedout(struct drm_sched_job *sched_job)
aie2_hwctx_restart(xdna, hwctx);
mutex_unlock(&xdna->dev_lock);
return DRM_GPU_SCHED_STAT_NOMINAL;
return DRM_GPU_SCHED_STAT_RESET;
}
static const struct drm_sched_backend_ops sched_ops = {

View File

@ -66,6 +66,20 @@ static pm_message_t pm_transition;
static DEFINE_MUTEX(async_wip_mtx);
static int async_error;
/**
* pm_hibernate_is_recovering - if recovering from hibernate due to error.
*
* Used to query if dev_pm_ops.thaw() is called for normal hibernation case or
* recovering from some error.
*
* Return: true for error case, false for normal case.
*/
bool pm_hibernate_is_recovering(void)
{
return pm_transition.event == PM_EVENT_RECOVER;
}
EXPORT_SYMBOL_GPL(pm_hibernate_is_recovering);
static const char *pm_verb(int event)
{
switch (event) {

View File

@ -104,7 +104,11 @@ obj-$(CONFIG_DRM_PANEL_BACKLIGHT_QUIRKS) += drm_panel_backlight_quirks.o
#
obj-$(CONFIG_DRM_EXEC) += drm_exec.o
obj-$(CONFIG_DRM_GPUVM) += drm_gpuvm.o
obj-$(CONFIG_DRM_GPUSVM) += drm_gpusvm.o
drm_gpusvm_helper-y := \
drm_gpusvm.o\
drm_pagemap.o
obj-$(CONFIG_DRM_GPUSVM) += drm_gpusvm_helper.o
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o

View File

@ -883,6 +883,7 @@ struct amdgpu_mqd_prop {
uint64_t csa_addr;
uint64_t fence_address;
bool tmz_queue;
bool kernel_queue;
};
struct amdgpu_mqd {
@ -1562,16 +1563,16 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
int amdgpu_device_mode1_reset(struct amdgpu_device *adev);
int amdgpu_device_link_reset(struct amdgpu_device *adev);
bool amdgpu_device_supports_atpx(struct drm_device *dev);
bool amdgpu_device_supports_px(struct drm_device *dev);
bool amdgpu_device_supports_boco(struct drm_device *dev);
bool amdgpu_device_supports_smart_shift(struct drm_device *dev);
int amdgpu_device_supports_baco(struct drm_device *dev);
bool amdgpu_device_supports_atpx(struct amdgpu_device *adev);
bool amdgpu_device_supports_px(struct amdgpu_device *adev);
bool amdgpu_device_supports_boco(struct amdgpu_device *adev);
bool amdgpu_device_supports_smart_shift(struct amdgpu_device *adev);
int amdgpu_device_supports_baco(struct amdgpu_device *adev);
void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev);
bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
struct amdgpu_device *peer_adev);
int amdgpu_device_baco_enter(struct drm_device *dev);
int amdgpu_device_baco_exit(struct drm_device *dev);
int amdgpu_device_baco_enter(struct amdgpu_device *adev);
int amdgpu_device_baco_exit(struct amdgpu_device *adev);
void amdgpu_device_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring);
@ -1674,7 +1675,8 @@ int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
u8 perf_req, bool advertise);
int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
u8 dev_state, bool drv_state);
int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_state);
int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev,
enum amdgpu_ss ss_state);
int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset,
u64 *tmr_size);
@ -1705,8 +1707,11 @@ static inline void amdgpu_acpi_release(void) { }
static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
u8 dev_state, bool drv_state) { return 0; }
static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
enum amdgpu_ss ss_state) { return 0; }
static inline int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev,
enum amdgpu_ss ss_state)
{
return 0;
}
static inline void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps) { }
#endif
@ -1719,7 +1724,7 @@ static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return
#endif
#if defined(CONFIG_DRM_AMD_ISP)
int amdgpu_acpi_get_isp4_dev_hid(u8 (*hid)[ACPI_ID_LEN]);
int amdgpu_acpi_get_isp4_dev(struct acpi_device **dev);
#endif
void amdgpu_register_gpu_instance(struct amdgpu_device *adev);

View File

@ -811,18 +811,18 @@ int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
/**
* amdgpu_acpi_smart_shift_update - update dGPU device state to SBIOS
*
* @dev: drm_device pointer
* @adev: amdgpu device pointer
* @ss_state: current smart shift event
*
* returns 0 on success,
* otherwise return error number.
*/
int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_state)
int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev,
enum amdgpu_ss ss_state)
{
struct amdgpu_device *adev = drm_to_adev(dev);
int r;
if (!amdgpu_device_supports_smart_shift(dev))
if (!amdgpu_device_supports_smart_shift(adev))
return 0;
switch (ss_state) {
@ -1545,7 +1545,7 @@ static int isp_match_acpi_device_ids(struct device *dev, const void *data)
return acpi_match_device(data, dev) ? 1 : 0;
}
int amdgpu_acpi_get_isp4_dev_hid(u8 (*hid)[ACPI_ID_LEN])
int amdgpu_acpi_get_isp4_dev(struct acpi_device **dev)
{
struct device *pdev __free(put_device) = NULL;
struct acpi_device *acpi_pdev;
@ -1559,7 +1559,7 @@ int amdgpu_acpi_get_isp4_dev_hid(u8 (*hid)[ACPI_ID_LEN])
if (!acpi_pdev)
return -ENODEV;
strscpy(*hid, acpi_device_hid(acpi_pdev));
*dev = acpi_pdev;
return 0;
}

View File

@ -459,7 +459,7 @@ static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count)
{
u64 pos, wptr_old, rptr = *ring->rptr_cpu_addr & ring->ptr_mask;
u64 pos, wptr_old, rptr;
int rec_cnt_dw = count >> 2;
u32 chunk, ent_sz;
u8 *s = (u8 *)src;
@ -472,9 +472,11 @@ void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count)
return;
}
wptr_old = ring->wptr;
mutex_lock(&ring->adev->cper.ring_lock);
wptr_old = ring->wptr;
rptr = *ring->rptr_cpu_addr & ring->ptr_mask;
while (count) {
ent_sz = amdgpu_cper_ring_get_ent_sz(ring, ring->wptr);
chunk = umin(ent_sz, count);

View File

@ -411,19 +411,16 @@ static const struct attribute_group amdgpu_board_attrs_group = {
static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
/**
* amdgpu_device_supports_px - Is the device a dGPU with ATPX power control
*
* @dev: drm_device pointer
* @adev: amdgpu device pointer
*
* Returns true if the device is a dGPU with ATPX power control,
* otherwise return false.
*/
bool amdgpu_device_supports_px(struct drm_device *dev)
bool amdgpu_device_supports_px(struct amdgpu_device *adev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
if ((adev->flags & AMD_IS_PX) && !amdgpu_is_atpx_hybrid())
return true;
return false;
@ -432,15 +429,13 @@ bool amdgpu_device_supports_px(struct drm_device *dev)
/**
* amdgpu_device_supports_boco - Is the device a dGPU with ACPI power resources
*
* @dev: drm_device pointer
* @adev: amdgpu device pointer
*
* Returns true if the device is a dGPU with ACPI power control,
* otherwise return false.
*/
bool amdgpu_device_supports_boco(struct drm_device *dev)
bool amdgpu_device_supports_boco(struct amdgpu_device *adev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
return false;
@ -453,29 +448,24 @@ bool amdgpu_device_supports_boco(struct drm_device *dev)
/**
* amdgpu_device_supports_baco - Does the device support BACO
*
* @dev: drm_device pointer
* @adev: amdgpu device pointer
*
* Return:
* 1 if the device supports BACO;
* 3 if the device supports MACO (only works if BACO is supported)
* otherwise return 0.
*/
int amdgpu_device_supports_baco(struct drm_device *dev)
int amdgpu_device_supports_baco(struct amdgpu_device *adev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
return amdgpu_asic_supports_baco(adev);
}
void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
{
struct drm_device *dev;
int bamaco_support;
dev = adev_to_drm(adev);
adev->pm.rpm_mode = AMDGPU_RUNPM_NONE;
bamaco_support = amdgpu_device_supports_baco(dev);
bamaco_support = amdgpu_device_supports_baco(adev);
switch (amdgpu_runtime_pm) {
case 2:
@ -495,10 +485,12 @@ void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
break;
case -1:
case -2:
if (amdgpu_device_supports_px(dev)) { /* enable PX as runtime mode */
if (amdgpu_device_supports_px(adev)) {
/* enable PX as runtime mode */
adev->pm.rpm_mode = AMDGPU_RUNPM_PX;
dev_info(adev->dev, "Using ATPX for runtime pm\n");
} else if (amdgpu_device_supports_boco(dev)) { /* enable boco as runtime mode */
} else if (amdgpu_device_supports_boco(adev)) {
/* enable boco as runtime mode */
adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO;
dev_info(adev->dev, "Using BOCO for runtime pm\n");
} else {
@ -547,14 +539,14 @@ void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
* amdgpu_device_supports_smart_shift - Is the device dGPU with
* smart shift support
*
* @dev: drm_device pointer
* @adev: amdgpu device pointer
*
* Returns true if the device is a dGPU with Smart Shift support,
* otherwise returns false.
*/
bool amdgpu_device_supports_smart_shift(struct drm_device *dev)
bool amdgpu_device_supports_smart_shift(struct amdgpu_device *adev)
{
return (amdgpu_device_supports_boco(dev) &&
return (amdgpu_device_supports_boco(adev) &&
amdgpu_acpi_is_power_shift_control_supported());
}
@ -2200,7 +2192,8 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
struct drm_device *dev = pci_get_drvdata(pdev);
int r;
if (amdgpu_device_supports_px(dev) && state == VGA_SWITCHEROO_OFF)
if (amdgpu_device_supports_px(drm_to_adev(dev)) &&
state == VGA_SWITCHEROO_OFF)
return;
if (state == VGA_SWITCHEROO_ON) {
@ -4192,13 +4185,13 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
task_barrier_enter(&hive->tb);
adev->asic_reset_res = amdgpu_device_baco_enter(adev_to_drm(adev));
adev->asic_reset_res = amdgpu_device_baco_enter(adev);
if (adev->asic_reset_res)
goto fail;
task_barrier_exit(&hive->tb);
adev->asic_reset_res = amdgpu_device_baco_exit(adev_to_drm(adev));
adev->asic_reset_res = amdgpu_device_baco_exit(adev);
if (adev->asic_reset_res)
goto fail;
@ -4227,18 +4220,10 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
int ret = 0;
/*
* By default timeout for non compute jobs is 10000
* and 60000 for compute jobs.
* In SR-IOV or passthrough mode, timeout for compute
* jobs are 60000 by default.
* By default timeout for jobs is 10 sec
*/
adev->gfx_timeout = msecs_to_jiffies(10000);
adev->compute_timeout = adev->gfx_timeout = msecs_to_jiffies(10000);
adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
if (amdgpu_sriov_vf(adev))
adev->compute_timeout = amdgpu_sriov_is_pp_one_vf(adev) ?
msecs_to_jiffies(60000) : msecs_to_jiffies(10000);
else
adev->compute_timeout = msecs_to_jiffies(60000);
if (strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
while ((timeout_setting = strsep(&input, ",")) &&
@ -4353,7 +4338,6 @@ static void amdgpu_device_set_mcbp(struct amdgpu_device *adev)
int amdgpu_device_init(struct amdgpu_device *adev,
uint32_t flags)
{
struct drm_device *ddev = adev_to_drm(adev);
struct pci_dev *pdev = adev->pdev;
int r, i;
bool px = false;
@ -4814,7 +4798,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
vga_client_register(adev->pdev, amdgpu_device_vga_set_decode);
px = amdgpu_device_supports_px(ddev);
px = amdgpu_device_supports_px(adev);
if (px || (!dev_is_removable(&adev->pdev->dev) &&
apple_gmux_detect(NULL, NULL)))
@ -4980,7 +4964,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
kfree(adev->xcp_mgr);
adev->xcp_mgr = NULL;
px = amdgpu_device_supports_px(adev_to_drm(adev));
px = amdgpu_device_supports_px(adev);
if (px || (!dev_is_removable(&adev->pdev->dev) &&
apple_gmux_detect(NULL, NULL)))
@ -5029,8 +5013,16 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
return 0;
ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
if (ret)
if (ret) {
dev_warn(adev->dev, "evicting device resources failed\n");
return ret;
}
if (adev->in_s4) {
ret = ttm_device_prepare_hibernation(&adev->mman.bdev);
if (ret)
dev_err(adev->dev, "prepare hibernation failed, %d\n", ret);
}
return ret;
}
@ -5152,7 +5144,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients)
return r;
}
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
if (amdgpu_acpi_smart_shift_update(adev, AMDGPU_SS_DEV_D3))
dev_warn(adev->dev, "smart shift update failed\n");
if (notify_clients)
@ -5321,7 +5313,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
}
adev->in_suspend = false;
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))
if (amdgpu_acpi_smart_shift_update(adev, AMDGPU_SS_DEV_D0))
dev_warn(adev->dev, "smart shift update failed\n");
return 0;
@ -6365,7 +6357,8 @@ static int amdgpu_device_sched_resume(struct list_head *device_list,
amdgpu_vf_error_put(tmp_adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r);
} else {
dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&tmp_adev->gpu_reset_counter));
if (amdgpu_acpi_smart_shift_update(adev_to_drm(tmp_adev), AMDGPU_SS_DEV_D0))
if (amdgpu_acpi_smart_shift_update(tmp_adev,
AMDGPU_SS_DEV_D0))
dev_warn(tmp_adev->dev,
"smart shift update failed\n");
}
@ -6839,12 +6832,11 @@ bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
#endif
}
int amdgpu_device_baco_enter(struct drm_device *dev)
int amdgpu_device_baco_enter(struct amdgpu_device *adev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
if (!amdgpu_device_supports_baco(dev))
if (!amdgpu_device_supports_baco(adev))
return -ENOTSUPP;
if (ras && adev->ras_enabled &&
@ -6854,13 +6846,12 @@ int amdgpu_device_baco_enter(struct drm_device *dev)
return amdgpu_dpm_baco_enter(adev);
}
int amdgpu_device_baco_exit(struct drm_device *dev)
int amdgpu_device_baco_exit(struct amdgpu_device *adev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
int ret = 0;
if (!amdgpu_device_supports_baco(dev))
if (!amdgpu_device_supports_baco(adev))
return -ENOTSUPP;
ret = amdgpu_dpm_baco_exit(adev);

View File

@ -1196,13 +1196,14 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb
static int amdgpu_display_gem_fb_verify_and_init(struct drm_device *dev,
struct amdgpu_framebuffer *rfb,
struct drm_file *file_priv,
const struct drm_format_info *info,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
rfb->base.obj[0] = obj;
drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd);
drm_helper_mode_fill_fb_struct(dev, &rfb->base, info, mode_cmd);
/* Verify that the modifier is supported. */
if (!drm_any_plane_has_format(dev, mode_cmd->pixel_format,
mode_cmd->modifier[0])) {
@ -1297,6 +1298,7 @@ static int amdgpu_display_framebuffer_init(struct drm_device *dev,
struct drm_framebuffer *
amdgpu_display_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
const struct drm_format_info *info,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct amdgpu_framebuffer *amdgpu_fb;
@ -1330,7 +1332,7 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
}
ret = amdgpu_display_gem_fb_verify_and_init(dev, amdgpu_fb, file_priv,
mode_cmd, obj);
info, mode_cmd, obj);
if (ret) {
kfree(amdgpu_fb);
drm_gem_object_put(obj);

View File

@ -44,6 +44,7 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
struct drm_framebuffer *
amdgpu_display_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
const struct drm_format_info *info,
const struct drm_mode_fb_cmd2 *mode_cmd);
const struct drm_format_info *
amdgpu_lookup_format_info(u32 format, uint64_t modifier);

View File

@ -362,12 +362,12 @@ module_param_named(svm_default_granularity, amdgpu_svm_default_granularity, uint
* The second one is for Compute. The third and fourth ones are
* for SDMA and Video.
*
* By default(with no lockup_timeout settings), the timeout for all non-compute(GFX, SDMA and Video)
* jobs is 10000. The timeout for compute is 60000.
* By default(with no lockup_timeout settings), the timeout for all jobs is 10000.
*/
MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default: for bare metal 10000 for non-compute jobs and 60000 for compute jobs; "
"for passthrough or sriov, 10000 for all jobs. 0: keep default value. negative: infinity timeout), format: for bare metal [Non-Compute] or [GFX,Compute,SDMA,Video]; "
"for passthrough or sriov [all jobs] or [GFX,Compute,SDMA,Video].");
MODULE_PARM_DESC(lockup_timeout,
"GPU lockup timeout in ms (default: 10000 for all jobs. "
"0: keep default value. negative: infinity timeout), format: for bare metal [Non-Compute] or [GFX,Compute,SDMA,Video]; "
"for passthrough or sriov [all jobs] or [GFX,Compute,SDMA,Video].");
module_param_string(lockup_timeout, amdgpu_lockup_timeout, sizeof(amdgpu_lockup_timeout), 0444);
/**
@ -2457,10 +2457,10 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) {
/* only need to skip on ATPX */
if (amdgpu_device_supports_px(ddev))
if (amdgpu_device_supports_px(adev))
dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
/* we want direct complete for BOCO */
if (amdgpu_device_supports_boco(ddev))
if (amdgpu_device_supports_boco(adev))
dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_SMART_PREPARE |
DPM_FLAG_SMART_SUSPEND |
DPM_FLAG_MAY_SKIP_RESUME);
@ -2493,9 +2493,9 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
* into D0 state. Then there will be a PMFW-aware D-state
* transition(D0->D3) on runpm suspend.
*/
if (amdgpu_device_supports_baco(ddev) &&
if (amdgpu_device_supports_baco(adev) &&
!(adev->flags & AMD_IS_APU) &&
(adev->asic_type >= CHIP_NAVI10))
adev->asic_type >= CHIP_NAVI10)
amdgpu_get_secondary_funcs(adev);
}
@ -2512,6 +2512,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
amdgpu_ras_eeprom_check_and_recover(adev);
amdgpu_xcp_dev_unplug(adev);
amdgpu_gmc_prepare_nps_mode_change(adev);
drm_dev_unplug(dev);
@ -2541,6 +2542,10 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
if (amdgpu_ras_intr_triggered())
return;
/* device maybe not resumed here, return immediately in this case */
if (adev->in_s4 && adev->in_suspend)
return;
/* if we are running in a VM, make sure the device
* torn down properly on reboot/shutdown.
* unfortunately we can't detect certain
@ -2557,11 +2562,14 @@ static int amdgpu_pmops_prepare(struct device *dev)
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
/* device maybe not resumed here, return immediately in this case */
if (adev->in_s4 && adev->in_suspend)
return 0;
/* Return a positive number here so
* DPM_FLAG_SMART_SUSPEND works properly
*/
if (amdgpu_device_supports_boco(drm_dev) &&
pm_runtime_suspended(dev))
if (amdgpu_device_supports_boco(adev) && pm_runtime_suspended(dev))
return 1;
/* if we will not support s3 or s2i for the device
@ -2656,12 +2664,21 @@ static int amdgpu_pmops_thaw(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
/* do not resume device if it's normal hibernation */
if (!pm_hibernate_is_recovering())
return 0;
return amdgpu_device_resume(drm_dev, true);
}
static int amdgpu_pmops_poweroff(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
/* device maybe not resumed here, return immediately in this case */
if (adev->in_s4 && adev->in_suspend)
return 0;
return amdgpu_device_suspend(drm_dev, true);
}
@ -2834,7 +2851,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
/* nothing to do */
} else if ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) ||
(adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)) {
amdgpu_device_baco_enter(drm_dev);
amdgpu_device_baco_enter(adev);
}
dev_dbg(&pdev->dev, "asic/device is runtime suspended\n");
@ -2875,7 +2892,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
pci_set_master(pdev);
} else if ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) ||
(adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)) {
amdgpu_device_baco_exit(drm_dev);
amdgpu_device_baco_exit(adev);
}
ret = amdgpu_device_resume(drm_dev, false);
if (ret) {
@ -2912,6 +2929,20 @@ static int amdgpu_pmops_runtime_idle(struct device *dev)
return ret;
}
static int amdgpu_drm_release(struct inode *inode, struct file *filp)
{
struct drm_file *file_priv = filp->private_data;
struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
if (fpriv) {
fpriv->evf_mgr.fd_closing = true;
amdgpu_eviction_fence_destroy(&fpriv->evf_mgr);
amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
}
return drm_release(inode, filp);
}
long amdgpu_drm_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
@ -2963,7 +2994,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.flush = amdgpu_flush,
.release = drm_release,
.release = amdgpu_drm_release,
.unlocked_ioctl = amdgpu_drm_ioctl,
.mmap = drm_gem_mmap,
.poll = drm_poll,

View File

@ -120,6 +120,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
am_fence = kzalloc(sizeof(*am_fence), GFP_KERNEL);
if (!am_fence)
return -ENOMEM;
am_fence->context = 0;
} else {
am_fence = af;
}
@ -127,6 +128,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
am_fence->ring = ring;
seq = ++ring->fence_drv.sync_seq;
am_fence->seq = seq;
if (af) {
dma_fence_init(fence, &amdgpu_job_fence_ops,
&ring->fence_drv.lock,
@ -141,6 +143,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
seq, flags | AMDGPU_FENCE_FLAG_INT);
amdgpu_fence_save_wptr(fence);
pm_runtime_get_noresume(adev_to_drm(adev)->dev);
ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask];
if (unlikely(rcu_dereference_protected(*ptr, 1))) {
@ -253,6 +256,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
do {
struct dma_fence *fence, **ptr;
struct amdgpu_fence *am_fence;
++last_seq;
last_seq &= drv->num_fences_mask;
@ -265,6 +269,12 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
if (!fence)
continue;
/* Save the wptr in the fence driver so we know what the last processed
* wptr was. This is required for re-emitting the ring state for
* queues that are reset but are not guilty and thus have no guilty fence.
*/
am_fence = container_of(fence, struct amdgpu_fence, base);
drv->signalled_wptr = am_fence->wptr;
dma_fence_signal(fence);
dma_fence_put(fence);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
@ -727,6 +737,86 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
amdgpu_fence_process(ring);
}
/**
* Kernel queue reset handling
*
* The driver can reset individual queues for most engines, but those queues
* may contain work from multiple contexts. Resetting the queue will reset
* lose all of that state. In order to minimize the collateral damage, the
* driver will save the ring contents which are not associated with the guilty
* context prior to resetting the queue. After resetting the queue the queue
* contents from the other contexts is re-emitted to the rings so that it can
* be processed by the engine. To handle this, we save the queue's write
* pointer (wptr) in the fences associated with each context. If we get a
* queue timeout, we can then use the wptrs from the fences to determine
* which data needs to be saved out of the queue's ring buffer.
*/
/**
* amdgpu_fence_driver_guilty_force_completion - force signal of specified sequence
*
* @fence: fence of the ring to signal
*
*/
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *fence)
{
dma_fence_set_error(&fence->base, -ETIME);
amdgpu_fence_write(fence->ring, fence->seq);
amdgpu_fence_process(fence->ring);
}
void amdgpu_fence_save_wptr(struct dma_fence *fence)
{
struct amdgpu_fence *am_fence = container_of(fence, struct amdgpu_fence, base);
am_fence->wptr = am_fence->ring->wptr;
}
static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
u64 start_wptr, u32 end_wptr)
{
unsigned int first_idx = start_wptr & ring->buf_mask;
unsigned int last_idx = end_wptr & ring->buf_mask;
unsigned int i;
/* Backup the contents of the ring buffer. */
for (i = first_idx; i != last_idx; ++i, i &= ring->buf_mask)
ring->ring_backup[ring->ring_backup_entries_to_copy++] = ring->ring[i];
}
void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
struct amdgpu_fence *guilty_fence)
{
struct dma_fence *unprocessed;
struct dma_fence __rcu **ptr;
struct amdgpu_fence *fence;
u64 wptr, i, seqno;
seqno = amdgpu_fence_read(ring);
wptr = ring->fence_drv.signalled_wptr;
ring->ring_backup_entries_to_copy = 0;
for (i = seqno + 1; i <= ring->fence_drv.sync_seq; ++i) {
ptr = &ring->fence_drv.fences[i & ring->fence_drv.num_fences_mask];
rcu_read_lock();
unprocessed = rcu_dereference(*ptr);
if (unprocessed && !dma_fence_is_signaled(unprocessed)) {
fence = container_of(unprocessed, struct amdgpu_fence, base);
/* save everything if the ring is not guilty, otherwise
* just save the content from other contexts.
*/
if (!guilty_fence || (fence->context != guilty_fence->context))
amdgpu_ring_backup_unprocessed_command(ring, wptr,
fence->wptr);
wptr = fence->wptr;
}
rcu_read_unlock();
}
}
/*
* Common fence implementation
*/

View File

@ -139,7 +139,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
int vmid = AMDGPU_JOB_GET_VMID(job);
bool need_pipe_sync = false;
unsigned int cond_exec;
unsigned int i;
int r = 0;
@ -156,6 +155,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
gds_va = job->gds_va;
init_shadow = job->init_shadow;
af = &job->hw_fence;
/* Save the context of the job for reset handling.
* The driver needs this so it can skip the ring
* contents for guilty contexts.
*/
af->context = job->base.s_fence ? job->base.s_fence->finished.context : 0;
} else {
vm = NULL;
fence_ctx = 0;
@ -307,8 +311,17 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
ring->funcs->emit_wave_limit(ring, false);
/* Save the wptr associated with this fence.
* This must be last for resets to work properly
* as we need to save the wptr associated with this
* fence so we know what rings contents to backup
* after we reset the queue.
*/
amdgpu_fence_save_wptr(*f);
amdgpu_ring_ib_end(ring);
amdgpu_ring_commit(ring);
return 0;
}

View File

@ -624,7 +624,7 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
unsigned int type)
{
/* When the threshold is reached,the interrupt source may not be enabled.return -EINVAL */
if (amdgpu_ras_is_rma(adev))
if (amdgpu_ras_is_rma(adev) && !amdgpu_irq_enabled(adev, src, type))
return -EINVAL;
if (!adev->irq.installed)

View File

@ -33,6 +33,8 @@
#include "isp_v4_1_0.h"
#include "isp_v4_1_1.h"
#define ISP_MC_ADDR_ALIGN (1024 * 32)
/**
* isp_hw_init - start and test isp block
*
@ -141,6 +143,179 @@ static int isp_set_powergating_state(struct amdgpu_ip_block *ip_block,
return 0;
}
static int is_valid_isp_device(struct device *isp_parent, struct device *amdgpu_dev)
{
if (isp_parent != amdgpu_dev)
return -EINVAL;
return 0;
}
/**
* isp_user_buffer_alloc - create user buffer object (BO) for isp
*
* @dev: isp device handle
* @dmabuf: DMABUF handle for isp buffer allocated in system memory
* @buf_obj: GPU buffer object handle to initialize
* @buf_addr: GPU addr of the pinned BO to initialize
*
* Imports isp DMABUF to allocate and pin a user BO for isp internal use. It does
* GART alloc to generate GPU addr for BO to make it accessible through the
* GART aperture for ISP HW.
*
* This function is exported to allow the V4L2 isp device external to drm device
* to create and access the isp user BO.
*
* Returns:
* 0 on success, negative error code otherwise.
*/
int isp_user_buffer_alloc(struct device *dev, void *dmabuf,
void **buf_obj, u64 *buf_addr)
{
struct platform_device *ispdev = to_platform_device(dev);
const struct isp_platform_data *isp_pdata;
struct amdgpu_device *adev;
struct mfd_cell *mfd_cell;
struct amdgpu_bo *bo;
u64 gpu_addr;
int ret;
if (WARN_ON(!ispdev))
return -ENODEV;
if (WARN_ON(!buf_obj))
return -EINVAL;
if (WARN_ON(!buf_addr))
return -EINVAL;
mfd_cell = &ispdev->mfd_cell[0];
if (!mfd_cell)
return -ENODEV;
isp_pdata = mfd_cell->platform_data;
adev = isp_pdata->adev;
ret = is_valid_isp_device(ispdev->dev.parent, adev->dev);
if (ret)
return ret;
ret = amdgpu_bo_create_isp_user(adev, dmabuf,
AMDGPU_GEM_DOMAIN_GTT, &bo, &gpu_addr);
if (ret) {
drm_err(&adev->ddev, "failed to alloc gart user buffer (%d)", ret);
return ret;
}
*buf_obj = (void *)bo;
*buf_addr = gpu_addr;
return 0;
}
EXPORT_SYMBOL(isp_user_buffer_alloc);
/**
* isp_user_buffer_free - free isp user buffer object (BO)
*
* @buf_obj: amdgpu isp user BO to free
*
* unpin and unref BO for isp internal use.
*
* This function is exported to allow the V4L2 isp device
* external to drm device to free the isp user BO.
*/
void isp_user_buffer_free(void *buf_obj)
{
amdgpu_bo_free_isp_user(buf_obj);
}
EXPORT_SYMBOL(isp_user_buffer_free);
/**
* isp_kernel_buffer_alloc - create kernel buffer object (BO) for isp
*
* @dev: isp device handle
* @size: size for the new BO
* @buf_obj: GPU BO handle to initialize
* @gpu_addr: GPU addr of the pinned BO
* @cpu_addr: CPU address mapping of BO
*
* Allocates and pins a kernel BO for internal isp firmware use.
*
* This function is exported to allow the V4L2 isp device
* external to drm device to create and access the kernel BO.
*
* Returns:
* 0 on success, negative error code otherwise.
*/
int isp_kernel_buffer_alloc(struct device *dev, u64 size,
void **buf_obj, u64 *gpu_addr, void **cpu_addr)
{
struct platform_device *ispdev = to_platform_device(dev);
struct amdgpu_bo **bo = (struct amdgpu_bo **)buf_obj;
const struct isp_platform_data *isp_pdata;
struct amdgpu_device *adev;
struct mfd_cell *mfd_cell;
int ret;
if (WARN_ON(!ispdev))
return -ENODEV;
if (WARN_ON(!buf_obj))
return -EINVAL;
if (WARN_ON(!gpu_addr))
return -EINVAL;
if (WARN_ON(!cpu_addr))
return -EINVAL;
mfd_cell = &ispdev->mfd_cell[0];
if (!mfd_cell)
return -ENODEV;
isp_pdata = mfd_cell->platform_data;
adev = isp_pdata->adev;
ret = is_valid_isp_device(ispdev->dev.parent, adev->dev);
if (ret)
return ret;
ret = amdgpu_bo_create_kernel(adev,
size,
ISP_MC_ADDR_ALIGN,
AMDGPU_GEM_DOMAIN_GTT,
bo,
gpu_addr,
cpu_addr);
if (!cpu_addr || ret) {
drm_err(&adev->ddev, "failed to alloc gart kernel buffer (%d)", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL(isp_kernel_buffer_alloc);
/**
* isp_kernel_buffer_free - free isp kernel buffer object (BO)
*
* @buf_obj: amdgpu isp user BO to free
* @gpu_addr: GPU addr of isp kernel BO
* @cpu_addr: CPU addr of isp kernel BO
*
* unmaps and unpin a isp kernel BO.
*
* This function is exported to allow the V4L2 isp device
* external to drm device to free the kernel BO.
*/
void isp_kernel_buffer_free(void **buf_obj, u64 *gpu_addr, void **cpu_addr)
{
struct amdgpu_bo **bo = (struct amdgpu_bo **)buf_obj;
amdgpu_bo_free_kernel(bo, gpu_addr, cpu_addr);
}
EXPORT_SYMBOL(isp_kernel_buffer_free);
static const struct amd_ip_funcs isp_ip_funcs = {
.name = "isp_ip",
.early_init = isp_early_init,

View File

@ -28,18 +28,13 @@
#ifndef __AMDGPU_ISP_H__
#define __AMDGPU_ISP_H__
#include <drm/amd/isp.h>
#include <linux/pm_domain.h>
#define ISP_REGS_OFFSET_END 0x629A4
struct amdgpu_isp;
struct isp_platform_data {
void *adev;
u32 asic_type;
resource_size_t base_rmmio_size;
};
struct isp_funcs {
int (*hw_init)(struct amdgpu_isp *isp);
int (*hw_fini)(struct amdgpu_isp *isp);

View File

@ -90,7 +90,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched);
struct amdgpu_job *job = to_amdgpu_job(s_job);
struct drm_wedge_task_info *info = NULL;
struct amdgpu_task_info *ti;
struct amdgpu_task_info *ti = NULL;
struct amdgpu_device *adev = ring->adev;
int idx, r;
@ -112,6 +112,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
amdgpu_job_core_dump(adev, job);
if (amdgpu_gpu_recovery &&
amdgpu_ring_is_reset_type_supported(ring, AMDGPU_RESET_TYPE_SOFT_RESET) &&
amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
dev_err(adev->dev, "ring %s timeout, but soft recovered\n",
s_job->sched->name);
@ -131,10 +132,12 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
/* attempt a per ring reset */
if (unlikely(adev->debug_disable_gpu_ring_reset)) {
dev_err(adev->dev, "Ring reset disabled by debug mask\n");
} else if (amdgpu_gpu_recovery && ring->funcs->reset) {
} else if (amdgpu_gpu_recovery &&
amdgpu_ring_is_reset_type_supported(ring, AMDGPU_RESET_TYPE_PER_QUEUE) &&
ring->funcs->reset) {
dev_err(adev->dev, "Starting %s ring reset\n",
s_job->sched->name);
r = amdgpu_ring_reset(ring, job->vmid, NULL);
r = amdgpu_ring_reset(ring, job->vmid, &job->hw_fence);
if (!r) {
atomic_inc(&ring->adev->gpu_reset_counter);
dev_err(adev->dev, "Ring %s reset succeeded\n",
@ -148,8 +151,6 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
amdgpu_vm_put_task_info(ti);
if (amdgpu_device_should_recover_gpu(ring->adev)) {
struct amdgpu_reset_context reset_context;
memset(&reset_context, 0, sizeof(reset_context));
@ -175,8 +176,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
}
exit:
amdgpu_vm_put_task_info(ti);
drm_dev_exit(idx);
return DRM_GPU_SCHED_STAT_NOMINAL;
return DRM_GPU_SCHED_STAT_RESET;
}
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,

View File

@ -91,7 +91,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
if (adev->rmmio == NULL)
return;
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_UNLOAD))
if (amdgpu_acpi_smart_shift_update(adev, AMDGPU_SS_DRV_UNLOAD))
DRM_WARN("smart shift update failed\n");
amdgpu_acpi_fini(adev);
@ -161,7 +161,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
if (acpi_status)
dev_dbg(dev->dev, "Error during ACPI methods call\n");
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_LOAD))
if (amdgpu_acpi_smart_shift_update(adev, AMDGPU_SS_DRV_LOAD))
DRM_WARN("smart shift update failed\n");
out:
@ -399,6 +399,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
uint32_t ib_size_alignment = 0;
enum amd_ip_block_type type;
unsigned int num_rings = 0;
uint32_t num_slots = 0;
unsigned int i, j;
if (info->query_hw_ip.ip_instance >= AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
@ -411,6 +412,12 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->gfx.gfx_ring[i].sched.ready &&
!adev->gfx.gfx_ring[i].no_user_submission)
++num_rings;
if (!adev->gfx.disable_uq) {
for (i = 0; i < AMDGPU_MES_MAX_GFX_PIPES; i++)
num_slots += hweight32(adev->mes.gfx_hqd_mask[i]);
}
ib_start_alignment = 32;
ib_size_alignment = 32;
break;
@ -420,6 +427,12 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->gfx.compute_ring[i].sched.ready &&
!adev->gfx.compute_ring[i].no_user_submission)
++num_rings;
if (!adev->sdma.disable_uq) {
for (i = 0; i < AMDGPU_MES_MAX_COMPUTE_PIPES; i++)
num_slots += hweight32(adev->mes.compute_hqd_mask[i]);
}
ib_start_alignment = 32;
ib_size_alignment = 32;
break;
@ -429,6 +442,12 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
if (adev->sdma.instance[i].ring.sched.ready &&
!adev->sdma.instance[i].ring.no_user_submission)
++num_rings;
if (!adev->gfx.disable_uq) {
for (i = 0; i < AMDGPU_MES_MAX_SDMA_PIPES; i++)
num_slots += hweight32(adev->mes.sdma_hqd_mask[i]);
}
ib_start_alignment = 256;
ib_size_alignment = 4;
break;
@ -570,6 +589,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
}
result->capabilities_flags = 0;
result->available_rings = (1 << num_rings) - 1;
result->userq_num_slots = num_slots;
result->ib_start_alignment = ib_start_alignment;
result->ib_size_alignment = ib_size_alignment;
return 0;
@ -1503,9 +1523,6 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
amdgpu_vm_bo_del(adev, fpriv->prt_va);
amdgpu_bo_unreserve(pd);
}
fpriv->evf_mgr.fd_closing = true;
amdgpu_eviction_fence_destroy(&fpriv->evf_mgr);
amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
amdgpu_vm_fini(adev, &fpriv->vm);

View File

@ -352,7 +352,6 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
return 0;
}
EXPORT_SYMBOL(amdgpu_bo_create_kernel);
/**
* amdgpu_bo_create_isp_user - create user BO for isp
@ -421,7 +420,6 @@ int amdgpu_bo_create_isp_user(struct amdgpu_device *adev,
return r;
}
EXPORT_SYMBOL(amdgpu_bo_create_isp_user);
/**
* amdgpu_bo_create_kernel_at - create BO for kernel use at specific location
@ -525,7 +523,6 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
if (cpu_addr)
*cpu_addr = NULL;
}
EXPORT_SYMBOL(amdgpu_bo_free_kernel);
/**
* amdgpu_bo_free_isp_user - free BO for isp use
@ -548,7 +545,6 @@ void amdgpu_bo_free_isp_user(struct amdgpu_bo *bo)
}
amdgpu_bo_unref(&bo);
}
EXPORT_SYMBOL(amdgpu_bo_free_isp_user);
/* Validate bo size is bit bigger than the request domain */
static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,

View File

@ -575,9 +575,11 @@ static int psp_sw_fini(struct amdgpu_ip_block *ip_block)
return 0;
}
int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
uint32_t reg_val, uint32_t mask, bool check_changed)
int psp_wait_for(struct psp_context *psp, uint32_t reg_index, uint32_t reg_val,
uint32_t mask, uint32_t flags)
{
bool check_changed = flags & PSP_WAITREG_CHANGED;
bool verbose = !(flags & PSP_WAITREG_NOVERBOSE);
uint32_t val;
int i;
struct amdgpu_device *adev = psp->adev;
@ -597,9 +599,10 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
udelay(1);
}
dev_err(adev->dev,
"psp reg (0x%x) wait timed out, mask: %x, read: %x exp: %x",
reg_index, mask, val, reg_val);
if (verbose)
dev_err(adev->dev,
"psp reg (0x%x) wait timed out, mask: %x, read: %x exp: %x",
reg_index, mask, val, reg_val);
return -ETIME;
}

View File

@ -134,6 +134,9 @@ enum psp_reg_prog_id {
PSP_REG_LAST
};
#define PSP_WAITREG_CHANGED BIT(0) /* check if the value has changed */
#define PSP_WAITREG_NOVERBOSE BIT(1) /* No error verbose */
struct psp_funcs {
int (*init_microcode)(struct psp_context *psp);
int (*wait_for_bootloader)(struct psp_context *psp);
@ -532,8 +535,8 @@ extern const struct amdgpu_ip_block_version psp_v13_0_ip_block;
extern const struct amdgpu_ip_block_version psp_v13_0_4_ip_block;
extern const struct amdgpu_ip_block_version psp_v14_0_ip_block;
extern int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
uint32_t field_val, uint32_t mask, bool check_changed);
int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
uint32_t field_val, uint32_t mask, uint32_t flags);
extern int psp_wait_for_spirom_update(struct psp_context *psp, uint32_t reg_index,
uint32_t field_val, uint32_t mask, uint32_t msec_timeout);

View File

@ -2857,6 +2857,13 @@ static int __amdgpu_ras_convert_rec_array_from_rom(struct amdgpu_device *adev,
if (amdgpu_umc_pages_in_a_row(adev, err_data,
bps[0].retired_page << AMDGPU_GPU_PAGE_SHIFT))
return -EINVAL;
for (i = 0; i < adev->umc.retire_unit; i++) {
err_data->err_addr[i].address = bps[0].address;
err_data->err_addr[i].mem_channel = bps[0].mem_channel;
err_data->err_addr[i].bank = bps[0].bank;
err_data->err_addr[i].err_type = bps[0].err_type;
err_data->err_addr[i].mcumc_id = bps[0].mcumc_id;
}
} else {
if (amdgpu_ras_mca2pa_by_idx(adev, &bps[0], err_data))
return -EINVAL;
@ -2888,6 +2895,7 @@ static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev,
struct eeprom_table_record *bps, struct ras_err_data *err_data,
enum amdgpu_memory_partition nps)
{
int i = 0;
enum amdgpu_memory_partition save_nps;
save_nps = (bps->retired_page >> UMC_NPS_SHIFT) & UMC_NPS_MASK;
@ -2897,6 +2905,13 @@ static int __amdgpu_ras_convert_rec_from_rom(struct amdgpu_device *adev,
if (amdgpu_umc_pages_in_a_row(adev, err_data,
bps->retired_page << AMDGPU_GPU_PAGE_SHIFT))
return -EINVAL;
for (i = 0; i < adev->umc.retire_unit; i++) {
err_data->err_addr[i].address = bps->address;
err_data->err_addr[i].mem_channel = bps->mem_channel;
err_data->err_addr[i].bank = bps->bank;
err_data->err_addr[i].err_type = bps->err_type;
err_data->err_addr[i].mcumc_id = bps->mcumc_id;
}
} else {
if (bps->address) {
if (amdgpu_ras_mca2pa_by_idx(adev, bps, err_data))

View File

@ -1531,3 +1531,31 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control)
return res < 0 ? res : 0;
}
void amdgpu_ras_eeprom_check_and_recover(struct amdgpu_device *adev)
{
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
struct amdgpu_ras_eeprom_control *control;
int res;
if (!__is_ras_eeprom_supported(adev) || !ras)
return;
control = &ras->eeprom_control;
if (!control->is_eeprom_valid)
return;
res = __verify_ras_table_checksum(control);
if (res) {
dev_warn(adev->dev,
"RAS table incorrect checksum or error:%d, try to recover\n",
res);
if (!amdgpu_ras_eeprom_reset_table(control))
if (!amdgpu_ras_save_bad_pages(adev, NULL))
if (!__verify_ras_table_checksum(control)) {
dev_info(adev->dev, "RAS table recovery succeed\n");
return;
}
dev_err(adev->dev, "RAS table recovery failed\n");
control->is_eeprom_valid = false;
}
return;
}

View File

@ -161,6 +161,8 @@ void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control);
int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control);
void amdgpu_ras_eeprom_check_and_recover(struct amdgpu_device *adev);
extern const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops;
extern const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops;

View File

@ -99,6 +99,29 @@ int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned int ndw)
return 0;
}
/**
* amdgpu_ring_alloc_reemit - allocate space on the ring buffer for reemit
*
* @ring: amdgpu_ring structure holding ring information
* @ndw: number of dwords to allocate in the ring buffer
*
* Allocate @ndw dwords in the ring buffer (all asics).
* doesn't check the max_dw limit as we may be reemitting
* several submissions.
*/
static void amdgpu_ring_alloc_reemit(struct amdgpu_ring *ring, unsigned int ndw)
{
/* Align requested size with padding so unlock_commit can
* pad safely */
ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask;
ring->count_dw = ndw;
ring->wptr_old = ring->wptr;
if (ring->funcs->begin_use)
ring->funcs->begin_use(ring);
}
/** amdgpu_ring_insert_nop - insert NOP packets
*
* @ring: amdgpu_ring structure holding ring information
@ -333,6 +356,12 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
/* Initialize cached_rptr to 0 */
ring->cached_rptr = 0;
if (!ring->ring_backup) {
ring->ring_backup = kvzalloc(ring->ring_size, GFP_KERNEL);
if (!ring->ring_backup)
return -ENOMEM;
}
/* Allocate ring buffer */
if (ring->ring_obj == NULL) {
r = amdgpu_bo_create_kernel(adev, ring->ring_size + ring->funcs->extra_dw, PAGE_SIZE,
@ -342,6 +371,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
(void **)&ring->ring);
if (r) {
dev_err(adev->dev, "(%d) ring create failed\n", r);
kvfree(ring->ring_backup);
return r;
}
amdgpu_ring_clear_ring(ring);
@ -385,6 +415,8 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
amdgpu_bo_free_kernel(&ring->ring_obj,
&ring->gpu_addr,
(void **)&ring->ring);
kvfree(ring->ring_backup);
ring->ring_backup = NULL;
dma_fence_put(ring->vmid_wait);
ring->vmid_wait = NULL;
@ -427,6 +459,7 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
{
unsigned long flags;
ktime_t deadline;
bool ret;
if (unlikely(ring->adev->debug_disable_soft_recovery))
return false;
@ -441,12 +474,16 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
dma_fence_set_error(fence, -ENODATA);
spin_unlock_irqrestore(fence->lock, flags);
atomic_inc(&ring->adev->gpu_reset_counter);
while (!dma_fence_is_signaled(fence) &&
ktime_to_ns(ktime_sub(deadline, ktime_get())) > 0)
ring->funcs->soft_recovery(ring, vmid);
return dma_fence_is_signaled(fence);
ret = dma_fence_is_signaled(fence);
/* increment the counter only if soft reset worked */
if (ret)
atomic_inc(&ring->adev->gpu_reset_counter);
return ret;
}
/*
@ -682,6 +719,7 @@ static void amdgpu_ring_to_mqd_prop(struct amdgpu_ring *ring,
prop->eop_gpu_addr = ring->eop_gpu_addr;
prop->use_doorbell = ring->use_doorbell;
prop->doorbell_index = ring->doorbell_index;
prop->kernel_queue = true;
/* map_queues packet doesn't need activate the queue,
* so only kiq need set this field.
@ -753,3 +791,69 @@ bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring)
return true;
}
void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
struct amdgpu_fence *guilty_fence)
{
/* Stop the scheduler to prevent anybody else from touching the ring buffer. */
drm_sched_wqueue_stop(&ring->sched);
/* back up the non-guilty commands */
amdgpu_ring_backup_unprocessed_commands(ring, guilty_fence);
}
int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
struct amdgpu_fence *guilty_fence)
{
unsigned int i;
int r;
/* verify that the ring is functional */
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
/* signal the fence of the bad job */
if (guilty_fence)
amdgpu_fence_driver_guilty_force_completion(guilty_fence);
/* Re-emit the non-guilty commands */
if (ring->ring_backup_entries_to_copy) {
amdgpu_ring_alloc_reemit(ring, ring->ring_backup_entries_to_copy);
for (i = 0; i < ring->ring_backup_entries_to_copy; i++)
amdgpu_ring_write(ring, ring->ring_backup[i]);
amdgpu_ring_commit(ring);
}
/* Start the scheduler again */
drm_sched_wqueue_start(&ring->sched);
return 0;
}
bool amdgpu_ring_is_reset_type_supported(struct amdgpu_ring *ring,
u32 reset_type)
{
switch (ring->funcs->type) {
case AMDGPU_RING_TYPE_GFX:
if (ring->adev->gfx.gfx_supported_reset & reset_type)
return true;
break;
case AMDGPU_RING_TYPE_COMPUTE:
if (ring->adev->gfx.compute_supported_reset & reset_type)
return true;
break;
case AMDGPU_RING_TYPE_SDMA:
if (ring->adev->sdma.supported_reset & reset_type)
return true;
break;
case AMDGPU_RING_TYPE_VCN_DEC:
case AMDGPU_RING_TYPE_VCN_ENC:
if (ring->adev->vcn.supported_reset & reset_type)
return true;
break;
case AMDGPU_RING_TYPE_VCN_JPEG:
if (ring->adev->jpeg.supported_reset & reset_type)
return true;
break;
default:
break;
}
return false;
}

View File

@ -118,6 +118,7 @@ struct amdgpu_fence_driver {
/* sync_seq is protected by ring emission lock */
uint32_t sync_seq;
atomic_t last_seq;
u64 signalled_wptr;
bool initialized;
struct amdgpu_irq_src *irq_src;
unsigned irq_type;
@ -141,6 +142,12 @@ struct amdgpu_fence {
/* RB, DMA, etc. */
struct amdgpu_ring *ring;
ktime_t start_timestamp;
/* wptr for the fence for resets */
u64 wptr;
/* fence context for resets */
u64 context;
uint32_t seq;
};
extern const struct drm_sched_backend_ops amdgpu_sched_ops;
@ -148,6 +155,8 @@ extern const struct drm_sched_backend_ops amdgpu_sched_ops;
void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring);
void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error);
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *fence);
void amdgpu_fence_save_wptr(struct dma_fence *fence);
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
@ -284,6 +293,9 @@ struct amdgpu_ring {
struct amdgpu_bo *ring_obj;
uint32_t *ring;
/* backups for resets */
uint32_t *ring_backup;
unsigned int ring_backup_entries_to_copy;
unsigned rptr_offs;
u64 rptr_gpu_addr;
volatile u32 *rptr_cpu_addr;
@ -550,4 +562,12 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev);
void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring);
void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
struct amdgpu_fence *guilty_fence);
void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
struct amdgpu_fence *guilty_fence);
int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
struct amdgpu_fence *guilty_fence);
bool amdgpu_ring_is_reset_type_supported(struct amdgpu_ring *ring,
u32 reset_type);
#endif

View File

@ -545,10 +545,13 @@ static int amdgpu_sdma_soft_reset(struct amdgpu_device *adev, u32 instance_id)
* amdgpu_sdma_reset_engine - Reset a specific SDMA engine
* @adev: Pointer to the AMDGPU device
* @instance_id: Logical ID of the SDMA engine instance to reset
* @caller_handles_kernel_queues: Skip kernel queue processing. Caller
* will handle it.
*
* Returns: 0 on success, or a negative error code on failure.
*/
int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id,
bool caller_handles_kernel_queues)
{
int ret = 0;
struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];
@ -556,14 +559,17 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
struct amdgpu_ring *page_ring = &sdma_instance->page;
mutex_lock(&sdma_instance->engine_reset_mutex);
/* Stop the scheduler's work queue for the GFX and page rings if they are running.
* This ensures that no new tasks are submitted to the queues while
* the reset is in progress.
*/
drm_sched_wqueue_stop(&gfx_ring->sched);
if (adev->sdma.has_page_queue)
drm_sched_wqueue_stop(&page_ring->sched);
if (!caller_handles_kernel_queues) {
/* Stop the scheduler's work queue for the GFX and page rings if they are running.
* This ensures that no new tasks are submitted to the queues while
* the reset is in progress.
*/
drm_sched_wqueue_stop(&gfx_ring->sched);
if (adev->sdma.has_page_queue)
drm_sched_wqueue_stop(&page_ring->sched);
}
if (sdma_instance->funcs->stop_kernel_queue) {
sdma_instance->funcs->stop_kernel_queue(gfx_ring);
@ -585,14 +591,19 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
}
exit:
/* Restart the scheduler's work queue for the GFX and page rings
* if they were stopped by this function. This allows new tasks
* to be submitted to the queues after the reset is complete.
*/
if (!ret) {
drm_sched_wqueue_start(&gfx_ring->sched);
if (adev->sdma.has_page_queue)
drm_sched_wqueue_start(&page_ring->sched);
if (!caller_handles_kernel_queues) {
/* Restart the scheduler's work queue for the GFX and page rings
* if they were stopped by this function. This allows new tasks
* to be submitted to the queues after the reset is complete.
*/
if (!ret) {
amdgpu_fence_driver_force_completion(gfx_ring);
drm_sched_wqueue_start(&gfx_ring->sched);
if (adev->sdma.has_page_queue) {
amdgpu_fence_driver_force_completion(page_ring);
drm_sched_wqueue_start(&page_ring->sched);
}
}
}
mutex_unlock(&sdma_instance->engine_reset_mutex);

View File

@ -172,7 +172,8 @@ struct amdgpu_buffer_funcs {
uint32_t byte_count);
};
int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id);
int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id,
bool caller_handles_kernel_queues);
#define amdgpu_emit_copy_buffer(adev, ib, s, d, b, t) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b), (t))
#define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))

View File

@ -32,6 +32,7 @@
static const struct kicker_device kicker_device_list[] = {
{0x744B, 0x00},
{0x7551, 0xC8}
};
static void amdgpu_ucode_print_common_hdr(const struct common_firmware_header *hdr)

View File

@ -521,8 +521,10 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
}
queue_name = kasprintf(GFP_KERNEL, "queue-%d", qid);
if (!queue_name)
return -ENOMEM;
if (!queue_name) {
r = -ENOMEM;
goto unlock;
}
#if defined(CONFIG_DEBUG_FS)
/* Queue dentry per client to hold MQD information */
@ -719,7 +721,7 @@ static void amdgpu_userq_restore_worker(struct work_struct *work)
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
int ret;
flush_work(&fpriv->evf_mgr.suspend_work.work);
flush_delayed_work(&fpriv->evf_mgr.suspend_work);
mutex_lock(&uq_mgr->userq_mutex);

View File

@ -134,6 +134,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
mutex_init(&adev->vcn.inst[i].engine_reset_mutex);
atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
@ -1451,3 +1452,78 @@ int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
return ret;
}
/**
* amdgpu_vcn_reset_engine - Reset a specific VCN engine
* @adev: Pointer to the AMDGPU device
* @instance_id: VCN engine instance to reset
*
* Returns: 0 on success, or a negative error code on failure.
*/
static int amdgpu_vcn_reset_engine(struct amdgpu_device *adev,
uint32_t instance_id)
{
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[instance_id];
int r, i;
mutex_lock(&vinst->engine_reset_mutex);
/* Stop the scheduler's work queue for the dec and enc rings if they are running.
* This ensures that no new tasks are submitted to the queues while
* the reset is in progress.
*/
drm_sched_wqueue_stop(&vinst->ring_dec.sched);
for (i = 0; i < vinst->num_enc_rings; i++)
drm_sched_wqueue_stop(&vinst->ring_enc[i].sched);
/* Perform the VCN reset for the specified instance */
r = vinst->reset(vinst);
if (r)
goto unlock;
r = amdgpu_ring_test_ring(&vinst->ring_dec);
if (r)
goto unlock;
for (i = 0; i < vinst->num_enc_rings; i++) {
r = amdgpu_ring_test_ring(&vinst->ring_enc[i]);
if (r)
goto unlock;
}
amdgpu_fence_driver_force_completion(&vinst->ring_dec);
for (i = 0; i < vinst->num_enc_rings; i++)
amdgpu_fence_driver_force_completion(&vinst->ring_enc[i]);
/* Restart the scheduler's work queue for the dec and enc rings
* if they were stopped by this function. This allows new tasks
* to be submitted to the queues after the reset is complete.
*/
drm_sched_wqueue_start(&vinst->ring_dec.sched);
for (i = 0; i < vinst->num_enc_rings; i++)
drm_sched_wqueue_start(&vinst->ring_enc[i].sched);
unlock:
mutex_unlock(&vinst->engine_reset_mutex);
return r;
}
/**
* amdgpu_vcn_ring_reset - Reset a VCN ring
* @ring: ring to reset
* @vmid: vmid of guilty job
* @timedout_fence: fence of timed out job
*
* This helper is for VCN blocks without unified queues because
* resetting the engine resets all queues in that case. With
* unified queues we have one queue per engine.
* Returns: 0 on success, or a negative error code on failure.
*/
int amdgpu_vcn_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
if (adev->vcn.inst[ring->me].using_unified_queue)
return -EINVAL;
return amdgpu_vcn_reset_engine(adev, ring->me);
}

View File

@ -330,7 +330,9 @@ struct amdgpu_vcn_inst {
struct dpg_pause_state *new_state);
int (*set_pg_state)(struct amdgpu_vcn_inst *vinst,
enum amd_powergating_state state);
int (*reset)(struct amdgpu_vcn_inst *vinst);
bool using_unified_queue;
struct mutex engine_reset_mutex;
};
struct amdgpu_vcn_ras {
@ -552,5 +554,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev);
int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
enum amd_powergating_state state);
int amdgpu_vcn_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *guilty_fence);
#endif

View File

@ -152,8 +152,10 @@ enum AMDGIM_REG_ACCESS_FLAG {
AMDGIM_FEATURE_MMHUB_REG_RLC_EN = (1 << 1),
/* Use RLC to program GC regs */
AMDGIM_FEATURE_GC_REG_RLC_EN = (1 << 2),
/* Use PSP to program L1_TLB_CNTL*/
/* Use PSP to program L1_TLB_CNTL */
AMDGIM_FEATURE_L1_TLB_CNTL_PSP_EN = (1 << 3),
/* Use RLCG to program SQ_CONFIG1 */
AMDGIM_FEATURE_REG_ACCESS_SQ_CONFIG = (1 << 4),
};
struct amdgim_pf2vf_info_v1 {
@ -346,6 +348,10 @@ struct amdgpu_video_codec_info;
#define amdgpu_sriov_rlcg_error_report_enabled(adev) \
(amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev))
#define amdgpu_sriov_reg_access_sq_config(adev) \
(amdgpu_sriov_vf((adev)) && \
((adev)->virt.reg_access & (AMDGIM_FEATURE_REG_ACCESS_SQ_CONFIG)))
#define amdgpu_passthrough(adev) \
((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)

View File

@ -765,6 +765,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
bool cleaner_shader_needed = false;
bool pasid_mapping_needed = false;
struct dma_fence *fence = NULL;
struct amdgpu_fence *af;
unsigned int patch;
int r;
@ -830,6 +831,9 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
r = amdgpu_fence_emit(ring, &fence, NULL, 0);
if (r)
return r;
/* this is part of the job's context */
af = container_of(fence, struct amdgpu_fence, base);
af->context = job->base.s_fence ? job->base.s_fence->finished.context : 0;
}
if (vm_flush_needed) {
@ -2410,13 +2414,11 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
*/
long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
{
timeout = dma_resv_wait_timeout(vm->root.bo->tbo.base.resv,
DMA_RESV_USAGE_BOOKKEEP,
true, timeout);
timeout = drm_sched_entity_flush(&vm->immediate, timeout);
if (timeout <= 0)
return timeout;
return dma_fence_wait_timeout(vm->last_unlocked, true, timeout);
return drm_sched_entity_flush(&vm->delayed, timeout);
}
static void amdgpu_vm_destroy_task_info(struct kref *kref)

View File

@ -66,7 +66,10 @@ to_amdgpu_vram_mgr_resource(struct ttm_resource *res)
static inline void amdgpu_vram_mgr_set_cleared(struct ttm_resource *res)
{
to_amdgpu_vram_mgr_resource(res)->flags |= DRM_BUDDY_CLEARED;
struct amdgpu_vram_mgr_resource *ares = to_amdgpu_vram_mgr_resource(res);
WARN_ON(ares->flags & DRM_BUDDY_CLEARED);
ares->flags |= DRM_BUDDY_CLEARED;
}
#endif

View File

@ -218,15 +218,27 @@ int amdgpu_xcp_restore_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr)
return __amdgpu_xcp_switch_partition_mode(xcp_mgr, xcp_mgr->mode);
}
static bool __amdgpu_xcp_is_cached_mode_valid(struct amdgpu_xcp_mgr *xcp_mgr)
{
if (!xcp_mgr->funcs || !xcp_mgr->funcs->query_partition_mode)
return true;
if (!amdgpu_sriov_vf(xcp_mgr->adev) &&
xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
return true;
if (xcp_mgr->mode != AMDGPU_XCP_MODE_NONE &&
xcp_mgr->mode != AMDGPU_XCP_MODE_TRANS)
return true;
return false;
}
int amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
{
int mode;
if (!amdgpu_sriov_vf(xcp_mgr->adev) &&
xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
return xcp_mgr->mode;
if (!xcp_mgr->funcs || !xcp_mgr->funcs->query_partition_mode)
if (__amdgpu_xcp_is_cached_mode_valid(xcp_mgr))
return xcp_mgr->mode;
if (!(flags & AMDGPU_XCP_FL_LOCKED))

View File

@ -113,7 +113,8 @@ union amd_sriov_reg_access_flags {
uint32_t vf_reg_access_mmhub : 1;
uint32_t vf_reg_access_gc : 1;
uint32_t vf_reg_access_l1_tlb_cntl : 1;
uint32_t reserved : 28;
uint32_t vf_reg_access_sq_config : 1;
uint32_t reserved : 27;
} flags;
uint32_t all;
};

View File

@ -4952,11 +4952,15 @@ static int gfx_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
}
/* TODO: Add queue reset mask when FW fully supports it */
adev->gfx.gfx_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
adev->gfx.compute_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
if (!amdgpu_sriov_vf(adev)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
}
r = amdgpu_gfx_kiq_init(adev, GFX10_MEC_HPD_SIZE, 0);
if (r) {
@ -9046,21 +9050,6 @@ static void gfx_v10_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
ref, mask);
}
static void gfx_v10_0_ring_soft_recovery(struct amdgpu_ring *ring,
unsigned int vmid)
{
struct amdgpu_device *adev = ring->adev;
uint32_t value = 0;
value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
WREG32_SOC15(GC, 0, mmSQ_CMD, value);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void
gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
uint32_t me, uint32_t pipe,
@ -9534,17 +9523,14 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
u64 addr;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
if (amdgpu_ring_alloc(kiq_ring, 5 + 7 + 7 + kiq->pmf->map_queues_size)) {
if (amdgpu_ring_alloc(kiq_ring, 5 + 7 + 7)) {
spin_unlock_irqrestore(&kiq->ring_lock, flags);
return -ENOMEM;
}
@ -9564,12 +9550,9 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
0, 1, 0x20);
gfx_v10_0_ring_emit_reg_wait(kiq_ring,
SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), 0, 0xffffffff);
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
r = amdgpu_ring_test_ring(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
@ -9579,12 +9562,20 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
r = amdgpu_ring_test_ring(ring);
spin_lock_irqsave(&kiq->ring_lock, flags);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size)) {
spin_unlock_irqrestore(&kiq->ring_lock, flags);
return -ENOMEM;
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
r = amdgpu_ring_test_ring(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
@ -9597,13 +9588,10 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
unsigned long flags;
int i, r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@ -9615,9 +9603,8 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES,
0, 0);
amdgpu_ring_commit(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
r = amdgpu_ring_test_ring(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
@ -9653,18 +9640,12 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
r = amdgpu_ring_test_ring(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v10_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
@ -9899,7 +9880,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
.emit_wreg = gfx_v10_0_ring_emit_wreg,
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
.soft_recovery = gfx_v10_0_ring_soft_recovery,
.emit_mem_sync = gfx_v10_0_emit_mem_sync,
.reset = gfx_v10_0_reset_kgq,
.emit_cleaner_shader = gfx_v10_0_ring_emit_cleaner_shader,
@ -9940,7 +9920,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
.emit_wreg = gfx_v10_0_ring_emit_wreg,
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
.soft_recovery = gfx_v10_0_ring_soft_recovery,
.emit_mem_sync = gfx_v10_0_emit_mem_sync,
.reset = gfx_v10_0_reset_kcq,
.emit_cleaner_shader = gfx_v10_0_ring_emit_cleaner_shader,

View File

@ -1806,12 +1806,17 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
if ((adev->gfx.me_fw_version >= 2280) &&
(adev->gfx.mec_fw_version >= 2410)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
(adev->gfx.mec_fw_version >= 2410) &&
!amdgpu_sriov_vf(adev)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
}
break;
default:
if (!amdgpu_sriov_vf(adev)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
}
break;
}
@ -6283,21 +6288,6 @@ static void gfx_v11_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
ref, mask, 0x20);
}
static void gfx_v11_0_ring_soft_recovery(struct amdgpu_ring *ring,
unsigned vmid)
{
struct amdgpu_device *adev = ring->adev;
uint32_t value = 0;
value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
WREG32_SOC15(GC, 0, regSQ_CMD, value);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void
gfx_v11_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
uint32_t me, uint32_t pipe,
@ -6818,10 +6808,7 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
struct amdgpu_device *adev = ring->adev;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
if (r) {
@ -6844,12 +6831,7 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int gfx_v11_0_reset_compute_pipe(struct amdgpu_ring *ring)
@ -6989,10 +6971,7 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
struct amdgpu_device *adev = ring->adev;
int r = 0;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
@ -7013,12 +6992,7 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
return r;
}
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v11_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
@ -7254,7 +7228,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
.emit_wreg = gfx_v11_0_ring_emit_wreg,
.emit_reg_wait = gfx_v11_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v11_0_ring_emit_reg_write_reg_wait,
.soft_recovery = gfx_v11_0_ring_soft_recovery,
.emit_mem_sync = gfx_v11_0_emit_mem_sync,
.reset = gfx_v11_0_reset_kgq,
.emit_cleaner_shader = gfx_v11_0_ring_emit_cleaner_shader,
@ -7296,7 +7269,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_compute = {
.emit_wreg = gfx_v11_0_ring_emit_wreg,
.emit_reg_wait = gfx_v11_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v11_0_ring_emit_reg_write_reg_wait,
.soft_recovery = gfx_v11_0_ring_soft_recovery,
.emit_mem_sync = gfx_v11_0_emit_mem_sync,
.reset = gfx_v11_0_reset_kcq,
.emit_cleaner_shader = gfx_v11_0_ring_emit_cleaner_shader,

View File

@ -79,6 +79,7 @@ MODULE_FIRMWARE("amdgpu/gc_12_0_1_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_me.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc_kicker.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_toc.bin");
static const struct amdgpu_hwip_reg_entry gc_reg_list_12_0[] = {
@ -586,7 +587,7 @@ static int gfx_v12_0_init_toc_microcode(struct amdgpu_device *adev, const char *
static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
{
char ucode_prefix[15];
char ucode_prefix[30];
int err;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
uint16_t version_major;
@ -613,9 +614,14 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK);
if (!amdgpu_sriov_vf(adev)) {
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_rlc.bin", ucode_prefix);
if (amdgpu_is_kicker_fw(adev))
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_rlc_kicker.bin", ucode_prefix);
else
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_rlc.bin", ucode_prefix);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
@ -1542,10 +1548,14 @@ static int gfx_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
if ((adev->gfx.me_fw_version >= 2660) &&
(adev->gfx.mec_fw_version >= 2920)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
(adev->gfx.mec_fw_version >= 2920) &&
!amdgpu_sriov_vf(adev)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
}
break;
default:
break;
}
if (!adev->enable_mes_kiq) {
@ -4690,21 +4700,6 @@ static void gfx_v12_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
ref, mask, 0x20);
}
static void gfx_v12_0_ring_soft_recovery(struct amdgpu_ring *ring,
unsigned vmid)
{
struct amdgpu_device *adev = ring->adev;
uint32_t value = 0;
value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
WREG32_SOC15(GC, 0, regSQ_CMD, value);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void
gfx_v12_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
uint32_t me, uint32_t pipe,
@ -5314,10 +5309,7 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
struct amdgpu_device *adev = ring->adev;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
if (r) {
@ -5339,12 +5331,7 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring)
@ -5437,10 +5424,7 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
struct amdgpu_device *adev = ring->adev;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
@ -5461,12 +5445,7 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
return r;
}
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v12_0_ring_begin_use(struct amdgpu_ring *ring)
@ -5544,7 +5523,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
.soft_recovery = gfx_v12_0_ring_soft_recovery,
.emit_mem_sync = gfx_v12_0_emit_mem_sync,
.reset = gfx_v12_0_reset_kgq,
.emit_cleaner_shader = gfx_v12_0_ring_emit_cleaner_shader,
@ -5583,7 +5561,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_compute = {
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
.soft_recovery = gfx_v12_0_ring_soft_recovery,
.emit_mem_sync = gfx_v12_0_emit_mem_sync,
.reset = gfx_v12_0_reset_kcq,
.emit_cleaner_shader = gfx_v12_0_ring_emit_cleaner_shader,

View File

@ -4640,6 +4640,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring)
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation));
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
amdgpu_ring_clear_ring(ring);
}
return 0;

View File

@ -2410,6 +2410,8 @@ static int gfx_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
adev->gfx.compute_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
if (!amdgpu_sriov_vf(adev))
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_gfx_kiq_init(adev, GFX9_MEC_HPD_SIZE, 0);
if (r) {
@ -7181,13 +7183,10 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
unsigned long flags;
int i, r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@ -7238,19 +7237,13 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
r = amdgpu_ring_test_ring(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r) {
DRM_ERROR("fail to remap queue\n");
return r;
}
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v9_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)

View File

@ -1148,13 +1148,15 @@ static int gfx_v9_4_3_sw_init(struct amdgpu_ip_block *ip_block)
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 3):
case IP_VERSION(9, 4, 4):
if (adev->gfx.mec_fw_version >= 155) {
if ((adev->gfx.mec_fw_version >= 155) &&
!amdgpu_sriov_vf(adev)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_PIPE;
}
break;
case IP_VERSION(9, 5, 0):
if (adev->gfx.mec_fw_version >= 21) {
if ((adev->gfx.mec_fw_version >= 21) &&
!amdgpu_sriov_vf(adev)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_PIPE;
}
@ -1349,7 +1351,9 @@ static void gfx_v9_4_3_constants_init(struct amdgpu_device *adev)
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
/* ToDo: GC 9.4.4 */
case IP_VERSION(9, 4, 3):
if (adev->gfx.mec_fw_version >= 184)
if (adev->gfx.mec_fw_version >= 184 &&
(amdgpu_sriov_reg_access_sq_config(adev) ||
!amdgpu_sriov_vf(adev)))
adev->gmc.xnack_flags |= AMDGPU_GMC_XNACK_FLAG_CHAIN;
break;
case IP_VERSION(9, 5, 0):
@ -3561,13 +3565,10 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
unsigned long flags;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@ -3594,7 +3595,9 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
dev_err(adev->dev, "fail to wait on hqd deactive and will try pipe reset\n");
pipe_reset:
if(r) {
if (r) {
if (!(adev->gfx.compute_supported_reset & AMDGPU_RESET_TYPE_PER_PIPE))
return -EOPNOTSUPP;
r = gfx_v9_4_3_reset_hw_pipe(ring);
dev_info(adev->dev, "ring: %s pipe reset :%s\n", ring->name,
r ? "failed" : "successfully");
@ -3615,20 +3618,14 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
r = amdgpu_ring_test_ring(kiq_ring);
spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r) {
dev_err(adev->dev, "fail to remap queue\n");
return r;
}
r = amdgpu_ring_test_ring(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
enum amdgpu_gfx_cp_ras_mem_id {

View File

@ -1121,8 +1121,8 @@ static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level,
}
static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
struct amdgpu_bo *bo,
struct amdgpu_bo_va_mapping *mapping,
uint64_t *flags)
{
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
@ -1132,7 +1132,6 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
AMDGPU_GEM_CREATE_EXT_COHERENT);
bool ext_coherent = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENT;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
uint32_t gc_ip_version = amdgpu_ip_version(adev, GC_HWIP, 0);
bool snoop = false;
@ -1162,7 +1161,7 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
mtype = MTYPE_UC;
else
mtype = MTYPE_NC;
if (mapping->bo_va->is_xgmi)
if (amdgpu_xgmi_same_hive(adev, bo_adev))
snoop = true;
}
} else {
@ -1254,7 +1253,8 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
}
if ((*flags & AMDGPU_PTE_VALID) && bo)
gmc_v9_0_get_coherence_flags(adev, bo, mapping, flags);
gmc_v9_0_get_coherence_flags(adev, mapping->bo_va->base.vm, bo,
flags);
}
static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,

View File

@ -34,12 +34,13 @@
MODULE_FIRMWARE("amdgpu/gc_12_0_0_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu_kicker.bin");
#define TRANSFER_RAM_MASK 0x001c0000
static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
{
char ucode_prefix[15];
char ucode_prefix[30];
int err;
const struct imu_firmware_header_v1_0 *imu_hdr;
struct amdgpu_firmware_info *info = NULL;
@ -47,8 +48,12 @@ static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
DRM_DEBUG("\n");
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_imu.bin", ucode_prefix);
if (amdgpu_is_kicker_fw(adev))
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_imu_kicker.bin", ucode_prefix);
else
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_imu.bin", ucode_prefix);
if (err)
goto out;
@ -362,7 +367,7 @@ static void program_imu_rlc_ram(struct amdgpu_device *adev,
static void imu_v12_0_program_rlc_ram(struct amdgpu_device *adev)
{
u32 reg_data, size = 0;
const u32 *data;
const u32 *data = NULL;
int r = -EINVAL;
WREG32_SOC15(GC, 0, regGFX_IMU_RLC_RAM_INDEX, 0x2);

View File

@ -183,15 +183,16 @@ static int isp_genpd_remove_device(struct device *dev, void *data)
static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
{
const struct software_node *amd_camera_node, *isp4_node;
struct amdgpu_device *adev = isp->adev;
struct acpi_device *acpi_dev;
int idx, int_idx, num_res, r;
u8 isp_dev_hid[ACPI_ID_LEN];
u64 isp_base;
if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
return -EINVAL;
r = amdgpu_acpi_get_isp4_dev_hid(&isp_dev_hid);
r = amdgpu_acpi_get_isp4_dev(&acpi_dev);
if (r) {
drm_dbg(&adev->ddev, "Invalid isp platform detected (%d)", r);
/* allow GPU init to progress */
@ -199,7 +200,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
}
/* add GPIO resources required for OMNI5C10 sensor */
if (!strcmp("OMNI5C10", isp_dev_hid)) {
if (!strcmp("OMNI5C10", acpi_device_hid(acpi_dev))) {
gpiod_add_lookup_table(&isp_gpio_table);
gpiod_add_lookup_table(&isp_sensor_gpio_table);
}
@ -241,6 +242,9 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
goto failure;
}
amd_camera_node = (const struct software_node *)acpi_dev->driver_data;
isp4_node = software_node_find_by_name(amd_camera_node, "isp4");
/* initialize isp platform data */
isp->isp_pdata->adev = (void *)adev;
isp->isp_pdata->asic_type = adev->asic_type;
@ -269,6 +273,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
isp->isp_cell[0].num_resources = num_res;
isp->isp_cell[0].resources = &isp->isp_res[0];
isp->isp_cell[0].platform_data = isp->isp_pdata;
isp->isp_cell[0].swnode = isp4_node;
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
/* initialize isp i2c platform data */

View File

@ -118,7 +118,10 @@ static int jpeg_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(adev->jpeg.inst[0].ring_dec);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
return r;
@ -770,15 +773,14 @@ static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring,
{
int r;
drm_sched_wqueue_stop(&ring->sched);
jpeg_v2_0_stop(ring->adev);
jpeg_v2_0_start(ring->adev);
r = amdgpu_ring_test_helper(ring);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v2_0_stop(ring->adev);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
r = jpeg_v2_0_start(ring->adev);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {

View File

@ -167,7 +167,10 @@ static int jpeg_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(adev->jpeg.inst[0].ring_dec);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
return r;
@ -647,17 +650,10 @@ static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
int r;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v2_5_stop_inst(ring->adev, ring->me);
jpeg_v2_5_start_inst(ring->adev, ring->me);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {

View File

@ -132,7 +132,10 @@ static int jpeg_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(adev->jpeg.inst[0].ring_dec);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
return r;
@ -561,15 +564,14 @@ static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring,
{
int r;
drm_sched_wqueue_stop(&ring->sched);
jpeg_v3_0_stop(ring->adev);
jpeg_v3_0_start(ring->adev);
r = amdgpu_ring_test_helper(ring);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v3_0_stop(ring->adev);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
r = jpeg_v3_0_start(ring->adev);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {

View File

@ -143,7 +143,10 @@ static int jpeg_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(adev->jpeg.inst[0].ring_dec);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
return r;
@ -726,18 +729,14 @@ static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring,
{
int r;
if (amdgpu_sriov_vf(ring->adev))
return -EINVAL;
drm_sched_wqueue_stop(&ring->sched);
jpeg_v4_0_stop(ring->adev);
jpeg_v4_0_start(ring->adev);
r = amdgpu_ring_test_helper(ring);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v4_0_stop(ring->adev);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
r = jpeg_v4_0_start(ring->adev);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {

View File

@ -216,12 +216,11 @@ static int jpeg_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
if (!amdgpu_sriov_vf(adev)) {
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
if (r)
return r;
}
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(adev->jpeg.inst[0].ring_dec);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
return 0;
}
@ -242,8 +241,7 @@ static int jpeg_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
if (!amdgpu_sriov_vf(adev))
amdgpu_jpeg_sysfs_reset_mask_fini(adev);
amdgpu_jpeg_sysfs_reset_mask_fini(adev);
r = amdgpu_jpeg_sw_fini(adev);
@ -1147,20 +1145,13 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
int r;
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v4_0_3_core_stall_reset(ring);
jpeg_v4_0_3_start_jrbc(ring);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {

View File

@ -174,9 +174,10 @@ static int jpeg_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
/* TODO: Add queue reset mask when FW fully supports it */
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
if (r)
return r;
@ -767,6 +768,22 @@ static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev,
return 0;
}
static int jpeg_v4_0_5_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
int r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v4_0_5_stop(ring->adev);
if (r)
return r;
r = jpeg_v4_0_5_start(ring->adev);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {
.name = "jpeg_v4_0_5",
.early_init = jpeg_v4_0_5_early_init,
@ -812,6 +829,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = {
.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = jpeg_v4_0_5_ring_reset,
};
static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)

View File

@ -120,13 +120,13 @@ static int jpeg_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
/* TODO: Add queue reset mask when FW fully supports it */
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
if (r)
return r;
return 0;
return r;
}
/**
@ -644,6 +644,22 @@ static int jpeg_v5_0_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
static int jpeg_v5_0_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
int r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = jpeg_v5_0_0_stop(ring->adev);
if (r)
return r;
r = jpeg_v5_0_0_start(ring->adev);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = {
.name = "jpeg_v5_0_0",
.early_init = jpeg_v5_0_0_early_init,
@ -689,6 +705,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = {
.emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
.emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = jpeg_v5_0_0_ring_reset,
};
static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev)

View File

@ -200,14 +200,13 @@ static int jpeg_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
if (!amdgpu_sriov_vf(adev)) {
adev->jpeg.supported_reset = AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
if (r)
return r;
}
adev->jpeg.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
if (!amdgpu_sriov_vf(adev))
adev->jpeg.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
return 0;
return r;
}
/**
@ -226,8 +225,7 @@ static int jpeg_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
if (!amdgpu_sriov_vf(adev))
amdgpu_jpeg_sysfs_reset_mask_fini(adev);
amdgpu_jpeg_sysfs_reset_mask_fini(adev);
r = amdgpu_jpeg_sw_fini(adev);
@ -838,20 +836,10 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
int r;
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v5_0_1_core_stall_reset(ring);
jpeg_v5_0_1_init_jrbc(ring);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {

View File

@ -37,39 +37,31 @@
static const char *mmhub_client_ids_v4_1_0[][2] = {
[0][0] = "VMC",
[4][0] = "DCEDMC",
[5][0] = "DCEVGA",
[6][0] = "MP0",
[7][0] = "MP1",
[8][0] = "MPIO",
[16][0] = "HDP",
[17][0] = "LSDMA",
[18][0] = "JPEG",
[19][0] = "VCNU0",
[21][0] = "VSCH",
[22][0] = "VCNU1",
[23][0] = "VCN1",
[32+20][0] = "VCN0",
[2][1] = "DBGUNBIO",
[16][0] = "LSDMA",
[17][0] = "JPEG",
[19][0] = "VCNU",
[22][0] = "VSCH",
[23][0] = "HDP",
[32+23][0] = "VCNRD",
[3][1] = "DCEDWB",
[4][1] = "DCEDMC",
[5][1] = "DCEVGA",
[6][1] = "MP0",
[7][1] = "MP1",
[8][1] = "MPIO",
[10][1] = "DBGU0",
[11][1] = "DBGU1",
[12][1] = "DBGU2",
[13][1] = "DBGU3",
[12][1] = "DBGUNBIO",
[14][1] = "XDP",
[15][1] = "OSSSYS",
[16][1] = "HDP",
[17][1] = "LSDMA",
[18][1] = "JPEG",
[19][1] = "VCNU0",
[20][1] = "VCN0",
[21][1] = "VSCH",
[22][1] = "VCNU1",
[23][1] = "VCN1",
[16][1] = "LSDMA",
[17][1] = "JPEG",
[18][1] = "VCNWR",
[19][1] = "VCNU",
[22][1] = "VSCH",
[23][1] = "HDP",
};
static uint32_t mmhub_v4_1_0_get_invalidate_req(unsigned int vmid,

View File

@ -94,7 +94,7 @@ static int psp_v10_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
return ret;
}
@ -115,7 +115,7 @@ static int psp_v10_0_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
return ret;
}

View File

@ -152,11 +152,9 @@ static int psp_v11_0_wait_for_bootloader(struct psp_context *psp)
for (retry_loop = 0; retry_loop < 10; retry_loop++) {
/* Wait for bootloader to signify that is
ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000,
0x80000000,
false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
return 0;
@ -252,8 +250,8 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
0, true);
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81), 0,
PSP_WAITREG_CHANGED);
return ret;
}
@ -279,11 +277,11 @@ static int psp_v11_0_ring_stop(struct psp_context *psp,
if (amdgpu_sriov_vf(adev))
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
else
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
return ret;
}
@ -321,13 +319,13 @@ static int psp_v11_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_101 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_ERROR("Failed to wait for sOS ready for ring creation\n");
return ret;
@ -353,7 +351,7 @@ static int psp_v11_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -387,7 +385,7 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp)
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64);
ret = psp_wait_for(psp, offset, MBOX_TOS_READY_FLAG,
MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_INFO("psp is not working correctly before mode1 reset!\n");
@ -402,7 +400,7 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp)
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33);
ret = psp_wait_for(psp, offset, MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK,
false);
0);
if (ret) {
DRM_INFO("psp mode 1 reset failed!\n");
@ -428,8 +426,9 @@ static int psp_v11_0_memory_training_send_msg(struct psp_context *psp, int msg)
max_wait = MEM_TRAIN_SEND_MSG_TIMEOUT_US / adev->usec_timeout;
for (i = 0; i < max_wait; i++) {
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
break;
}
@ -608,7 +607,7 @@ static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -645,7 +644,7 @@ static int psp_v11_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver)
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (!ret)
*fw_ver = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36);

View File

@ -43,7 +43,7 @@ static int psp_v11_0_8_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
@ -53,7 +53,7 @@ static int psp_v11_0_8_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -91,13 +91,13 @@ static int psp_v11_0_8_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_101 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
return ret;
@ -123,7 +123,7 @@ static int psp_v11_0_8_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;

View File

@ -82,7 +82,7 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -97,7 +97,7 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
psp_gfxdrv_command_reg);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
return ret;
}
@ -118,7 +118,7 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp)
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -133,8 +133,8 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp)
psp_gfxdrv_command_reg);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
0, true);
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81), 0,
PSP_WAITREG_CHANGED);
return ret;
}
@ -163,7 +163,7 @@ static int psp_v12_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
return ret;
}
@ -186,11 +186,11 @@ static int psp_v12_0_ring_stop(struct psp_context *psp,
if (amdgpu_sriov_vf(adev))
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
else
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
return ret;
}
@ -222,7 +222,7 @@ static int psp_v12_0_mode1_reset(struct psp_context *psp)
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64);
ret = psp_wait_for(psp, offset, MBOX_TOS_READY_FLAG,
MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_INFO("psp is not working correctly before mode1 reset!\n");
@ -237,7 +237,7 @@ static int psp_v12_0_mode1_reset(struct psp_context *psp)
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33);
ret = psp_wait_for(psp, offset, MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK,
false);
0);
if (ret) {
DRM_INFO("psp mode 1 reset failed!\n");

View File

@ -182,7 +182,7 @@ static int psp_v13_0_wait_for_vmbx_ready(struct psp_context *psp)
ready having bit 31 of C2PMSG_33 set to 1 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_33),
0x80000000, 0xffffffff, false);
0x80000000, 0xffffffff, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
break;
@ -213,7 +213,7 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp)
for (retry_loop = 0; retry_loop < retry_cnt; retry_loop++) {
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0xffffffff, false);
0x80000000, 0xffffffff, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
return 0;
@ -362,8 +362,8 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81),
0, true);
RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81), 0,
PSP_WAITREG_CHANGED);
if (!ret)
psp_v13_0_init_sos_version(psp);
@ -386,7 +386,7 @@ static int psp_v13_0_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_64,
@ -396,7 +396,7 @@ static int psp_v13_0_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -434,13 +434,13 @@ static int psp_v13_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_101 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_64),
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
return ret;
@ -466,7 +466,7 @@ static int psp_v13_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -529,8 +529,9 @@ static int psp_v13_0_memory_training_send_msg(struct psp_context *psp, int msg)
max_wait = MEM_TRAIN_SEND_MSG_TIMEOUT_US / adev->usec_timeout;
for (i = 0; i < max_wait; i++) {
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
break;
}
@ -682,7 +683,7 @@ static int psp_v13_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -719,7 +720,7 @@ static int psp_v13_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver)
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (!ret)
*fw_ver = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36);
@ -744,8 +745,9 @@ static int psp_v13_0_exec_spi_cmd(struct psp_context *psp, int cmd)
ret = psp_wait_for_spirom_update(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, PSP_SPIROM_UPDATE_TIMEOUT);
else
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, 0);
if (ret) {
dev_err(adev->dev, "SPI cmd %x timed out, ret = %d", cmd, ret);
return ret;
@ -769,7 +771,7 @@ static int psp_v13_0_update_spirom(struct psp_context *psp,
/* Confirm PSP is ready to start */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, false);
MBOX_READY_FLAG, MBOX_READY_MASK, 0);
if (ret) {
dev_err(adev->dev, "PSP Not ready to start processing, ret = %d", ret);
return ret;
@ -804,7 +806,7 @@ static int psp_v13_0_dump_spirom(struct psp_context *psp,
/* Confirm PSP is ready to start */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, false);
MBOX_READY_FLAG, MBOX_READY_MASK, 0);
if (ret) {
dev_err(adev->dev, "PSP Not ready to start processing, ret = %d", ret);
return ret;
@ -931,8 +933,9 @@ static int psp_v13_0_reg_program_no_ring(struct psp_context *psp, uint32_t val,
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_102, id);
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_103, val);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_101),
0x80000000, 0x80000000, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_101),
0x80000000, 0x80000000, 0);
}
return ret;

View File

@ -76,11 +76,9 @@ static int psp_v13_0_4_wait_for_bootloader(struct psp_context *psp)
for (retry_loop = 0; retry_loop < 10; retry_loop++) {
/* Wait for bootloader to signify that is
ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000,
0x80000000,
false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
return 0;
@ -185,8 +183,8 @@ static int psp_v13_0_4_bootloader_load_sos(struct psp_context *psp)
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81),
0, true);
RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81), 0,
PSP_WAITREG_CHANGED);
return ret;
}
@ -206,7 +204,7 @@ static int psp_v13_0_4_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_64,
@ -216,7 +214,7 @@ static int psp_v13_0_4_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -254,13 +252,13 @@ static int psp_v13_0_4_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_101 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_64),
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
return ret;
@ -286,7 +284,7 @@ static int psp_v13_0_4_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;

View File

@ -34,7 +34,9 @@
MODULE_FIRMWARE("amdgpu/psp_14_0_2_sos.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_2_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos_kicker.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta_kicker.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_5_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_14_0_5_ta.bin");
@ -109,11 +111,9 @@ static int psp_v14_0_wait_for_bootloader(struct psp_context *psp)
for (retry_loop = 0; retry_loop < 10; retry_loop++) {
/* Wait for bootloader to signify that is
ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000,
0x80000000,
false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
return 0;
@ -228,9 +228,10 @@ static int psp_v14_0_bootloader_load_sos(struct psp_context *psp)
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81),
0, true);
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81), 0,
PSP_WAITREG_CHANGED);
return ret;
}
@ -250,7 +251,7 @@ static int psp_v14_0_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64,
@ -260,7 +261,7 @@ static int psp_v14_0_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -298,13 +299,13 @@ static int psp_v14_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_101 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_101),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, 0);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
return ret;
@ -330,7 +331,7 @@ static int psp_v14_0_ring_create(struct psp_context *psp,
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, 0);
}
return ret;
@ -393,8 +394,9 @@ static int psp_v14_0_memory_training_send_msg(struct psp_context *psp, int msg)
max_wait = MEM_TRAIN_SEND_MSG_TIMEOUT_US / adev->usec_timeout;
for (i = 0; i < max_wait; i++) {
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
if (ret == 0)
break;
}
@ -545,8 +547,9 @@ static int psp_v14_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc
*/
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20));
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -582,8 +585,9 @@ static int psp_v14_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver)
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_35),
0x80000000, 0x80000000, 0);
if (!ret)
*fw_ver = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_36);
@ -607,11 +611,13 @@ static int psp_v14_0_exec_spi_cmd(struct psp_context *psp, int cmd)
ret = psp_wait_for_spirom_update(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, PSP_SPIROM_UPDATE_TIMEOUT);
else
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, 0);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, false);
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, 0);
if (ret) {
dev_err(adev->dev, "SPI cmd %x timed out, ret = %d", cmd, ret);
return ret;
@ -634,8 +640,9 @@ static int psp_v14_0_update_spirom(struct psp_context *psp,
int ret;
/* Confirm PSP is ready to start */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, false);
ret = psp_wait_for(psp,
SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_115),
MBOX_READY_FLAG, MBOX_READY_MASK, 0);
if (ret) {
dev_err(adev->dev, "PSP Not ready to start processing, ret = %d", ret);
return ret;

View File

@ -91,7 +91,7 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -109,7 +109,7 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
mdelay(20);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
return ret;
}
@ -130,7 +130,7 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
0x80000000, 0x80000000, 0);
if (ret)
return ret;
@ -147,8 +147,8 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
0, true);
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81), 0,
PSP_WAITREG_CHANGED);
return ret;
}
@ -168,7 +168,7 @@ static void psp_v3_1_reroute_ih(struct psp_context *psp)
mdelay(20);
psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
0x80000000, 0x8000FFFF, false);
0x80000000, 0x8000FFFF, 0);
/* Change IH ring for UMC */
tmp = REG_SET_FIELD(0, IH_CLIENT_CFG_DATA, CREDIT_RETURN_ADDR, 0x1216b);
@ -180,7 +180,7 @@ static void psp_v3_1_reroute_ih(struct psp_context *psp)
mdelay(20);
psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
0x80000000, 0x8000FFFF, false);
0x80000000, 0x8000FFFF, 0);
}
static int psp_v3_1_ring_create(struct psp_context *psp,
@ -217,9 +217,9 @@ static int psp_v3_1_ring_create(struct psp_context *psp,
mdelay(20);
/* Wait for response flag (bit 31) in C2PMSG_101 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0,
mmMP0_SMN_C2PMSG_101), 0x80000000,
0x8000FFFF, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
0x80000000, 0x8000FFFF, 0);
} else {
/* Write low address of the ring to C2PMSG_69 */
@ -240,10 +240,9 @@ static int psp_v3_1_ring_create(struct psp_context *psp,
mdelay(20);
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0,
mmMP0_SMN_C2PMSG_64), 0x80000000,
0x8000FFFF, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
0x80000000, 0x8000FFFF, 0);
}
return ret;
}
@ -267,11 +266,13 @@ static int psp_v3_1_ring_stop(struct psp_context *psp,
/* Wait for response flag (bit 31) */
if (amdgpu_sriov_vf(adev))
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
0x80000000, 0x80000000, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
0x80000000, 0x80000000, 0);
else
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
0x80000000, 0x80000000, false);
ret = psp_wait_for(
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
0x80000000, 0x80000000, 0);
return ret;
}
@ -311,7 +312,7 @@ static int psp_v3_1_mode1_reset(struct psp_context *psp)
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64);
ret = psp_wait_for(psp, offset, 0x80000000, 0x8000FFFF, false);
ret = psp_wait_for(psp, offset, 0x80000000, 0x8000FFFF, 0);
if (ret) {
DRM_INFO("psp is not working correctly before mode1 reset!\n");
@ -325,7 +326,7 @@ static int psp_v3_1_mode1_reset(struct psp_context *psp)
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33);
ret = psp_wait_for(psp, offset, 0x80000000, 0x80000000, false);
ret = psp_wait_for(psp, offset, 0x80000000, 0x80000000, 0);
if (ret) {
DRM_INFO("psp mode 1 reset failed!\n");

View File

@ -1664,11 +1664,8 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring,
u32 id = ring->me;
int r;
if (!(adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, id);
r = amdgpu_sdma_reset_engine(adev, id, false);
amdgpu_amdkfd_resume(adev, true);
return r;
}
@ -1714,7 +1711,7 @@ static int sdma_v4_4_2_stop_queue(struct amdgpu_ring *ring)
static int sdma_v4_4_2_restore_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u32 inst_mask, tmp_mask;
u32 inst_mask;
int i, r;
inst_mask = 1 << ring->me;
@ -1733,21 +1730,6 @@ static int sdma_v4_4_2_restore_queue(struct amdgpu_ring *ring)
}
r = sdma_v4_4_2_inst_start(adev, inst_mask, true);
if (r)
return r;
tmp_mask = inst_mask;
for_each_inst(i, tmp_mask) {
ring = &adev->sdma.instance[i].ring;
amdgpu_fence_driver_force_completion(ring);
if (adev->sdma.has_page_queue) {
struct amdgpu_ring *page = &adev->sdma.instance[i].page;
amdgpu_fence_driver_force_completion(page);
}
}
return r;
}

View File

@ -1428,7 +1428,8 @@ static int sdma_v5_0_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(5, 0, 0):
case IP_VERSION(5, 0, 2):
case IP_VERSION(5, 0, 5):
if (adev->sdma.instance[0].fw_version >= 35)
if ((adev->sdma.instance[0].fw_version >= 35) &&
!amdgpu_sriov_vf(adev))
adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
break;
default:
@ -1544,14 +1545,22 @@ static int sdma_v5_0_reset_queue(struct amdgpu_ring *ring,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 inst_id = ring->me;
int r;
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, inst_id);
amdgpu_amdkfd_resume(adev, true);
if (ring->me >= adev->sdma.num_instances) {
dev_err(adev->dev, "sdma instance not found\n");
return -EINVAL;
}
return r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, ring->me, true);
amdgpu_amdkfd_resume(adev, true);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int sdma_v5_0_stop_queue(struct amdgpu_ring *ring)
@ -1618,10 +1627,8 @@ static int sdma_v5_0_restore_queue(struct amdgpu_ring *ring)
r = sdma_v5_0_gfx_resume_instance(adev, inst_id, true);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
return 0;
return r;
}
static int sdma_v5_0_ring_preempt_ib(struct amdgpu_ring *ring)

View File

@ -1347,11 +1347,13 @@ static int sdma_v5_2_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(5, 2, 2):
case IP_VERSION(5, 2, 3):
case IP_VERSION(5, 2, 4):
if (adev->sdma.instance[0].fw_version >= 76)
if ((adev->sdma.instance[0].fw_version >= 76) &&
!amdgpu_sriov_vf(adev))
adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
break;
case IP_VERSION(5, 2, 5):
if (adev->sdma.instance[0].fw_version >= 34)
if ((adev->sdma.instance[0].fw_version >= 34) &&
!amdgpu_sriov_vf(adev))
adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
break;
default:
@ -1457,14 +1459,22 @@ static int sdma_v5_2_reset_queue(struct amdgpu_ring *ring,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 inst_id = ring->me;
int r;
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, inst_id);
amdgpu_amdkfd_resume(adev, true);
if (ring->me >= adev->sdma.num_instances) {
dev_err(adev->dev, "sdma instance not found\n");
return -EINVAL;
}
return r;
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, ring->me, true);
amdgpu_amdkfd_resume(adev, true);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int sdma_v5_2_stop_queue(struct amdgpu_ring *ring)
@ -1534,10 +1544,8 @@ static int sdma_v5_2_restore_queue(struct amdgpu_ring *ring)
r = sdma_v5_2_gfx_resume_instance(adev, inst_id, true);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
return 0;
return r;
}
static int sdma_v5_2_ring_preempt_ib(struct amdgpu_ring *ring)

View File

@ -1355,7 +1355,8 @@ static int sdma_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(6, 0, 0):
case IP_VERSION(6, 0, 2):
case IP_VERSION(6, 0, 3):
if (adev->sdma.instance[0].fw_version >= 21)
if ((adev->sdma.instance[0].fw_version >= 21) &&
!amdgpu_sriov_vf(adev))
adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
break;
default:
@ -1575,33 +1576,24 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int i, r;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
for (i = 0; i < adev->sdma.num_instances; i++) {
if (ring == &adev->sdma.instance[i].ring)
break;
}
if (i == adev->sdma.num_instances) {
DRM_ERROR("sdma instance not found\n");
if (ring->me >= adev->sdma.num_instances) {
dev_err(adev->dev, "sdma instance not found\n");
return -EINVAL;
}
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
if (r)
return r;
r = sdma_v6_0_gfx_resume_instance(adev, i, true);
r = sdma_v6_0_gfx_resume_instance(adev, ring->me, true);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int sdma_v6_0_set_trap_irq_state(struct amdgpu_device *adev,

View File

@ -807,33 +807,24 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int i, r;
int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
for (i = 0; i < adev->sdma.num_instances; i++) {
if (ring == &adev->sdma.instance[i].ring)
break;
}
if (i == adev->sdma.num_instances) {
DRM_ERROR("sdma instance not found\n");
if (ring->me >= adev->sdma.num_instances) {
dev_err(adev->dev, "sdma instance not found\n");
return -EINVAL;
}
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
if (r)
return r;
r = sdma_v7_0_gfx_resume_instance(adev, i, true);
r = sdma_v7_0_gfx_resume_instance(adev, ring->me, true);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
/**
@ -1346,7 +1337,8 @@ static int sdma_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->sdma.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->sdma.instance[0].ring);
adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (!amdgpu_sriov_vf(adev))
adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_sdma_sysfs_reset_mask_init(adev);
if (r)

View File

@ -98,6 +98,8 @@ static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state);
static int vcn_v2_0_start_sriov(struct amdgpu_device *adev);
static int vcn_v2_0_reset(struct amdgpu_vcn_inst *vinst);
/**
* vcn_v2_0_early_init - set function pointers and load microcode
*
@ -213,6 +215,12 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
}
adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
adev->vcn.inst[0].reset = vcn_v2_0_reset;
adev->vcn.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
if (!amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@ -233,6 +241,10 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
r = amdgpu_vcn_sysfs_reset_mask_init(adev);
if (r)
return r;
return 0;
}
@ -260,6 +272,8 @@ static int vcn_v2_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev, 0);
kfree(adev->vcn.ip_dump);
@ -1355,6 +1369,16 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
return 0;
}
static int vcn_v2_0_reset(struct amdgpu_vcn_inst *vinst)
{
int r;
r = vcn_v2_0_stop(vinst);
if (r)
return r;
return vcn_v2_0_start(vinst);
}
static bool vcn_v2_0_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@ -2176,6 +2200,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = amdgpu_vcn_ring_reset,
};
static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
@ -2205,6 +2230,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = amdgpu_vcn_ring_reset,
};
static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)

View File

@ -102,6 +102,7 @@ static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state);
static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev);
static int vcn_v2_5_reset(struct amdgpu_vcn_inst *vinst);
static int amdgpu_ih_clientid_vcns[] = {
SOC15_IH_CLIENTID_VCN,
@ -404,8 +405,14 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.inst[j].pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
adev->vcn.inst[j].reset = vcn_v2_5_reset;
}
adev->vcn.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
if (!amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@ -425,6 +432,10 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
r = amdgpu_vcn_sysfs_reset_mask_init(adev);
if (r)
return r;
return 0;
}
@ -455,6 +466,8 @@ static int vcn_v2_5_sw_fini(struct amdgpu_ip_block *ip_block)
if (amdgpu_sriov_vf(adev))
amdgpu_virt_free_mm_table(adev);
amdgpu_vcn_sysfs_reset_mask_fini(adev);
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
r = amdgpu_vcn_suspend(adev, i);
if (r)
@ -1816,6 +1829,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_dec_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = amdgpu_vcn_ring_reset,
};
/**
@ -1914,6 +1928,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_enc_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = amdgpu_vcn_ring_reset,
};
static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
@ -1942,6 +1957,16 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
}
}
static int vcn_v2_5_reset(struct amdgpu_vcn_inst *vinst)
{
int r;
r = vcn_v2_5_stop(vinst);
if (r)
return r;
return vcn_v2_5_start(vinst);
}
static bool vcn_v2_5_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;

View File

@ -110,6 +110,7 @@ static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
enum amd_powergating_state state);
static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state);
static int vcn_v3_0_reset(struct amdgpu_vcn_inst *vinst);
static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring);
static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
@ -289,8 +290,14 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
adev->vcn.inst[i].reset = vcn_v3_0_reset;
}
adev->vcn.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
if (!amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@ -306,6 +313,10 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
r = amdgpu_vcn_sysfs_reset_mask_init(adev);
if (r)
return r;
return 0;
}
@ -338,6 +349,8 @@ static int vcn_v3_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (amdgpu_sriov_vf(adev))
amdgpu_virt_free_mm_table(adev);
amdgpu_vcn_sysfs_reset_mask_fini(adev);
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
r = amdgpu_vcn_suspend(adev, i);
if (r)
@ -2033,6 +2046,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = amdgpu_vcn_ring_reset,
};
/**
@ -2131,6 +2145,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_enc_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = amdgpu_vcn_ring_reset,
};
static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
@ -2164,6 +2179,18 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
}
}
static int vcn_v3_0_reset(struct amdgpu_vcn_inst *vinst)
{
int r;
r = vcn_v3_0_stop(vinst);
if (r)
return r;
vcn_v3_0_enable_clock_gating(vinst);
vcn_v3_0_enable_static_power_gating(vinst);
return vcn_v3_0_start(vinst);
}
static bool vcn_v3_0_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;

View File

@ -241,7 +241,8 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (!amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
@ -1975,19 +1976,14 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
drm_sched_wqueue_stop(&ring->sched);
vcn_v4_0_stop(vinst);
vcn_v4_0_start(vinst);
r = amdgpu_ring_test_helper(ring);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = vcn_v4_0_stop(vinst);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
r = vcn_v4_0_start(vinst);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {

View File

@ -1603,13 +1603,7 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
drm_sched_wqueue_stop(&ring->sched);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
vcn_inst = GET_INST(VCN, ring->me);
r = amdgpu_dpm_reset_vcn(adev, 1 << vcn_inst);
@ -1624,12 +1618,8 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
adev->vcn.caps |= AMDGPU_VCN_CAPS(RRMT_ENABLED);
vcn_v4_0_3_hw_init_inst(vinst);
vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {

View File

@ -220,7 +220,8 @@ static int vcn_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
}
adev->vcn.supported_reset = amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (!amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
r = amdgpu_vcn_sysfs_reset_mask_init(adev);
if (r)
@ -1473,19 +1474,14 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
drm_sched_wqueue_stop(&ring->sched);
vcn_v4_0_5_stop(vinst);
vcn_v4_0_5_start(vinst);
r = amdgpu_ring_test_helper(ring);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = vcn_v4_0_5_stop(vinst);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
r = vcn_v4_0_5_start(vinst);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {

View File

@ -198,7 +198,8 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
if (!amdgpu_sriov_vf(adev))
adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
vcn_v5_0_0_alloc_ip_dump(adev);
@ -1200,19 +1201,14 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
drm_sched_wqueue_stop(&ring->sched);
vcn_v5_0_0_stop(vinst);
vcn_v5_0_0_start(vinst);
r = amdgpu_ring_test_helper(ring);
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = vcn_v5_0_0_stop(vinst);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
drm_sched_wqueue_start(&ring->sched);
return 0;
r = vcn_v5_0_0_start(vinst);
if (r)
return r;
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = {

View File

@ -5,7 +5,7 @@
config HSA_AMD
bool "HSA kernel driver for AMD GPU devices"
depends on DRM_AMDGPU && (X86_64 || ARM64 || PPC64 || (RISCV && 64BIT))
depends on DRM_AMDGPU && (X86_64 || ARM64 || PPC64 || (RISCV && 64BIT) || (LOONGARCH && 64BIT))
select HMM_MIRROR
select MMU_NOTIFIER
select DRM_AMDGPU_USERPTR

View File

@ -2312,7 +2312,7 @@ static int reset_hung_queues_sdma(struct device_queue_manager *dqm)
continue;
/* Reset engine and check. */
if (amdgpu_sdma_reset_engine(dqm->dev->adev, i) ||
if (amdgpu_sdma_reset_engine(dqm->dev->adev, i, false) ||
dqm->dev->kfd2kgd->hqd_sdma_get_doorbell(dqm->dev->adev, i, j) ||
!set_sdma_queue_as_reset(dqm, doorbell_off)) {
r = -ENOTRECOVERABLE;
@ -2339,9 +2339,18 @@ static int reset_hung_queues_sdma(struct device_queue_manager *dqm)
static int reset_queues_on_hws_hang(struct device_queue_manager *dqm, bool is_sdma)
{
struct amdgpu_device *adev = dqm->dev->adev;
while (halt_if_hws_hang)
schedule();
if (adev->debug_disable_gpu_ring_reset) {
dev_info_once(adev->dev,
"%s queue hung, but ring reset disabled",
is_sdma ? "sdma" : "compute");
return -EPERM;
}
if (!amdgpu_gpu_recovery)
return -ENOTRECOVERABLE;

View File

@ -3398,8 +3398,10 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
link_enc_cfg_copy(adev->dm.dc->current_state, dc_state);
r = dm_dmub_hw_init(adev);
if (r)
if (r) {
drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r);
return r;
}
dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0);
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
@ -4983,9 +4985,9 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
caps = &dm->backlight_caps[aconnector->bl_idx];
if (get_brightness_range(caps, &min, &max)) {
if (power_supply_is_system_supplied() > 0)
props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->ac_level, 100);
props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->ac_level, 100);
else
props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->dc_level, 100);
props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->dc_level, 100);
/* min is zero, so max needs to be adjusted */
props.max_brightness = max - min;
drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max,
@ -5410,7 +5412,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
{
drm_atomic_private_obj_fini(&dm->atomic_obj);
if (dm->atomic_obj.state)
drm_atomic_private_obj_fini(&dm->atomic_obj);
}
/******************************************************************************
@ -7901,7 +7904,8 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
int clock, bpp = 0;
bool is_y420 = false;
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
enum drm_mode_status result;
@ -8374,7 +8378,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
drm_add_modes_noedid(connector, 1920, 1080);
} else {
amdgpu_dm_connector_ddc_get_modes(connector, drm_edid);
if (encoder && connector->connector_type != DRM_MODE_CONNECTOR_eDP)
if (encoder && (connector->connector_type != DRM_MODE_CONNECTOR_eDP) &&
(connector->connector_type != DRM_MODE_CONNECTOR_LVDS))
amdgpu_dm_connector_add_common_modes(encoder, connector);
amdgpu_dm_connector_add_freesync_modes(connector, drm_edid);
}

View File

@ -728,7 +728,16 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
* support programmable degamma anywhere.
*/
is_dcn = dm->adev->dm.dc->caps.color.dpp.dcn_arch;
drm_crtc_enable_color_mgmt(&acrtc->base, is_dcn ? MAX_COLOR_LUT_ENTRIES : 0,
/* Dont't enable DRM CRTC degamma property for DCN401 since the
* pre-blending degamma LUT doesn't apply to cursor, and therefore
* can't work similar to a post-blending degamma LUT as in other hw
* versions.
* TODO: revisit it once KMS plane color API is merged.
*/
drm_crtc_enable_color_mgmt(&acrtc->base,
(is_dcn &&
dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01) ?
MAX_COLOR_LUT_ENTRIES : 0,
true, MAX_COLOR_LUT_ENTRIES);
drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);

View File

@ -3988,7 +3988,7 @@ static int capabilities_show(struct seq_file *m, void *unused)
struct hubbub *hubbub = dc->res_pool->hubbub;
if (hubbub->funcs->get_mall_en)
if (hubbub && hubbub->funcs->get_mall_en)
hubbub->funcs->get_mall_en(hubbub, &mall_in_use);
if (dc->cap_funcs.get_subvp_en)

View File

@ -92,9 +92,9 @@ enum dm_micro_swizzle {
MICRO_SWIZZLE_R = 3
};
const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
const struct drm_format_info *amdgpu_dm_plane_get_format_info(u32 pixel_format, u64 modifier)
{
return amdgpu_lookup_format_info(cmd->pixel_format, cmd->modifier[0]);
return amdgpu_lookup_format_info(pixel_format, modifier);
}
void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,

View File

@ -58,7 +58,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
unsigned long possible_crtcs,
const struct dc_plane_cap *plane_cap);
const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
const struct drm_format_info *amdgpu_dm_plane_get_format_info(u32 pixel_format, u64 modifier);
void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
bool *per_pixel_alpha, bool *pre_multiplied_alpha,

View File

@ -119,8 +119,10 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream)
psr_config.allow_multi_disp_optimizations =
(amdgpu_dc_feature_mask & DC_PSR_ALLOW_MULTI_DISP_OPT);
if (!psr_su_set_dsc_slice_height(dc, link, stream, &psr_config))
return false;
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
if (!psr_su_set_dsc_slice_height(dc, link, stream, &psr_config))
return false;
}
ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context);

View File

@ -112,7 +112,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
###############################################################################
# DCN30
###############################################################################
CLK_MGR_DCN30 = dcn30_clk_mgr.o dcn30_clk_mgr_smu_msg.o
CLK_MGR_DCN30 = dcn30_clk_mgr.o dcn30_clk_mgr_smu_msg.o dcn30m_clk_mgr.o dcn30m_clk_mgr_smu_msg.o
AMD_DAL_CLK_MGR_DCN30 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn30/,$(CLK_MGR_DCN30))

View File

@ -67,7 +67,7 @@ int clk_mgr_helper_get_active_display_cnt(
if (dc_state_get_stream_subvp_type(context, stream) == SUBVP_PHANTOM)
continue;
if (!stream->dpms_off || (stream_status && stream_status->plane_count))
if (!stream->dpms_off || dc->is_switch_in_progress_dest || (stream_status && stream_status->plane_count))
display_count++;
}

View File

@ -56,6 +56,7 @@
#define DALSMC_MSG_SetDisplayRefreshFromMall 0xF
#define DALSMC_MSG_SetExternalClientDfCstateAllow 0x10
#define DALSMC_MSG_BacoAudioD3PME 0x11
#define DALSMC_Message_Count 0x12
#define DALSMC_MSG_SmartAccess 0x12
#define DALSMC_Message_Count 0x13
#endif

View File

@ -30,6 +30,7 @@
#include "dce100/dce_clk_mgr.h"
#include "dcn30/dcn30_clk_mgr.h"
#include "dml/dcn30/dcn30_fpu.h"
#include "dcn30/dcn30m_clk_mgr.h"
#include "reg_helper.h"
#include "core_types.h"
#include "dm_helpers.h"
@ -498,7 +499,8 @@ static struct clk_mgr_funcs dcn3_funcs = {
.are_clock_states_equal = dcn3_are_clock_states_equal,
.enable_pme_wa = dcn3_enable_pme_wa,
.notify_link_rate_change = dcn30_notify_link_rate_change,
.is_smu_present = dcn3_is_smu_present
.is_smu_present = dcn3_is_smu_present,
.set_smartmux_switch = dcn30m_set_smartmux_switch
};
static void dcn3_init_clocks_fpga(struct clk_mgr *clk_mgr)

View File

@ -0,0 +1,36 @@
/*
* Copyright 2019 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "clk_mgr_internal.h"
#include "dcn30/dcn30m_clk_mgr.h"
#include "dcn30m_clk_mgr_smu_msg.h"
uint32_t dcn30m_set_smartmux_switch(struct clk_mgr *clk_mgr_base, uint32_t pins_to_set)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
return dcn30m_smu_set_smart_mux_switch(clk_mgr, pins_to_set);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2019 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DCN30M_CLK_MGR_H__
#define __DCN30M_CLK_MGR_H__
uint32_t dcn30m_set_smartmux_switch(struct clk_mgr *clk_mgr_base, uint32_t pins_to_set);
#endif //__DCN30M_CLK_MGR_H__

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