mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 02:53:36 +02:00
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:
commit
220994d61c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -58,12 +58,6 @@ properties:
|
|||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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
|
||||
----------------------
|
||||
|
|
|
|||
61
Documentation/gpu/nova/core/devinit.rst
Normal file
61
Documentation/gpu/nova/core/devinit.rst
Normal 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.
|
||||
158
Documentation/gpu/nova/core/falcon.rst
Normal file
158
Documentation/gpu/nova/core/falcon.rst
Normal 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) | |
|
||||
| | +---------------+ +------------+ |
|
||||
| +---------------------------------------+
|
||||
+-----------------------------------------------------+
|
||||
181
Documentation/gpu/nova/core/fwsec.rst
Normal file
181
Documentation/gpu/nova/core/fwsec.rst
Normal 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).
|
||||
|
|
@ -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
|
||||
-------------------
|
||||
|
||||
|
|
|
|||
181
Documentation/gpu/nova/core/vbios.rst
Normal file
181
Documentation/gpu/nova/core/vbios.rst
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
===============================
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
Loading…
Reference in New Issue
Block a user