Merge 8d0749b4f8
("Merge tag 'drm-next-2022-01-07' of git://anongit.freedesktop.org/drm/drm") into android-mainline
Steps on the way to 5.17-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I887d1805ee3597eb12b69894a11f01c785f6be0f
This commit is contained in:
commit
fa8445fc05
8
.mailmap
8
.mailmap
@ -10,10 +10,12 @@
|
|||||||
# Please keep this list dictionary sorted.
|
# Please keep this list dictionary sorted.
|
||||||
#
|
#
|
||||||
Aaron Durbin <adurbin@google.com>
|
Aaron Durbin <adurbin@google.com>
|
||||||
|
Abhinav Kumar <quic_abhinavk@quicinc.com> <abhinavk@codeaurora.org>
|
||||||
Adam Oldham <oldhamca@gmail.com>
|
Adam Oldham <oldhamca@gmail.com>
|
||||||
Adam Radford <aradford@gmail.com>
|
Adam Radford <aradford@gmail.com>
|
||||||
Adriana Reus <adi.reus@gmail.com> <adriana.reus@intel.com>
|
Adriana Reus <adi.reus@gmail.com> <adriana.reus@intel.com>
|
||||||
Adrian Bunk <bunk@stusta.de>
|
Adrian Bunk <bunk@stusta.de>
|
||||||
|
Akhil P Oommen <quic_akhilpo@quicinc.com> <akhilpo@codeaurora.org>
|
||||||
Alan Cox <alan@lxorguk.ukuu.org.uk>
|
Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||||
Alan Cox <root@hraefn.swansea.linux.org.uk>
|
Alan Cox <root@hraefn.swansea.linux.org.uk>
|
||||||
Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com>
|
Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com>
|
||||||
@ -172,6 +174,7 @@ Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com>
|
|||||||
Jens Axboe <axboe@suse.de>
|
Jens Axboe <axboe@suse.de>
|
||||||
Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
|
Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
|
||||||
Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
|
Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
|
||||||
|
Jessica Zhang <quic_jesszhan@quicinc.com> <jesszhan@codeaurora.org>
|
||||||
Jiri Slaby <jirislaby@kernel.org> <jirislaby@gmail.com>
|
Jiri Slaby <jirislaby@kernel.org> <jirislaby@gmail.com>
|
||||||
Jiri Slaby <jirislaby@kernel.org> <jslaby@novell.com>
|
Jiri Slaby <jirislaby@kernel.org> <jslaby@novell.com>
|
||||||
Jiri Slaby <jirislaby@kernel.org> <jslaby@suse.com>
|
Jiri Slaby <jirislaby@kernel.org> <jslaby@suse.com>
|
||||||
@ -191,6 +194,7 @@ Juha Yrjola <at solidboot.com>
|
|||||||
Juha Yrjola <juha.yrjola@nokia.com>
|
Juha Yrjola <juha.yrjola@nokia.com>
|
||||||
Juha Yrjola <juha.yrjola@solidboot.com>
|
Juha Yrjola <juha.yrjola@solidboot.com>
|
||||||
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
|
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
|
||||||
|
Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org>
|
||||||
Kay Sievers <kay.sievers@vrfy.org>
|
Kay Sievers <kay.sievers@vrfy.org>
|
||||||
Kees Cook <keescook@chromium.org> <kees.cook@canonical.com>
|
Kees Cook <keescook@chromium.org> <kees.cook@canonical.com>
|
||||||
Kees Cook <keescook@chromium.org> <keescook@google.com>
|
Kees Cook <keescook@chromium.org> <keescook@google.com>
|
||||||
@ -202,9 +206,11 @@ Kenneth W Chen <kenneth.w.chen@intel.com>
|
|||||||
Konstantin Khlebnikov <koct9i@gmail.com> <khlebnikov@yandex-team.ru>
|
Konstantin Khlebnikov <koct9i@gmail.com> <khlebnikov@yandex-team.ru>
|
||||||
Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
|
Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
|
||||||
Koushik <raghavendra.koushik@neterion.com>
|
Koushik <raghavendra.koushik@neterion.com>
|
||||||
|
Krishna Manikandan <quic_mkrishn@quicinc.com> <mkrishn@codeaurora.org>
|
||||||
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski.k@gmail.com>
|
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski.k@gmail.com>
|
||||||
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com>
|
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com>
|
||||||
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||||
|
Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org>
|
||||||
Leonardo Bras <leobras.c@gmail.com> <leonardo@linux.ibm.com>
|
Leonardo Bras <leobras.c@gmail.com> <leonardo@linux.ibm.com>
|
||||||
Leonid I Ananiev <leonid.i.ananiev@intel.com>
|
Leonid I Ananiev <leonid.i.ananiev@intel.com>
|
||||||
Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
|
Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
|
||||||
@ -311,6 +317,7 @@ Qais Yousef <qsyousef@gmail.com> <qais.yousef@imgtec.com>
|
|||||||
Quentin Monnet <quentin@isovalent.com> <quentin.monnet@netronome.com>
|
Quentin Monnet <quentin@isovalent.com> <quentin.monnet@netronome.com>
|
||||||
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
||||||
Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
|
Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
|
||||||
|
Rajeev Nandan <quic_rajeevny@quicinc.com> <rajeevny@codeaurora.org>
|
||||||
Rajesh Shah <rajesh.shah@intel.com>
|
Rajesh Shah <rajesh.shah@intel.com>
|
||||||
Ralf Baechle <ralf@linux-mips.org>
|
Ralf Baechle <ralf@linux-mips.org>
|
||||||
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||||
@ -325,6 +332,7 @@ Rui Saraiva <rmps@joel.ist.utl.pt>
|
|||||||
Sachin P Sant <ssant@in.ibm.com>
|
Sachin P Sant <ssant@in.ibm.com>
|
||||||
Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
|
Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
|
||||||
Sam Ravnborg <sam@mars.ravnborg.org>
|
Sam Ravnborg <sam@mars.ravnborg.org>
|
||||||
|
Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org>
|
||||||
Santosh Shilimkar <santosh.shilimkar@oracle.org>
|
Santosh Shilimkar <santosh.shilimkar@oracle.org>
|
||||||
Santosh Shilimkar <ssantosh@kernel.org>
|
Santosh Shilimkar <ssantosh@kernel.org>
|
||||||
Sarangdhar Joshi <spjoshi@codeaurora.org>
|
Sarangdhar Joshi <spjoshi@codeaurora.org>
|
||||||
|
@ -3555,6 +3555,13 @@
|
|||||||
shutdown the other cpus. Instead use the REBOOT_VECTOR
|
shutdown the other cpus. Instead use the REBOOT_VECTOR
|
||||||
irq.
|
irq.
|
||||||
|
|
||||||
|
nomodeset Disable kernel modesetting. DRM drivers will not perform
|
||||||
|
display-mode changes or accelerated rendering. Only the
|
||||||
|
system framebuffer will be available for use if this was
|
||||||
|
set-up by the firmware or boot loader.
|
||||||
|
|
||||||
|
Useful as fallback, or for testing and debugging.
|
||||||
|
|
||||||
nomodule Disable module load
|
nomodule Disable module load
|
||||||
|
|
||||||
nopat [X86] Disable PAT (page attribute table extension of
|
nopat [X86] Disable PAT (page attribute table extension of
|
||||||
|
@ -43,14 +43,70 @@ properties:
|
|||||||
vdd33-supply:
|
vdd33-supply:
|
||||||
description: Regulator that provides the supply 3.3V power.
|
description: Regulator that provides the supply 3.3V power.
|
||||||
|
|
||||||
|
analogix,lane0-swing:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 20
|
||||||
|
description:
|
||||||
|
an array of swing register setting for DP tx lane0 PHY.
|
||||||
|
Registers 0~9 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
|
||||||
|
Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
|
||||||
|
Swing1_Pre2, Swing0_Pre3, they are for [Boost control] and
|
||||||
|
[Swing control] setting.
|
||||||
|
Registers 0~9, bit 3:0 is [Boost control], these bits control
|
||||||
|
post cursor manual, increase the [Boost control] to increase
|
||||||
|
Pre-emphasis value.
|
||||||
|
Registers 0~9, bit 6:4 is [Swing control], these bits control
|
||||||
|
swing manual, increase [Swing control] setting to add Vp-p value
|
||||||
|
for each Swing, Pre.
|
||||||
|
Registers 10~19 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
|
||||||
|
Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
|
||||||
|
Swing1_Pre2, Swing0_Pre3, they are for [R select control] and
|
||||||
|
[R Termination control] setting.
|
||||||
|
Registers 10~19, bit 4:0 is [R select control], these bits are
|
||||||
|
compensation manual, increase it can enhance IO driven strength
|
||||||
|
and Vp-p.
|
||||||
|
Registers 10~19, bit 5:6 is [R termination control], these bits
|
||||||
|
adjust 50ohm impedance of DP tx termination. 00:55 ohm,
|
||||||
|
01:50 ohm(default), 10:45 ohm, 11:40 ohm.
|
||||||
|
|
||||||
|
analogix,lane1-swing:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 20
|
||||||
|
description:
|
||||||
|
an array of swing register setting for DP tx lane1 PHY.
|
||||||
|
DP TX lane1 swing register setting same with lane0
|
||||||
|
swing, please refer lane0-swing property description.
|
||||||
|
|
||||||
|
analogix,audio-enable:
|
||||||
|
type: boolean
|
||||||
|
description: let the driver enable audio HDMI codec function or not.
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
$ref: /schemas/graph.yaml#/properties/ports
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
port@0:
|
port@0:
|
||||||
$ref: /schemas/graph.yaml#/properties/port
|
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||||
|
unevaluatedProperties: false
|
||||||
description:
|
description:
|
||||||
Video port for MIPI DSI input.
|
MIPI DSI/DPI input.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
endpoint:
|
||||||
|
$ref: /schemas/media/video-interfaces.yaml#
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
remote-endpoint: true
|
||||||
|
|
||||||
|
bus-type:
|
||||||
|
enum: [1, 5]
|
||||||
|
default: 1
|
||||||
|
|
||||||
|
data-lanes: true
|
||||||
|
|
||||||
port@1:
|
port@1:
|
||||||
$ref: /schemas/graph.yaml#/properties/port
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
@ -87,6 +143,9 @@ examples:
|
|||||||
vdd10-supply = <&pp1000_mipibrdg>;
|
vdd10-supply = <&pp1000_mipibrdg>;
|
||||||
vdd18-supply = <&pp1800_mipibrdg>;
|
vdd18-supply = <&pp1800_mipibrdg>;
|
||||||
vdd33-supply = <&pp3300_mipibrdg>;
|
vdd33-supply = <&pp3300_mipibrdg>;
|
||||||
|
analogix,audio-enable;
|
||||||
|
analogix,lane0-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
|
||||||
|
analogix,lane1-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
|
||||||
|
|
||||||
ports {
|
ports {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
@ -96,6 +155,8 @@ examples:
|
|||||||
reg = <0>;
|
reg = <0>;
|
||||||
anx7625_in: endpoint {
|
anx7625_in: endpoint {
|
||||||
remote-endpoint = <&mipi_dsi>;
|
remote-endpoint = <&mipi_dsi>;
|
||||||
|
bus-type = <5>;
|
||||||
|
data-lanes = <0 1 2 3>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,6 +79,14 @@ properties:
|
|||||||
- port@0
|
- port@0
|
||||||
- port@1
|
- port@1
|
||||||
|
|
||||||
|
pclk-sample:
|
||||||
|
description:
|
||||||
|
Data sampling on rising or falling edge.
|
||||||
|
enum:
|
||||||
|
- 0 # Falling edge
|
||||||
|
- 1 # Rising edge
|
||||||
|
default: 0
|
||||||
|
|
||||||
powerdown-gpios:
|
powerdown-gpios:
|
||||||
description:
|
description:
|
||||||
The GPIO used to control the power down line of this device.
|
The GPIO used to control the power down line of this device.
|
||||||
@ -86,21 +94,32 @@ properties:
|
|||||||
|
|
||||||
power-supply: true
|
power-supply: true
|
||||||
|
|
||||||
if:
|
allOf:
|
||||||
not:
|
- if:
|
||||||
properties:
|
not:
|
||||||
compatible:
|
properties:
|
||||||
contains:
|
compatible:
|
||||||
const: lvds-decoder
|
contains:
|
||||||
then:
|
const: lvds-decoder
|
||||||
properties:
|
then:
|
||||||
ports:
|
|
||||||
properties:
|
properties:
|
||||||
port@0:
|
ports:
|
||||||
properties:
|
properties:
|
||||||
endpoint:
|
port@0:
|
||||||
properties:
|
properties:
|
||||||
data-mapping: false
|
endpoint:
|
||||||
|
properties:
|
||||||
|
data-mapping: false
|
||||||
|
|
||||||
|
- if:
|
||||||
|
not:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: lvds-encoder
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
pclk-sample: false
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/bridge/nxp,ptn3460.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: NXP PTN3460 eDP to LVDS bridge
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Sean Paul <seanpaul@chromium.org>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: nxp,ptn3460
|
||||||
|
|
||||||
|
reg:
|
||||||
|
description: I2C address of the bridge
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
edid-emulation:
|
||||||
|
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||||
|
description:
|
||||||
|
The EDID emulation entry to use
|
||||||
|
Value Resolution Description
|
||||||
|
0 1024x768 NXP Generic
|
||||||
|
1 1920x1080 NXP Generic
|
||||||
|
2 1920x1080 NXP Generic
|
||||||
|
3 1600x900 Samsung LTM200KT
|
||||||
|
4 1920x1080 Samsung LTM230HT
|
||||||
|
5 1366x768 NXP Generic
|
||||||
|
6 1600x900 ChiMei M215HGE
|
||||||
|
enum: [0, 1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
|
powerdown-gpios:
|
||||||
|
description: GPIO connected to the PD_N signal.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description: GPIO connected to the RST_N signal.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
Video port for LVDS output
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
Video port for eDP input
|
||||||
|
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
- port@1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- edid-emulation
|
||||||
|
- powerdown-gpios
|
||||||
|
- reset-gpios
|
||||||
|
- ports
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
i2c1 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
bridge@20 {
|
||||||
|
compatible = "nxp,ptn3460";
|
||||||
|
reg = <0x20>;
|
||||||
|
edid-emulation = <5>;
|
||||||
|
powerdown-gpios = <&gpy2 5 GPIO_ACTIVE_HIGH>;
|
||||||
|
reset-gpios = <&gpx1 5 GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
bridge_out: endpoint {
|
||||||
|
remote-endpoint = <&panel_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
bridge_in: endpoint {
|
||||||
|
remote-endpoint = <&dp_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -1,39 +0,0 @@
|
|||||||
ptn3460 bridge bindings
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: "nxp,ptn3460"
|
|
||||||
- reg: i2c address of the bridge
|
|
||||||
- powerdown-gpio: OF device-tree gpio specification for PD_N pin.
|
|
||||||
- reset-gpio: OF device-tree gpio specification for RST_N pin.
|
|
||||||
- edid-emulation: The EDID emulation entry to use
|
|
||||||
+-------+------------+------------------+
|
|
||||||
| Value | Resolution | Description |
|
|
||||||
| 0 | 1024x768 | NXP Generic |
|
|
||||||
| 1 | 1920x1080 | NXP Generic |
|
|
||||||
| 2 | 1920x1080 | NXP Generic |
|
|
||||||
| 3 | 1600x900 | Samsung LTM200KT |
|
|
||||||
| 4 | 1920x1080 | Samsung LTM230HT |
|
|
||||||
| 5 | 1366x768 | NXP Generic |
|
|
||||||
| 6 | 1600x900 | ChiMei M215HGE |
|
|
||||||
+-------+------------+------------------+
|
|
||||||
|
|
||||||
- video interfaces: Device node can contain video interface port
|
|
||||||
nodes for panel according to [1].
|
|
||||||
|
|
||||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
|
||||||
|
|
||||||
Example:
|
|
||||||
lvds-bridge@20 {
|
|
||||||
compatible = "nxp,ptn3460";
|
|
||||||
reg = <0x20>;
|
|
||||||
powerdown-gpio = <&gpy2 5 1 0 0>;
|
|
||||||
reset-gpio = <&gpx1 5 1 0 0>;
|
|
||||||
edid-emulation = <5>;
|
|
||||||
ports {
|
|
||||||
port@0 {
|
|
||||||
bridge_out: endpoint {
|
|
||||||
remote-endpoint = <&panel_in>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
@ -0,0 +1,118 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/bridge/renesas,dsi-csi2-tx.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Renesas R-Car MIPI DSI/CSI-2 Encoder
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
This binding describes the MIPI DSI/CSI-2 encoder embedded in the Renesas
|
||||||
|
R-Car V3U SoC. The encoder can operate in either DSI or CSI-2 mode, with up
|
||||||
|
to four data lanes.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- renesas,r8a779a0-dsi-csi2-tx # for V3U
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: Functional clock
|
||||||
|
- description: DSI (and CSI-2) functional clock
|
||||||
|
- description: PLL reference clock
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: fck
|
||||||
|
- const: dsi
|
||||||
|
- const: pll
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
resets:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description: Parallel input port
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||||
|
unevaluatedProperties: false
|
||||||
|
description: DSI/CSI-2 output port
|
||||||
|
|
||||||
|
properties:
|
||||||
|
endpoint:
|
||||||
|
$ref: /schemas/media/video-interfaces.yaml#
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
data-lanes:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
|
required:
|
||||||
|
- data-lanes
|
||||||
|
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
- port@1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- clocks
|
||||||
|
- power-domains
|
||||||
|
- resets
|
||||||
|
- ports
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
|
||||||
|
#include <dt-bindings/power/r8a779a0-sysc.h>
|
||||||
|
|
||||||
|
dsi0: dsi-encoder@fed80000 {
|
||||||
|
compatible = "renesas,r8a779a0-dsi-csi2-tx";
|
||||||
|
reg = <0xfed80000 0x10000>;
|
||||||
|
power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
|
||||||
|
clocks = <&cpg CPG_MOD 415>,
|
||||||
|
<&cpg CPG_CORE R8A779A0_CLK_DSI>,
|
||||||
|
<&cpg CPG_CORE R8A779A0_CLK_CP>;
|
||||||
|
clock-names = "fck", "dsi", "pll";
|
||||||
|
resets = <&cpg 415>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
dsi0_in: endpoint {
|
||||||
|
remote-endpoint = <&du_out_dsi0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
dsi0_out: endpoint {
|
||||||
|
data-lanes = <1 2>;
|
||||||
|
remote-endpoint = <&sn65dsi86_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
@ -1,49 +0,0 @@
|
|||||||
Silicon Image SiI9234 HDMI/MHL bridge bindings
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible : "sil,sii9234".
|
|
||||||
- reg : I2C address for TPI interface, use 0x39
|
|
||||||
- avcc33-supply : MHL/USB Switch Supply Voltage (3.3V)
|
|
||||||
- iovcc18-supply : I/O Supply Voltage (1.8V)
|
|
||||||
- avcc12-supply : TMDS Analog Supply Voltage (1.2V)
|
|
||||||
- cvcc12-supply : Digital Core Supply Voltage (1.2V)
|
|
||||||
- interrupts: interrupt specifier of INT pin
|
|
||||||
- reset-gpios: gpio specifier of RESET pin (active low)
|
|
||||||
- video interfaces: Device node can contain two video interface port
|
|
||||||
nodes for HDMI encoder and connector according to [1].
|
|
||||||
- port@0 - MHL to HDMI
|
|
||||||
- port@1 - MHL to connector
|
|
||||||
|
|
||||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
|
||||||
|
|
||||||
|
|
||||||
Example:
|
|
||||||
sii9234@39 {
|
|
||||||
compatible = "sil,sii9234";
|
|
||||||
reg = <0x39>;
|
|
||||||
avcc33-supply = <&vcc33mhl>;
|
|
||||||
iovcc18-supply = <&vcc18mhl>;
|
|
||||||
avcc12-supply = <&vsil12>;
|
|
||||||
cvcc12-supply = <&vsil12>;
|
|
||||||
reset-gpios = <&gpf3 4 GPIO_ACTIVE_LOW>;
|
|
||||||
interrupt-parent = <&gpf3>;
|
|
||||||
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
|
|
||||||
ports {
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
|
|
||||||
port@0 {
|
|
||||||
reg = <0>;
|
|
||||||
mhl_to_hdmi: endpoint {
|
|
||||||
remote-endpoint = <&hdmi_to_mhl>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
port@1 {
|
|
||||||
reg = <1>;
|
|
||||||
mhl_to_connector: endpoint {
|
|
||||||
remote-endpoint = <&connector_to_mhl>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
@ -0,0 +1,110 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/bridge/sil,sii9234.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Silicon Image SiI9234 HDMI/MHL bridge
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Maciej Purski <m.purski@samsung.com>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: sil,sii9234
|
||||||
|
|
||||||
|
reg:
|
||||||
|
description: I2C address for TPI interface
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
avcc12-supply:
|
||||||
|
description: TMDS Analog Supply Voltage, 1.2V
|
||||||
|
|
||||||
|
avcc33-supply:
|
||||||
|
description: MHL/USB Switch Supply Voltage, 3.3V
|
||||||
|
|
||||||
|
cvcc12-supply:
|
||||||
|
description: Digital Core Supply Voltage, 1.2V
|
||||||
|
|
||||||
|
iovcc18-supply:
|
||||||
|
description: I/O voltage supply, 1.8V
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description: GPIO connected to the reset pin.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
Video port for HDMI (encoder) input
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
MHL to connector port
|
||||||
|
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- avcc12-supply
|
||||||
|
- avcc33-supply
|
||||||
|
- cvcc12-supply
|
||||||
|
- iovcc18-supply
|
||||||
|
- interrupts
|
||||||
|
- reset-gpios
|
||||||
|
- ports
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
|
||||||
|
i2c1 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
bridge@39 {
|
||||||
|
compatible = "sil,sii9234";
|
||||||
|
reg = <0x39>;
|
||||||
|
avcc12-supply = <&vsil12>;
|
||||||
|
avcc33-supply = <&vcc33mhl>;
|
||||||
|
cvcc12-supply = <&vsil12>;
|
||||||
|
iovcc18-supply = <&vcc18mhl>;
|
||||||
|
interrupt-parent = <&gpf3>;
|
||||||
|
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
reset-gpios = <&gpf3 4 GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
mhl_to_hdmi: endpoint {
|
||||||
|
remote-endpoint = <&hdmi_to_mhl>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
mhl_to_connector: endpoint {
|
||||||
|
remote-endpoint = <&connector_to_mhl>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -17,6 +17,8 @@ properties:
|
|||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
- qcom,sc7180-dp
|
- qcom,sc7180-dp
|
||||||
|
- qcom,sc7280-dp
|
||||||
|
- qcom,sc7280-edp
|
||||||
- qcom,sc8180x-dp
|
- qcom,sc8180x-dp
|
||||||
- qcom,sc8180x-edp
|
- qcom,sc8180x-edp
|
||||||
|
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
Qualcomm Technologies Inc. adreno/snapdragon eDP output
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible:
|
|
||||||
* "qcom,mdss-edp"
|
|
||||||
- reg: Physical base address and length of the registers of controller and PLL
|
|
||||||
- reg-names: The names of register regions. The following regions are required:
|
|
||||||
* "edp"
|
|
||||||
* "pll_base"
|
|
||||||
- interrupts: The interrupt signal from the eDP block.
|
|
||||||
- power-domains: Should be <&mmcc MDSS_GDSC>.
|
|
||||||
- clocks: device clocks
|
|
||||||
See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
|
|
||||||
- clock-names: the following clocks are required:
|
|
||||||
* "core"
|
|
||||||
* "iface"
|
|
||||||
* "mdp_core"
|
|
||||||
* "pixel"
|
|
||||||
* "link"
|
|
||||||
- #clock-cells: The value should be 1.
|
|
||||||
- vdda-supply: phandle to vdda regulator device node
|
|
||||||
- lvl-vdd-supply: phandle to regulator device node which is used to supply power
|
|
||||||
to HPD receiving chip
|
|
||||||
- panel-en-gpios: GPIO pin to supply power to panel.
|
|
||||||
- panel-hpd-gpios: GPIO pin used for eDP hpd.
|
|
||||||
|
|
||||||
|
|
||||||
Example:
|
|
||||||
mdss_edp: qcom,mdss_edp@fd923400 {
|
|
||||||
compatible = "qcom,mdss-edp";
|
|
||||||
reg-names =
|
|
||||||
"edp",
|
|
||||||
"pll_base";
|
|
||||||
reg = <0xfd923400 0x700>,
|
|
||||||
<0xfd923a00 0xd4>;
|
|
||||||
interrupt-parent = <&mdss_mdp>;
|
|
||||||
interrupts = <12 0>;
|
|
||||||
power-domains = <&mmcc MDSS_GDSC>;
|
|
||||||
clock-names =
|
|
||||||
"core",
|
|
||||||
"pixel",
|
|
||||||
"iface",
|
|
||||||
"link",
|
|
||||||
"mdp_core";
|
|
||||||
clocks =
|
|
||||||
<&mmcc MDSS_EDPAUX_CLK>,
|
|
||||||
<&mmcc MDSS_EDPPIXEL_CLK>,
|
|
||||||
<&mmcc MDSS_AHB_CLK>,
|
|
||||||
<&mmcc MDSS_EDPLINK_CLK>,
|
|
||||||
<&mmcc MDSS_MDP_CLK>;
|
|
||||||
#clock-cells = <1>;
|
|
||||||
vdda-supply = <&pma8084_l12>;
|
|
||||||
lvl-vdd-supply = <&lvl_vreg>;
|
|
||||||
panel-en-gpios = <&tlmm 137 0>;
|
|
||||||
panel-hpd-gpios = <&tlmm 103 0>;
|
|
||||||
};
|
|
@ -0,0 +1,81 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/boe,bf060y8m-aj0.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: BOE BF060Y8M-AJ0 5.99" 1080x2160 AMOLED Panel
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
This is a 5.99" 1080x2160 16.7M Color active matrix AMOLED
|
||||||
|
video mode panel module on MIPI-DSI 4-Lane interface, GGRB
|
||||||
|
pixel arrangement, 63 micrometers pitch, with an active
|
||||||
|
area of 68.04 x 136.08 millimeters.
|
||||||
|
Each pixel is divided into red and green dots, or blue and
|
||||||
|
green dots, and two pixels share red or blue dots which are
|
||||||
|
arranged in vertical stripe.
|
||||||
|
The DriverIC for this panel module is SW43404.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: boe,bf060y8m-aj0
|
||||||
|
|
||||||
|
elvdd-supply:
|
||||||
|
description: EL Driving positive (VDD) supply (4.40-4.80V)
|
||||||
|
elvss-supply:
|
||||||
|
description: EL Driving negative (VSS) supply (-5.00V to -1.40V)
|
||||||
|
vcc-supply:
|
||||||
|
description: Core (TSP) voltage supply (2.70-3.60V)
|
||||||
|
vci-supply:
|
||||||
|
description: DriverIC Operation supply (2.60-3.60V)
|
||||||
|
vddio-supply:
|
||||||
|
description: I/O voltage supply (1.62-1.98V)
|
||||||
|
|
||||||
|
port: true
|
||||||
|
reg: true
|
||||||
|
reset-gpios: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- elvdd-supply
|
||||||
|
- elvss-supply
|
||||||
|
- vcc-supply
|
||||||
|
- vci-supply
|
||||||
|
- vddio-supply
|
||||||
|
- reg
|
||||||
|
- reset-gpios
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
dsi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
panel@0 {
|
||||||
|
compatible = "boe,bf060y8m-aj0";
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||||
|
|
||||||
|
vcc-supply = <&disp_vcc_vreg>;
|
||||||
|
vddio-supply = <&disp_vddio_vreg>;
|
||||||
|
vci-supply = <&disp_vci_vreg>;
|
||||||
|
elvdd-supply = <&disp_elvdd_vreg>;
|
||||||
|
elvss-supply = <&disp_elvss_vreg>;
|
||||||
|
|
||||||
|
port {
|
||||||
|
panel_in: endpoint {
|
||||||
|
remote-endpoint = <&dsi0_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,69 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/ilitek,ili9163.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Ilitek ILI9163 display panels device tree bindings
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Daniel Mack <daniel@zonque.org>
|
||||||
|
|
||||||
|
description:
|
||||||
|
This binding is for display panels using an Ilitek ILI9163 controller in SPI
|
||||||
|
mode.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- enum:
|
||||||
|
- newhaven,1.8-128160EF
|
||||||
|
- const: ilitek,ili9163
|
||||||
|
|
||||||
|
spi-max-frequency:
|
||||||
|
maximum: 32000000
|
||||||
|
|
||||||
|
dc-gpios:
|
||||||
|
maxItems: 1
|
||||||
|
description: Display data/command selection (D/CX)
|
||||||
|
|
||||||
|
backlight: true
|
||||||
|
reg: true
|
||||||
|
reset-gpios: true
|
||||||
|
rotation: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- dc-gpios
|
||||||
|
- reset-gpios
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
backlight: backlight {
|
||||||
|
compatible = "gpio-backlight";
|
||||||
|
gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
spi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
display@0 {
|
||||||
|
compatible = "newhaven,1.8-128160EF", "ilitek,ili9163";
|
||||||
|
reg = <0>;
|
||||||
|
spi-max-frequency = <32000000>;
|
||||||
|
dc-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
|
||||||
|
reset-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
|
||||||
|
rotation = <180>;
|
||||||
|
backlight = <&backlight>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -9,24 +9,28 @@ title: Ilitek ILI9881c based MIPI-DSI panels
|
|||||||
maintainers:
|
maintainers:
|
||||||
- Maxime Ripard <mripard@kernel.org>
|
- Maxime Ripard <mripard@kernel.org>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
items:
|
items:
|
||||||
- enum:
|
- enum:
|
||||||
- bananapi,lhr050h41
|
- bananapi,lhr050h41
|
||||||
- feixin,k101-im2byl02
|
- feixin,k101-im2byl02
|
||||||
|
- wanchanglong,w552946aba
|
||||||
- const: ilitek,ili9881c
|
- const: ilitek,ili9881c
|
||||||
|
|
||||||
backlight: true
|
backlight: true
|
||||||
power-supply: true
|
power-supply: true
|
||||||
reg: true
|
reg: true
|
||||||
reset-gpios: true
|
reset-gpios: true
|
||||||
|
rotation: true
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- power-supply
|
- power-supply
|
||||||
- reg
|
- reg
|
||||||
- reset-gpios
|
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/novatek,nt35950.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Novatek NT35950-based display panels
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The nt35950 IC from Novatek is a Driver IC used to drive MIPI-DSI panels,
|
||||||
|
with Static RAM for content retention in command mode and also supports
|
||||||
|
video mode with VESA Frame Buffer Compression or Display Stream Compression
|
||||||
|
on single, or dual dsi port(s).
|
||||||
|
This DDIC is also capable of upscaling an input image to the panel's native
|
||||||
|
resolution, for example it can upscale a 1920x1080 input to 3840x2160 with
|
||||||
|
either bilinear interpolation or pixel duplication.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- enum:
|
||||||
|
- sharp,ls055d1sx04
|
||||||
|
- const: novatek,nt35950
|
||||||
|
description: This indicates the panel manufacturer of the panel
|
||||||
|
that is in turn using the NT35950 panel driver. The compatible
|
||||||
|
string determines how the NT35950 panel driver shall be configured
|
||||||
|
to work with the indicated panel. The novatek,nt35950 compatible shall
|
||||||
|
always be provided as a fallback.
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
maxItems: 1
|
||||||
|
description: phandle of gpio for reset line - This should be 8mA, gpio
|
||||||
|
can be configured using mux, pinctrl, pinctrl-names (active high)
|
||||||
|
|
||||||
|
avdd-supply:
|
||||||
|
description: positive boost supply regulator
|
||||||
|
avee-supply:
|
||||||
|
description: negative boost supply regulator
|
||||||
|
dvdd-supply:
|
||||||
|
description: regulator that supplies the digital voltage
|
||||||
|
vddio-supply:
|
||||||
|
description: regulator that supplies the I/O voltage
|
||||||
|
|
||||||
|
backlight: true
|
||||||
|
ports: true
|
||||||
|
reg: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- reset-gpios
|
||||||
|
- avdd-supply
|
||||||
|
- avee-supply
|
||||||
|
- dvdd-supply
|
||||||
|
- vddio-supply
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
dsi0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
panel@0 {
|
||||||
|
compatible = "sharp,ls055d1sx04", "novatek,nt35950";
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
backlight = <&pmi8998_wled>;
|
||||||
|
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||||
|
|
||||||
|
avdd-supply = <&lab>;
|
||||||
|
avee-supply = <&ibb>;
|
||||||
|
dvdd-supply = <&disp_dvdd_vreg>;
|
||||||
|
vddio-supply = <&vreg_l14a_1p85>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
panel_in0: endpoint {
|
||||||
|
remote-endpoint = <&dsi0_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
panel_in1: endpoint {
|
||||||
|
remote-endpoint = <&dsi1_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -35,6 +35,8 @@ properties:
|
|||||||
- boe,tv080wum-nl0
|
- boe,tv080wum-nl0
|
||||||
# Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
# Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||||
- innolux,p079zca
|
- innolux,p079zca
|
||||||
|
# JDI FHD_R63452 1080x1920 5.2" IPS LCD Panel
|
||||||
|
- jdi,fhd-r63452
|
||||||
# Khadas TS050 5" 1080x1920 LCD panel
|
# Khadas TS050 5" 1080x1920 LCD panel
|
||||||
- khadas,ts050
|
- khadas,ts050
|
||||||
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
||||||
|
@ -290,6 +290,8 @@ properties:
|
|||||||
- starry,kr070pe2t
|
- starry,kr070pe2t
|
||||||
# Starry 12.2" (1920x1200 pixels) TFT LCD panel
|
# Starry 12.2" (1920x1200 pixels) TFT LCD panel
|
||||||
- starry,kr122ea0sra
|
- starry,kr122ea0sra
|
||||||
|
# Team Source Display Technology TST043015CMHX 4.3" WQVGA TFT LCD panel
|
||||||
|
- team-source-display,tst043015cmhx
|
||||||
# Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel
|
# Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel
|
||||||
- tianma,tm070jdhg30
|
- tianma,tm070jdhg30
|
||||||
# Tianma Micro-electronics TM070JVHG33 7.0" WXGA TFT LCD panel
|
# Tianma Micro-electronics TM070JVHG33 7.0" WXGA TFT LCD panel
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/sony,tulip-truly-nt35521.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Sony Tulip Truly NT35521 5.24" 1280x720 MIPI-DSI Panel
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Shawn Guo <shawn.guo@linaro.org>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The Sony Tulip Truly NT35521 is a 5.24" 1280x720 MIPI-DSI panel, which
|
||||||
|
can be found no Sony Xperia M4 phone. The panel backlight is managed
|
||||||
|
through DSI link.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: sony,tulip-truly-nt35521
|
||||||
|
|
||||||
|
reg: true
|
||||||
|
|
||||||
|
positive5-supply:
|
||||||
|
description: Positive 5V supply
|
||||||
|
|
||||||
|
negative5-supply:
|
||||||
|
description: Negative 5V supply
|
||||||
|
|
||||||
|
reset-gpios: true
|
||||||
|
|
||||||
|
enable-gpios: true
|
||||||
|
|
||||||
|
port: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- positive5-supply
|
||||||
|
- negative5-supply
|
||||||
|
- reset-gpios
|
||||||
|
- enable-gpios
|
||||||
|
- port
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
dsi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
panel@0 {
|
||||||
|
compatible = "sony,tulip-truly-nt35521";
|
||||||
|
reg = <0>;
|
||||||
|
positive5-supply = <&positive5_reg>;
|
||||||
|
negative5-supply = <&negative5_reg>;
|
||||||
|
reset-gpios = <&msmgpio 25 GPIO_ACTIVE_LOW>;
|
||||||
|
enable-gpios = <&msmgpio 10 GPIO_ACTIVE_HIGH>;
|
||||||
|
|
||||||
|
port {
|
||||||
|
panel_in: endpoint {
|
||||||
|
remote-endpoint = <&dsi0_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
@ -0,0 +1,64 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/sprd/sprd,display-subsystem.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Unisoc DRM master device
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Kevin Tang <kevin.tang@unisoc.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The Unisoc DRM master device is a virtual device needed to list all
|
||||||
|
DPU devices or other display interface nodes that comprise the
|
||||||
|
graphics subsystem.
|
||||||
|
|
||||||
|
Unisoc's display pipeline have several components as below description,
|
||||||
|
multi display controllers and corresponding physical interfaces.
|
||||||
|
For different display scenarios, dpu0 and dpu1 maybe binding to different
|
||||||
|
encoder.
|
||||||
|
|
||||||
|
E.g:
|
||||||
|
dpu0 and dpu1 both binding to DSI for dual mipi-dsi display;
|
||||||
|
dpu0 binding to DSI for primary display, and dpu1 binding to DP for external display;
|
||||||
|
|
||||||
|
+-----------------------------------------+
|
||||||
|
| |
|
||||||
|
| +---------+ |
|
||||||
|
+----+ | +----+ +---------+ |DPHY/CPHY| | +------+
|
||||||
|
| +----->+dpu0+--->+MIPI|DSI +--->+Combo +----->+Panel0|
|
||||||
|
|AXI | | +----+ +---------+ +---------+ | +------+
|
||||||
|
| | | ^ |
|
||||||
|
| | | | |
|
||||||
|
| | | +-----------+ |
|
||||||
|
| | | | |
|
||||||
|
|APB | | +--+-+ +-----------+ +---+ | +------+
|
||||||
|
| +----->+dpu1+--->+DisplayPort+--->+PHY+--------->+Panel1|
|
||||||
|
| | | +----+ +-----------+ +---+ | +------+
|
||||||
|
+----+ | |
|
||||||
|
+-----------------------------------------+
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: sprd,display-subsystem
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
|
description:
|
||||||
|
Should contain a list of phandles pointing to display interface port
|
||||||
|
of DPU devices.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- ports
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
display-subsystem {
|
||||||
|
compatible = "sprd,display-subsystem";
|
||||||
|
ports = <&dpu_out>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,77 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/sprd/sprd,sharkl3-dpu.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Unisoc Sharkl3 Display Processor Unit (DPU)
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Kevin Tang <kevin.tang@unisoc.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
DPU (Display Processor Unit) is the Display Controller for the Unisoc SoCs
|
||||||
|
which transfers the image data from a video memory buffer to an internal
|
||||||
|
LCD interface.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: sprd,sharkl3-dpu
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 2
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: clk_src_128m
|
||||||
|
- const: clk_src_384m
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
iommus:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
port:
|
||||||
|
type: object
|
||||||
|
description:
|
||||||
|
A port node with endpoint definitions as defined in
|
||||||
|
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||||
|
That port should be the output endpoint, usually output to
|
||||||
|
the associated DSI.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
- port
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/clock/sprd,sc9860-clk.h>
|
||||||
|
dpu: dpu@63000000 {
|
||||||
|
compatible = "sprd,sharkl3-dpu";
|
||||||
|
reg = <0x63000000 0x1000>;
|
||||||
|
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clock-names = "clk_src_128m", "clk_src_384m";
|
||||||
|
|
||||||
|
clocks = <&pll CLK_TWPLL_128M>,
|
||||||
|
<&pll CLK_TWPLL_384M>;
|
||||||
|
|
||||||
|
dpu_port: port {
|
||||||
|
dpu_out: endpoint {
|
||||||
|
remote-endpoint = <&dsi_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,88 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/sprd/sprd,sharkl3-dsi-host.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Unisoc MIPI DSI Controller
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Kevin Tang <kevin.tang@unisoc.com>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: sprd,sharkl3-dsi-host
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 1
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: clk_src_96m
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ports:
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
"#address-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
"#size-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
port@0:
|
||||||
|
type: object
|
||||||
|
description:
|
||||||
|
A port node with endpoint definitions as defined in
|
||||||
|
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||||
|
That port should be the input endpoint, usually coming from
|
||||||
|
the associated DPU.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- "#address-cells"
|
||||||
|
- "#size-cells"
|
||||||
|
- port@0
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
- ports
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/clock/sprd,sc9860-clk.h>
|
||||||
|
dsi: dsi@63100000 {
|
||||||
|
compatible = "sprd,sharkl3-dsi-host";
|
||||||
|
reg = <0x63100000 0x1000>;
|
||||||
|
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clock-names = "clk_src_96m";
|
||||||
|
clocks = <&pll CLK_TWPLL_96M>;
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
dsi_in: endpoint {
|
||||||
|
remote-endpoint = <&dpu_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -1240,6 +1240,8 @@ patternProperties:
|
|||||||
description: Truly Semiconductors Limited
|
description: Truly Semiconductors Limited
|
||||||
"^visionox,.*":
|
"^visionox,.*":
|
||||||
description: Visionox
|
description: Visionox
|
||||||
|
"^team-source-display,.*":
|
||||||
|
description: Shenzhen Team Source Display Technology Co., Ltd. (TSD)
|
||||||
"^tsd,.*":
|
"^tsd,.*":
|
||||||
description: Theobroma Systems Design und Consulting GmbH
|
description: Theobroma Systems Design und Consulting GmbH
|
||||||
"^tyan,.*":
|
"^tyan,.*":
|
||||||
@ -1334,6 +1336,8 @@ patternProperties:
|
|||||||
description: Wondermedia Technologies, Inc.
|
description: Wondermedia Technologies, Inc.
|
||||||
"^wobo,.*":
|
"^wobo,.*":
|
||||||
description: Wobo
|
description: Wobo
|
||||||
|
"^wanchanglong,.*":
|
||||||
|
description: Wanchanglong Electronics Technology(SHENZHEN)Co.,Ltd.
|
||||||
"^x-powers,.*":
|
"^x-powers,.*":
|
||||||
description: X-Powers
|
description: X-Powers
|
||||||
"^xes,.*":
|
"^xes,.*":
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
===================================
|
|
||||||
drm/amd/display - Display Core (DC)
|
|
||||||
===================================
|
|
||||||
|
|
||||||
*placeholder - general description of supported platforms, what dc is, etc.*
|
|
||||||
|
|
||||||
Because it is partially shared with other operating systems, the Display Core
|
|
||||||
Driver is divided in two pieces.
|
|
||||||
|
|
||||||
1. **Display Core (DC)** contains the OS-agnostic components. Things like
|
|
||||||
hardware programming and resource management are handled here.
|
|
||||||
2. **Display Manager (DM)** contains the OS-dependent components. Hooks to the
|
|
||||||
amdgpu base driver and DRM are implemented here.
|
|
||||||
|
|
||||||
It doesn't help that the entire package is frequently referred to as DC. But
|
|
||||||
with the context in mind, it should be clear.
|
|
||||||
|
|
||||||
When CONFIG_DRM_AMD_DC is enabled, DC will be initialized by default for
|
|
||||||
supported ASICs. To force disable, set `amdgpu.dc=0` on kernel command line.
|
|
||||||
Likewise, to force enable on unsupported ASICs, set `amdgpu.dc=1`.
|
|
||||||
|
|
||||||
To determine if DC is loaded, search dmesg for the following entry:
|
|
||||||
|
|
||||||
``Display Core initialized with <version number here>``
|
|
||||||
|
|
||||||
AMDgpu Display Manager
|
|
||||||
======================
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:doc: overview
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
Lifecycle
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:doc: DM Lifecycle
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:functions: dm_hw_init dm_hw_fini
|
|
||||||
|
|
||||||
Interrupts
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
|
||||||
:doc: overview
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:functions: register_hpd_handlers dm_crtc_high_irq dm_pflip_high_irq
|
|
||||||
|
|
||||||
Atomic Implementation
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:doc: atomic
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:functions: amdgpu_dm_atomic_check amdgpu_dm_atomic_commit_tail
|
|
||||||
|
|
||||||
Display Core
|
|
||||||
============
|
|
||||||
|
|
||||||
**WIP**
|
|
||||||
|
|
||||||
FreeSync Video
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
||||||
:doc: FreeSync Video
|
|
@ -1,324 +0,0 @@
|
|||||||
=========================
|
|
||||||
drm/amdgpu AMDgpu driver
|
|
||||||
=========================
|
|
||||||
|
|
||||||
The drm/amdgpu driver supports all AMD Radeon GPUs based on the Graphics Core
|
|
||||||
Next (GCN) architecture.
|
|
||||||
|
|
||||||
Module Parameters
|
|
||||||
=================
|
|
||||||
|
|
||||||
The amdgpu driver supports the following module parameters:
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
|
||||||
|
|
||||||
Core Driver Infrastructure
|
|
||||||
==========================
|
|
||||||
|
|
||||||
This section covers core driver infrastructure.
|
|
||||||
|
|
||||||
.. _amdgpu_memory_domains:
|
|
||||||
|
|
||||||
Memory Domains
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. kernel-doc:: include/uapi/drm/amdgpu_drm.h
|
|
||||||
:doc: memory domains
|
|
||||||
|
|
||||||
Buffer Objects
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
|
||||||
:doc: amdgpu_object
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
PRIME Buffer Sharing
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
|
||||||
:doc: PRIME Buffer Sharing
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
MMU Notifier
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
|
||||||
:doc: MMU Notifier
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
AMDGPU Virtual Memory
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
|
||||||
:doc: GPUVM
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
Interrupt Handling
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
|
||||||
:doc: Interrupt Handling
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
|
||||||
:internal:
|
|
||||||
|
|
||||||
IP Blocks
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
|
||||||
:doc: IP Blocks
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
|
||||||
:identifiers: amd_ip_block_type amd_ip_funcs
|
|
||||||
|
|
||||||
AMDGPU XGMI Support
|
|
||||||
===================
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
|
||||||
|
|
||||||
AMDGPU RAS Support
|
|
||||||
==================
|
|
||||||
|
|
||||||
The AMDGPU RAS interfaces are exposed via sysfs (for informational queries) and
|
|
||||||
debugfs (for error injection).
|
|
||||||
|
|
||||||
RAS debugfs/sysfs Control and Error Injection Interfaces
|
|
||||||
--------------------------------------------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
||||||
:doc: AMDGPU RAS debugfs control interface
|
|
||||||
|
|
||||||
RAS Reboot Behavior for Unrecoverable Errors
|
|
||||||
--------------------------------------------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
||||||
:doc: AMDGPU RAS Reboot Behavior for Unrecoverable Errors
|
|
||||||
|
|
||||||
RAS Error Count sysfs Interface
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
||||||
:doc: AMDGPU RAS sysfs Error Count Interface
|
|
||||||
|
|
||||||
RAS EEPROM debugfs Interface
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
||||||
:doc: AMDGPU RAS debugfs EEPROM table reset interface
|
|
||||||
|
|
||||||
RAS VRAM Bad Pages sysfs Interface
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
||||||
:doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
|
|
||||||
|
|
||||||
Sample Code
|
|
||||||
-----------
|
|
||||||
Sample code for testing error injection can be found here:
|
|
||||||
https://cgit.freedesktop.org/mesa/drm/tree/tests/amdgpu/ras_tests.c
|
|
||||||
|
|
||||||
This is part of the libdrm amdgpu unit tests which cover several areas of the GPU.
|
|
||||||
There are four sets of tests:
|
|
||||||
|
|
||||||
RAS Basic Test
|
|
||||||
|
|
||||||
The test verifies the RAS feature enabled status and makes sure the necessary sysfs and debugfs files
|
|
||||||
are present.
|
|
||||||
|
|
||||||
RAS Query Test
|
|
||||||
|
|
||||||
This test checks the RAS availability and enablement status for each supported IP block as well as
|
|
||||||
the error counts.
|
|
||||||
|
|
||||||
RAS Inject Test
|
|
||||||
|
|
||||||
This test injects errors for each IP.
|
|
||||||
|
|
||||||
RAS Disable Test
|
|
||||||
|
|
||||||
This test tests disabling of RAS features for each IP block.
|
|
||||||
|
|
||||||
|
|
||||||
GPU Power/Thermal Controls and Monitoring
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
This section covers hwmon and power/thermal controls.
|
|
||||||
|
|
||||||
HWMON Interfaces
|
|
||||||
----------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: hwmon
|
|
||||||
|
|
||||||
GPU sysfs Power State Interfaces
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
GPU power controls are exposed via sysfs files.
|
|
||||||
|
|
||||||
power_dpm_state
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: power_dpm_state
|
|
||||||
|
|
||||||
power_dpm_force_performance_level
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: power_dpm_force_performance_level
|
|
||||||
|
|
||||||
pp_table
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: pp_table
|
|
||||||
|
|
||||||
pp_od_clk_voltage
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: pp_od_clk_voltage
|
|
||||||
|
|
||||||
pp_dpm_*
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie
|
|
||||||
|
|
||||||
pp_power_profile_mode
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: pp_power_profile_mode
|
|
||||||
|
|
||||||
\*_busy_percent
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: gpu_busy_percent
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: mem_busy_percent
|
|
||||||
|
|
||||||
gpu_metrics
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: gpu_metrics
|
|
||||||
|
|
||||||
GPU Product Information
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Information about the GPU can be obtained on certain cards
|
|
||||||
via sysfs
|
|
||||||
|
|
||||||
product_name
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
||||||
:doc: product_name
|
|
||||||
|
|
||||||
product_number
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
||||||
:doc: product_name
|
|
||||||
|
|
||||||
serial_number
|
|
||||||
-------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
||||||
:doc: serial_number
|
|
||||||
|
|
||||||
unique_id
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: unique_id
|
|
||||||
|
|
||||||
GPU Memory Usage Information
|
|
||||||
============================
|
|
||||||
|
|
||||||
Various memory accounting can be accessed via sysfs
|
|
||||||
|
|
||||||
mem_info_vram_total
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
|
||||||
:doc: mem_info_vram_total
|
|
||||||
|
|
||||||
mem_info_vram_used
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
|
||||||
:doc: mem_info_vram_used
|
|
||||||
|
|
||||||
mem_info_vis_vram_total
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
|
||||||
:doc: mem_info_vis_vram_total
|
|
||||||
|
|
||||||
mem_info_vis_vram_used
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
|
||||||
:doc: mem_info_vis_vram_used
|
|
||||||
|
|
||||||
mem_info_gtt_total
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
|
||||||
:doc: mem_info_gtt_total
|
|
||||||
|
|
||||||
mem_info_gtt_used
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
|
||||||
:doc: mem_info_gtt_used
|
|
||||||
|
|
||||||
PCIe Accounting Information
|
|
||||||
===========================
|
|
||||||
|
|
||||||
pcie_bw
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: pcie_bw
|
|
||||||
|
|
||||||
pcie_replay_count
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
||||||
:doc: pcie_replay_count
|
|
||||||
|
|
||||||
GPU SmartShift Information
|
|
||||||
==========================
|
|
||||||
|
|
||||||
GPU SmartShift information via sysfs
|
|
||||||
|
|
||||||
smartshift_apu_power
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: smartshift_apu_power
|
|
||||||
|
|
||||||
smartshift_dgpu_power
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: smartshift_dgpu_power
|
|
||||||
|
|
||||||
smartshift_bias
|
|
||||||
---------------
|
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
||||||
:doc: smartshift_bias
|
|
87
Documentation/gpu/amdgpu/amdgpu-glossary.rst
Normal file
87
Documentation/gpu/amdgpu/amdgpu-glossary.rst
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
===============
|
||||||
|
AMDGPU Glossary
|
||||||
|
===============
|
||||||
|
|
||||||
|
Here you can find some generic acronyms used in the amdgpu driver. Notice that
|
||||||
|
we have a dedicated glossary for Display Core at
|
||||||
|
'Documentation/gpu/amdgpu/display/dc-glossary.rst'.
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
CP
|
||||||
|
Command Processor
|
||||||
|
|
||||||
|
CPLIB
|
||||||
|
Content Protection Library
|
||||||
|
|
||||||
|
DFS
|
||||||
|
Digital Frequency Synthesizer
|
||||||
|
|
||||||
|
ECP
|
||||||
|
Enhanced Content Protection
|
||||||
|
|
||||||
|
EOP
|
||||||
|
End Of Pipe/Pipeline
|
||||||
|
|
||||||
|
GC
|
||||||
|
Graphics and Compute
|
||||||
|
|
||||||
|
GMC
|
||||||
|
Graphic Memory Controller
|
||||||
|
|
||||||
|
IH
|
||||||
|
Interrupt Handler
|
||||||
|
|
||||||
|
HQD
|
||||||
|
Hardware Queue Descriptor
|
||||||
|
|
||||||
|
IB
|
||||||
|
Indirect Buffer
|
||||||
|
|
||||||
|
IP
|
||||||
|
Intellectual Property blocks
|
||||||
|
|
||||||
|
KCQ
|
||||||
|
Kernel Compute Queue
|
||||||
|
|
||||||
|
KGQ
|
||||||
|
Kernel Graphics Queue
|
||||||
|
|
||||||
|
KIQ
|
||||||
|
Kernel Interface Queue
|
||||||
|
|
||||||
|
MEC
|
||||||
|
MicroEngine Compute
|
||||||
|
|
||||||
|
MES
|
||||||
|
MicroEngine Scheduler
|
||||||
|
|
||||||
|
MMHUB
|
||||||
|
Multi-Media HUB
|
||||||
|
|
||||||
|
MQD
|
||||||
|
Memory Queue Descriptor
|
||||||
|
|
||||||
|
PPLib
|
||||||
|
PowerPlay Library - PowerPlay is the power management component.
|
||||||
|
|
||||||
|
PSP
|
||||||
|
Platform Security Processor
|
||||||
|
|
||||||
|
RCL
|
||||||
|
RunList Controller
|
||||||
|
|
||||||
|
SDMA
|
||||||
|
System DMA
|
||||||
|
|
||||||
|
SMU
|
||||||
|
System Management Unit
|
||||||
|
|
||||||
|
SS
|
||||||
|
Spread Spectrum
|
||||||
|
|
||||||
|
VCE
|
||||||
|
Video Compression Engine
|
||||||
|
|
||||||
|
VCN
|
||||||
|
Video Codec Next
|
414
Documentation/gpu/amdgpu/display/config_example.svg
Normal file
414
Documentation/gpu/amdgpu/display/config_example.svg
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="144.63406mm"
|
||||||
|
height="66.596054mm"
|
||||||
|
viewBox="0 0 144.15195 66.596054"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||||
|
sodipodi:docname="config_example.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Mend"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path4547"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Mend-3"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4547-6"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Mend-3-5"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4547-6-3"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Mend-3-5-0"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4547-6-3-6"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Mend-3-5-7"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4547-6-3-3"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.98994949"
|
||||||
|
inkscape:cx="518.91791"
|
||||||
|
inkscape:cy="172.50112"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
viewbox-width="209.3"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="1136"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid817"
|
||||||
|
originx="4.390216"
|
||||||
|
originy="-208.88856" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(4.4048992,-21.515392)">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 20.816662,35.062492 h 23.8125 v -5.291667 h 5.291667 v 5.291667 h 10.583334 v -5.291667 h 5.291667 v 5.291667 h 2.645833 v -5.291667 h 5.291667 v 5.291667 h 66.14583"
|
||||||
|
id="path4522"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 20.816662,48.291659 h 7.9375 v -5.291667 h 5.291667 v 5.291667 h 58.208335 v -5.291667 h 5.291666 v 5.291667 h 42.33333"
|
||||||
|
id="path4524"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 20.816662,61.520826 h 26.458334 v -5.291667 h 44.979168 v 5.291667 h 47.624996"
|
||||||
|
id="path4526"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 20.816662,72.104159 H 139.87916"
|
||||||
|
id="path4528"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 20.816662,77.395826 H 139.87916"
|
||||||
|
id="path4530"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 20.816662,82.687493 H 139.87916"
|
||||||
|
id="path4532"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 20.816662,87.97916 H 139.87916"
|
||||||
|
id="path4534"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916668, 0.52916668;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
|
||||||
|
d="m 47.274996,29.770826 c 3.836215,14.933158 3.472151,27.586643 0.264583,41.010418"
|
||||||
|
id="path4536"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916669, 0.52916669;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3)"
|
||||||
|
d="m 63.149996,29.770826 c 3.836214,14.933158 5.059652,27.586642 1.852084,41.010418"
|
||||||
|
id="path4536-7"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.5291667, 0.5291667;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3-5)"
|
||||||
|
d="m 71.087496,29.770825 c 3.836214,14.933158 5.059652,27.586643 1.852084,41.010419"
|
||||||
|
id="path4536-7-5"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="59.359009"
|
||||||
|
y="24.195677"
|
||||||
|
id="text6572"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="59.359009"
|
||||||
|
y="24.195677"
|
||||||
|
style="font-size:3.52777791px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan6574">Configurations</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="46.825508"
|
||||||
|
y="28.542402"
|
||||||
|
id="text6572-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="46.825508"
|
||||||
|
y="28.542402"
|
||||||
|
style="font-size:3.52777815px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#008000;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2">A</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="62.8895"
|
||||||
|
y="28.825886"
|
||||||
|
id="text6572-6-2"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="62.8895"
|
||||||
|
y="28.825886"
|
||||||
|
style="font-size:3.52777839px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#0000ff;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2-7">B</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="70.827003"
|
||||||
|
y="29.109362"
|
||||||
|
id="text6572-6-2-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="70.827003"
|
||||||
|
y="29.109362"
|
||||||
|
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#c87137;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2-7-6">C</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916671, 0.52916671;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3-5-0)"
|
||||||
|
d="m 92.254164,42.999993 c 9.142136,12.745655 4.411987,28.608461 0.529167,38.364584"
|
||||||
|
id="path4536-7-5-2"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 47.274996,72.104159 v 5.291667"
|
||||||
|
id="path8053"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 64.472913,72.10416 v 5.291667"
|
||||||
|
id="path8053-6"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 72.410413,72.10416 v 5.291667"
|
||||||
|
id="path8053-6-1"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 92.254164,82.687494 v 5.291667"
|
||||||
|
id="path8053-6-1-8"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="55.802444"
|
||||||
|
y="76.167412"
|
||||||
|
id="text6572-6-7"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="55.802444"
|
||||||
|
y="76.167412"
|
||||||
|
style="font-size:3.52777839px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#008000;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2-9">A</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="68.559143"
|
||||||
|
y="75.883926"
|
||||||
|
id="text6572-6-2-2"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="68.559143"
|
||||||
|
y="75.883926"
|
||||||
|
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#0000ff;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2-7-0">B</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="84.812119"
|
||||||
|
y="75.883911"
|
||||||
|
id="text6572-6-2-3-2"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="84.812119"
|
||||||
|
y="75.883911"
|
||||||
|
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#c87137;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2-7-6-3">C</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="98.513756"
|
||||||
|
y="86.845222"
|
||||||
|
id="text6572-6-2-3-2-7"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="98.513756"
|
||||||
|
y="86.845222"
|
||||||
|
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#c87137;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-2-7-6-3-5">C</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="35.452015"
|
||||||
|
y="75.694931"
|
||||||
|
id="text6572-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="35.452015"
|
||||||
|
y="75.694931"
|
||||||
|
style="font-size:3.52777815px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-22">Old config</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="55.484753"
|
||||||
|
y="86.656235"
|
||||||
|
id="text6572-9-8"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="55.484753"
|
||||||
|
y="86.656235"
|
||||||
|
style="font-size:3.52777839px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan6574-22-9">Old config</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916671, 0.52916671;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3-5-7)"
|
||||||
|
d="m 92.254164,42.999993 c 4.233333,4.7625 2.645833,13.229167 0.79375,17.197917"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="3.7020128"
|
||||||
|
y="33.550579"
|
||||||
|
id="text6572-1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="3.7020128"
|
||||||
|
y="42.914349"
|
||||||
|
style="font-size:3.52777815px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15310" /></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17500019px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="13.366468"
|
||||||
|
y="46.590767"
|
||||||
|
id="text15316"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="13.366468"
|
||||||
|
y="46.590767"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15318">VUpdate</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17500043px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="14.45245"
|
||||||
|
y="29.676321"
|
||||||
|
id="text15316-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan15314-1"
|
||||||
|
x="14.45245"
|
||||||
|
y="29.676321"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335">Update</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="14.45245"
|
||||||
|
y="33.645073"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15318-9">Lock</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17500043px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="7.5676007"
|
||||||
|
y="56.985115"
|
||||||
|
id="text15316-4"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="7.5676007"
|
||||||
|
y="56.985115"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15318-7">Register update</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="7.5676007"
|
||||||
|
y="60.953865"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15361">Pending Status</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17500043px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="16.074829"
|
||||||
|
y="76.167404"
|
||||||
|
id="text15316-8"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="16.074829"
|
||||||
|
y="76.167404"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15318-4">Buf 0</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17500067px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||||
|
x="16.156994"
|
||||||
|
y="86.089279"
|
||||||
|
id="text15316-8-5"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="16.156994"
|
||||||
|
y="86.089279"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||||
|
id="tspan15318-4-0">Buf 1</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 19 KiB |
77
Documentation/gpu/amdgpu/display/dc-debug.rst
Normal file
77
Documentation/gpu/amdgpu/display/dc-debug.rst
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
========================
|
||||||
|
Display Core Debug tools
|
||||||
|
========================
|
||||||
|
|
||||||
|
DC Visual Confirmation
|
||||||
|
======================
|
||||||
|
|
||||||
|
Display core provides a feature named visual confirmation, which is a set of
|
||||||
|
bars added at the scanout time by the driver to convey some specific
|
||||||
|
information. In general, you can enable this debug option by using::
|
||||||
|
|
||||||
|
echo <N> > /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
|
||||||
|
|
||||||
|
Where `N` is an integer number for some specific scenarios that the developer
|
||||||
|
wants to enable, you will see some of these debug cases in the following
|
||||||
|
subsection.
|
||||||
|
|
||||||
|
Multiple Planes Debug
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
If you want to enable or debug multiple planes in a specific user-space
|
||||||
|
application, you can leverage a debug feature named visual confirm. For
|
||||||
|
enabling it, you will need::
|
||||||
|
|
||||||
|
echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
|
||||||
|
|
||||||
|
You need to reload your GUI to see the visual confirmation. When the plane
|
||||||
|
configuration changes or a full update occurs there will be a colored bar at
|
||||||
|
the bottom of each hardware plane being drawn on the screen.
|
||||||
|
|
||||||
|
* The color indicates the format - For example, red is AR24 and green is NV12
|
||||||
|
* The height of the bar indicates the index of the plane
|
||||||
|
* Pipe split can be observed if there are two bars with a difference in height
|
||||||
|
covering the same plane
|
||||||
|
|
||||||
|
Consider the video playback case in which a video is played in a specific
|
||||||
|
plane, and the desktop is drawn in another plane. The video plane should
|
||||||
|
feature one or two green bars at the bottom of the video depending on pipe
|
||||||
|
split configuration.
|
||||||
|
|
||||||
|
* There should **not** be any visual corruption
|
||||||
|
* There should **not** be any underflow or screen flashes
|
||||||
|
* There should **not** be any black screens
|
||||||
|
* There should **not** be any cursor corruption
|
||||||
|
* Multiple plane **may** be briefly disabled during window transitions or
|
||||||
|
resizing but should come back after the action has finished
|
||||||
|
|
||||||
|
Pipe Split Debug
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Sometimes we need to debug if DCN is splitting pipes correctly, and visual
|
||||||
|
confirmation is also handy for this case. Similar to the MPO case, you can use
|
||||||
|
the below command to enable visual confirmation::
|
||||||
|
|
||||||
|
echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
|
||||||
|
|
||||||
|
In this case, if you have a pipe split, you will see one small red bar at the
|
||||||
|
bottom of the display covering the entire display width and another bar
|
||||||
|
covering the second pipe. In other words, you will see a bit high bar in the
|
||||||
|
second pipe.
|
||||||
|
|
||||||
|
DTN Debug
|
||||||
|
=========
|
||||||
|
|
||||||
|
DC (DCN) provides an extensive log that dumps multiple details from our
|
||||||
|
hardware configuration. Via debugfs, you can capture those status values by
|
||||||
|
using Display Test Next (DTN) log, which can be captured via debugfs by using::
|
||||||
|
|
||||||
|
cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
|
||||||
|
|
||||||
|
Since this log is updated accordingly with DCN status, you can also follow the
|
||||||
|
change in real-time by using something like::
|
||||||
|
|
||||||
|
sudo watch -d cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
|
||||||
|
|
||||||
|
When reporting a bug related to DC, consider attaching this log before and
|
||||||
|
after you reproduce the bug.
|
237
Documentation/gpu/amdgpu/display/dc-glossary.rst
Normal file
237
Documentation/gpu/amdgpu/display/dc-glossary.rst
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
===========
|
||||||
|
DC Glossary
|
||||||
|
===========
|
||||||
|
|
||||||
|
On this page, we try to keep track of acronyms related to the display
|
||||||
|
component. If you do not find what you are looking for, look at the
|
||||||
|
'Documentation/gpu/amdgpu/amdgpu-glossary.rst'; if you cannot find it anywhere,
|
||||||
|
consider asking in the amdgfx and update this page.
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
ABM
|
||||||
|
Adaptive Backlight Modulation
|
||||||
|
|
||||||
|
APU
|
||||||
|
Accelerated Processing Unit
|
||||||
|
|
||||||
|
ASIC
|
||||||
|
Application-Specific Integrated Circuit
|
||||||
|
|
||||||
|
ASSR
|
||||||
|
Alternate Scrambler Seed Reset
|
||||||
|
|
||||||
|
AZ
|
||||||
|
Azalia (HD audio DMA engine)
|
||||||
|
|
||||||
|
BPC
|
||||||
|
Bits Per Colour/Component
|
||||||
|
|
||||||
|
BPP
|
||||||
|
Bits Per Pixel
|
||||||
|
|
||||||
|
Clocks
|
||||||
|
* PCLK: Pixel Clock
|
||||||
|
* SYMCLK: Symbol Clock
|
||||||
|
* SOCCLK: GPU Engine Clock
|
||||||
|
* DISPCLK: Display Clock
|
||||||
|
* DPPCLK: DPP Clock
|
||||||
|
* DCFCLK: Display Controller Fabric Clock
|
||||||
|
* REFCLK: Real Time Reference Clock
|
||||||
|
* PPLL: Pixel PLL
|
||||||
|
* FCLK: Fabric Clock
|
||||||
|
* MCLK: Memory Clock
|
||||||
|
|
||||||
|
CRC
|
||||||
|
Cyclic Redundancy Check
|
||||||
|
|
||||||
|
CRTC
|
||||||
|
Cathode Ray Tube Controller - commonly called "Controller" - Generates
|
||||||
|
raw stream of pixels, clocked at pixel clock
|
||||||
|
|
||||||
|
CVT
|
||||||
|
Coordinated Video Timings
|
||||||
|
|
||||||
|
DAL
|
||||||
|
Display Abstraction layer
|
||||||
|
|
||||||
|
DC (Software)
|
||||||
|
Display Core
|
||||||
|
|
||||||
|
DC (Hardware)
|
||||||
|
Display Controller
|
||||||
|
|
||||||
|
DCC
|
||||||
|
Delta Colour Compression
|
||||||
|
|
||||||
|
DCE
|
||||||
|
Display Controller Engine
|
||||||
|
|
||||||
|
DCHUB
|
||||||
|
Display Controller HUB
|
||||||
|
|
||||||
|
ARB
|
||||||
|
Arbiter
|
||||||
|
|
||||||
|
VTG
|
||||||
|
Vertical Timing Generator
|
||||||
|
|
||||||
|
DCN
|
||||||
|
Display Core Next
|
||||||
|
|
||||||
|
DCCG
|
||||||
|
Display Clock Generator block
|
||||||
|
|
||||||
|
DDC
|
||||||
|
Display Data Channel
|
||||||
|
|
||||||
|
DIO
|
||||||
|
Display IO
|
||||||
|
|
||||||
|
DPP
|
||||||
|
Display Pipes and Planes
|
||||||
|
|
||||||
|
DSC
|
||||||
|
Display Stream Compression (Reduce the amount of bits to represent pixel
|
||||||
|
count while at the same pixel clock)
|
||||||
|
|
||||||
|
dGPU
|
||||||
|
discrete GPU
|
||||||
|
|
||||||
|
DMIF
|
||||||
|
Display Memory Interface
|
||||||
|
|
||||||
|
DML
|
||||||
|
Display Mode Library
|
||||||
|
|
||||||
|
DMCU
|
||||||
|
Display Micro-Controller Unit
|
||||||
|
|
||||||
|
DMCUB
|
||||||
|
Display Micro-Controller Unit, version B
|
||||||
|
|
||||||
|
DPCD
|
||||||
|
DisplayPort Configuration Data
|
||||||
|
|
||||||
|
DPM(S)
|
||||||
|
Display Power Management (Signaling)
|
||||||
|
|
||||||
|
DRR
|
||||||
|
Dynamic Refresh Rate
|
||||||
|
|
||||||
|
DWB
|
||||||
|
Display Writeback
|
||||||
|
|
||||||
|
FB
|
||||||
|
Frame Buffer
|
||||||
|
|
||||||
|
FBC
|
||||||
|
Frame Buffer Compression
|
||||||
|
|
||||||
|
FEC
|
||||||
|
Forward Error Correction
|
||||||
|
|
||||||
|
FRL
|
||||||
|
Fixed Rate Link
|
||||||
|
|
||||||
|
GCO
|
||||||
|
Graphical Controller Object
|
||||||
|
|
||||||
|
GSL
|
||||||
|
Global Swap Lock
|
||||||
|
|
||||||
|
iGPU
|
||||||
|
integrated GPU
|
||||||
|
|
||||||
|
ISR
|
||||||
|
Interrupt Service Request
|
||||||
|
|
||||||
|
ISV
|
||||||
|
Independent Software Vendor
|
||||||
|
|
||||||
|
KMD
|
||||||
|
Kernel Mode Driver
|
||||||
|
|
||||||
|
LB
|
||||||
|
Line Buffer
|
||||||
|
|
||||||
|
LFC
|
||||||
|
Low Framerate Compensation
|
||||||
|
|
||||||
|
LTTPR
|
||||||
|
Link Training Tunable Phy Repeater
|
||||||
|
|
||||||
|
LUT
|
||||||
|
Lookup Table
|
||||||
|
|
||||||
|
MALL
|
||||||
|
Memory Access at Last Level
|
||||||
|
|
||||||
|
MC
|
||||||
|
Memory Controller
|
||||||
|
|
||||||
|
MPC
|
||||||
|
Multiple pipes and plane combine
|
||||||
|
|
||||||
|
MPO
|
||||||
|
Multi Plane Overlay
|
||||||
|
|
||||||
|
MST
|
||||||
|
Multi Stream Transport
|
||||||
|
|
||||||
|
NBP State
|
||||||
|
Northbridge Power State
|
||||||
|
|
||||||
|
NBIO
|
||||||
|
North Bridge Input/Output
|
||||||
|
|
||||||
|
ODM
|
||||||
|
Output Data Mapping
|
||||||
|
|
||||||
|
OPM
|
||||||
|
Output Protection Manager
|
||||||
|
|
||||||
|
OPP
|
||||||
|
Output Plane Processor
|
||||||
|
|
||||||
|
OPTC
|
||||||
|
Output Pipe Timing Combiner
|
||||||
|
|
||||||
|
OTG
|
||||||
|
Output Timing Generator
|
||||||
|
|
||||||
|
PCON
|
||||||
|
Power Controller
|
||||||
|
|
||||||
|
PGFSM
|
||||||
|
Power Gate Finite State Machine
|
||||||
|
|
||||||
|
PSR
|
||||||
|
Panel Self Refresh
|
||||||
|
|
||||||
|
SCL
|
||||||
|
Scaler
|
||||||
|
|
||||||
|
SDP
|
||||||
|
Scalable Data Port
|
||||||
|
|
||||||
|
SLS
|
||||||
|
Single Large Surface
|
||||||
|
|
||||||
|
SST
|
||||||
|
Single Stream Transport
|
||||||
|
|
||||||
|
TMDS
|
||||||
|
Transition-Minimized Differential Signaling
|
||||||
|
|
||||||
|
TMZ
|
||||||
|
Trusted Memory Zone
|
||||||
|
|
||||||
|
TTU
|
||||||
|
Time to Underflow
|
||||||
|
|
||||||
|
VRR
|
||||||
|
Variable Refresh Rate
|
||||||
|
|
||||||
|
UVD
|
||||||
|
Unified Video Decoder
|
1125
Documentation/gpu/amdgpu/display/dc_pipeline_overview.svg
Normal file
1125
Documentation/gpu/amdgpu/display/dc_pipeline_overview.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 54 KiB |
171
Documentation/gpu/amdgpu/display/dcn-overview.rst
Normal file
171
Documentation/gpu/amdgpu/display/dcn-overview.rst
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
=======================
|
||||||
|
Display Core Next (DCN)
|
||||||
|
=======================
|
||||||
|
|
||||||
|
To equip our readers with the basic knowledge of how AMD Display Core Next
|
||||||
|
(DCN) works, we need to start with an overview of the hardware pipeline. Below
|
||||||
|
you can see a picture that provides a DCN overview, keep in mind that this is a
|
||||||
|
generic diagram, and we have variations per ASIC.
|
||||||
|
|
||||||
|
.. kernel-figure:: dc_pipeline_overview.svg
|
||||||
|
|
||||||
|
Based on this diagram, we can pass through each block and briefly describe
|
||||||
|
them:
|
||||||
|
|
||||||
|
* **Display Controller Hub (DCHUB)**: This is the gateway between the Scalable
|
||||||
|
Data Port (SDP) and DCN. This component has multiple features, such as memory
|
||||||
|
arbitration, rotation, and cursor manipulation.
|
||||||
|
|
||||||
|
* **Display Pipe and Plane (DPP)**: This block provides pre-blend pixel
|
||||||
|
processing such as color space conversion, linearization of pixel data, tone
|
||||||
|
mapping, and gamut mapping.
|
||||||
|
|
||||||
|
* **Multiple Pipe/Plane Combined (MPC)**: This component performs blending of
|
||||||
|
multiple planes, using global or per-pixel alpha.
|
||||||
|
|
||||||
|
* **Output Pixel Processing (OPP)**: Process and format pixels to be sent to
|
||||||
|
the display.
|
||||||
|
|
||||||
|
* **Output Pipe Timing Combiner (OPTC)**: It generates time output to combine
|
||||||
|
streams or divide capabilities. CRC values are generated in this block.
|
||||||
|
|
||||||
|
* **Display Output (DIO)**: Codify the output to the display connected to our
|
||||||
|
GPU.
|
||||||
|
|
||||||
|
* **Display Writeback (DWB)**: It provides the ability to write the output of
|
||||||
|
the display pipe back to memory as video frames.
|
||||||
|
|
||||||
|
* **Multi-Media HUB (MMHUBBUB)**: Memory controller interface for DMCUB and DWB
|
||||||
|
(Note that DWB is not hooked yet).
|
||||||
|
|
||||||
|
* **DCN Management Unit (DMU)**: It provides registers with access control and
|
||||||
|
interrupts the controller to the SOC host interrupt unit. This block includes
|
||||||
|
the Display Micro-Controller Unit - version B (DMCUB), which is handled via
|
||||||
|
firmware.
|
||||||
|
|
||||||
|
* **DCN Clock Generator Block (DCCG)**: It provides the clocks and resets
|
||||||
|
for all of the display controller clock domains.
|
||||||
|
|
||||||
|
* **Azalia (AZ)**: Audio engine.
|
||||||
|
|
||||||
|
The above diagram is an architecture generalization of DCN, which means that
|
||||||
|
every ASIC has variations around this base model. Notice that the display
|
||||||
|
pipeline is connected to the Scalable Data Port (SDP) via DCHUB; you can see
|
||||||
|
the SDP as the element from our Data Fabric that feeds the display pipe.
|
||||||
|
|
||||||
|
Always approach the DCN architecture as something flexible that can be
|
||||||
|
configured and reconfigured in multiple ways; in other words, each block can be
|
||||||
|
setup or ignored accordingly with userspace demands. For example, if we
|
||||||
|
want to drive an 8k@60Hz with a DSC enabled, our DCN may require 4 DPP and 2
|
||||||
|
OPP. It is DC's responsibility to drive the best configuration for each
|
||||||
|
specific scenario. Orchestrate all of these components together requires a
|
||||||
|
sophisticated communication interface which is highlighted in the diagram by
|
||||||
|
the edges that connect each block; from the chart, each connection between
|
||||||
|
these blocks represents:
|
||||||
|
|
||||||
|
1. Pixel data interface (red): Represents the pixel data flow;
|
||||||
|
2. Global sync signals (green): It is a set of synchronization signals composed
|
||||||
|
by VStartup, VUpdate, and VReady;
|
||||||
|
3. Config interface: Responsible to configure blocks;
|
||||||
|
4. Sideband signals: All other signals that do not fit the previous one.
|
||||||
|
|
||||||
|
These signals are essential and play an important role in DCN. Nevertheless,
|
||||||
|
the Global Sync deserves an extra level of detail described in the next
|
||||||
|
section.
|
||||||
|
|
||||||
|
All of these components are represented by a data structure named dc_state.
|
||||||
|
From DCHUB to MPC, we have a representation called dc_plane; from MPC to OPTC,
|
||||||
|
we have dc_stream, and the output (DIO) is handled by dc_link. Keep in mind
|
||||||
|
that HUBP accesses a surface using a specific format read from memory, and our
|
||||||
|
dc_plane should work to convert all pixels in the plane to something that can
|
||||||
|
be sent to the display via dc_stream and dc_link.
|
||||||
|
|
||||||
|
Front End and Back End
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Display pipeline can be broken down into two components that are usually
|
||||||
|
referred as **Front End (FE)** and **Back End (BE)**, where FE consists of:
|
||||||
|
|
||||||
|
* DCHUB (Mainly referring to a subcomponent named HUBP)
|
||||||
|
* DPP
|
||||||
|
* MPC
|
||||||
|
|
||||||
|
On the other hand, BE consist of
|
||||||
|
|
||||||
|
* OPP
|
||||||
|
* OPTC
|
||||||
|
* DIO (DP/HDMI stream encoder and link encoder)
|
||||||
|
|
||||||
|
OPP and OPTC are two joining blocks between FE and BE. On a side note, this is
|
||||||
|
a one-to-one mapping of the link encoder to PHY, but we can configure the DCN
|
||||||
|
to choose which link encoder to connect to which PHY. FE's main responsibility
|
||||||
|
is to change, blend and compose pixel data, while BE's job is to frame a
|
||||||
|
generic pixel stream to a specific display's pixel stream.
|
||||||
|
|
||||||
|
Data Flow
|
||||||
|
---------
|
||||||
|
|
||||||
|
Initially, data is passed in from VRAM through Data Fabric (DF) in native pixel
|
||||||
|
formats. Such data format stays through till HUBP in DCHUB, where HUBP unpacks
|
||||||
|
different pixel formats and outputs them to DPP in uniform streams through 4
|
||||||
|
channels (1 for alpha + 3 for colors).
|
||||||
|
|
||||||
|
The Converter and Cursor (CNVC) in DPP would then normalize the data
|
||||||
|
representation and convert them to a DCN specific floating-point format (i.e.,
|
||||||
|
different from the IEEE floating-point format). In the process, CNVC also
|
||||||
|
applies a degamma function to transform the data from non-linear to linear
|
||||||
|
space to relax the floating-point calculations following. Data would stay in
|
||||||
|
this floating-point format from DPP to OPP.
|
||||||
|
|
||||||
|
Starting OPP, because color transformation and blending have been completed
|
||||||
|
(i.e alpha can be dropped), and the end sinks do not require the precision and
|
||||||
|
dynamic range that floating points provide (i.e. all displays are in integer
|
||||||
|
depth format), bit-depth reduction/dithering would kick in. In OPP, we would
|
||||||
|
also apply a regamma function to introduce the gamma removed earlier back.
|
||||||
|
Eventually, we output data in integer format at DIO.
|
||||||
|
|
||||||
|
Global Sync
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Many DCN registers are double buffered, most importantly the surface address.
|
||||||
|
This allows us to update DCN hardware atomically for page flips, as well as
|
||||||
|
for most other updates that don't require enabling or disabling of new pipes.
|
||||||
|
|
||||||
|
(Note: There are many scenarios when DC will decide to reserve extra pipes
|
||||||
|
in order to support outputs that need a very high pixel clock, or for
|
||||||
|
power saving purposes.)
|
||||||
|
|
||||||
|
These atomic register updates are driven by global sync signals in DCN. In
|
||||||
|
order to understand how atomic updates interact with DCN hardware, and how DCN
|
||||||
|
signals page flip and vblank events it is helpful to understand how global sync
|
||||||
|
is programmed.
|
||||||
|
|
||||||
|
Global sync consists of three signals, VSTARTUP, VUPDATE, and VREADY. These are
|
||||||
|
calculated by the Display Mode Library - DML (drivers/gpu/drm/amd/display/dc/dml)
|
||||||
|
based on a large number of parameters and ensure our hardware is able to feed
|
||||||
|
the DCN pipeline without underflows or hangs in any given system configuration.
|
||||||
|
The global sync signals always happen during VBlank, are independent from the
|
||||||
|
VSync signal, and do not overlap each other.
|
||||||
|
|
||||||
|
VUPDATE is the only signal that is of interest to the rest of the driver stack
|
||||||
|
or userspace clients as it signals the point at which hardware latches to
|
||||||
|
atomically programmed (i.e. double buffered) registers. Even though it is
|
||||||
|
independent of the VSync signal we use VUPDATE to signal the VSync event as it
|
||||||
|
provides the best indication of how atomic commits and hardware interact.
|
||||||
|
|
||||||
|
Since DCN hardware is double-buffered the DC driver is able to program the
|
||||||
|
hardware at any point during the frame.
|
||||||
|
|
||||||
|
The below picture illustrates the global sync signals:
|
||||||
|
|
||||||
|
.. kernel-figure:: global_sync_vblank.svg
|
||||||
|
|
||||||
|
These signals affect core DCN behavior. Programming them incorrectly will lead
|
||||||
|
to a number of negative consequences, most of them quite catastrophic.
|
||||||
|
|
||||||
|
The following picture shows how global sync allows for a mailbox style of
|
||||||
|
updates, i.e. it allows for multiple re-configurations between VUpdate
|
||||||
|
events where only the last configuration programmed before the VUpdate signal
|
||||||
|
becomes effective.
|
||||||
|
|
||||||
|
.. kernel-figure:: config_example.svg
|
42
Documentation/gpu/amdgpu/display/display-manager.rst
Normal file
42
Documentation/gpu/amdgpu/display/display-manager.rst
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
======================
|
||||||
|
AMDgpu Display Manager
|
||||||
|
======================
|
||||||
|
|
||||||
|
.. contents:: Table of Contents
|
||||||
|
:depth: 3
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||||
|
:doc: overview
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
Lifecycle
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||||
|
:doc: DM Lifecycle
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||||
|
:functions: dm_hw_init dm_hw_fini
|
||||||
|
|
||||||
|
Interrupts
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
||||||
|
:doc: overview
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||||
|
:functions: register_hpd_handlers dm_crtc_high_irq dm_pflip_high_irq
|
||||||
|
|
||||||
|
Atomic Implementation
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||||
|
:doc: atomic
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||||
|
:functions: amdgpu_dm_atomic_check amdgpu_dm_atomic_commit_tail
|
485
Documentation/gpu/amdgpu/display/global_sync_vblank.svg
Normal file
485
Documentation/gpu/amdgpu/display/global_sync_vblank.svg
Normal file
@ -0,0 +1,485 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="232.24133mm"
|
||||||
|
height="96.174995mm"
|
||||||
|
viewBox="0 0 232.24133 96.174995"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||||
|
sodipodi:docname="global_sync_vblank.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Mend"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path862"
|
||||||
|
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="scale(-0.6)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Send"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path868"
|
||||||
|
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Lend"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path856"
|
||||||
|
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="marker1719"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path1717"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="marker1661"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path1659"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:isstock="true"
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker1311"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto"
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path1309"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:isstock="true"
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker1253"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto"
|
||||||
|
inkscape:stockid="Arrow1Lstart">
|
||||||
|
<path
|
||||||
|
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path1251"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<path
|
||||||
|
id="path838"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lstart"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<path
|
||||||
|
id="path835"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Send"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path850"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Sstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Sstart"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path865"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Mend-2"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path862-3"
|
||||||
|
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="scale(-0.6)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Mend-2-5"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path862-3-9"
|
||||||
|
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="scale(-0.6)" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.979899"
|
||||||
|
inkscape:cx="747.52324"
|
||||||
|
inkscape:cy="319.84503"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="2096"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid815"
|
||||||
|
originx="15.282997"
|
||||||
|
originy="-184.54792" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(15.282998,-16.277083)">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 15.875,27.125001 V 16.541666 H 26.458333 V 27.125001 H 177.27084 V 16.541666 h 10.58333 v 10.583335 h 29.10416"
|
||||||
|
id="path817"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 15.875,37.708334 H 44.979166 V 48.291667 H 100.54167 V 37.708334 H 206.375 v 10.583333 h 10.58333"
|
||||||
|
id="path819"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 15.875,66.8125 h 97.89583 V 56.229167 h 7.9375 V 66.8125 h 92.60417"
|
||||||
|
id="path821"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 15.875,85.333334 c 0,0 132.29166,0 132.29166,0 V 74.75 h 15.875 v 10.583334 h 47.625"
|
||||||
|
id="path823"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 15.875,101.20833 H 187.85416 V 90.625 h 10.58334 v 10.58333 h 10.58333"
|
||||||
|
id="path825"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916667;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="M 100.54167,48.291667 V 111.79167"
|
||||||
|
id="path827"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916667;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="m 113.77083,66.8125 v 44.97917"
|
||||||
|
id="path829"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916667;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="M 206.375,48.291667 V 109.14583"
|
||||||
|
id="path831"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
|
||||||
|
d="m 100.54167,106.5 h 13.22916"
|
||||||
|
id="path833"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1253);marker-end:url(#marker1311)"
|
||||||
|
d="M 113.77083,106.5 H 206.375"
|
||||||
|
id="path1243"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="105.83333"
|
||||||
|
y="111.79166"
|
||||||
|
id="text1405"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1403"
|
||||||
|
x="105.83333"
|
||||||
|
y="111.79166"
|
||||||
|
style="stroke-width:0.26458332">To</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="145.52083"
|
||||||
|
y="111.79166"
|
||||||
|
id="text1409"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1407"
|
||||||
|
x="145.52083"
|
||||||
|
y="111.79166"
|
||||||
|
style="stroke-width:0.26458332">VStartup Period</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="156.01123"
|
||||||
|
y="78.71875"
|
||||||
|
id="text1413"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="156.01123"
|
||||||
|
y="78.71875"
|
||||||
|
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||||
|
id="tspan1415">VUpdate</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="156.01123"
|
||||||
|
y="82.6875"
|
||||||
|
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||||
|
id="tspan1440">Width</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="173.77611"
|
||||||
|
y="92.703873"
|
||||||
|
id="text1413-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1411-6"
|
||||||
|
x="173.77611"
|
||||||
|
y="92.703873"
|
||||||
|
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332">VReady</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="173.77611"
|
||||||
|
y="96.672623"
|
||||||
|
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||||
|
id="tspan1415-7">Offset</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="135.78951"
|
||||||
|
y="70.78125"
|
||||||
|
id="text1413-5"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="135.78951"
|
||||||
|
y="70.78125"
|
||||||
|
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||||
|
id="tspan1440-5">VUpdate</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="135.78951"
|
||||||
|
y="74.75"
|
||||||
|
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||||
|
id="tspan1465">Offset</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="137.39433"
|
||||||
|
y="48.291664"
|
||||||
|
id="text1479"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1477"
|
||||||
|
x="137.39433"
|
||||||
|
y="48.291664"
|
||||||
|
style="font-weight:bold;stroke-width:0.26458332">VSTARTUP_START</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="-5.4806676"
|
||||||
|
y="22.778271"
|
||||||
|
id="text1479-1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1477-2"
|
||||||
|
x="-5.4806676"
|
||||||
|
y="22.778271"
|
||||||
|
style="font-weight:bold;font-size:4.93888903px;stroke-width:0.26458332">VSYNC</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="-9.3767252"
|
||||||
|
y="45.64584"
|
||||||
|
id="text1479-1-7"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1477-2-0"
|
||||||
|
x="-9.3767252"
|
||||||
|
y="45.64584"
|
||||||
|
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VBlank</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="-15.310558"
|
||||||
|
y="64.92263"
|
||||||
|
id="text1479-1-7-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1477-2-0-3"
|
||||||
|
x="-15.310558"
|
||||||
|
y="64.92263"
|
||||||
|
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VStartup</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="-14.17781"
|
||||||
|
y="85.144356"
|
||||||
|
id="text1479-1-7-9-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1477-2-0-3-0"
|
||||||
|
x="-14.17781"
|
||||||
|
y="85.144356"
|
||||||
|
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VUpdate</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="-11.052421"
|
||||||
|
y="101.39733"
|
||||||
|
id="text1479-1-7-9-6-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1477-2-0-3-0-2"
|
||||||
|
x="-11.052421"
|
||||||
|
y="101.39733"
|
||||||
|
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VReady</tspan></text>
|
||||||
|
<g
|
||||||
|
id="g5189"
|
||||||
|
transform="translate(269.875,-14.287499)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5143"
|
||||||
|
d="m -202.40625,45.645828 3.96875,-7.9375"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5143-2"
|
||||||
|
d="m -199.76042,45.645828 3.96874,-7.937499"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g5189-3"
|
||||||
|
transform="translate(268.55209,7.9375003)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5143-6"
|
||||||
|
d="m -202.40625,45.645828 3.96875,-7.9375"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5143-2-1"
|
||||||
|
d="m -199.76042,45.645828 3.96874,-7.937499"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 20 KiB |
31
Documentation/gpu/amdgpu/display/index.rst
Normal file
31
Documentation/gpu/amdgpu/display/index.rst
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
.. _amdgpu-display-core:
|
||||||
|
|
||||||
|
===================================
|
||||||
|
drm/amd/display - Display Core (DC)
|
||||||
|
===================================
|
||||||
|
|
||||||
|
AMD display engine is partially shared with other operating systems; for this
|
||||||
|
reason, our Display Core Driver is divided into two pieces:
|
||||||
|
|
||||||
|
1. **Display Core (DC)** contains the OS-agnostic components. Things like
|
||||||
|
hardware programming and resource management are handled here.
|
||||||
|
2. **Display Manager (DM)** contains the OS-dependent components. Hooks to the
|
||||||
|
amdgpu base driver and DRM are implemented here.
|
||||||
|
|
||||||
|
The display pipe is responsible for "scanning out" a rendered frame from the
|
||||||
|
GPU memory (also called VRAM, FrameBuffer, etc.) to a display. In other words,
|
||||||
|
it would:
|
||||||
|
|
||||||
|
1. Read frame information from memory;
|
||||||
|
2. Perform required transformation;
|
||||||
|
3. Send pixel data to sink devices.
|
||||||
|
|
||||||
|
If you want to learn more about our driver details, take a look at the below
|
||||||
|
table of content:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
display-manager.rst
|
||||||
|
dc-debug.rst
|
||||||
|
dcn-overview.rst
|
||||||
|
dc-glossary.rst
|
182
Documentation/gpu/amdgpu/driver-core.rst
Normal file
182
Documentation/gpu/amdgpu/driver-core.rst
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
============================
|
||||||
|
Core Driver Infrastructure
|
||||||
|
============================
|
||||||
|
|
||||||
|
GPU Hardware Structure
|
||||||
|
======================
|
||||||
|
|
||||||
|
Each ASIC is a collection of hardware blocks. We refer to them as
|
||||||
|
"IPs" (Intellectual Property blocks). Each IP encapsulates certain
|
||||||
|
functionality. IPs are versioned and can also be mixed and matched.
|
||||||
|
E.g., you might have two different ASICs that both have System DMA (SDMA) 5.x IPs.
|
||||||
|
The driver is arranged by IPs. There are driver components to handle
|
||||||
|
the initialization and operation of each IP. There are also a bunch
|
||||||
|
of smaller IPs that don't really need much if any driver interaction.
|
||||||
|
Those end up getting lumped into the common stuff in the soc files.
|
||||||
|
The soc files (e.g., vi.c, soc15.c nv.c) contain code for aspects of
|
||||||
|
the SoC itself rather than specific IPs. E.g., things like GPU resets
|
||||||
|
and register access functions are SoC dependent.
|
||||||
|
|
||||||
|
An APU contains more than just CPU and GPU, it also contains all of
|
||||||
|
the platform stuff (audio, usb, gpio, etc.). Also, a lot of
|
||||||
|
components are shared between the CPU, platform, and the GPU (e.g.,
|
||||||
|
SMU, PSP, etc.). Specific components (CPU, GPU, etc.) usually have
|
||||||
|
their interface to interact with those common components. For things
|
||||||
|
like S0i3 there is a ton of coordination required across all the
|
||||||
|
components, but that is probably a bit beyond the scope of this
|
||||||
|
section.
|
||||||
|
|
||||||
|
With respect to the GPU, we have the following major IPs:
|
||||||
|
|
||||||
|
GMC (Graphics Memory Controller)
|
||||||
|
This was a dedicated IP on older pre-vega chips, but has since
|
||||||
|
become somewhat decentralized on vega and newer chips. They now
|
||||||
|
have dedicated memory hubs for specific IPs or groups of IPs. We
|
||||||
|
still treat it as a single component in the driver however since
|
||||||
|
the programming model is still pretty similar. This is how the
|
||||||
|
different IPs on the GPU get the memory (VRAM or system memory).
|
||||||
|
It also provides the support for per process GPU virtual address
|
||||||
|
spaces.
|
||||||
|
|
||||||
|
IH (Interrupt Handler)
|
||||||
|
This is the interrupt controller on the GPU. All of the IPs feed
|
||||||
|
their interrupts into this IP and it aggregates them into a set of
|
||||||
|
ring buffers that the driver can parse to handle interrupts from
|
||||||
|
different IPs.
|
||||||
|
|
||||||
|
PSP (Platform Security Processor)
|
||||||
|
This handles security policy for the SoC and executes trusted
|
||||||
|
applications, and validates and loads firmwares for other blocks.
|
||||||
|
|
||||||
|
SMU (System Management Unit)
|
||||||
|
This is the power management microcontroller. It manages the entire
|
||||||
|
SoC. The driver interacts with it to control power management
|
||||||
|
features like clocks, voltages, power rails, etc.
|
||||||
|
|
||||||
|
DCN (Display Controller Next)
|
||||||
|
This is the display controller. It handles the display hardware.
|
||||||
|
It is described in more details in :ref:`Display Core <amdgpu-display-core>`.
|
||||||
|
|
||||||
|
SDMA (System DMA)
|
||||||
|
This is a multi-purpose DMA engine. The kernel driver uses it for
|
||||||
|
various things including paging and GPU page table updates. It's also
|
||||||
|
exposed to userspace for use by user mode drivers (OpenGL, Vulkan,
|
||||||
|
etc.)
|
||||||
|
|
||||||
|
GC (Graphics and Compute)
|
||||||
|
This is the graphics and compute engine, i.e., the block that
|
||||||
|
encompasses the 3D pipeline and and shader blocks. This is by far the
|
||||||
|
largest block on the GPU. The 3D pipeline has tons of sub-blocks. In
|
||||||
|
addition to that, it also contains the CP microcontrollers (ME, PFP,
|
||||||
|
CE, MEC) and the RLC microcontroller. It's exposed to userspace for
|
||||||
|
user mode drivers (OpenGL, Vulkan, OpenCL, etc.)
|
||||||
|
|
||||||
|
VCN (Video Core Next)
|
||||||
|
This is the multi-media engine. It handles video and image encode and
|
||||||
|
decode. It's exposed to userspace for user mode drivers (VA-API,
|
||||||
|
OpenMAX, etc.)
|
||||||
|
|
||||||
|
Graphics and Compute Microcontrollers
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
CP (Command Processor)
|
||||||
|
The name for the hardware block that encompasses the front end of the
|
||||||
|
GFX/Compute pipeline. Consists mainly of a bunch of microcontrollers
|
||||||
|
(PFP, ME, CE, MEC). The firmware that runs on these microcontrollers
|
||||||
|
provides the driver interface to interact with the GFX/Compute engine.
|
||||||
|
|
||||||
|
MEC (MicroEngine Compute)
|
||||||
|
This is the microcontroller that controls the compute queues on the
|
||||||
|
GFX/compute engine.
|
||||||
|
|
||||||
|
MES (MicroEngine Scheduler)
|
||||||
|
This is a new engine for managing queues. This is currently unused.
|
||||||
|
|
||||||
|
RLC (RunList Controller)
|
||||||
|
This is another microcontroller in the GFX/Compute engine. It handles
|
||||||
|
power management related functionality within the GFX/Compute engine.
|
||||||
|
The name is a vestige of old hardware where it was originally added
|
||||||
|
and doesn't really have much relation to what the engine does now.
|
||||||
|
|
||||||
|
Driver Structure
|
||||||
|
================
|
||||||
|
|
||||||
|
In general, the driver has a list of all of the IPs on a particular
|
||||||
|
SoC and for things like init/fini/suspend/resume, more or less just
|
||||||
|
walks the list and handles each IP.
|
||||||
|
|
||||||
|
Some useful constructs:
|
||||||
|
|
||||||
|
KIQ (Kernel Interface Queue)
|
||||||
|
This is a control queue used by the kernel driver to manage other gfx
|
||||||
|
and compute queues on the GFX/compute engine. You can use it to
|
||||||
|
map/unmap additional queues, etc.
|
||||||
|
|
||||||
|
IB (Indirect Buffer)
|
||||||
|
A command buffer for a particular engine. Rather than writing
|
||||||
|
commands directly to the queue, you can write the commands into a
|
||||||
|
piece of memory and then put a pointer to the memory into the queue.
|
||||||
|
The hardware will then follow the pointer and execute the commands in
|
||||||
|
the memory, then returning to the rest of the commands in the ring.
|
||||||
|
|
||||||
|
.. _amdgpu_memory_domains:
|
||||||
|
|
||||||
|
Memory Domains
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. kernel-doc:: include/uapi/drm/amdgpu_drm.h
|
||||||
|
:doc: memory domains
|
||||||
|
|
||||||
|
Buffer Objects
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
||||||
|
:doc: amdgpu_object
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
PRIME Buffer Sharing
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
||||||
|
:doc: PRIME Buffer Sharing
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
MMU Notifier
|
||||||
|
============
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
||||||
|
:doc: MMU Notifier
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
AMDGPU Virtual Memory
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
||||||
|
:doc: GPUVM
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
Interrupt Handling
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
||||||
|
:doc: Interrupt Handling
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
IP Blocks
|
||||||
|
=========
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||||
|
:doc: IP Blocks
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||||
|
:identifiers: amd_ip_block_type amd_ip_funcs
|
112
Documentation/gpu/amdgpu/driver-misc.rst
Normal file
112
Documentation/gpu/amdgpu/driver-misc.rst
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
================================
|
||||||
|
Misc AMDGPU driver information
|
||||||
|
================================
|
||||||
|
|
||||||
|
GPU Product Information
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Information about the GPU can be obtained on certain cards
|
||||||
|
via sysfs
|
||||||
|
|
||||||
|
product_name
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||||
|
:doc: product_name
|
||||||
|
|
||||||
|
product_number
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||||
|
:doc: product_name
|
||||||
|
|
||||||
|
serial_number
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||||
|
:doc: serial_number
|
||||||
|
|
||||||
|
unique_id
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: unique_id
|
||||||
|
|
||||||
|
GPU Memory Usage Information
|
||||||
|
============================
|
||||||
|
|
||||||
|
Various memory accounting can be accessed via sysfs
|
||||||
|
|
||||||
|
mem_info_vram_total
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||||
|
:doc: mem_info_vram_total
|
||||||
|
|
||||||
|
mem_info_vram_used
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||||
|
:doc: mem_info_vram_used
|
||||||
|
|
||||||
|
mem_info_vis_vram_total
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||||
|
:doc: mem_info_vis_vram_total
|
||||||
|
|
||||||
|
mem_info_vis_vram_used
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||||
|
:doc: mem_info_vis_vram_used
|
||||||
|
|
||||||
|
mem_info_gtt_total
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
||||||
|
:doc: mem_info_gtt_total
|
||||||
|
|
||||||
|
mem_info_gtt_used
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
||||||
|
:doc: mem_info_gtt_used
|
||||||
|
|
||||||
|
PCIe Accounting Information
|
||||||
|
===========================
|
||||||
|
|
||||||
|
pcie_bw
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: pcie_bw
|
||||||
|
|
||||||
|
pcie_replay_count
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||||
|
:doc: pcie_replay_count
|
||||||
|
|
||||||
|
GPU SmartShift Information
|
||||||
|
==========================
|
||||||
|
|
||||||
|
GPU SmartShift information via sysfs
|
||||||
|
|
||||||
|
smartshift_apu_power
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: smartshift_apu_power
|
||||||
|
|
||||||
|
smartshift_dgpu_power
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: smartshift_dgpu_power
|
||||||
|
|
||||||
|
smartshift_bias
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: smartshift_bias
|
17
Documentation/gpu/amdgpu/index.rst
Normal file
17
Documentation/gpu/amdgpu/index.rst
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
==========================
|
||||||
|
drm/amdgpu AMDgpu driver
|
||||||
|
==========================
|
||||||
|
|
||||||
|
The drm/amdgpu driver supports all AMD Radeon GPUs based on the Graphics Core
|
||||||
|
Next (GCN) architecture.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
module-parameters
|
||||||
|
driver-core
|
||||||
|
display/index
|
||||||
|
xgmi
|
||||||
|
ras
|
||||||
|
thermal
|
||||||
|
driver-misc
|
||||||
|
amdgpu-glossary
|
7
Documentation/gpu/amdgpu/module-parameters.rst
Normal file
7
Documentation/gpu/amdgpu/module-parameters.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
===================
|
||||||
|
Module Parameters
|
||||||
|
===================
|
||||||
|
|
||||||
|
The amdgpu driver supports the following module parameters:
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
62
Documentation/gpu/amdgpu/ras.rst
Normal file
62
Documentation/gpu/amdgpu/ras.rst
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
====================
|
||||||
|
AMDGPU RAS Support
|
||||||
|
====================
|
||||||
|
|
||||||
|
The AMDGPU RAS interfaces are exposed via sysfs (for informational queries) and
|
||||||
|
debugfs (for error injection).
|
||||||
|
|
||||||
|
RAS debugfs/sysfs Control and Error Injection Interfaces
|
||||||
|
========================================================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||||
|
:doc: AMDGPU RAS debugfs control interface
|
||||||
|
|
||||||
|
RAS Reboot Behavior for Unrecoverable Errors
|
||||||
|
============================================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||||
|
:doc: AMDGPU RAS Reboot Behavior for Unrecoverable Errors
|
||||||
|
|
||||||
|
RAS Error Count sysfs Interface
|
||||||
|
===============================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||||
|
:doc: AMDGPU RAS sysfs Error Count Interface
|
||||||
|
|
||||||
|
RAS EEPROM debugfs Interface
|
||||||
|
============================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||||
|
:doc: AMDGPU RAS debugfs EEPROM table reset interface
|
||||||
|
|
||||||
|
RAS VRAM Bad Pages sysfs Interface
|
||||||
|
==================================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||||
|
:doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
|
||||||
|
|
||||||
|
Sample Code
|
||||||
|
===========
|
||||||
|
Sample code for testing error injection can be found here:
|
||||||
|
https://cgit.freedesktop.org/mesa/drm/tree/tests/amdgpu/ras_tests.c
|
||||||
|
|
||||||
|
This is part of the libdrm amdgpu unit tests which cover several areas of the GPU.
|
||||||
|
There are four sets of tests:
|
||||||
|
|
||||||
|
RAS Basic Test
|
||||||
|
|
||||||
|
The test verifies the RAS feature enabled status and makes sure the necessary sysfs and debugfs files
|
||||||
|
are present.
|
||||||
|
|
||||||
|
RAS Query Test
|
||||||
|
|
||||||
|
This test checks the RAS availability and enablement status for each supported IP block as well as
|
||||||
|
the error counts.
|
||||||
|
|
||||||
|
RAS Inject Test
|
||||||
|
|
||||||
|
This test injects errors for each IP.
|
||||||
|
|
||||||
|
RAS Disable Test
|
||||||
|
|
||||||
|
This test tests disabling of RAS features for each IP block.
|
65
Documentation/gpu/amdgpu/thermal.rst
Normal file
65
Documentation/gpu/amdgpu/thermal.rst
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
===========================================
|
||||||
|
GPU Power/Thermal Controls and Monitoring
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
HWMON Interfaces
|
||||||
|
================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: hwmon
|
||||||
|
|
||||||
|
GPU sysfs Power State Interfaces
|
||||||
|
================================
|
||||||
|
|
||||||
|
GPU power controls are exposed via sysfs files.
|
||||||
|
|
||||||
|
power_dpm_state
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: power_dpm_state
|
||||||
|
|
||||||
|
power_dpm_force_performance_level
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: power_dpm_force_performance_level
|
||||||
|
|
||||||
|
pp_table
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: pp_table
|
||||||
|
|
||||||
|
pp_od_clk_voltage
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: pp_od_clk_voltage
|
||||||
|
|
||||||
|
pp_dpm_*
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie
|
||||||
|
|
||||||
|
pp_power_profile_mode
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: pp_power_profile_mode
|
||||||
|
|
||||||
|
\*_busy_percent
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: gpu_busy_percent
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: mem_busy_percent
|
||||||
|
|
||||||
|
gpu_metrics
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||||
|
:doc: gpu_metrics
|
5
Documentation/gpu/amdgpu/xgmi.rst
Normal file
5
Documentation/gpu/amdgpu/xgmi.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
=====================
|
||||||
|
AMDGPU XGMI Support
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
@ -4,8 +4,7 @@ GPU Driver Documentation
|
|||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
amdgpu
|
amdgpu/index
|
||||||
amdgpu-dc
|
|
||||||
i915
|
i915
|
||||||
mcde
|
mcde
|
||||||
meson
|
meson
|
||||||
|
@ -435,3 +435,18 @@ Legacy CRTC/Modeset Helper Functions Reference
|
|||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
|
Privacy-screen class
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c
|
||||||
|
:doc: overview
|
||||||
|
|
||||||
|
.. kernel-doc:: include/drm/drm_privacy_screen_driver.h
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
.. kernel-doc:: include/drm/drm_privacy_screen_machine.h
|
||||||
|
:internal:
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c
|
||||||
|
:export:
|
||||||
|
@ -506,6 +506,8 @@ Property Types and Blob Property Support
|
|||||||
.. kernel-doc:: drivers/gpu/drm/drm_property.c
|
.. kernel-doc:: drivers/gpu/drm/drm_property.c
|
||||||
:export:
|
:export:
|
||||||
|
|
||||||
|
.. _standard_connector_properties:
|
||||||
|
|
||||||
Standard Connector Properties
|
Standard Connector Properties
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
@ -268,17 +268,6 @@ Contact: Daniel Vetter
|
|||||||
|
|
||||||
Level: Intermediate
|
Level: Intermediate
|
||||||
|
|
||||||
Clean up mmap forwarding
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
A lot of drivers forward gem mmap calls to dma-buf mmap for imported buffers.
|
|
||||||
And also a lot of them forward dma-buf mmap to the gem mmap implementations.
|
|
||||||
There's drm_gem_prime_mmap() for this now, but still needs to be rolled out.
|
|
||||||
|
|
||||||
Contact: Daniel Vetter
|
|
||||||
|
|
||||||
Level: Intermediate
|
|
||||||
|
|
||||||
Generic fbdev defio support
|
Generic fbdev defio support
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
@ -463,6 +452,21 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>, Christian König, Daniel Vette
|
|||||||
|
|
||||||
Level: Intermediate
|
Level: Intermediate
|
||||||
|
|
||||||
|
Review all drivers for setting struct drm_mode_config.{max_width,max_height} correctly
|
||||||
|
--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The values in struct drm_mode_config.{max_width,max_height} describe the
|
||||||
|
maximum supported framebuffer size. It's the virtual screen size, but many
|
||||||
|
drivers treat it like limitations of the physical resolution.
|
||||||
|
|
||||||
|
The maximum width depends on the hardware's maximum scanline pitch. The
|
||||||
|
maximum height depends on the amount of addressable video memory. Review all
|
||||||
|
drivers to initialize the fields to the correct values.
|
||||||
|
|
||||||
|
Contact: Thomas Zimmermann <tzimmermann@suse.de>
|
||||||
|
|
||||||
|
Level: Intermediate
|
||||||
|
|
||||||
|
|
||||||
Core refactorings
|
Core refactorings
|
||||||
=================
|
=================
|
||||||
@ -642,6 +646,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks.
|
|||||||
|
|
||||||
Contact: Harry Wentland, Alex Deucher
|
Contact: Harry Wentland, Alex Deucher
|
||||||
|
|
||||||
|
vmwgfx: Replace hashtable with Linux' implementation
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
The vmwgfx driver uses its own hashtable implementation. Replace the
|
||||||
|
code with Linux' implementation and update the callers. It's mostly a
|
||||||
|
refactoring task, but the interfaces are different.
|
||||||
|
|
||||||
|
Contact: Zack Rusin, Thomas Zimmermann <tzimmermann@suse.de>
|
||||||
|
|
||||||
|
Level: Intermediate
|
||||||
|
|
||||||
Bootsplash
|
Bootsplash
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
23
MAINTAINERS
23
MAINTAINERS
@ -966,6 +966,7 @@ F: drivers/gpu/drm/amd/include/kgd_kfd_interface.h
|
|||||||
F: drivers/gpu/drm/amd/include/v9_structs.h
|
F: drivers/gpu/drm/amd/include/v9_structs.h
|
||||||
F: drivers/gpu/drm/amd/include/vi_structs.h
|
F: drivers/gpu/drm/amd/include/vi_structs.h
|
||||||
F: include/uapi/linux/kfd_ioctl.h
|
F: include/uapi/linux/kfd_ioctl.h
|
||||||
|
F: include/uapi/linux/kfd_sysfs.h
|
||||||
|
|
||||||
AMD SPI DRIVER
|
AMD SPI DRIVER
|
||||||
M: Sanjay R Mehta <sanju.mehta@amd.com>
|
M: Sanjay R Mehta <sanju.mehta@amd.com>
|
||||||
@ -6057,6 +6058,7 @@ F: drivers/gpu/drm/tiny/mi0283qt.c
|
|||||||
DRM DRIVER FOR MSM ADRENO GPU
|
DRM DRIVER FOR MSM ADRENO GPU
|
||||||
M: Rob Clark <robdclark@gmail.com>
|
M: Rob Clark <robdclark@gmail.com>
|
||||||
M: Sean Paul <sean@poorly.run>
|
M: Sean Paul <sean@poorly.run>
|
||||||
|
R: Abhinav Kumar <quic_abhinavk@quicinc.com>
|
||||||
L: linux-arm-msm@vger.kernel.org
|
L: linux-arm-msm@vger.kernel.org
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
L: freedreno@lists.freedesktop.org
|
L: freedreno@lists.freedesktop.org
|
||||||
@ -6082,10 +6084,17 @@ F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
|
|||||||
|
|
||||||
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
|
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
|
||||||
M: Ben Skeggs <bskeggs@redhat.com>
|
M: Ben Skeggs <bskeggs@redhat.com>
|
||||||
|
M: Karol Herbst <kherbst@redhat.com>
|
||||||
|
M: Lyude Paul <lyude@redhat.com>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
L: nouveau@lists.freedesktop.org
|
L: nouveau@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
T: git git://github.com/skeggsb/linux
|
W: https://nouveau.freedesktop.org/
|
||||||
|
Q: https://patchwork.freedesktop.org/project/nouveau/
|
||||||
|
Q: https://gitlab.freedesktop.org/drm/nouveau/-/merge_requests
|
||||||
|
B: https://gitlab.freedesktop.org/drm/nouveau/-/issues
|
||||||
|
C: irc://irc.oftc.net/nouveau
|
||||||
|
T: git https://gitlab.freedesktop.org/drm/nouveau.git
|
||||||
F: drivers/gpu/drm/nouveau/
|
F: drivers/gpu/drm/nouveau/
|
||||||
F: include/uapi/drm/nouveau_drm.h
|
F: include/uapi/drm/nouveau_drm.h
|
||||||
|
|
||||||
@ -6425,6 +6434,7 @@ L: dri-devel@lists.freedesktop.org
|
|||||||
L: linux-renesas-soc@vger.kernel.org
|
L: linux-renesas-soc@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
T: git git://linuxtv.org/pinchartl/media drm/du/next
|
T: git git://linuxtv.org/pinchartl/media drm/du/next
|
||||||
|
F: Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
|
||||||
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
|
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
|
||||||
F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
|
F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
|
||||||
F: Documentation/devicetree/bindings/display/renesas,du.yaml
|
F: Documentation/devicetree/bindings/display/renesas,du.yaml
|
||||||
@ -6543,6 +6553,14 @@ F: drivers/gpu/drm/drm_panel.c
|
|||||||
F: drivers/gpu/drm/panel/
|
F: drivers/gpu/drm/panel/
|
||||||
F: include/drm/drm_panel.h
|
F: include/drm/drm_panel.h
|
||||||
|
|
||||||
|
DRM PRIVACY-SCREEN CLASS
|
||||||
|
M: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
L: dri-devel@lists.freedesktop.org
|
||||||
|
S: Maintained
|
||||||
|
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||||
|
F: drivers/gpu/drm/drm_privacy_screen*
|
||||||
|
F: include/drm/drm_privacy_screen*
|
||||||
|
|
||||||
DRM TTM SUBSYSTEM
|
DRM TTM SUBSYSTEM
|
||||||
M: Christian Koenig <christian.koenig@amd.com>
|
M: Christian Koenig <christian.koenig@amd.com>
|
||||||
M: Huang Rui <ray.huang@amd.com>
|
M: Huang Rui <ray.huang@amd.com>
|
||||||
@ -9506,6 +9524,7 @@ INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
|
|||||||
M: Jani Nikula <jani.nikula@linux.intel.com>
|
M: Jani Nikula <jani.nikula@linux.intel.com>
|
||||||
M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
|
M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
|
||||||
M: Rodrigo Vivi <rodrigo.vivi@intel.com>
|
M: Rodrigo Vivi <rodrigo.vivi@intel.com>
|
||||||
|
M: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
|
||||||
L: intel-gfx@lists.freedesktop.org
|
L: intel-gfx@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: https://01.org/linuxgraphics/
|
W: https://01.org/linuxgraphics/
|
||||||
@ -20235,6 +20254,8 @@ F: include/uapi/linux/virtio_gpio.h
|
|||||||
VIRTIO GPU DRIVER
|
VIRTIO GPU DRIVER
|
||||||
M: David Airlie <airlied@linux.ie>
|
M: David Airlie <airlied@linux.ie>
|
||||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
R: Gurchetan Singh <gurchetansingh@chromium.org>
|
||||||
|
R: Chia-I Wu <olvaffe@gmail.com>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
L: virtualization@lists.linux-foundation.org
|
L: virtualization@lists.linux-foundation.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
@ -554,6 +554,7 @@ static const struct pci_device_id intel_early_ids[] __initconst = {
|
|||||||
INTEL_RKL_IDS(&gen11_early_ops),
|
INTEL_RKL_IDS(&gen11_early_ops),
|
||||||
INTEL_ADLS_IDS(&gen11_early_ops),
|
INTEL_ADLS_IDS(&gen11_early_ops),
|
||||||
INTEL_ADLP_IDS(&gen11_early_ops),
|
INTEL_ADLP_IDS(&gen11_early_ops),
|
||||||
|
INTEL_RPLS_IDS(&gen11_early_ops),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0);
|
struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/agp_backend.h>
|
#include <linux/agp_backend.h>
|
||||||
|
#include <linux/intel-iommu.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include "agp.h"
|
#include "agp.h"
|
||||||
|
@ -932,8 +932,7 @@ static int bcm2835_clock_is_on(struct clk_hw *hw)
|
|||||||
|
|
||||||
static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
unsigned long rate,
|
||||||
unsigned long parent_rate,
|
unsigned long parent_rate)
|
||||||
bool round_up)
|
|
||||||
{
|
{
|
||||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||||
const struct bcm2835_clock_data *data = clock->data;
|
const struct bcm2835_clock_data *data = clock->data;
|
||||||
@ -945,10 +944,6 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
|||||||
|
|
||||||
rem = do_div(temp, rate);
|
rem = do_div(temp, rate);
|
||||||
div = temp;
|
div = temp;
|
||||||
|
|
||||||
/* Round up and mask off the unused bits */
|
|
||||||
if (round_up && ((div & unused_frac_mask) != 0 || rem != 0))
|
|
||||||
div += unused_frac_mask + 1;
|
|
||||||
div &= ~unused_frac_mask;
|
div &= ~unused_frac_mask;
|
||||||
|
|
||||||
/* different clamping limits apply for a mash clock */
|
/* different clamping limits apply for a mash clock */
|
||||||
@ -1079,7 +1074,7 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
|
|||||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||||
struct bcm2835_cprman *cprman = clock->cprman;
|
struct bcm2835_cprman *cprman = clock->cprman;
|
||||||
const struct bcm2835_clock_data *data = clock->data;
|
const struct bcm2835_clock_data *data = clock->data;
|
||||||
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
|
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
|
||||||
u32 ctl;
|
u32 ctl;
|
||||||
|
|
||||||
spin_lock(&cprman->regs_lock);
|
spin_lock(&cprman->regs_lock);
|
||||||
@ -1130,7 +1125,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
|
|||||||
|
|
||||||
if (!(BIT(parent_idx) & data->set_rate_parent)) {
|
if (!(BIT(parent_idx) & data->set_rate_parent)) {
|
||||||
*prate = clk_hw_get_rate(parent);
|
*prate = clk_hw_get_rate(parent);
|
||||||
*div = bcm2835_clock_choose_div(hw, rate, *prate, true);
|
*div = bcm2835_clock_choose_div(hw, rate, *prate);
|
||||||
|
|
||||||
*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
|
*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
|
||||||
|
|
||||||
@ -1216,7 +1211,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
|
|||||||
rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
|
rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
|
||||||
&div, &prate,
|
&div, &prate,
|
||||||
&avgrate);
|
&avgrate);
|
||||||
if (rate > best_rate && rate <= req->rate) {
|
if (abs(req->rate - rate) < abs(req->rate - best_rate)) {
|
||||||
best_parent = parent;
|
best_parent = parent;
|
||||||
best_prate = prate;
|
best_prate = prate;
|
||||||
best_rate = rate;
|
best_rate = rate;
|
||||||
|
@ -11,6 +11,7 @@ obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o
|
|||||||
dmabuf_selftests-y := \
|
dmabuf_selftests-y := \
|
||||||
selftest.o \
|
selftest.o \
|
||||||
st-dma-fence.o \
|
st-dma-fence.o \
|
||||||
st-dma-fence-chain.o
|
st-dma-fence-chain.o \
|
||||||
|
st-dma-resv.o
|
||||||
|
|
||||||
obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
|
obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
|
||||||
|
@ -299,10 +299,8 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* dma_buf_set_name - Set a name to a specific dma_buf to track the usage.
|
* dma_buf_set_name - Set a name to a specific dma_buf to track the usage.
|
||||||
* The name of the dma-buf buffer can only be set when the dma-buf is not
|
* It could support changing the name of the dma-buf if the same
|
||||||
* attached to any devices. It could theoritically support changing the
|
* piece of memory is used for multiple purpose between different devices.
|
||||||
* name of the dma-buf if the same piece of memory is used for multiple
|
|
||||||
* purpose between different devices.
|
|
||||||
*
|
*
|
||||||
* @dmabuf: [in] dmabuf buffer that will be renamed.
|
* @dmabuf: [in] dmabuf buffer that will be renamed.
|
||||||
* @buf: [in] A piece of userspace memory that contains the name of
|
* @buf: [in] A piece of userspace memory that contains the name of
|
||||||
@ -315,25 +313,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
|
|||||||
static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
|
static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
|
||||||
{
|
{
|
||||||
char *name = strndup_user(buf, DMA_BUF_NAME_LEN);
|
char *name = strndup_user(buf, DMA_BUF_NAME_LEN);
|
||||||
long ret = 0;
|
|
||||||
|
|
||||||
if (IS_ERR(name))
|
if (IS_ERR(name))
|
||||||
return PTR_ERR(name);
|
return PTR_ERR(name);
|
||||||
|
|
||||||
dma_resv_lock(dmabuf->resv, NULL);
|
|
||||||
if (!list_empty(&dmabuf->attachments)) {
|
|
||||||
ret = -EBUSY;
|
|
||||||
kfree(name);
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
spin_lock(&dmabuf->name_lock);
|
spin_lock(&dmabuf->name_lock);
|
||||||
kfree(dmabuf->name);
|
kfree(dmabuf->name);
|
||||||
dmabuf->name = name;
|
dmabuf->name = name;
|
||||||
spin_unlock(&dmabuf->name_lock);
|
spin_unlock(&dmabuf->name_lock);
|
||||||
|
|
||||||
out_unlock:
|
return 0;
|
||||||
dma_resv_unlock(dmabuf->resv);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long dma_buf_ioctl(struct file *file,
|
static long dma_buf_ioctl(struct file *file,
|
||||||
@ -1058,8 +1047,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF);
|
|||||||
*
|
*
|
||||||
* Interfaces::
|
* Interfaces::
|
||||||
*
|
*
|
||||||
* void \*dma_buf_vmap(struct dma_buf \*dmabuf)
|
* void \*dma_buf_vmap(struct dma_buf \*dmabuf, struct dma_buf_map \*map)
|
||||||
* void dma_buf_vunmap(struct dma_buf \*dmabuf, void \*vaddr)
|
* void dma_buf_vunmap(struct dma_buf \*dmabuf, struct dma_buf_map \*map)
|
||||||
*
|
*
|
||||||
* The vmap call can fail if there is no vmap support in the exporter, or if
|
* The vmap call can fail if there is no vmap support in the exporter, or if
|
||||||
* it runs out of vmalloc space. Note that the dma-buf layer keeps a reference
|
* it runs out of vmalloc space. Note that the dma-buf layer keeps a reference
|
||||||
@ -1391,8 +1380,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||||||
{
|
{
|
||||||
struct dma_buf *buf_obj;
|
struct dma_buf *buf_obj;
|
||||||
struct dma_buf_attachment *attach_obj;
|
struct dma_buf_attachment *attach_obj;
|
||||||
struct dma_resv_iter cursor;
|
|
||||||
struct dma_fence *fence;
|
|
||||||
int count = 0, attach_count;
|
int count = 0, attach_count;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1423,14 +1410,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||||||
buf_obj->name ?: "");
|
buf_obj->name ?: "");
|
||||||
spin_unlock(&buf_obj->name_lock);
|
spin_unlock(&buf_obj->name_lock);
|
||||||
|
|
||||||
dma_resv_for_each_fence(&cursor, buf_obj->resv, true, fence) {
|
dma_resv_describe(buf_obj->resv, s);
|
||||||
seq_printf(s, "\t%s fence: %s %s %ssignalled\n",
|
|
||||||
dma_resv_iter_is_exclusive(&cursor) ?
|
|
||||||
"Exclusive" : "Shared",
|
|
||||||
fence->ops->get_driver_name(fence),
|
|
||||||
fence->ops->get_timeline_name(fence),
|
|
||||||
dma_fence_is_signaled(fence) ? "" : "un");
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_puts(s, "\tAttached Devices:\n");
|
seq_puts(s, "\tAttached Devices:\n");
|
||||||
attach_count = 0;
|
attach_count = 0;
|
||||||
|
@ -104,7 +104,11 @@ static bool dma_fence_array_signaled(struct dma_fence *fence)
|
|||||||
{
|
{
|
||||||
struct dma_fence_array *array = to_dma_fence_array(fence);
|
struct dma_fence_array *array = to_dma_fence_array(fence);
|
||||||
|
|
||||||
return atomic_read(&array->num_pending) <= 0;
|
if (atomic_read(&array->num_pending) > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dma_fence_array_clear_pending_error(array);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dma_fence_array_release(struct dma_fence *fence)
|
static void dma_fence_array_release(struct dma_fence *fence)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/dma-fence.h>
|
#include <linux/dma-fence.h>
|
||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/dma_fence.h>
|
#include <trace/events/dma_fence.h>
|
||||||
@ -907,6 +908,22 @@ dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t count,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dma_fence_wait_any_timeout);
|
EXPORT_SYMBOL(dma_fence_wait_any_timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dma_fence_describe - Dump fence describtion into seq_file
|
||||||
|
* @fence: the 6fence to describe
|
||||||
|
* @seq: the seq_file to put the textual description into
|
||||||
|
*
|
||||||
|
* Dump a textual description of the fence and it's state into the seq_file.
|
||||||
|
*/
|
||||||
|
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
|
||||||
|
{
|
||||||
|
seq_printf(seq, "%s %s seq %llu %ssignalled\n",
|
||||||
|
fence->ops->get_driver_name(fence),
|
||||||
|
fence->ops->get_timeline_name(fence), fence->seqno,
|
||||||
|
dma_fence_is_signaled(fence) ? "" : "un");
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dma_fence_describe);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dma_fence_init - Initialize a custom fence.
|
* dma_fence_init - Initialize a custom fence.
|
||||||
* @fence: the fence to initialize
|
* @fence: the fence to initialize
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/sched/mm.h>
|
#include <linux/sched/mm.h>
|
||||||
#include <linux/mmu_notifier.h>
|
#include <linux/mmu_notifier.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOC: Reservation Object Overview
|
* DOC: Reservation Object Overview
|
||||||
@ -304,8 +305,7 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
|
|||||||
if (old)
|
if (old)
|
||||||
i = old->shared_count;
|
i = old->shared_count;
|
||||||
|
|
||||||
if (fence)
|
dma_fence_get(fence);
|
||||||
dma_fence_get(fence);
|
|
||||||
|
|
||||||
write_seqcount_begin(&obj->seq);
|
write_seqcount_begin(&obj->seq);
|
||||||
/* write_seqcount_begin provides the necessary memory barrier */
|
/* write_seqcount_begin provides the necessary memory barrier */
|
||||||
@ -666,6 +666,28 @@ bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dma_resv_test_signaled);
|
EXPORT_SYMBOL_GPL(dma_resv_test_signaled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dma_resv_describe - Dump description of the resv object into seq_file
|
||||||
|
* @obj: the reservation object
|
||||||
|
* @seq: the seq_file to dump the description into
|
||||||
|
*
|
||||||
|
* Dump a textual description of the fences inside an dma_resv object into the
|
||||||
|
* seq_file.
|
||||||
|
*/
|
||||||
|
void dma_resv_describe(struct dma_resv *obj, struct seq_file *seq)
|
||||||
|
{
|
||||||
|
struct dma_resv_iter cursor;
|
||||||
|
struct dma_fence *fence;
|
||||||
|
|
||||||
|
dma_resv_for_each_fence(&cursor, obj, true, fence) {
|
||||||
|
seq_printf(seq, "\t%s fence:",
|
||||||
|
dma_resv_iter_is_exclusive(&cursor) ?
|
||||||
|
"Exclusive" : "Shared");
|
||||||
|
dma_fence_describe(fence, seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dma_resv_describe);
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_LOCKDEP)
|
#if IS_ENABLED(CONFIG_LOCKDEP)
|
||||||
static int __init dma_resv_lockdep(void)
|
static int __init dma_resv_lockdep(void)
|
||||||
{
|
{
|
||||||
|
@ -12,3 +12,4 @@
|
|||||||
selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
|
selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
|
||||||
selftest(dma_fence, dma_fence)
|
selftest(dma_fence, dma_fence)
|
||||||
selftest(dma_fence_chain, dma_fence_chain)
|
selftest(dma_fence_chain, dma_fence_chain)
|
||||||
|
selftest(dma_resv, dma_resv)
|
||||||
|
371
drivers/dma-buf/st-dma-resv.c
Normal file
371
drivers/dma-buf/st-dma-resv.c
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Intel Corporation
|
||||||
|
* Copyright © 2021 Advanced Micro Devices, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/dma-resv.h>
|
||||||
|
|
||||||
|
#include "selftest.h"
|
||||||
|
|
||||||
|
static struct spinlock fence_lock;
|
||||||
|
|
||||||
|
static const char *fence_name(struct dma_fence *f)
|
||||||
|
{
|
||||||
|
return "selftest";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dma_fence_ops fence_ops = {
|
||||||
|
.get_driver_name = fence_name,
|
||||||
|
.get_timeline_name = fence_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dma_fence *alloc_fence(void)
|
||||||
|
{
|
||||||
|
struct dma_fence *f;
|
||||||
|
|
||||||
|
f = kmalloc(sizeof(*f), GFP_KERNEL);
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dma_fence_init(f, &fence_ops, &fence_lock, 0, 0);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sanitycheck(void *arg)
|
||||||
|
{
|
||||||
|
struct dma_resv resv;
|
||||||
|
struct dma_fence *f;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
f = alloc_fence();
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_fence_signal(f);
|
||||||
|
dma_fence_put(f);
|
||||||
|
|
||||||
|
dma_resv_init(&resv);
|
||||||
|
r = dma_resv_lock(&resv, NULL);
|
||||||
|
if (r)
|
||||||
|
pr_err("Resv locking failed\n");
|
||||||
|
else
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
dma_resv_fini(&resv);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_signaling(void *arg, bool shared)
|
||||||
|
{
|
||||||
|
struct dma_resv resv;
|
||||||
|
struct dma_fence *f;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
f = alloc_fence();
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_resv_init(&resv);
|
||||||
|
r = dma_resv_lock(&resv, NULL);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv locking failed\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shared) {
|
||||||
|
r = dma_resv_reserve_shared(&resv, 1);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv shared slot allocation failed\n");
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_resv_add_shared_fence(&resv, f);
|
||||||
|
} else {
|
||||||
|
dma_resv_add_excl_fence(&resv, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_resv_test_signaled(&resv, shared)) {
|
||||||
|
pr_err("Resv unexpectedly signaled\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
dma_fence_signal(f);
|
||||||
|
if (!dma_resv_test_signaled(&resv, shared)) {
|
||||||
|
pr_err("Resv not reporting signaled\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
err_unlock:
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
err_free:
|
||||||
|
dma_resv_fini(&resv);
|
||||||
|
dma_fence_put(f);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_excl_signaling(void *arg)
|
||||||
|
{
|
||||||
|
return test_signaling(arg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_shared_signaling(void *arg)
|
||||||
|
{
|
||||||
|
return test_signaling(arg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_for_each(void *arg, bool shared)
|
||||||
|
{
|
||||||
|
struct dma_resv_iter cursor;
|
||||||
|
struct dma_fence *f, *fence;
|
||||||
|
struct dma_resv resv;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
f = alloc_fence();
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_resv_init(&resv);
|
||||||
|
r = dma_resv_lock(&resv, NULL);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv locking failed\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shared) {
|
||||||
|
r = dma_resv_reserve_shared(&resv, 1);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv shared slot allocation failed\n");
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_resv_add_shared_fence(&resv, f);
|
||||||
|
} else {
|
||||||
|
dma_resv_add_excl_fence(&resv, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = -ENOENT;
|
||||||
|
dma_resv_for_each_fence(&cursor, &resv, shared, fence) {
|
||||||
|
if (!r) {
|
||||||
|
pr_err("More than one fence found\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
if (f != fence) {
|
||||||
|
pr_err("Unexpected fence\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
|
||||||
|
pr_err("Unexpected fence usage\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
if (r) {
|
||||||
|
pr_err("No fence found\n");
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
dma_fence_signal(f);
|
||||||
|
err_unlock:
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
err_free:
|
||||||
|
dma_resv_fini(&resv);
|
||||||
|
dma_fence_put(f);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_excl_for_each(void *arg)
|
||||||
|
{
|
||||||
|
return test_for_each(arg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_shared_for_each(void *arg)
|
||||||
|
{
|
||||||
|
return test_for_each(arg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_for_each_unlocked(void *arg, bool shared)
|
||||||
|
{
|
||||||
|
struct dma_resv_iter cursor;
|
||||||
|
struct dma_fence *f, *fence;
|
||||||
|
struct dma_resv resv;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
f = alloc_fence();
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_resv_init(&resv);
|
||||||
|
r = dma_resv_lock(&resv, NULL);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv locking failed\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shared) {
|
||||||
|
r = dma_resv_reserve_shared(&resv, 1);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv shared slot allocation failed\n");
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_resv_add_shared_fence(&resv, f);
|
||||||
|
} else {
|
||||||
|
dma_resv_add_excl_fence(&resv, f);
|
||||||
|
}
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
|
||||||
|
r = -ENOENT;
|
||||||
|
dma_resv_iter_begin(&cursor, &resv, shared);
|
||||||
|
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
||||||
|
if (!r) {
|
||||||
|
pr_err("More than one fence found\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_iter_end;
|
||||||
|
}
|
||||||
|
if (!dma_resv_iter_is_restarted(&cursor)) {
|
||||||
|
pr_err("No restart flag\n");
|
||||||
|
goto err_iter_end;
|
||||||
|
}
|
||||||
|
if (f != fence) {
|
||||||
|
pr_err("Unexpected fence\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_iter_end;
|
||||||
|
}
|
||||||
|
if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
|
||||||
|
pr_err("Unexpected fence usage\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto err_iter_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use r as state here */
|
||||||
|
if (r == -ENOENT) {
|
||||||
|
r = -EINVAL;
|
||||||
|
/* That should trigger an restart */
|
||||||
|
cursor.seq--;
|
||||||
|
} else if (r == -EINVAL) {
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r)
|
||||||
|
pr_err("No fence found\n");
|
||||||
|
err_iter_end:
|
||||||
|
dma_resv_iter_end(&cursor);
|
||||||
|
dma_fence_signal(f);
|
||||||
|
err_free:
|
||||||
|
dma_resv_fini(&resv);
|
||||||
|
dma_fence_put(f);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_excl_for_each_unlocked(void *arg)
|
||||||
|
{
|
||||||
|
return test_for_each_unlocked(arg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_shared_for_each_unlocked(void *arg)
|
||||||
|
{
|
||||||
|
return test_for_each_unlocked(arg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_get_fences(void *arg, bool shared)
|
||||||
|
{
|
||||||
|
struct dma_fence *f, *excl = NULL, **fences = NULL;
|
||||||
|
struct dma_resv resv;
|
||||||
|
int r, i;
|
||||||
|
|
||||||
|
f = alloc_fence();
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_resv_init(&resv);
|
||||||
|
r = dma_resv_lock(&resv, NULL);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv locking failed\n");
|
||||||
|
goto err_resv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shared) {
|
||||||
|
r = dma_resv_reserve_shared(&resv, 1);
|
||||||
|
if (r) {
|
||||||
|
pr_err("Resv shared slot allocation failed\n");
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
goto err_resv;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_resv_add_shared_fence(&resv, f);
|
||||||
|
} else {
|
||||||
|
dma_resv_add_excl_fence(&resv, f);
|
||||||
|
}
|
||||||
|
dma_resv_unlock(&resv);
|
||||||
|
|
||||||
|
r = dma_resv_get_fences(&resv, &excl, &i, &fences);
|
||||||
|
if (r) {
|
||||||
|
pr_err("get_fences failed\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shared) {
|
||||||
|
if (excl != NULL) {
|
||||||
|
pr_err("get_fences returned unexpected excl fence\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
if (i != 1 || fences[0] != f) {
|
||||||
|
pr_err("get_fences returned unexpected shared fence\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (excl != f) {
|
||||||
|
pr_err("get_fences returned unexpected excl fence\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
if (i != 0) {
|
||||||
|
pr_err("get_fences returned unexpected shared fence\n");
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_fence_signal(f);
|
||||||
|
err_free:
|
||||||
|
dma_fence_put(excl);
|
||||||
|
while (i--)
|
||||||
|
dma_fence_put(fences[i]);
|
||||||
|
kfree(fences);
|
||||||
|
err_resv:
|
||||||
|
dma_resv_fini(&resv);
|
||||||
|
dma_fence_put(f);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_excl_get_fences(void *arg)
|
||||||
|
{
|
||||||
|
return test_get_fences(arg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_shared_get_fences(void *arg)
|
||||||
|
{
|
||||||
|
return test_get_fences(arg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dma_resv(void)
|
||||||
|
{
|
||||||
|
static const struct subtest tests[] = {
|
||||||
|
SUBTEST(sanitycheck),
|
||||||
|
SUBTEST(test_excl_signaling),
|
||||||
|
SUBTEST(test_shared_signaling),
|
||||||
|
SUBTEST(test_excl_for_each),
|
||||||
|
SUBTEST(test_shared_for_each),
|
||||||
|
SUBTEST(test_excl_for_each_unlocked),
|
||||||
|
SUBTEST(test_shared_for_each_unlocked),
|
||||||
|
SUBTEST(test_excl_get_fences),
|
||||||
|
SUBTEST(test_shared_get_fences),
|
||||||
|
};
|
||||||
|
|
||||||
|
spin_lock_init(&fence_lock);
|
||||||
|
return subtests(tests, NULL);
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
menuconfig DRM
|
menuconfig DRM
|
||||||
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
|
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
|
||||||
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA
|
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA
|
||||||
|
select DRM_NOMODESET
|
||||||
select DRM_PANEL_ORIENTATION_QUIRKS
|
select DRM_PANEL_ORIENTATION_QUIRKS
|
||||||
select HDMI
|
select HDMI
|
||||||
select FB_CMDLINE
|
select FB_CMDLINE
|
||||||
@ -211,20 +212,13 @@ config DRM_TTM_HELPER
|
|||||||
Helpers for ttm-based gem objects
|
Helpers for ttm-based gem objects
|
||||||
|
|
||||||
config DRM_GEM_CMA_HELPER
|
config DRM_GEM_CMA_HELPER
|
||||||
bool
|
tristate
|
||||||
depends on DRM
|
depends on DRM
|
||||||
help
|
help
|
||||||
Choose this if you need the GEM CMA helper functions
|
Choose this if you need the GEM CMA helper functions
|
||||||
|
|
||||||
config DRM_KMS_CMA_HELPER
|
|
||||||
bool
|
|
||||||
depends on DRM
|
|
||||||
select DRM_GEM_CMA_HELPER
|
|
||||||
help
|
|
||||||
Choose this if you need the KMS CMA helper functions
|
|
||||||
|
|
||||||
config DRM_GEM_SHMEM_HELPER
|
config DRM_GEM_SHMEM_HELPER
|
||||||
bool
|
tristate
|
||||||
depends on DRM && MMU
|
depends on DRM && MMU
|
||||||
help
|
help
|
||||||
Choose this if you need the GEM shmem helper functions
|
Choose this if you need the GEM shmem helper functions
|
||||||
@ -394,6 +388,8 @@ source "drivers/gpu/drm/xlnx/Kconfig"
|
|||||||
|
|
||||||
source "drivers/gpu/drm/gud/Kconfig"
|
source "drivers/gpu/drm/gud/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/gpu/drm/sprd/Kconfig"
|
||||||
|
|
||||||
config DRM_HYPERV
|
config DRM_HYPERV
|
||||||
tristate "DRM Support for Hyper-V synthetic video device"
|
tristate "DRM Support for Hyper-V synthetic video device"
|
||||||
depends on DRM && PCI && MMU && HYPERV
|
depends on DRM && PCI && MMU && HYPERV
|
||||||
@ -492,6 +488,15 @@ config DRM_EXPORT_FOR_TESTS
|
|||||||
config DRM_PANEL_ORIENTATION_QUIRKS
|
config DRM_PANEL_ORIENTATION_QUIRKS
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
|
# Separate option because nomodeset parameter is global and expected built-in
|
||||||
|
config DRM_NOMODESET
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
|
||||||
config DRM_LIB_RANDOM
|
config DRM_LIB_RANDOM
|
||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config DRM_PRIVACY_SCREEN
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
@ -4,37 +4,44 @@
|
|||||||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||||
|
|
||||||
drm-y := drm_aperture.o drm_auth.o drm_cache.o \
|
drm-y := drm_aperture.o drm_auth.o drm_cache.o \
|
||||||
drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \
|
drm_file.o drm_gem.o drm_ioctl.o \
|
||||||
drm_drv.o \
|
drm_drv.o \
|
||||||
drm_sysfs.o drm_hashtab.o drm_mm.o \
|
drm_sysfs.o drm_mm.o \
|
||||||
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \
|
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \
|
||||||
drm_encoder_slave.o \
|
|
||||||
drm_trace_points.o drm_prime.o \
|
drm_trace_points.o drm_prime.o \
|
||||||
drm_rect.o drm_vma_manager.o drm_flip_work.o \
|
drm_vma_manager.o \
|
||||||
drm_modeset_lock.o drm_atomic.o drm_bridge.o \
|
drm_modeset_lock.o drm_atomic.o drm_bridge.o \
|
||||||
drm_framebuffer.o drm_connector.o drm_blend.o \
|
drm_framebuffer.o drm_connector.o drm_blend.o \
|
||||||
drm_encoder.o drm_mode_object.o drm_property.o \
|
drm_encoder.o drm_mode_object.o drm_property.o \
|
||||||
drm_plane.o drm_color_mgmt.o drm_print.o \
|
drm_plane.o drm_color_mgmt.o drm_print.o \
|
||||||
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
|
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
|
||||||
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
|
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
|
||||||
drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
|
drm_client_modeset.o drm_atomic_uapi.o \
|
||||||
drm_managed.o drm_vblank_work.o
|
drm_managed.o drm_vblank_work.o
|
||||||
|
|
||||||
drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o drm_dma.o \
|
drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o drm_dma.o \
|
||||||
drm_legacy_misc.o drm_lock.o drm_memory.o drm_scatter.o \
|
drm_hashtab.o drm_irq.o drm_legacy_misc.o drm_lock.o \
|
||||||
drm_vm.o
|
drm_memory.o drm_scatter.o drm_vm.o
|
||||||
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
|
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
|
||||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||||
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
|
||||||
drm-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_gem_shmem_helper.o
|
|
||||||
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
|
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
|
||||||
drm-$(CONFIG_OF) += drm_of.o
|
drm-$(CONFIG_OF) += drm_of.o
|
||||||
drm-$(CONFIG_PCI) += drm_pci.o
|
drm-$(CONFIG_PCI) += drm_pci.o
|
||||||
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
|
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
|
||||||
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||||
|
drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o
|
||||||
|
|
||||||
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
|
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
|
||||||
|
|
||||||
|
drm_cma_helper-y := drm_gem_cma_helper.o
|
||||||
|
drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o
|
||||||
|
obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o
|
||||||
|
|
||||||
|
drm_shmem_helper-y := drm_gem_shmem_helper.o
|
||||||
|
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
|
||||||
|
|
||||||
drm_vram_helper-y := drm_gem_vram_helper.o
|
drm_vram_helper-y := drm_gem_vram_helper.o
|
||||||
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
|
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
|
||||||
|
|
||||||
@ -42,18 +49,18 @@ drm_ttm_helper-y := drm_gem_ttm_helper.o
|
|||||||
obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
|
obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
|
||||||
|
|
||||||
drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
|
drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
|
||||||
drm_dsc.o drm_probe_helper.o \
|
drm_dsc.o drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \
|
||||||
|
drm_probe_helper.o \
|
||||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
||||||
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
|
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
|
||||||
drm_simple_kms_helper.o drm_modeset_helper.o \
|
drm_simple_kms_helper.o drm_modeset_helper.o \
|
||||||
drm_scdc_helper.o drm_gem_atomic_helper.o \
|
drm_scdc_helper.o drm_gem_atomic_helper.o \
|
||||||
drm_gem_framebuffer_helper.o \
|
drm_gem_framebuffer_helper.o \
|
||||||
drm_atomic_state_helper.o drm_damage_helper.o \
|
drm_atomic_state_helper.o drm_damage_helper.o \
|
||||||
drm_format_helper.o drm_self_refresh_helper.o
|
drm_format_helper.o drm_self_refresh_helper.o drm_rect.o
|
||||||
|
|
||||||
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
|
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
|
|
||||||
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
|
drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
|
||||||
|
|
||||||
@ -127,3 +134,4 @@ obj-$(CONFIG_DRM_TIDSS) += tidss/
|
|||||||
obj-y += xlnx/
|
obj-y += xlnx/
|
||||||
obj-y += gud/
|
obj-y += gud/
|
||||||
obj-$(CONFIG_DRM_HYPERV) += hyperv/
|
obj-$(CONFIG_DRM_HYPERV) += hyperv/
|
||||||
|
obj-$(CONFIG_DRM_SPRD) += sprd/
|
||||||
|
@ -45,7 +45,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
|
|||||||
amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \
|
amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \
|
||||||
atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \
|
atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \
|
||||||
amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \
|
amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \
|
||||||
amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \
|
amdgpu_gem.o amdgpu_ring.o \
|
||||||
amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \
|
amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \
|
||||||
atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \
|
atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \
|
||||||
atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
|
atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
|
||||||
|
@ -458,7 +458,6 @@ struct amdgpu_flip_work {
|
|||||||
uint64_t base;
|
uint64_t base;
|
||||||
struct drm_pending_vblank_event *event;
|
struct drm_pending_vblank_event *event;
|
||||||
struct amdgpu_bo *old_abo;
|
struct amdgpu_bo *old_abo;
|
||||||
struct dma_fence *excl;
|
|
||||||
unsigned shared_count;
|
unsigned shared_count;
|
||||||
struct dma_fence **shared;
|
struct dma_fence **shared;
|
||||||
struct dma_fence_cb cb;
|
struct dma_fence_cb cb;
|
||||||
@ -813,6 +812,7 @@ struct amd_powerplay {
|
|||||||
|
|
||||||
#define AMDGPU_RESET_MAGIC_NUM 64
|
#define AMDGPU_RESET_MAGIC_NUM 64
|
||||||
#define AMDGPU_MAX_DF_PERFMONS 4
|
#define AMDGPU_MAX_DF_PERFMONS 4
|
||||||
|
#define AMDGPU_PRODUCT_NAME_LEN 64
|
||||||
struct amdgpu_device {
|
struct amdgpu_device {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
@ -1084,7 +1084,7 @@ struct amdgpu_device {
|
|||||||
|
|
||||||
/* Chip product information */
|
/* Chip product information */
|
||||||
char product_number[16];
|
char product_number[16];
|
||||||
char product_name[32];
|
char product_name[AMDGPU_PRODUCT_NAME_LEN];
|
||||||
char serial[20];
|
char serial[20];
|
||||||
|
|
||||||
atomic_t throttling_logging_enabled;
|
atomic_t throttling_logging_enabled;
|
||||||
@ -1097,7 +1097,9 @@ struct amdgpu_device {
|
|||||||
pci_channel_state_t pci_channel_state;
|
pci_channel_state_t pci_channel_state;
|
||||||
|
|
||||||
struct amdgpu_reset_control *reset_cntl;
|
struct amdgpu_reset_control *reset_cntl;
|
||||||
uint32_t ip_versions[HW_ID_MAX][HWIP_MAX_INSTANCE];
|
uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||||
|
|
||||||
|
bool ram_is_direct_mapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
||||||
@ -1318,6 +1320,8 @@ void amdgpu_device_flush_hdp(struct amdgpu_device *adev,
|
|||||||
void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
||||||
struct amdgpu_ring *ring);
|
struct amdgpu_ring *ring);
|
||||||
|
|
||||||
|
void amdgpu_device_halt(struct amdgpu_device *adev);
|
||||||
|
|
||||||
/* atpx handler */
|
/* atpx handler */
|
||||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||||
void amdgpu_register_atpx_handler(void);
|
void amdgpu_register_atpx_handler(void);
|
||||||
@ -1361,8 +1365,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
|
|||||||
u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc);
|
u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc);
|
||||||
int amdgpu_enable_vblank_kms(struct drm_crtc *crtc);
|
int amdgpu_enable_vblank_kms(struct drm_crtc *crtc);
|
||||||
void amdgpu_disable_vblank_kms(struct drm_crtc *crtc);
|
void amdgpu_disable_vblank_kms(struct drm_crtc *crtc);
|
||||||
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
|
|
||||||
unsigned long arg);
|
|
||||||
int amdgpu_info_ioctl(struct drm_device *dev, void *data,
|
int amdgpu_info_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *filp);
|
struct drm_file *filp);
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
|||||||
if (!kfd_initialized)
|
if (!kfd_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev, vf);
|
adev->kfd.dev = kgd2kfd_probe(adev, vf);
|
||||||
|
|
||||||
if (adev->kfd.dev)
|
if (adev->kfd.dev)
|
||||||
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
|
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
|
||||||
@ -233,19 +233,16 @@ int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd)
|
void amdgpu_amdkfd_gpu_reset(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
if (amdgpu_device_should_recover_gpu(adev))
|
if (amdgpu_device_should_recover_gpu(adev))
|
||||||
amdgpu_device_gpu_recover(adev, NULL);
|
amdgpu_device_gpu_recover(adev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
|
||||||
void **mem_obj, uint64_t *gpu_addr,
|
void **mem_obj, uint64_t *gpu_addr,
|
||||||
void **cpu_ptr, bool cp_mqd_gfx9)
|
void **cpu_ptr, bool cp_mqd_gfx9)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct amdgpu_bo *bo = NULL;
|
struct amdgpu_bo *bo = NULL;
|
||||||
struct amdgpu_bo_param bp;
|
struct amdgpu_bo_param bp;
|
||||||
int r;
|
int r;
|
||||||
@ -314,7 +311,7 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)
|
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj)
|
||||||
{
|
{
|
||||||
struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj;
|
struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj;
|
||||||
|
|
||||||
@ -325,10 +322,9 @@ void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)
|
|||||||
amdgpu_bo_unref(&(bo));
|
amdgpu_bo_unref(&(bo));
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size,
|
int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
|
||||||
void **mem_obj)
|
void **mem_obj)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct amdgpu_bo *bo = NULL;
|
struct amdgpu_bo *bo = NULL;
|
||||||
struct amdgpu_bo_user *ubo;
|
struct amdgpu_bo_user *ubo;
|
||||||
struct amdgpu_bo_param bp;
|
struct amdgpu_bo_param bp;
|
||||||
@ -355,18 +351,16 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj)
|
void amdgpu_amdkfd_free_gws(struct amdgpu_device *adev, void *mem_obj)
|
||||||
{
|
{
|
||||||
struct amdgpu_bo *bo = (struct amdgpu_bo *)mem_obj;
|
struct amdgpu_bo *bo = (struct amdgpu_bo *)mem_obj;
|
||||||
|
|
||||||
amdgpu_bo_unref(&bo);
|
amdgpu_bo_unref(&bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd,
|
uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
|
||||||
enum kgd_engine_type type)
|
enum kgd_engine_type type)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case KGD_ENGINE_PFP:
|
case KGD_ENGINE_PFP:
|
||||||
return adev->gfx.pfp_fw_version;
|
return adev->gfx.pfp_fw_version;
|
||||||
@ -399,11 +393,9 @@ uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
|
||||||
struct kfd_local_mem_info *mem_info)
|
struct kfd_local_mem_info *mem_info)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
memset(mem_info, 0, sizeof(*mem_info));
|
memset(mem_info, 0, sizeof(*mem_info));
|
||||||
|
|
||||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||||
@ -428,19 +420,15 @@ void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
|||||||
mem_info->mem_clk_max = 100;
|
mem_info->mem_clk_max = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct kgd_dev *kgd)
|
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
if (adev->gfx.funcs->get_gpu_clock_counter)
|
if (adev->gfx.funcs->get_gpu_clock_counter)
|
||||||
return adev->gfx.funcs->get_gpu_clock_counter(adev);
|
return adev->gfx.funcs->get_gpu_clock_counter(adev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
|
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
/* the sclk is in quantas of 10kHz */
|
/* the sclk is in quantas of 10kHz */
|
||||||
if (amdgpu_sriov_vf(adev))
|
if (amdgpu_sriov_vf(adev))
|
||||||
return adev->clock.default_sclk / 100;
|
return adev->clock.default_sclk / 100;
|
||||||
@ -450,9 +438,8 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info)
|
void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev, struct kfd_cu_info *cu_info)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct amdgpu_cu_info acu_info = adev->gfx.cu_info;
|
struct amdgpu_cu_info acu_info = adev->gfx.cu_info;
|
||||||
|
|
||||||
memset(cu_info, 0, sizeof(*cu_info));
|
memset(cu_info, 0, sizeof(*cu_info));
|
||||||
@ -473,13 +460,12 @@ void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info)
|
|||||||
cu_info->lds_size = acu_info.lds_size;
|
cu_info->lds_size = acu_info.lds_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||||
struct kgd_dev **dma_buf_kgd,
|
struct amdgpu_device **dmabuf_adev,
|
||||||
uint64_t *bo_size, void *metadata_buffer,
|
uint64_t *bo_size, void *metadata_buffer,
|
||||||
size_t buffer_size, uint32_t *metadata_size,
|
size_t buffer_size, uint32_t *metadata_size,
|
||||||
uint32_t *flags)
|
uint32_t *flags)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct dma_buf *dma_buf;
|
struct dma_buf *dma_buf;
|
||||||
struct drm_gem_object *obj;
|
struct drm_gem_object *obj;
|
||||||
struct amdgpu_bo *bo;
|
struct amdgpu_bo *bo;
|
||||||
@ -507,8 +493,8 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
|||||||
goto out_put;
|
goto out_put;
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
if (dma_buf_kgd)
|
if (dmabuf_adev)
|
||||||
*dma_buf_kgd = (struct kgd_dev *)adev;
|
*dmabuf_adev = adev;
|
||||||
if (bo_size)
|
if (bo_size)
|
||||||
*bo_size = amdgpu_bo_size(bo);
|
*bo_size = amdgpu_bo_size(bo);
|
||||||
if (metadata_buffer)
|
if (metadata_buffer)
|
||||||
@ -528,32 +514,18 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd)
|
uint64_t amdgpu_amdkfd_get_vram_usage(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||||
|
|
||||||
return amdgpu_vram_mgr_usage(vram_man);
|
return amdgpu_vram_mgr_usage(vram_man);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd)
|
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||||
|
struct amdgpu_device *src)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
struct amdgpu_device *peer_adev = src;
|
||||||
|
struct amdgpu_device *adev = dst;
|
||||||
return adev->gmc.xgmi.hive_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t amdgpu_amdkfd_get_unique_id(struct kgd_dev *kgd)
|
|
||||||
{
|
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
return adev->unique_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src)
|
|
||||||
{
|
|
||||||
struct amdgpu_device *peer_adev = (struct amdgpu_device *)src;
|
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)dst;
|
|
||||||
int ret = amdgpu_xgmi_get_hops_count(adev, peer_adev);
|
int ret = amdgpu_xgmi_get_hops_count(adev, peer_adev);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -565,16 +537,18 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
|
|||||||
return (uint8_t)ret;
|
return (uint8_t)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min)
|
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||||
|
struct amdgpu_device *src,
|
||||||
|
bool is_min)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)dst, *peer_adev;
|
struct amdgpu_device *adev = dst, *peer_adev;
|
||||||
int num_links;
|
int num_links;
|
||||||
|
|
||||||
if (adev->asic_type != CHIP_ALDEBARAN)
|
if (adev->asic_type != CHIP_ALDEBARAN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (src)
|
if (src)
|
||||||
peer_adev = (struct amdgpu_device *)src;
|
peer_adev = src;
|
||||||
|
|
||||||
/* num links returns 0 for indirect peers since indirect route is unknown. */
|
/* num links returns 0 for indirect peers since indirect route is unknown. */
|
||||||
num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev);
|
num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev);
|
||||||
@ -589,9 +563,8 @@ int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev
|
|||||||
return (num_links * 16 * 25000)/BITS_PER_BYTE;
|
return (num_links * 16 * 25000)/BITS_PER_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min)
|
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)dev;
|
|
||||||
int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) :
|
int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) :
|
||||||
fls(adev->pm.pcie_mlw_mask)) - 1;
|
fls(adev->pm.pcie_mlw_mask)) - 1;
|
||||||
int gen_speed_shift = (is_min ? ffs(adev->pm.pcie_gen_mask &
|
int gen_speed_shift = (is_min ? ffs(adev->pm.pcie_gen_mask &
|
||||||
@ -647,39 +620,11 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min)
|
|||||||
return (num_lanes_factor * gen_speed_mbits_factor)/BITS_PER_BYTE;
|
return (num_lanes_factor * gen_speed_mbits_factor)/BITS_PER_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd)
|
int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||||
{
|
enum kgd_engine_type engine,
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
return adev->rmmio_remap.bus_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd)
|
|
||||||
{
|
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
return adev->gds.gws_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd)
|
|
||||||
{
|
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
return adev->rev_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd)
|
|
||||||
{
|
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
return adev->gmc.noretry;
|
|
||||||
}
|
|
||||||
|
|
||||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
|
||||||
uint32_t vmid, uint64_t gpu_addr,
|
uint32_t vmid, uint64_t gpu_addr,
|
||||||
uint32_t *ib_cmd, uint32_t ib_len)
|
uint32_t *ib_cmd, uint32_t ib_len)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct amdgpu_job *job;
|
struct amdgpu_job *job;
|
||||||
struct amdgpu_ib *ib;
|
struct amdgpu_ib *ib;
|
||||||
struct amdgpu_ring *ring;
|
struct amdgpu_ring *ring;
|
||||||
@ -730,10 +675,8 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
|
void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
amdgpu_dpm_switch_power_profile(adev,
|
amdgpu_dpm_switch_power_profile(adev,
|
||||||
PP_SMC_POWER_PROFILE_COMPUTE,
|
PP_SMC_POWER_PROFILE_COMPUTE,
|
||||||
!idle);
|
!idle);
|
||||||
@ -747,10 +690,9 @@ bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
|
||||||
|
uint16_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
if (adev->family == AMDGPU_FAMILY_AI) {
|
if (adev->family == AMDGPU_FAMILY_AI) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -763,10 +705,9 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
|
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||||
enum TLB_FLUSH_TYPE flush_type)
|
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
bool all_hub = false;
|
bool all_hub = false;
|
||||||
|
|
||||||
if (adev->family == AMDGPU_FAMILY_AI)
|
if (adev->family == AMDGPU_FAMILY_AI)
|
||||||
@ -775,21 +716,18 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
|
|||||||
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
|
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd)
|
bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
return adev->have_atomics_support;
|
return adev->have_atomics_support;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct kgd_dev *kgd)
|
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct ras_err_data err_data = {0, 0, 0, NULL};
|
struct ras_err_data err_data = {0, 0, 0, NULL};
|
||||||
|
|
||||||
/* CPU MCA will handle page retirement if connected_to_cpu is 1 */
|
/* CPU MCA will handle page retirement if connected_to_cpu is 1 */
|
||||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||||
amdgpu_umc_process_ras_data_cb(adev, &err_data, NULL);
|
amdgpu_umc_poison_handler(adev, &err_data, reset);
|
||||||
else
|
else if (reset)
|
||||||
amdgpu_amdkfd_gpu_reset(kgd);
|
amdgpu_amdkfd_gpu_reset(adev);
|
||||||
}
|
}
|
||||||
|
@ -144,14 +144,16 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
|
|||||||
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
||||||
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
||||||
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev);
|
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev);
|
||||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||||
|
enum kgd_engine_type engine,
|
||||||
uint32_t vmid, uint64_t gpu_addr,
|
uint32_t vmid, uint64_t gpu_addr,
|
||||||
uint32_t *ib_cmd, uint32_t ib_len);
|
uint32_t *ib_cmd, uint32_t ib_len);
|
||||||
void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle);
|
void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle);
|
||||||
bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd);
|
bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev);
|
||||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid);
|
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
|
||||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
|
uint16_t vmid);
|
||||||
enum TLB_FLUSH_TYPE flush_type);
|
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||||
|
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type);
|
||||||
|
|
||||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
|
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
|
||||||
|
|
||||||
@ -159,7 +161,7 @@ int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev);
|
|||||||
|
|
||||||
int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev);
|
int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev);
|
||||||
|
|
||||||
void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd);
|
void amdgpu_amdkfd_gpu_reset(struct amdgpu_device *adev);
|
||||||
|
|
||||||
int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
|
int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
|
||||||
int queue_bit);
|
int queue_bit);
|
||||||
@ -198,37 +200,36 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Shared API */
|
/* Shared API */
|
||||||
int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
|
||||||
void **mem_obj, uint64_t *gpu_addr,
|
void **mem_obj, uint64_t *gpu_addr,
|
||||||
void **cpu_ptr, bool mqd_gfx9);
|
void **cpu_ptr, bool mqd_gfx9);
|
||||||
void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj);
|
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj);
|
||||||
int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, void **mem_obj);
|
int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
|
||||||
void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj);
|
void **mem_obj);
|
||||||
|
void amdgpu_amdkfd_free_gws(struct amdgpu_device *adev, void *mem_obj);
|
||||||
int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem);
|
int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem);
|
||||||
int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem);
|
int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem);
|
||||||
uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd,
|
uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
|
||||||
enum kgd_engine_type type);
|
enum kgd_engine_type type);
|
||||||
void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
|
||||||
struct kfd_local_mem_info *mem_info);
|
struct kfd_local_mem_info *mem_info);
|
||||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct kgd_dev *kgd);
|
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
|
||||||
|
|
||||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd);
|
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
|
||||||
void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info);
|
void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev,
|
||||||
int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
struct kfd_cu_info *cu_info);
|
||||||
struct kgd_dev **dmabuf_kgd,
|
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||||
|
struct amdgpu_device **dmabuf_adev,
|
||||||
uint64_t *bo_size, void *metadata_buffer,
|
uint64_t *bo_size, void *metadata_buffer,
|
||||||
size_t buffer_size, uint32_t *metadata_size,
|
size_t buffer_size, uint32_t *metadata_size,
|
||||||
uint32_t *flags);
|
uint32_t *flags);
|
||||||
uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd);
|
uint64_t amdgpu_amdkfd_get_vram_usage(struct amdgpu_device *adev);
|
||||||
uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd);
|
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||||
uint64_t amdgpu_amdkfd_get_unique_id(struct kgd_dev *kgd);
|
struct amdgpu_device *src);
|
||||||
uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd);
|
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||||
uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd);
|
struct amdgpu_device *src,
|
||||||
uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd);
|
bool is_min);
|
||||||
int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd);
|
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
|
||||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src);
|
|
||||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min);
|
|
||||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min);
|
|
||||||
|
|
||||||
/* Read user wptr from a specified user address space with page fault
|
/* Read user wptr from a specified user address space with page fault
|
||||||
* disabled. The memory must be pinned and mapped to the hardware when
|
* disabled. The memory must be pinned and mapped to the hardware when
|
||||||
@ -258,45 +259,55 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min);
|
|||||||
(&((struct amdgpu_fpriv *) \
|
(&((struct amdgpu_fpriv *) \
|
||||||
((struct drm_file *)(drm_priv))->driver_priv)->vm)
|
((struct drm_file *)(drm_priv))->driver_priv)->vm)
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||||
struct file *filp, u32 pasid,
|
struct file *filp, u32 pasid,
|
||||||
void **process_info,
|
void **process_info,
|
||||||
struct dma_fence **ef);
|
struct dma_fence **ef);
|
||||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *drm_priv);
|
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||||
|
void *drm_priv);
|
||||||
uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv);
|
uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv);
|
||||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||||
struct kgd_dev *kgd, uint64_t va, uint64_t size,
|
struct amdgpu_device *adev, uint64_t va, uint64_t size,
|
||||||
void *drm_priv, struct kgd_mem **mem,
|
void *drm_priv, struct kgd_mem **mem,
|
||||||
uint64_t *offset, uint32_t flags);
|
uint64_t *offset, uint32_t flags);
|
||||||
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv,
|
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||||
uint64_t *size);
|
uint64_t *size);
|
||||||
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, bool *table_freed);
|
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||||
|
bool *table_freed);
|
||||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv);
|
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);
|
||||||
int amdgpu_amdkfd_gpuvm_sync_memory(
|
int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr);
|
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
|
||||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device *adev,
|
||||||
struct kgd_mem *mem, void **kptr, uint64_t *size);
|
struct kgd_mem *mem, void **kptr, uint64_t *size);
|
||||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem);
|
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct amdgpu_device *adev,
|
||||||
|
struct kgd_mem *mem);
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
||||||
struct dma_fence **ef);
|
struct dma_fence **ef);
|
||||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct amdgpu_device *adev,
|
||||||
struct kfd_vm_fault_info *info);
|
struct kfd_vm_fault_info *info);
|
||||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||||
struct dma_buf *dmabuf,
|
struct dma_buf *dmabuf,
|
||||||
uint64_t va, void *drm_priv,
|
uint64_t va, void *drm_priv,
|
||||||
struct kgd_mem **mem, uint64_t *size,
|
struct kgd_mem **mem, uint64_t *size,
|
||||||
uint64_t *mmap_offset);
|
uint64_t *mmap_offset);
|
||||||
int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||||
struct tile_config *config);
|
struct tile_config *config);
|
||||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct kgd_dev *kgd);
|
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||||
|
bool reset);
|
||||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||||
struct amdgpu_vm *vm);
|
struct amdgpu_vm *vm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @amdgpu_amdkfd_release_notify() - Notify KFD when GEM object is released
|
||||||
|
*
|
||||||
|
* Allows KFD to release its resources associated with the GEM object.
|
||||||
|
*/
|
||||||
void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo);
|
void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo);
|
||||||
void amdgpu_amdkfd_reserve_system_mem(uint64_t size);
|
void amdgpu_amdkfd_reserve_system_mem(uint64_t size);
|
||||||
#else
|
#else
|
||||||
@ -324,7 +335,7 @@ int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
|
|||||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||||
int kgd2kfd_init(void);
|
int kgd2kfd_init(void);
|
||||||
void kgd2kfd_exit(void);
|
void kgd2kfd_exit(void);
|
||||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, bool vf);
|
struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf);
|
||||||
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||||
struct drm_device *ddev,
|
struct drm_device *ddev,
|
||||||
const struct kgd2kfd_shared_resources *gpu_resources);
|
const struct kgd2kfd_shared_resources *gpu_resources);
|
||||||
@ -348,7 +359,7 @@ static inline void kgd2kfd_exit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, bool vf)
|
struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -57,11 +57,6 @@
|
|||||||
(*dump)[i++][1] = RREG32(addr); \
|
(*dump)[i++][1] = RREG32(addr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||||
{
|
{
|
||||||
return (struct v9_sdma_mqd *)mqd;
|
return (struct v9_sdma_mqd *)mqd;
|
||||||
@ -123,10 +118,9 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
|
|||||||
return sdma_rlc_reg_offset;
|
return sdma_rlc_reg_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_arcturus_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
int kgd_arcturus_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm)
|
uint32_t __user *wptr, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_sdma_mqd *m;
|
struct v9_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
@ -193,11 +187,10 @@ int kgd_arcturus_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_arcturus_hqd_sdma_dump(struct kgd_dev *kgd,
|
int kgd_arcturus_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||||
engine_id, queue_id);
|
engine_id, queue_id);
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
@ -225,9 +218,9 @@ int kgd_arcturus_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kgd_arcturus_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
bool kgd_arcturus_hqd_sdma_is_occupied(struct amdgpu_device *adev,
|
||||||
|
void *mqd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_sdma_mqd *m;
|
struct v9_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t sdma_rlc_rb_cntl;
|
uint32_t sdma_rlc_rb_cntl;
|
||||||
@ -244,10 +237,9 @@ bool kgd_arcturus_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_arcturus_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
int kgd_arcturus_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout)
|
unsigned int utimeout)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_sdma_mqd *m;
|
struct v9_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
|
@ -20,11 +20,12 @@
|
|||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int kgd_arcturus_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
int kgd_arcturus_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm);
|
uint32_t __user *wptr, struct mm_struct *mm);
|
||||||
int kgd_arcturus_hqd_sdma_dump(struct kgd_dev *kgd,
|
int kgd_arcturus_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||||
bool kgd_arcturus_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
|
bool kgd_arcturus_hqd_sdma_is_occupied(struct amdgpu_device *adev,
|
||||||
int kgd_arcturus_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
void *mqd);
|
||||||
|
int kgd_arcturus_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout);
|
unsigned int utimeout);
|
||||||
|
@ -39,37 +39,26 @@ enum hqd_dequeue_request_type {
|
|||||||
SAVE_WAVES
|
SAVE_WAVES
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
|
||||||
uint32_t queue, uint32_t vmid)
|
uint32_t queue, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
mutex_lock(&adev->srbm_mutex);
|
mutex_lock(&adev->srbm_mutex);
|
||||||
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlock_srbm(struct kgd_dev *kgd)
|
static void unlock_srbm(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||||
mutex_unlock(&adev->srbm_mutex);
|
mutex_unlock(&adev->srbm_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||||
@ -81,33 +70,29 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
|||||||
return 1ull << bit;
|
return 1ull << bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_queue(struct kgd_dev *kgd)
|
static void release_queue(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t sh_mem_config,
|
uint32_t sh_mem_config,
|
||||||
uint32_t sh_mem_ape1_base,
|
uint32_t sh_mem_ape1_base,
|
||||||
uint32_t sh_mem_ape1_limit,
|
uint32_t sh_mem_ape1_limit,
|
||||||
uint32_t sh_mem_bases)
|
uint32_t sh_mem_bases)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
|
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
|
||||||
WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
|
WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
|
||||||
/* APE1 no longer exists on GFX9 */
|
/* APE1 no longer exists on GFX9 */
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||||
unsigned int vmid)
|
unsigned int vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to assume that there is no outstanding mapping.
|
* We have to assume that there is no outstanding mapping.
|
||||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||||
@ -150,22 +135,21 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||||||
* but still works
|
* but still works
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t mec;
|
uint32_t mec;
|
||||||
uint32_t pipe;
|
uint32_t pipe;
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
lock_srbm(adev, mec, pipe, 0, 0);
|
||||||
|
|
||||||
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
||||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -218,12 +202,11 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||||||
return (struct v10_sdma_mqd *)mqd;
|
return (struct v10_sdma_mqd *)mqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t queue_id, uint32_t __user *wptr,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||||
struct mm_struct *mm)
|
uint32_t wptr_mask, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_compute_mqd *m;
|
struct v10_compute_mqd *m;
|
||||||
uint32_t *mqd_hqd;
|
uint32_t *mqd_hqd;
|
||||||
uint32_t reg, hqd_base, data;
|
uint32_t reg, hqd_base, data;
|
||||||
@ -231,7 +214,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
||||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||||
@ -296,16 +279,15 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||||
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, data);
|
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, data);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t doorbell_off)
|
uint32_t doorbell_off)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||||
struct v10_compute_mqd *m;
|
struct v10_compute_mqd *m;
|
||||||
uint32_t mec, pipe;
|
uint32_t mec, pipe;
|
||||||
@ -313,7 +295,7 @@ static int kgd_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
@ -349,16 +331,15 @@ static int kgd_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
#define HQD_N_REGS 56
|
#define HQD_N_REGS 56
|
||||||
#define DUMP_REG(addr) do { \
|
#define DUMP_REG(addr) do { \
|
||||||
@ -372,13 +353,13 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
if (*dump == NULL)
|
if (*dump == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||||
DUMP_REG(reg);
|
DUMP_REG(reg);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||||
*n_regs = i;
|
*n_regs = i;
|
||||||
@ -386,10 +367,9 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm)
|
uint32_t __user *wptr, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_sdma_mqd *m;
|
struct v10_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
@ -456,11 +436,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||||
engine_id, queue_id);
|
engine_id, queue_id);
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
@ -488,15 +467,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id)
|
uint64_t queue_address, uint32_t pipe_id,
|
||||||
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t act;
|
uint32_t act;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
uint32_t low, high;
|
uint32_t low, high;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||||
if (act) {
|
if (act) {
|
||||||
low = lower_32_bits(queue_address >> 8);
|
low = lower_32_bits(queue_address >> 8);
|
||||||
@ -506,13 +485,12 @@ static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
|||||||
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_sdma_mqd *m;
|
struct v10_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t sdma_rlc_rb_cntl;
|
uint32_t sdma_rlc_rb_cntl;
|
||||||
@ -529,12 +507,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
enum kfd_preempt_type reset_type,
|
enum kfd_preempt_type reset_type,
|
||||||
unsigned int utimeout, uint32_t pipe_id,
|
unsigned int utimeout, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
enum hqd_dequeue_request_type type;
|
enum hqd_dequeue_request_type type;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -548,7 +525,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
int retry;
|
int retry;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
if (m->cp_hqd_vmid == 0)
|
if (m->cp_hqd_vmid == 0)
|
||||||
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||||
@ -633,20 +610,19 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
break;
|
break;
|
||||||
if (time_after(jiffies, end_jiffies)) {
|
if (time_after(jiffies, end_jiffies)) {
|
||||||
pr_err("cp queue preemption time out.\n");
|
pr_err("cp queue preemption time out.\n");
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
}
|
}
|
||||||
usleep_range(500, 1000);
|
usleep_range(500, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout)
|
unsigned int utimeout)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_sdma_mqd *m;
|
struct v10_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -683,11 +659,10 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||||
uint8_t vmid, uint16_t *p_pasid)
|
uint8_t vmid, uint16_t *p_pasid)
|
||||||
{
|
{
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
|
||||||
|
|
||||||
value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
||||||
+ vmid);
|
+ vmid);
|
||||||
@ -696,12 +671,12 @@ static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
uint32_t cntl_val,
|
uint32_t cntl_val,
|
||||||
uint32_t addr_hi,
|
uint32_t addr_hi,
|
||||||
@ -710,11 +685,10 @@ static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||||
uint32_t gfx_index_val,
|
uint32_t gfx_index_val,
|
||||||
uint32_t sq_cmd)
|
uint32_t sq_cmd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
@ -735,18 +709,16 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
unsigned int reg_offset)
|
unsigned int reg_offset)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||||
uint64_t page_table_base)
|
uint32_t vmid, uint64_t page_table_base)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||||
pr_err("trying to set page table base for wrong VMID %u\n",
|
pr_err("trying to set page table base for wrong VMID %u\n",
|
||||||
vmid);
|
vmid);
|
||||||
@ -757,12 +729,10 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
|||||||
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void program_trap_handler_settings(struct kgd_dev *kgd,
|
static void program_trap_handler_settings(struct amdgpu_device *adev,
|
||||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Program TBA registers
|
* Program TBA registers
|
||||||
@ -781,7 +751,7 @@ static void program_trap_handler_settings(struct kgd_dev *kgd,
|
|||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
||||||
upper_32_bits(tma_addr >> 8));
|
upper_32_bits(tma_addr >> 8));
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
||||||
|
@ -38,37 +38,26 @@ enum hqd_dequeue_request_type {
|
|||||||
SAVE_WAVES
|
SAVE_WAVES
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
|
||||||
uint32_t queue, uint32_t vmid)
|
uint32_t queue, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
mutex_lock(&adev->srbm_mutex);
|
mutex_lock(&adev->srbm_mutex);
|
||||||
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlock_srbm(struct kgd_dev *kgd)
|
static void unlock_srbm(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||||
mutex_unlock(&adev->srbm_mutex);
|
mutex_unlock(&adev->srbm_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||||
@ -80,34 +69,30 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
|||||||
return 1ull << bit;
|
return 1ull << bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_queue(struct kgd_dev *kgd)
|
static void release_queue(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void program_sh_mem_settings_v10_3(struct kgd_dev *kgd, uint32_t vmid,
|
static void program_sh_mem_settings_v10_3(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t sh_mem_config,
|
uint32_t sh_mem_config,
|
||||||
uint32_t sh_mem_ape1_base,
|
uint32_t sh_mem_ape1_base,
|
||||||
uint32_t sh_mem_ape1_limit,
|
uint32_t sh_mem_ape1_limit,
|
||||||
uint32_t sh_mem_bases)
|
uint32_t sh_mem_bases)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
|
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
|
||||||
WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
|
WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
|
||||||
/* APE1 no longer exists on GFX9 */
|
/* APE1 no longer exists on GFX9 */
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ATC is defeatured on Sienna_Cichlid */
|
/* ATC is defeatured on Sienna_Cichlid */
|
||||||
static int set_pasid_vmid_mapping_v10_3(struct kgd_dev *kgd, unsigned int pasid,
|
static int set_pasid_vmid_mapping_v10_3(struct amdgpu_device *adev, unsigned int pasid,
|
||||||
unsigned int vmid)
|
unsigned int vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
|
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
|
||||||
|
|
||||||
/* Mapping vmid to pasid also for IH block */
|
/* Mapping vmid to pasid also for IH block */
|
||||||
@ -118,22 +103,21 @@ static int set_pasid_vmid_mapping_v10_3(struct kgd_dev *kgd, unsigned int pasid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_interrupts_v10_3(struct kgd_dev *kgd, uint32_t pipe_id)
|
static int init_interrupts_v10_3(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t mec;
|
uint32_t mec;
|
||||||
uint32_t pipe;
|
uint32_t pipe;
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
lock_srbm(adev, mec, pipe, 0, 0);
|
||||||
|
|
||||||
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
||||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -188,12 +172,11 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||||||
return (struct v10_sdma_mqd *)mqd;
|
return (struct v10_sdma_mqd *)mqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
static int hqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t queue_id, uint32_t __user *wptr,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||||
struct mm_struct *mm)
|
uint32_t wptr_mask, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_compute_mqd *m;
|
struct v10_compute_mqd *m;
|
||||||
uint32_t *mqd_hqd;
|
uint32_t *mqd_hqd;
|
||||||
uint32_t reg, hqd_base, data;
|
uint32_t reg, hqd_base, data;
|
||||||
@ -201,7 +184,7 @@ static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
/* HIQ is set during driver init period with vmid set to 0*/
|
/* HIQ is set during driver init period with vmid set to 0*/
|
||||||
if (m->cp_hqd_vmid == 0) {
|
if (m->cp_hqd_vmid == 0) {
|
||||||
@ -281,16 +264,15 @@ static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||||
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, data);
|
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, data);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t doorbell_off)
|
uint32_t doorbell_off)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||||
struct v10_compute_mqd *m;
|
struct v10_compute_mqd *m;
|
||||||
uint32_t mec, pipe;
|
uint32_t mec, pipe;
|
||||||
@ -298,7 +280,7 @@ static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
@ -334,16 +316,15 @@ static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
static int hqd_dump_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
#define HQD_N_REGS 56
|
#define HQD_N_REGS 56
|
||||||
#define DUMP_REG(addr) do { \
|
#define DUMP_REG(addr) do { \
|
||||||
@ -357,13 +338,13 @@ static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
|||||||
if (*dump == NULL)
|
if (*dump == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||||
DUMP_REG(reg);
|
DUMP_REG(reg);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||||
*n_regs = i;
|
*n_regs = i;
|
||||||
@ -371,10 +352,9 @@ static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hqd_sdma_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
static int hqd_sdma_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm)
|
uint32_t __user *wptr, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_sdma_mqd *m;
|
struct v10_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
@ -441,11 +421,10 @@ static int hqd_sdma_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hqd_sdma_dump_v10_3(struct kgd_dev *kgd,
|
static int hqd_sdma_dump_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||||
engine_id, queue_id);
|
engine_id, queue_id);
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
@ -473,15 +452,15 @@ static int hqd_sdma_dump_v10_3(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hqd_is_occupied_v10_3(struct kgd_dev *kgd, uint64_t queue_address,
|
static bool hqd_is_occupied_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id)
|
uint64_t queue_address, uint32_t pipe_id,
|
||||||
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t act;
|
uint32_t act;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
uint32_t low, high;
|
uint32_t low, high;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||||
if (act) {
|
if (act) {
|
||||||
low = lower_32_bits(queue_address >> 8);
|
low = lower_32_bits(queue_address >> 8);
|
||||||
@ -491,13 +470,13 @@ static bool hqd_is_occupied_v10_3(struct kgd_dev *kgd, uint64_t queue_address,
|
|||||||
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hqd_sdma_is_occupied_v10_3(struct kgd_dev *kgd, void *mqd)
|
static bool hqd_sdma_is_occupied_v10_3(struct amdgpu_device *adev,
|
||||||
|
void *mqd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_sdma_mqd *m;
|
struct v10_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t sdma_rlc_rb_cntl;
|
uint32_t sdma_rlc_rb_cntl;
|
||||||
@ -514,18 +493,17 @@ static bool hqd_sdma_is_occupied_v10_3(struct kgd_dev *kgd, void *mqd)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
static int hqd_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||||
enum kfd_preempt_type reset_type,
|
enum kfd_preempt_type reset_type,
|
||||||
unsigned int utimeout, uint32_t pipe_id,
|
unsigned int utimeout, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
enum hqd_dequeue_request_type type;
|
enum hqd_dequeue_request_type type;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
struct v10_compute_mqd *m = get_mqd(mqd);
|
struct v10_compute_mqd *m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
if (m->cp_hqd_vmid == 0)
|
if (m->cp_hqd_vmid == 0)
|
||||||
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||||
@ -555,20 +533,19 @@ static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||||||
if (time_after(jiffies, end_jiffies)) {
|
if (time_after(jiffies, end_jiffies)) {
|
||||||
pr_err("cp queue pipe %d queue %d preemption failed\n",
|
pr_err("cp queue pipe %d queue %d preemption failed\n",
|
||||||
pipe_id, queue_id);
|
pipe_id, queue_id);
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
}
|
}
|
||||||
usleep_range(500, 1000);
|
usleep_range(500, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hqd_sdma_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
static int hqd_sdma_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout)
|
unsigned int utimeout)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v10_sdma_mqd *m;
|
struct v10_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -606,12 +583,12 @@ static int hqd_sdma_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int address_watch_disable_v10_3(struct kgd_dev *kgd)
|
static int address_watch_disable_v10_3(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int address_watch_execute_v10_3(struct kgd_dev *kgd,
|
static int address_watch_execute_v10_3(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
uint32_t cntl_val,
|
uint32_t cntl_val,
|
||||||
uint32_t addr_hi,
|
uint32_t addr_hi,
|
||||||
@ -620,11 +597,10 @@ static int address_watch_execute_v10_3(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wave_control_execute_v10_3(struct kgd_dev *kgd,
|
static int wave_control_execute_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t gfx_index_val,
|
uint32_t gfx_index_val,
|
||||||
uint32_t sq_cmd)
|
uint32_t sq_cmd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
@ -645,28 +621,24 @@ static int wave_control_execute_v10_3(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t address_watch_get_offset_v10_3(struct kgd_dev *kgd,
|
static uint32_t address_watch_get_offset_v10_3(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
unsigned int reg_offset)
|
unsigned int reg_offset)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_vm_context_page_table_base_v10_3(struct kgd_dev *kgd, uint32_t vmid,
|
static void set_vm_context_page_table_base_v10_3(struct amdgpu_device *adev,
|
||||||
uint64_t page_table_base)
|
uint32_t vmid, uint64_t page_table_base)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
/* SDMA is on gfxhub as well for Navi1* series */
|
/* SDMA is on gfxhub as well for Navi1* series */
|
||||||
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void program_trap_handler_settings_v10_3(struct kgd_dev *kgd,
|
static void program_trap_handler_settings_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Program TBA registers
|
* Program TBA registers
|
||||||
@ -685,15 +657,14 @@ static void program_trap_handler_settings_v10_3(struct kgd_dev *kgd,
|
|||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
||||||
upper_32_bits(tma_addr >> 8));
|
upper_32_bits(tma_addr >> 8));
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd,
|
uint32_t enable_debug_trap_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t trap_debug_wave_launch_mode,
|
uint32_t trap_debug_wave_launch_mode,
|
||||||
uint32_t vmid)
|
uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
uint32_t orig_wave_cntl_value;
|
uint32_t orig_wave_cntl_value;
|
||||||
uint32_t orig_stall_vmid;
|
uint32_t orig_stall_vmid;
|
||||||
@ -720,10 +691,8 @@ uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t disable_debug_trap_v10_3(struct kgd_dev *kgd)
|
uint32_t disable_debug_trap_v10_3(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
|
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||||
@ -733,11 +702,10 @@ uint32_t disable_debug_trap_v10_3(struct kgd_dev *kgd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t set_wave_launch_trap_override_v10_3(struct kgd_dev *kgd,
|
uint32_t set_wave_launch_trap_override_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t trap_override,
|
uint32_t trap_override,
|
||||||
uint32_t trap_mask)
|
uint32_t trap_mask)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
@ -762,11 +730,10 @@ uint32_t set_wave_launch_trap_override_v10_3(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t set_wave_launch_mode_v10_3(struct kgd_dev *kgd,
|
uint32_t set_wave_launch_mode_v10_3(struct amdgpu_device *adev,
|
||||||
uint8_t wave_launch_mode,
|
uint8_t wave_launch_mode,
|
||||||
uint32_t vmid)
|
uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
bool is_stall_mode;
|
bool is_stall_mode;
|
||||||
bool is_mode_set;
|
bool is_mode_set;
|
||||||
@ -805,16 +772,14 @@ uint32_t set_wave_launch_mode_v10_3(struct kgd_dev *kgd,
|
|||||||
* sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
|
* sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
|
||||||
* deq_retry_wait_time -- Wait Count for Global Wave Syncs.
|
* deq_retry_wait_time -- Wait Count for Global Wave Syncs.
|
||||||
*/
|
*/
|
||||||
void get_iq_wait_times_v10_3(struct kgd_dev *kgd,
|
void get_iq_wait_times_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t *wait_times)
|
uint32_t *wait_times)
|
||||||
|
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
*wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
|
*wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_grace_period_packet_info_v10_3(struct kgd_dev *kgd,
|
void build_grace_period_packet_info_v10_3(struct amdgpu_device *adev,
|
||||||
uint32_t wait_times,
|
uint32_t wait_times,
|
||||||
uint32_t grace_period,
|
uint32_t grace_period,
|
||||||
uint32_t *reg_offset,
|
uint32_t *reg_offset,
|
||||||
|
@ -82,68 +82,54 @@ union TCP_WATCH_CNTL_BITS {
|
|||||||
float f32All;
|
float f32All;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
|
||||||
uint32_t queue, uint32_t vmid)
|
uint32_t queue, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue);
|
uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue);
|
||||||
|
|
||||||
mutex_lock(&adev->srbm_mutex);
|
mutex_lock(&adev->srbm_mutex);
|
||||||
WREG32(mmSRBM_GFX_CNTL, value);
|
WREG32(mmSRBM_GFX_CNTL, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlock_srbm(struct kgd_dev *kgd)
|
static void unlock_srbm(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
WREG32(mmSRBM_GFX_CNTL, 0);
|
WREG32(mmSRBM_GFX_CNTL, 0);
|
||||||
mutex_unlock(&adev->srbm_mutex);
|
mutex_unlock(&adev->srbm_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_queue(struct kgd_dev *kgd)
|
static void release_queue(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t sh_mem_config,
|
uint32_t sh_mem_config,
|
||||||
uint32_t sh_mem_ape1_base,
|
uint32_t sh_mem_ape1_base,
|
||||||
uint32_t sh_mem_ape1_limit,
|
uint32_t sh_mem_ape1_limit,
|
||||||
uint32_t sh_mem_bases)
|
uint32_t sh_mem_bases)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
WREG32(mmSH_MEM_CONFIG, sh_mem_config);
|
WREG32(mmSH_MEM_CONFIG, sh_mem_config);
|
||||||
WREG32(mmSH_MEM_APE1_BASE, sh_mem_ape1_base);
|
WREG32(mmSH_MEM_APE1_BASE, sh_mem_ape1_base);
|
||||||
WREG32(mmSH_MEM_APE1_LIMIT, sh_mem_ape1_limit);
|
WREG32(mmSH_MEM_APE1_LIMIT, sh_mem_ape1_limit);
|
||||||
WREG32(mmSH_MEM_BASES, sh_mem_bases);
|
WREG32(mmSH_MEM_BASES, sh_mem_bases);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||||
unsigned int vmid)
|
unsigned int vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to assume that there is no outstanding mapping.
|
* We have to assume that there is no outstanding mapping.
|
||||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||||
@ -165,21 +151,20 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t mec;
|
uint32_t mec;
|
||||||
uint32_t pipe;
|
uint32_t pipe;
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
lock_srbm(adev, mec, pipe, 0, 0);
|
||||||
|
|
||||||
WREG32(mmCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
WREG32(mmCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -207,12 +192,11 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
|
|||||||
return (struct cik_sdma_rlc_registers *)mqd;
|
return (struct cik_sdma_rlc_registers *)mqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t queue_id, uint32_t __user *wptr,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||||
struct mm_struct *mm)
|
uint32_t wptr_mask, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct cik_mqd *m;
|
struct cik_mqd *m;
|
||||||
uint32_t *mqd_hqd;
|
uint32_t *mqd_hqd;
|
||||||
uint32_t reg, wptr_val, data;
|
uint32_t reg, wptr_val, data;
|
||||||
@ -220,7 +204,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
|
|
||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_MQD_CONTROL. */
|
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_MQD_CONTROL. */
|
||||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||||
@ -239,25 +223,24 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
* release srbm_mutex to avoid circular dependency between
|
* release srbm_mutex to avoid circular dependency between
|
||||||
* srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex.
|
* srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex.
|
||||||
*/
|
*/
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
valid_wptr = read_user_wptr(mm, wptr, wptr_val);
|
valid_wptr = read_user_wptr(mm, wptr, wptr_val);
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
if (valid_wptr)
|
if (valid_wptr)
|
||||||
WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask);
|
WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask);
|
||||||
|
|
||||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||||
WREG32(mmCP_HQD_ACTIVE, data);
|
WREG32(mmCP_HQD_ACTIVE, data);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
#define HQD_N_REGS (35+4)
|
#define HQD_N_REGS (35+4)
|
||||||
#define DUMP_REG(addr) do { \
|
#define DUMP_REG(addr) do { \
|
||||||
@ -271,7 +254,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
if (*dump == NULL)
|
if (*dump == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE0);
|
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE0);
|
||||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE1);
|
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE1);
|
||||||
@ -281,7 +264,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
for (reg = mmCP_MQD_BASE_ADDR; reg <= mmCP_MQD_CONTROL; reg++)
|
for (reg = mmCP_MQD_BASE_ADDR; reg <= mmCP_MQD_CONTROL; reg++)
|
||||||
DUMP_REG(reg);
|
DUMP_REG(reg);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||||
*n_regs = i;
|
*n_regs = i;
|
||||||
@ -289,10 +272,9 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm)
|
uint32_t __user *wptr, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct cik_sdma_rlc_registers *m;
|
struct cik_sdma_rlc_registers *m;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
@ -345,11 +327,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t sdma_offset = engine_id * SDMA1_REGISTER_OFFSET +
|
uint32_t sdma_offset = engine_id * SDMA1_REGISTER_OFFSET +
|
||||||
queue_id * KFD_CIK_SDMA_QUEUE_OFFSET;
|
queue_id * KFD_CIK_SDMA_QUEUE_OFFSET;
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
@ -372,15 +353,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id)
|
uint64_t queue_address, uint32_t pipe_id,
|
||||||
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t act;
|
uint32_t act;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
uint32_t low, high;
|
uint32_t low, high;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
act = RREG32(mmCP_HQD_ACTIVE);
|
act = RREG32(mmCP_HQD_ACTIVE);
|
||||||
if (act) {
|
if (act) {
|
||||||
low = lower_32_bits(queue_address >> 8);
|
low = lower_32_bits(queue_address >> 8);
|
||||||
@ -390,13 +371,12 @@ static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
|||||||
high == RREG32(mmCP_HQD_PQ_BASE_HI))
|
high == RREG32(mmCP_HQD_PQ_BASE_HI))
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct cik_sdma_rlc_registers *m;
|
struct cik_sdma_rlc_registers *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t sdma_rlc_rb_cntl;
|
uint32_t sdma_rlc_rb_cntl;
|
||||||
@ -412,12 +392,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
enum kfd_preempt_type reset_type,
|
enum kfd_preempt_type reset_type,
|
||||||
unsigned int utimeout, uint32_t pipe_id,
|
unsigned int utimeout, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
enum hqd_dequeue_request_type type;
|
enum hqd_dequeue_request_type type;
|
||||||
unsigned long flags, end_jiffies;
|
unsigned long flags, end_jiffies;
|
||||||
@ -426,7 +405,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
if (amdgpu_in_reset(adev))
|
if (amdgpu_in_reset(adev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, 0);
|
WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, 0);
|
||||||
|
|
||||||
switch (reset_type) {
|
switch (reset_type) {
|
||||||
@ -504,20 +483,19 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
break;
|
break;
|
||||||
if (time_after(jiffies, end_jiffies)) {
|
if (time_after(jiffies, end_jiffies)) {
|
||||||
pr_err("cp queue preemption time out\n");
|
pr_err("cp queue preemption time out\n");
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
}
|
}
|
||||||
usleep_range(500, 1000);
|
usleep_range(500, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout)
|
unsigned int utimeout)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct cik_sdma_rlc_registers *m;
|
struct cik_sdma_rlc_registers *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -551,9 +529,8 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
union TCP_WATCH_CNTL_BITS cntl;
|
union TCP_WATCH_CNTL_BITS cntl;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -571,13 +548,12 @@ static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
uint32_t cntl_val,
|
uint32_t cntl_val,
|
||||||
uint32_t addr_hi,
|
uint32_t addr_hi,
|
||||||
uint32_t addr_lo)
|
uint32_t addr_lo)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
union TCP_WATCH_CNTL_BITS cntl;
|
union TCP_WATCH_CNTL_BITS cntl;
|
||||||
|
|
||||||
cntl.u32All = cntl_val;
|
cntl.u32All = cntl_val;
|
||||||
@ -602,11 +578,10 @@ static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||||
uint32_t gfx_index_val,
|
uint32_t gfx_index_val,
|
||||||
uint32_t sq_cmd)
|
uint32_t sq_cmd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
@ -627,18 +602,17 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
unsigned int reg_offset)
|
unsigned int reg_offset)
|
||||||
{
|
{
|
||||||
return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset];
|
return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||||
uint8_t vmid, uint16_t *p_pasid)
|
uint8_t vmid, uint16_t *p_pasid)
|
||||||
{
|
{
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
|
||||||
|
|
||||||
value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||||
*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||||
@ -646,21 +620,17 @@ static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
static void set_scratch_backing_va(struct amdgpu_device *adev,
|
||||||
uint64_t va, uint32_t vmid)
|
uint64_t va, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
|
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||||
uint64_t page_table_base)
|
uint32_t vmid, uint64_t page_table_base)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||||
pr_err("trying to set page table base for wrong VMID\n");
|
pr_err("trying to set page table base for wrong VMID\n");
|
||||||
return;
|
return;
|
||||||
@ -676,10 +646,8 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
|||||||
* @vmid: vmid pointer
|
* @vmid: vmid pointer
|
||||||
* read vmid from register (CIK).
|
* read vmid from register (CIK).
|
||||||
*/
|
*/
|
||||||
static uint32_t read_vmid_from_vmfault_reg(struct kgd_dev *kgd)
|
static uint32_t read_vmid_from_vmfault_reg(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
uint32_t status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
||||||
|
|
||||||
return REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID);
|
return REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID);
|
||||||
|
@ -39,68 +39,54 @@ enum hqd_dequeue_request_type {
|
|||||||
RESET_WAVES
|
RESET_WAVES
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
|
||||||
uint32_t queue, uint32_t vmid)
|
uint32_t queue, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue);
|
uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue);
|
||||||
|
|
||||||
mutex_lock(&adev->srbm_mutex);
|
mutex_lock(&adev->srbm_mutex);
|
||||||
WREG32(mmSRBM_GFX_CNTL, value);
|
WREG32(mmSRBM_GFX_CNTL, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlock_srbm(struct kgd_dev *kgd)
|
static void unlock_srbm(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
WREG32(mmSRBM_GFX_CNTL, 0);
|
WREG32(mmSRBM_GFX_CNTL, 0);
|
||||||
mutex_unlock(&adev->srbm_mutex);
|
mutex_unlock(&adev->srbm_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_queue(struct kgd_dev *kgd)
|
static void release_queue(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t sh_mem_config,
|
uint32_t sh_mem_config,
|
||||||
uint32_t sh_mem_ape1_base,
|
uint32_t sh_mem_ape1_base,
|
||||||
uint32_t sh_mem_ape1_limit,
|
uint32_t sh_mem_ape1_limit,
|
||||||
uint32_t sh_mem_bases)
|
uint32_t sh_mem_bases)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
WREG32(mmSH_MEM_CONFIG, sh_mem_config);
|
WREG32(mmSH_MEM_CONFIG, sh_mem_config);
|
||||||
WREG32(mmSH_MEM_APE1_BASE, sh_mem_ape1_base);
|
WREG32(mmSH_MEM_APE1_BASE, sh_mem_ape1_base);
|
||||||
WREG32(mmSH_MEM_APE1_LIMIT, sh_mem_ape1_limit);
|
WREG32(mmSH_MEM_APE1_LIMIT, sh_mem_ape1_limit);
|
||||||
WREG32(mmSH_MEM_BASES, sh_mem_bases);
|
WREG32(mmSH_MEM_BASES, sh_mem_bases);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||||
unsigned int vmid)
|
unsigned int vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to assume that there is no outstanding mapping.
|
* We have to assume that there is no outstanding mapping.
|
||||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||||
@ -123,21 +109,20 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t mec;
|
uint32_t mec;
|
||||||
uint32_t pipe;
|
uint32_t pipe;
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
lock_srbm(adev, mec, pipe, 0, 0);
|
||||||
|
|
||||||
WREG32(mmCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
WREG32(mmCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -165,12 +150,11 @@ static inline struct vi_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||||||
return (struct vi_sdma_mqd *)mqd;
|
return (struct vi_sdma_mqd *)mqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t queue_id, uint32_t __user *wptr,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||||
struct mm_struct *mm)
|
uint32_t wptr_mask, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct vi_mqd *m;
|
struct vi_mqd *m;
|
||||||
uint32_t *mqd_hqd;
|
uint32_t *mqd_hqd;
|
||||||
uint32_t reg, wptr_val, data;
|
uint32_t reg, wptr_val, data;
|
||||||
@ -178,7 +162,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
|
|
||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
/* HIQ is set during driver init period with vmid set to 0*/
|
/* HIQ is set during driver init period with vmid set to 0*/
|
||||||
if (m->cp_hqd_vmid == 0) {
|
if (m->cp_hqd_vmid == 0) {
|
||||||
@ -206,7 +190,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
* on ASICs that do not support context-save.
|
* on ASICs that do not support context-save.
|
||||||
* EOP writes/reads can start anywhere in the ring.
|
* EOP writes/reads can start anywhere in the ring.
|
||||||
*/
|
*/
|
||||||
if (get_amdgpu_device(kgd)->asic_type != CHIP_TONGA) {
|
if (adev->asic_type != CHIP_TONGA) {
|
||||||
WREG32(mmCP_HQD_EOP_RPTR, m->cp_hqd_eop_rptr);
|
WREG32(mmCP_HQD_EOP_RPTR, m->cp_hqd_eop_rptr);
|
||||||
WREG32(mmCP_HQD_EOP_WPTR, m->cp_hqd_eop_wptr);
|
WREG32(mmCP_HQD_EOP_WPTR, m->cp_hqd_eop_wptr);
|
||||||
WREG32(mmCP_HQD_EOP_WPTR_MEM, m->cp_hqd_eop_wptr_mem);
|
WREG32(mmCP_HQD_EOP_WPTR_MEM, m->cp_hqd_eop_wptr_mem);
|
||||||
@ -226,25 +210,24 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
* release srbm_mutex to avoid circular dependency between
|
* release srbm_mutex to avoid circular dependency between
|
||||||
* srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex.
|
* srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex.
|
||||||
*/
|
*/
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
valid_wptr = read_user_wptr(mm, wptr, wptr_val);
|
valid_wptr = read_user_wptr(mm, wptr, wptr_val);
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
if (valid_wptr)
|
if (valid_wptr)
|
||||||
WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask);
|
WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask);
|
||||||
|
|
||||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||||
WREG32(mmCP_HQD_ACTIVE, data);
|
WREG32(mmCP_HQD_ACTIVE, data);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
#define HQD_N_REGS (54+4)
|
#define HQD_N_REGS (54+4)
|
||||||
#define DUMP_REG(addr) do { \
|
#define DUMP_REG(addr) do { \
|
||||||
@ -258,7 +241,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
if (*dump == NULL)
|
if (*dump == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE0);
|
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE0);
|
||||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE1);
|
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE1);
|
||||||
@ -268,7 +251,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
for (reg = mmCP_MQD_BASE_ADDR; reg <= mmCP_HQD_EOP_DONES; reg++)
|
for (reg = mmCP_MQD_BASE_ADDR; reg <= mmCP_HQD_EOP_DONES; reg++)
|
||||||
DUMP_REG(reg);
|
DUMP_REG(reg);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||||
*n_regs = i;
|
*n_regs = i;
|
||||||
@ -276,10 +259,9 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm)
|
uint32_t __user *wptr, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct vi_sdma_mqd *m;
|
struct vi_sdma_mqd *m;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
@ -331,11 +313,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t sdma_offset = engine_id * SDMA1_REGISTER_OFFSET +
|
uint32_t sdma_offset = engine_id * SDMA1_REGISTER_OFFSET +
|
||||||
queue_id * KFD_VI_SDMA_QUEUE_OFFSET;
|
queue_id * KFD_VI_SDMA_QUEUE_OFFSET;
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
@ -367,15 +348,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id)
|
uint64_t queue_address, uint32_t pipe_id,
|
||||||
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t act;
|
uint32_t act;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
uint32_t low, high;
|
uint32_t low, high;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
act = RREG32(mmCP_HQD_ACTIVE);
|
act = RREG32(mmCP_HQD_ACTIVE);
|
||||||
if (act) {
|
if (act) {
|
||||||
low = lower_32_bits(queue_address >> 8);
|
low = lower_32_bits(queue_address >> 8);
|
||||||
@ -385,13 +366,12 @@ static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
|||||||
high == RREG32(mmCP_HQD_PQ_BASE_HI))
|
high == RREG32(mmCP_HQD_PQ_BASE_HI))
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct vi_sdma_mqd *m;
|
struct vi_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t sdma_rlc_rb_cntl;
|
uint32_t sdma_rlc_rb_cntl;
|
||||||
@ -407,12 +387,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
enum kfd_preempt_type reset_type,
|
enum kfd_preempt_type reset_type,
|
||||||
unsigned int utimeout, uint32_t pipe_id,
|
unsigned int utimeout, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
enum hqd_dequeue_request_type type;
|
enum hqd_dequeue_request_type type;
|
||||||
unsigned long flags, end_jiffies;
|
unsigned long flags, end_jiffies;
|
||||||
@ -422,7 +401,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
if (amdgpu_in_reset(adev))
|
if (amdgpu_in_reset(adev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
if (m->cp_hqd_vmid == 0)
|
if (m->cp_hqd_vmid == 0)
|
||||||
WREG32_FIELD(RLC_CP_SCHEDULERS, scheduler1, 0);
|
WREG32_FIELD(RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||||
@ -502,20 +481,19 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
break;
|
break;
|
||||||
if (time_after(jiffies, end_jiffies)) {
|
if (time_after(jiffies, end_jiffies)) {
|
||||||
pr_err("cp queue preemption time out.\n");
|
pr_err("cp queue preemption time out.\n");
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
}
|
}
|
||||||
usleep_range(500, 1000);
|
usleep_range(500, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout)
|
unsigned int utimeout)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct vi_sdma_mqd *m;
|
struct vi_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -549,11 +527,10 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||||
uint8_t vmid, uint16_t *p_pasid)
|
uint8_t vmid, uint16_t *p_pasid)
|
||||||
{
|
{
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
|
||||||
|
|
||||||
value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||||
*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||||
@ -561,12 +538,12 @@ static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
uint32_t cntl_val,
|
uint32_t cntl_val,
|
||||||
uint32_t addr_hi,
|
uint32_t addr_hi,
|
||||||
@ -575,11 +552,10 @@ static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||||
uint32_t gfx_index_val,
|
uint32_t gfx_index_val,
|
||||||
uint32_t sq_cmd)
|
uint32_t sq_cmd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
@ -600,28 +576,24 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
unsigned int reg_offset)
|
unsigned int reg_offset)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
static void set_scratch_backing_va(struct amdgpu_device *adev,
|
||||||
uint64_t va, uint32_t vmid)
|
uint64_t va, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
|
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||||
uint64_t page_table_base)
|
uint32_t vmid, uint64_t page_table_base)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||||
pr_err("trying to set page table base for wrong VMID\n");
|
pr_err("trying to set page table base for wrong VMID\n");
|
||||||
return;
|
return;
|
||||||
|
@ -46,37 +46,26 @@ enum hqd_dequeue_request_type {
|
|||||||
SAVE_WAVES
|
SAVE_WAVES
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
|
||||||
uint32_t queue, uint32_t vmid)
|
uint32_t queue, uint32_t vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
mutex_lock(&adev->srbm_mutex);
|
mutex_lock(&adev->srbm_mutex);
|
||||||
soc15_grbm_select(adev, mec, pipe, queue, vmid);
|
soc15_grbm_select(adev, mec, pipe, queue, vmid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlock_srbm(struct kgd_dev *kgd)
|
static void unlock_srbm(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
soc15_grbm_select(adev, 0, 0, 0, 0);
|
soc15_grbm_select(adev, 0, 0, 0, 0);
|
||||||
mutex_unlock(&adev->srbm_mutex);
|
mutex_unlock(&adev->srbm_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||||
@ -88,33 +77,29 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
|||||||
return 1ull << bit;
|
return 1ull << bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_queue(struct kgd_dev *kgd)
|
static void release_queue(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kgd_gfx_v9_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t sh_mem_config,
|
uint32_t sh_mem_config,
|
||||||
uint32_t sh_mem_ape1_base,
|
uint32_t sh_mem_ape1_base,
|
||||||
uint32_t sh_mem_ape1_limit,
|
uint32_t sh_mem_ape1_limit,
|
||||||
uint32_t sh_mem_bases)
|
uint32_t sh_mem_bases)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
|
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
|
||||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
|
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
|
||||||
/* APE1 no longer exists on GFX9 */
|
/* APE1 no longer exists on GFX9 */
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||||
unsigned int vmid)
|
unsigned int vmid)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to assume that there is no outstanding mapping.
|
* We have to assume that there is no outstanding mapping.
|
||||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||||
@ -171,22 +156,21 @@ int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||||||
* but still works
|
* but still works
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int kgd_gfx_v9_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t mec;
|
uint32_t mec;
|
||||||
uint32_t pipe;
|
uint32_t pipe;
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
|
|
||||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
lock_srbm(adev, mec, pipe, 0, 0);
|
||||||
|
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL),
|
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
||||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -233,19 +217,18 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||||||
return (struct v9_sdma_mqd *)mqd;
|
return (struct v9_sdma_mqd *)mqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t queue_id, uint32_t __user *wptr,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||||
struct mm_struct *mm)
|
uint32_t wptr_mask, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_mqd *m;
|
struct v9_mqd *m;
|
||||||
uint32_t *mqd_hqd;
|
uint32_t *mqd_hqd;
|
||||||
uint32_t reg, hqd_base, data;
|
uint32_t reg, hqd_base, data;
|
||||||
|
|
||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
||||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||||
@ -296,7 +279,7 @@ int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
lower_32_bits((uintptr_t)wptr));
|
lower_32_bits((uintptr_t)wptr));
|
||||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||||
upper_32_bits((uintptr_t)wptr));
|
upper_32_bits((uintptr_t)wptr));
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1),
|
WREG32_SOC15(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1,
|
||||||
(uint32_t)get_queue_mask(adev, pipe_id, queue_id));
|
(uint32_t)get_queue_mask(adev, pipe_id, queue_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,16 +291,15 @@ int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), data);
|
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), data);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t doorbell_off)
|
uint32_t doorbell_off)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||||
struct v9_mqd *m;
|
struct v9_mqd *m;
|
||||||
uint32_t mec, pipe;
|
uint32_t mec, pipe;
|
||||||
@ -325,7 +307,7 @@ int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
m = get_mqd(mqd);
|
m = get_mqd(mqd);
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||||
@ -361,16 +343,15 @@ int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
#define HQD_N_REGS 56
|
#define HQD_N_REGS 56
|
||||||
#define DUMP_REG(addr) do { \
|
#define DUMP_REG(addr) do { \
|
||||||
@ -384,13 +365,13 @@ int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
|||||||
if (*dump == NULL)
|
if (*dump == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||||
DUMP_REG(reg);
|
DUMP_REG(reg);
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
|
|
||||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||||
*n_regs = i;
|
*n_regs = i;
|
||||||
@ -398,10 +379,9 @@ int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t __user *wptr, struct mm_struct *mm)
|
uint32_t __user *wptr, struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_sdma_mqd *m;
|
struct v9_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
@ -468,11 +448,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||||
uint32_t engine_id, uint32_t queue_id,
|
uint32_t engine_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||||
engine_id, queue_id);
|
engine_id, queue_id);
|
||||||
uint32_t i = 0, reg;
|
uint32_t i = 0, reg;
|
||||||
@ -500,31 +479,30 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kgd_gfx_v9_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id)
|
uint64_t queue_address, uint32_t pipe_id,
|
||||||
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t act;
|
uint32_t act;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
uint32_t low, high;
|
uint32_t low, high;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
act = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||||
if (act) {
|
if (act) {
|
||||||
low = lower_32_bits(queue_address >> 8);
|
low = lower_32_bits(queue_address >> 8);
|
||||||
high = upper_32_bits(queue_address >> 8);
|
high = upper_32_bits(queue_address >> 8);
|
||||||
|
|
||||||
if (low == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE)) &&
|
if (low == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE) &&
|
||||||
high == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI)))
|
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_sdma_mqd *m;
|
struct v9_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t sdma_rlc_rb_cntl;
|
uint32_t sdma_rlc_rb_cntl;
|
||||||
@ -541,12 +519,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
enum kfd_preempt_type reset_type,
|
enum kfd_preempt_type reset_type,
|
||||||
unsigned int utimeout, uint32_t pipe_id,
|
unsigned int utimeout, uint32_t pipe_id,
|
||||||
uint32_t queue_id)
|
uint32_t queue_id)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
enum hqd_dequeue_request_type type;
|
enum hqd_dequeue_request_type type;
|
||||||
unsigned long end_jiffies;
|
unsigned long end_jiffies;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -555,7 +532,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
if (amdgpu_in_reset(adev))
|
if (amdgpu_in_reset(adev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
acquire_queue(kgd, pipe_id, queue_id);
|
acquire_queue(adev, pipe_id, queue_id);
|
||||||
|
|
||||||
if (m->cp_hqd_vmid == 0)
|
if (m->cp_hqd_vmid == 0)
|
||||||
WREG32_FIELD15_RLC(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
WREG32_FIELD15_RLC(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||||
@ -579,25 +556,24 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
|
|
||||||
end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||||
while (true) {
|
while (true) {
|
||||||
temp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
temp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||||
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||||
break;
|
break;
|
||||||
if (time_after(jiffies, end_jiffies)) {
|
if (time_after(jiffies, end_jiffies)) {
|
||||||
pr_err("cp queue preemption time out.\n");
|
pr_err("cp queue preemption time out.\n");
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
}
|
}
|
||||||
usleep_range(500, 1000);
|
usleep_range(500, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_queue(kgd);
|
release_queue(adev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
unsigned int utimeout)
|
unsigned int utimeout)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct v9_sdma_mqd *m;
|
struct v9_sdma_mqd *m;
|
||||||
uint32_t sdma_rlc_reg_offset;
|
uint32_t sdma_rlc_reg_offset;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
@ -634,11 +610,10 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||||
uint8_t vmid, uint16_t *p_pasid)
|
uint8_t vmid, uint16_t *p_pasid)
|
||||||
{
|
{
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
|
||||||
|
|
||||||
value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
||||||
+ vmid);
|
+ vmid);
|
||||||
@ -647,12 +622,12 @@ bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||||||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_address_watch_disable(struct kgd_dev *kgd)
|
int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_address_watch_execute(struct kgd_dev *kgd,
|
int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
uint32_t cntl_val,
|
uint32_t cntl_val,
|
||||||
uint32_t addr_hi,
|
uint32_t addr_hi,
|
||||||
@ -661,17 +636,16 @@ int kgd_gfx_v9_address_watch_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kgd_gfx_v9_wave_control_execute(struct kgd_dev *kgd,
|
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||||
uint32_t gfx_index_val,
|
uint32_t gfx_index_val,
|
||||||
uint32_t sq_cmd)
|
uint32_t sq_cmd)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
mutex_lock(&adev->grbm_idx_mutex);
|
mutex_lock(&adev->grbm_idx_mutex);
|
||||||
|
|
||||||
WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_INDEX, gfx_index_val);
|
WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_INDEX, gfx_index_val);
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CMD), sq_cmd);
|
WREG32_SOC15(GC, 0, mmSQ_CMD, sq_cmd);
|
||||||
|
|
||||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||||
INSTANCE_BROADCAST_WRITES, 1);
|
INSTANCE_BROADCAST_WRITES, 1);
|
||||||
@ -686,18 +660,16 @@ int kgd_gfx_v9_wave_control_execute(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd,
|
uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
unsigned int reg_offset)
|
unsigned int reg_offset)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd,
|
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||||
uint32_t vmid, uint64_t page_table_base)
|
uint32_t vmid, uint64_t page_table_base)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
|
|
||||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||||
pr_err("trying to set page table base for wrong VMID %u\n",
|
pr_err("trying to set page table base for wrong VMID %u\n",
|
||||||
vmid);
|
vmid);
|
||||||
@ -750,7 +722,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
|||||||
pipe_idx = queue_idx / adev->gfx.mec.num_queue_per_pipe;
|
pipe_idx = queue_idx / adev->gfx.mec.num_queue_per_pipe;
|
||||||
queue_slot = queue_idx % adev->gfx.mec.num_queue_per_pipe;
|
queue_slot = queue_idx % adev->gfx.mec.num_queue_per_pipe;
|
||||||
soc15_grbm_select(adev, 1, pipe_idx, queue_slot, 0);
|
soc15_grbm_select(adev, 1, pipe_idx, queue_slot, 0);
|
||||||
reg_val = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_CSQ_WF_ACTIVE_COUNT_0) +
|
reg_val = RREG32_SOC15_IP(GC, SOC15_REG_OFFSET(GC, 0, mmSPI_CSQ_WF_ACTIVE_COUNT_0) +
|
||||||
queue_slot);
|
queue_slot);
|
||||||
*wave_cnt = reg_val & SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT_MASK;
|
*wave_cnt = reg_val & SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT_MASK;
|
||||||
if (*wave_cnt != 0)
|
if (*wave_cnt != 0)
|
||||||
@ -804,7 +776,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
|||||||
*
|
*
|
||||||
* Reading registers referenced above involves programming GRBM appropriately
|
* Reading registers referenced above involves programming GRBM appropriately
|
||||||
*/
|
*/
|
||||||
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
|
||||||
int *pasid_wave_cnt, int *max_waves_per_cu)
|
int *pasid_wave_cnt, int *max_waves_per_cu)
|
||||||
{
|
{
|
||||||
int qidx;
|
int qidx;
|
||||||
@ -818,10 +790,8 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
|||||||
int pasid_tmp;
|
int pasid_tmp;
|
||||||
int max_queue_cnt;
|
int max_queue_cnt;
|
||||||
int vmid_wave_cnt = 0;
|
int vmid_wave_cnt = 0;
|
||||||
struct amdgpu_device *adev;
|
|
||||||
DECLARE_BITMAP(cp_queue_bitmap, KGD_MAX_QUEUES);
|
DECLARE_BITMAP(cp_queue_bitmap, KGD_MAX_QUEUES);
|
||||||
|
|
||||||
adev = get_amdgpu_device(kgd);
|
|
||||||
lock_spi_csq_mutexes(adev);
|
lock_spi_csq_mutexes(adev);
|
||||||
soc15_grbm_select(adev, 1, 0, 0, 0);
|
soc15_grbm_select(adev, 1, 0, 0, 0);
|
||||||
|
|
||||||
@ -839,8 +809,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
|||||||
for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) {
|
for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) {
|
||||||
|
|
||||||
gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
|
gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
|
||||||
queue_map = RREG32(SOC15_REG_OFFSET(GC, 0,
|
queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS);
|
||||||
mmSPI_CSQ_WF_ACTIVE_STATUS));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assumption: queue map encodes following schema: four
|
* Assumption: queue map encodes following schema: four
|
||||||
@ -882,30 +851,28 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
|||||||
adev->gfx.cu_info.max_waves_per_simd;
|
adev->gfx.cu_info.max_waves_per_simd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd,
|
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
|
||||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
lock_srbm(adev, 0, 0, 0, vmid);
|
||||||
|
|
||||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Program TBA registers
|
* Program TBA registers
|
||||||
*/
|
*/
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO),
|
WREG32_SOC15(GC, 0, mmSQ_SHADER_TBA_LO,
|
||||||
lower_32_bits(tba_addr >> 8));
|
lower_32_bits(tba_addr >> 8));
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI),
|
WREG32_SOC15(GC, 0, mmSQ_SHADER_TBA_HI,
|
||||||
upper_32_bits(tba_addr >> 8));
|
upper_32_bits(tba_addr >> 8));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Program TMA registers
|
* Program TMA registers
|
||||||
*/
|
*/
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO),
|
WREG32_SOC15(GC, 0, mmSQ_SHADER_TMA_LO,
|
||||||
lower_32_bits(tma_addr >> 8));
|
lower_32_bits(tma_addr >> 8));
|
||||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
WREG32_SOC15(GC, 0, mmSQ_SHADER_TMA_HI,
|
||||||
upper_32_bits(tma_addr >> 8));
|
upper_32_bits(tma_addr >> 8));
|
||||||
|
|
||||||
unlock_srbm(kgd);
|
unlock_srbm(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
||||||
|
@ -22,48 +22,49 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void kgd_gfx_v9_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t sh_mem_config,
|
uint32_t sh_mem_config,
|
||||||
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
|
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
|
||||||
uint32_t sh_mem_bases);
|
uint32_t sh_mem_bases);
|
||||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||||
unsigned int vmid);
|
unsigned int vmid);
|
||||||
int kgd_gfx_v9_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
|
int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id);
|
||||||
int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
|
||||||
uint32_t queue_id, uint32_t __user *wptr,
|
uint32_t queue_id, uint32_t __user *wptr,
|
||||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||||
struct mm_struct *mm);
|
struct mm_struct *mm);
|
||||||
int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t doorbell_off);
|
uint32_t doorbell_off);
|
||||||
int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id,
|
uint32_t pipe_id, uint32_t queue_id,
|
||||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||||
bool kgd_gfx_v9_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
|
||||||
uint32_t pipe_id, uint32_t queue_id);
|
uint64_t queue_address, uint32_t pipe_id,
|
||||||
int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
uint32_t queue_id);
|
||||||
|
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||||
enum kfd_preempt_type reset_type,
|
enum kfd_preempt_type reset_type,
|
||||||
unsigned int utimeout, uint32_t pipe_id,
|
unsigned int utimeout, uint32_t pipe_id,
|
||||||
uint32_t queue_id);
|
uint32_t queue_id);
|
||||||
int kgd_gfx_v9_address_watch_disable(struct kgd_dev *kgd);
|
int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev);
|
||||||
int kgd_gfx_v9_address_watch_execute(struct kgd_dev *kgd,
|
int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
uint32_t cntl_val,
|
uint32_t cntl_val,
|
||||||
uint32_t addr_hi,
|
uint32_t addr_hi,
|
||||||
uint32_t addr_lo);
|
uint32_t addr_lo);
|
||||||
int kgd_gfx_v9_wave_control_execute(struct kgd_dev *kgd,
|
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||||
uint32_t gfx_index_val,
|
uint32_t gfx_index_val,
|
||||||
uint32_t sq_cmd);
|
uint32_t sq_cmd);
|
||||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd,
|
uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev,
|
||||||
unsigned int watch_point_id,
|
unsigned int watch_point_id,
|
||||||
unsigned int reg_offset);
|
unsigned int reg_offset);
|
||||||
|
|
||||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||||
uint8_t vmid, uint16_t *p_pasid);
|
uint8_t vmid, uint16_t *p_pasid);
|
||||||
|
|
||||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd,
|
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||||
uint32_t vmid, uint64_t page_table_base);
|
uint32_t vmid, uint64_t page_table_base);
|
||||||
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
|
||||||
int *pasid_wave_cnt, int *max_waves_per_cu);
|
int *pasid_wave_cnt, int *max_waves_per_cu);
|
||||||
void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd,
|
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
|
||||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
|
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
|
||||||
|
@ -60,12 +60,6 @@ static const char * const domain_bit_to_string[] = {
|
|||||||
|
|
||||||
static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work);
|
static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work);
|
||||||
|
|
||||||
|
|
||||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
|
||||||
{
|
|
||||||
return (struct amdgpu_device *)kgd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool kfd_mem_is_attached(struct amdgpu_vm *avm,
|
static bool kfd_mem_is_attached(struct amdgpu_vm *avm,
|
||||||
struct kgd_mem *mem)
|
struct kgd_mem *mem)
|
||||||
{
|
{
|
||||||
@ -126,8 +120,19 @@ static size_t amdgpu_amdkfd_acc_size(uint64_t size)
|
|||||||
PAGE_ALIGN(size);
|
PAGE_ALIGN(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @amdgpu_amdkfd_reserve_mem_limit() - Decrease available memory by size
|
||||||
|
* of buffer including any reserved for control structures
|
||||||
|
*
|
||||||
|
* @adev: Device to which allocated BO belongs to
|
||||||
|
* @size: Size of buffer, in bytes, encapsulated by B0. This should be
|
||||||
|
* equivalent to amdgpu_bo_size(BO)
|
||||||
|
* @alloc_flag: Flag used in allocating a BO as noted above
|
||||||
|
*
|
||||||
|
* Return: returns -ENOMEM in case of error, ZERO otherwise
|
||||||
|
*/
|
||||||
static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||||
uint64_t size, u32 domain, bool sg)
|
uint64_t size, u32 alloc_flag)
|
||||||
{
|
{
|
||||||
uint64_t reserved_for_pt =
|
uint64_t reserved_for_pt =
|
||||||
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
|
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
|
||||||
@ -137,20 +142,24 @@ static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
|||||||
acc_size = amdgpu_amdkfd_acc_size(size);
|
acc_size = amdgpu_amdkfd_acc_size(size);
|
||||||
|
|
||||||
vram_needed = 0;
|
vram_needed = 0;
|
||||||
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
|
||||||
/* TTM GTT memory */
|
|
||||||
system_mem_needed = acc_size + size;
|
system_mem_needed = acc_size + size;
|
||||||
ttm_mem_needed = acc_size + size;
|
ttm_mem_needed = acc_size + size;
|
||||||
} else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) {
|
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
|
||||||
/* Userptr */
|
|
||||||
system_mem_needed = acc_size + size;
|
|
||||||
ttm_mem_needed = acc_size;
|
|
||||||
} else {
|
|
||||||
/* VRAM and SG */
|
|
||||||
system_mem_needed = acc_size;
|
system_mem_needed = acc_size;
|
||||||
ttm_mem_needed = acc_size;
|
ttm_mem_needed = acc_size;
|
||||||
if (domain == AMDGPU_GEM_DOMAIN_VRAM)
|
vram_needed = size;
|
||||||
vram_needed = size;
|
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
|
||||||
|
system_mem_needed = acc_size + size;
|
||||||
|
ttm_mem_needed = acc_size;
|
||||||
|
} else if (alloc_flag &
|
||||||
|
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||||
|
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||||
|
system_mem_needed = acc_size;
|
||||||
|
ttm_mem_needed = acc_size;
|
||||||
|
} else {
|
||||||
|
pr_err("%s: Invalid BO type %#x\n", __func__, alloc_flag);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||||
@ -166,64 +175,72 @@ static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
|||||||
(adev->kfd.vram_used + vram_needed >
|
(adev->kfd.vram_used + vram_needed >
|
||||||
adev->gmc.real_vram_size - reserved_for_pt)) {
|
adev->gmc.real_vram_size - reserved_for_pt)) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
} else {
|
goto release;
|
||||||
kfd_mem_limit.system_mem_used += system_mem_needed;
|
|
||||||
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
|
|
||||||
adev->kfd.vram_used += vram_needed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update memory accounting by decreasing available system
|
||||||
|
* memory, TTM memory and GPU memory as computed above
|
||||||
|
*/
|
||||||
|
adev->kfd.vram_used += vram_needed;
|
||||||
|
kfd_mem_limit.system_mem_used += system_mem_needed;
|
||||||
|
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
|
||||||
|
|
||||||
|
release:
|
||||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unreserve_mem_limit(struct amdgpu_device *adev,
|
static void unreserve_mem_limit(struct amdgpu_device *adev,
|
||||||
uint64_t size, u32 domain, bool sg)
|
uint64_t size, u32 alloc_flag)
|
||||||
{
|
{
|
||||||
size_t acc_size;
|
size_t acc_size;
|
||||||
|
|
||||||
acc_size = amdgpu_amdkfd_acc_size(size);
|
acc_size = amdgpu_amdkfd_acc_size(size);
|
||||||
|
|
||||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||||
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
|
||||||
|
if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
|
||||||
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||||
kfd_mem_limit.ttm_mem_used -= (acc_size + size);
|
kfd_mem_limit.ttm_mem_used -= (acc_size + size);
|
||||||
} else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) {
|
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
|
||||||
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
|
||||||
kfd_mem_limit.ttm_mem_used -= acc_size;
|
|
||||||
} else {
|
|
||||||
kfd_mem_limit.system_mem_used -= acc_size;
|
kfd_mem_limit.system_mem_used -= acc_size;
|
||||||
kfd_mem_limit.ttm_mem_used -= acc_size;
|
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||||
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
|
adev->kfd.vram_used -= size;
|
||||||
adev->kfd.vram_used -= size;
|
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
|
||||||
WARN_ONCE(adev->kfd.vram_used < 0,
|
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||||
"kfd VRAM memory accounting unbalanced");
|
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||||
}
|
} else if (alloc_flag &
|
||||||
|
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||||
|
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||||
|
kfd_mem_limit.system_mem_used -= acc_size;
|
||||||
|
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||||
|
} else {
|
||||||
|
pr_err("%s: Invalid BO type %#x\n", __func__, alloc_flag);
|
||||||
|
goto release;
|
||||||
}
|
}
|
||||||
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
|
||||||
"kfd system memory accounting unbalanced");
|
|
||||||
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
|
||||||
"kfd TTM memory accounting unbalanced");
|
|
||||||
|
|
||||||
|
WARN_ONCE(adev->kfd.vram_used < 0,
|
||||||
|
"KFD VRAM memory accounting unbalanced");
|
||||||
|
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
||||||
|
"KFD TTM memory accounting unbalanced");
|
||||||
|
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
||||||
|
"KFD system memory accounting unbalanced");
|
||||||
|
|
||||||
|
release:
|
||||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
|
void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||||
u32 domain = bo->preferred_domains;
|
u32 alloc_flags = bo->kfd_bo->alloc_flags;
|
||||||
bool sg = (bo->preferred_domains == AMDGPU_GEM_DOMAIN_CPU);
|
u64 size = amdgpu_bo_size(bo);
|
||||||
|
|
||||||
if (bo->flags & AMDGPU_AMDKFD_CREATE_USERPTR_BO) {
|
unreserve_mem_limit(adev, size, alloc_flags);
|
||||||
domain = AMDGPU_GEM_DOMAIN_CPU;
|
|
||||||
sg = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unreserve_mem_limit(adev, amdgpu_bo_size(bo), domain, sg);
|
|
||||||
|
|
||||||
kfree(bo->kfd_bo);
|
kfree(bo->kfd_bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* amdgpu_amdkfd_remove_eviction_fence - Removes eviction fence from BO's
|
/* amdgpu_amdkfd_remove_eviction_fence - Removes eviction fence from BO's
|
||||||
* reservation object.
|
* reservation object.
|
||||||
*
|
*
|
||||||
@ -691,10 +708,12 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
|
|||||||
pr_debug("\t add VA 0x%llx - 0x%llx to vm %p\n", va,
|
pr_debug("\t add VA 0x%llx - 0x%llx to vm %p\n", va,
|
||||||
va + bo_size, vm);
|
va + bo_size, vm);
|
||||||
|
|
||||||
if (adev == bo_adev || (mem->domain == AMDGPU_GEM_DOMAIN_VRAM &&
|
if (adev == bo_adev ||
|
||||||
amdgpu_xgmi_same_hive(adev, bo_adev))) {
|
(amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) && adev->ram_is_direct_mapped) ||
|
||||||
/* Mappings on the local GPU and VRAM mappings in the
|
(mem->domain == AMDGPU_GEM_DOMAIN_VRAM && amdgpu_xgmi_same_hive(adev, bo_adev))) {
|
||||||
* local hive share the original BO
|
/* Mappings on the local GPU, or VRAM mappings in the
|
||||||
|
* local hive, or userptr mapping IOMMU direct map mode
|
||||||
|
* share the original BO
|
||||||
*/
|
*/
|
||||||
attachment[i]->type = KFD_MEM_ATT_SHARED;
|
attachment[i]->type = KFD_MEM_ATT_SHARED;
|
||||||
bo[i] = mem->bo;
|
bo[i] = mem->bo;
|
||||||
@ -1272,12 +1291,60 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
/**
|
||||||
|
* amdgpu_amdkfd_gpuvm_pin_bo() - Pins a BO using following criteria
|
||||||
|
* @bo: Handle of buffer object being pinned
|
||||||
|
* @domain: Domain into which BO should be pinned
|
||||||
|
*
|
||||||
|
* - USERPTR BOs are UNPINNABLE and will return error
|
||||||
|
* - All other BO types (GTT, VRAM, MMIO and DOORBELL) will have their
|
||||||
|
* PIN count incremented. It is valid to PIN a BO multiple times
|
||||||
|
*
|
||||||
|
* Return: ZERO if successful in pinning, Non-Zero in case of error.
|
||||||
|
*/
|
||||||
|
static int amdgpu_amdkfd_gpuvm_pin_bo(struct amdgpu_bo *bo, u32 domain)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = amdgpu_bo_reserve(bo, false);
|
||||||
|
if (unlikely(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = amdgpu_bo_pin_restricted(bo, domain, 0, 0);
|
||||||
|
if (ret)
|
||||||
|
pr_err("Error in Pinning BO to domain: %d\n", domain);
|
||||||
|
|
||||||
|
amdgpu_bo_sync_wait(bo, AMDGPU_FENCE_OWNER_KFD, false);
|
||||||
|
amdgpu_bo_unreserve(bo);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* amdgpu_amdkfd_gpuvm_unpin_bo() - Unpins BO using following criteria
|
||||||
|
* @bo: Handle of buffer object being unpinned
|
||||||
|
*
|
||||||
|
* - Is a illegal request for USERPTR BOs and is ignored
|
||||||
|
* - All other BO types (GTT, VRAM, MMIO and DOORBELL) will have their
|
||||||
|
* PIN count decremented. Calls to UNPIN must balance calls to PIN
|
||||||
|
*/
|
||||||
|
static void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = amdgpu_bo_reserve(bo, false);
|
||||||
|
if (unlikely(ret))
|
||||||
|
return;
|
||||||
|
|
||||||
|
amdgpu_bo_unpin(bo);
|
||||||
|
amdgpu_bo_unreserve(bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||||
struct file *filp, u32 pasid,
|
struct file *filp, u32 pasid,
|
||||||
void **process_info,
|
void **process_info,
|
||||||
struct dma_fence **ef)
|
struct dma_fence **ef)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_fpriv *drv_priv;
|
struct amdgpu_fpriv *drv_priv;
|
||||||
struct amdgpu_vm *avm;
|
struct amdgpu_vm *avm;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1353,12 +1420,12 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *drm_priv)
|
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||||
|
void *drm_priv)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_vm *avm;
|
struct amdgpu_vm *avm;
|
||||||
|
|
||||||
if (WARN_ON(!kgd || !drm_priv))
|
if (WARN_ON(!adev || !drm_priv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
avm = drm_priv_to_vm(drm_priv);
|
avm = drm_priv_to_vm(drm_priv);
|
||||||
@ -1386,11 +1453,10 @@ uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||||
struct kgd_dev *kgd, uint64_t va, uint64_t size,
|
struct amdgpu_device *adev, uint64_t va, uint64_t size,
|
||||||
void *drm_priv, struct kgd_mem **mem,
|
void *drm_priv, struct kgd_mem **mem,
|
||||||
uint64_t *offset, uint32_t flags)
|
uint64_t *offset, uint32_t flags)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||||
enum ttm_bo_type bo_type = ttm_bo_type_device;
|
enum ttm_bo_type bo_type = ttm_bo_type_device;
|
||||||
struct sg_table *sg = NULL;
|
struct sg_table *sg = NULL;
|
||||||
@ -1454,7 +1520,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||||||
|
|
||||||
amdgpu_sync_create(&(*mem)->sync);
|
amdgpu_sync_create(&(*mem)->sync);
|
||||||
|
|
||||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, alloc_domain, !!sg);
|
ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_debug("Insufficient memory\n");
|
pr_debug("Insufficient memory\n");
|
||||||
goto err_reserve_limit;
|
goto err_reserve_limit;
|
||||||
@ -1495,6 +1561,15 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||||||
ret = init_user_pages(*mem, user_addr);
|
ret = init_user_pages(*mem, user_addr);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto allocate_init_user_pages_failed;
|
goto allocate_init_user_pages_failed;
|
||||||
|
} else if (flags & (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||||
|
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||||
|
ret = amdgpu_amdkfd_gpuvm_pin_bo(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("Pinning MMIO/DOORBELL BO during ALLOC FAILED\n");
|
||||||
|
goto err_pin_bo;
|
||||||
|
}
|
||||||
|
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
|
||||||
|
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset)
|
if (offset)
|
||||||
@ -1503,13 +1578,14 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
allocate_init_user_pages_failed:
|
allocate_init_user_pages_failed:
|
||||||
|
err_pin_bo:
|
||||||
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
|
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
|
||||||
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
|
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
|
||||||
err_node_allow:
|
err_node_allow:
|
||||||
/* Don't unreserve system mem limit twice */
|
/* Don't unreserve system mem limit twice */
|
||||||
goto err_reserve_limit;
|
goto err_reserve_limit;
|
||||||
err_bo_create:
|
err_bo_create:
|
||||||
unreserve_mem_limit(adev, size, alloc_domain, !!sg);
|
unreserve_mem_limit(adev, size, flags);
|
||||||
err_reserve_limit:
|
err_reserve_limit:
|
||||||
mutex_destroy(&(*mem)->lock);
|
mutex_destroy(&(*mem)->lock);
|
||||||
if (gobj)
|
if (gobj)
|
||||||
@ -1525,7 +1601,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv,
|
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||||
uint64_t *size)
|
uint64_t *size)
|
||||||
{
|
{
|
||||||
struct amdkfd_process_info *process_info = mem->process_info;
|
struct amdkfd_process_info *process_info = mem->process_info;
|
||||||
@ -1538,6 +1614,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
|||||||
bool is_imported = false;
|
bool is_imported = false;
|
||||||
|
|
||||||
mutex_lock(&mem->lock);
|
mutex_lock(&mem->lock);
|
||||||
|
|
||||||
|
/* Unpin MMIO/DOORBELL BO's that were pinnned during allocation */
|
||||||
|
if (mem->alloc_flags &
|
||||||
|
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||||
|
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||||
|
amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
|
||||||
|
}
|
||||||
|
|
||||||
mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
|
mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
|
||||||
is_imported = mem->is_imported;
|
is_imported = mem->is_imported;
|
||||||
mutex_unlock(&mem->lock);
|
mutex_unlock(&mem->lock);
|
||||||
@ -1617,10 +1701,9 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem,
|
struct amdgpu_device *adev, struct kgd_mem *mem,
|
||||||
void *drm_priv, bool *table_freed)
|
void *drm_priv, bool *table_freed)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
|
||||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||||
int ret;
|
int ret;
|
||||||
struct amdgpu_bo *bo;
|
struct amdgpu_bo *bo;
|
||||||
@ -1747,7 +1830,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv)
|
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv)
|
||||||
{
|
{
|
||||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||||
struct amdkfd_process_info *process_info = avm->process_info;
|
struct amdkfd_process_info *process_info = avm->process_info;
|
||||||
@ -1808,7 +1891,7 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_sync_memory(
|
int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||||
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr)
|
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr)
|
||||||
{
|
{
|
||||||
struct amdgpu_sync sync;
|
struct amdgpu_sync sync;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1824,7 +1907,7 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device *adev,
|
||||||
struct kgd_mem *mem, void **kptr, uint64_t *size)
|
struct kgd_mem *mem, void **kptr, uint64_t *size)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1880,7 +1963,8 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem)
|
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct amdgpu_device *adev,
|
||||||
|
struct kgd_mem *mem)
|
||||||
{
|
{
|
||||||
struct amdgpu_bo *bo = mem->bo;
|
struct amdgpu_bo *bo = mem->bo;
|
||||||
|
|
||||||
@ -1890,12 +1974,9 @@ void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kg
|
|||||||
amdgpu_bo_unreserve(bo);
|
amdgpu_bo_unreserve(bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct amdgpu_device *adev,
|
||||||
struct kfd_vm_fault_info *mem)
|
struct kfd_vm_fault_info *mem)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev;
|
|
||||||
|
|
||||||
adev = (struct amdgpu_device *)kgd;
|
|
||||||
if (atomic_read(&adev->gmc.vm_fault_info_updated) == 1) {
|
if (atomic_read(&adev->gmc.vm_fault_info_updated) == 1) {
|
||||||
*mem = *adev->gmc.vm_fault_info;
|
*mem = *adev->gmc.vm_fault_info;
|
||||||
mb();
|
mb();
|
||||||
@ -1904,13 +1985,12 @@ int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||||
struct dma_buf *dma_buf,
|
struct dma_buf *dma_buf,
|
||||||
uint64_t va, void *drm_priv,
|
uint64_t va, void *drm_priv,
|
||||||
struct kgd_mem **mem, uint64_t *size,
|
struct kgd_mem **mem, uint64_t *size,
|
||||||
uint64_t *mmap_offset)
|
uint64_t *mmap_offset)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||||
struct drm_gem_object *obj;
|
struct drm_gem_object *obj;
|
||||||
struct amdgpu_bo *bo;
|
struct amdgpu_bo *bo;
|
||||||
@ -2537,11 +2617,9 @@ int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns GPU-specific tiling mode information */
|
/* Returns GPU-specific tiling mode information */
|
||||||
int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
|
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||||
struct tile_config *config)
|
struct tile_config *config)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
|
||||||
|
|
||||||
config->gb_addr_config = adev->gfx.config.gb_addr_config;
|
config->gb_addr_config = adev->gfx.config.gb_addr_config;
|
||||||
config->tile_config_ptr = adev->gfx.config.tile_mode_array;
|
config->tile_config_ptr = adev->gfx.config.tile_mode_array;
|
||||||
config->num_tile_configs =
|
config->num_tile_configs =
|
||||||
|
@ -470,8 +470,8 @@ bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *ade
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_atomfirmware_ras_rom_addr -- Get the RAS EEPROM addr from VBIOS
|
* amdgpu_atomfirmware_ras_rom_addr -- Get the RAS EEPROM addr from VBIOS
|
||||||
* adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
* i2c_address: pointer to u8; if not NULL, will contain
|
* @i2c_address: pointer to u8; if not NULL, will contain
|
||||||
* the RAS EEPROM address if the function returns true
|
* the RAS EEPROM address if the function returns true
|
||||||
*
|
*
|
||||||
* Return true if VBIOS supports RAS EEPROM address reporting,
|
* Return true if VBIOS supports RAS EEPROM address reporting,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
|
#include "amdgpu.h"
|
||||||
#include "amd_acpi.h"
|
#include "amd_acpi.h"
|
||||||
|
|
||||||
#define AMDGPU_PX_QUIRK_FORCE_ATPX (1 << 0)
|
#define AMDGPU_PX_QUIRK_FORCE_ATPX (1 << 0)
|
||||||
@ -165,7 +166,7 @@ static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mas
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_atpx_validate_functions - validate ATPX functions
|
* amdgpu_atpx_validate - validate ATPX functions
|
||||||
*
|
*
|
||||||
* @atpx: amdgpu atpx struct
|
* @atpx: amdgpu atpx struct
|
||||||
*
|
*
|
||||||
|
@ -108,7 +108,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||||||
case DRM_MODE_CONNECTOR_DVII:
|
case DRM_MODE_CONNECTOR_DVII:
|
||||||
case DRM_MODE_CONNECTOR_HDMIB:
|
case DRM_MODE_CONNECTOR_HDMIB:
|
||||||
if (amdgpu_connector->use_digital) {
|
if (amdgpu_connector->use_digital) {
|
||||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
if (connector->display_info.is_hdmi) {
|
||||||
if (connector->display_info.bpc)
|
if (connector->display_info.bpc)
|
||||||
bpc = connector->display_info.bpc;
|
bpc = connector->display_info.bpc;
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||||||
break;
|
break;
|
||||||
case DRM_MODE_CONNECTOR_DVID:
|
case DRM_MODE_CONNECTOR_DVID:
|
||||||
case DRM_MODE_CONNECTOR_HDMIA:
|
case DRM_MODE_CONNECTOR_HDMIA:
|
||||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
if (connector->display_info.is_hdmi) {
|
||||||
if (connector->display_info.bpc)
|
if (connector->display_info.bpc)
|
||||||
bpc = connector->display_info.bpc;
|
bpc = connector->display_info.bpc;
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||||||
dig_connector = amdgpu_connector->con_priv;
|
dig_connector = amdgpu_connector->con_priv;
|
||||||
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
|
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
|
||||||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
|
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
|
||||||
drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
connector->display_info.is_hdmi) {
|
||||||
if (connector->display_info.bpc)
|
if (connector->display_info.bpc)
|
||||||
bpc = connector->display_info.bpc;
|
bpc = connector->display_info.bpc;
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
if (connector->display_info.is_hdmi) {
|
||||||
/*
|
/*
|
||||||
* Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
|
* Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
|
||||||
* much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
|
* much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
|
||||||
@ -315,8 +315,10 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||||||
if (!amdgpu_connector->edid) {
|
if (!amdgpu_connector->edid) {
|
||||||
/* some laptops provide a hardcoded edid in rom for LCDs */
|
/* some laptops provide a hardcoded edid in rom for LCDs */
|
||||||
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
|
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
|
||||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
|
(connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
|
||||||
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
|
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
|
||||||
|
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,6 +328,7 @@ static void amdgpu_connector_free_edid(struct drm_connector *connector)
|
|||||||
|
|
||||||
kfree(amdgpu_connector->edid);
|
kfree(amdgpu_connector->edid);
|
||||||
amdgpu_connector->edid = NULL;
|
amdgpu_connector->edid = NULL;
|
||||||
|
drm_connector_update_edid_property(connector, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
|
static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
|
||||||
@ -387,6 +390,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
|
|||||||
native_mode->vdisplay != 0 &&
|
native_mode->vdisplay != 0 &&
|
||||||
native_mode->clock != 0) {
|
native_mode->clock != 0) {
|
||||||
mode = drm_mode_duplicate(dev, native_mode);
|
mode = drm_mode_duplicate(dev, native_mode);
|
||||||
|
if (!mode)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
||||||
drm_mode_set_name(mode);
|
drm_mode_set_name(mode);
|
||||||
|
|
||||||
@ -401,6 +407,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
|
|||||||
* simpler.
|
* simpler.
|
||||||
*/
|
*/
|
||||||
mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
|
mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
|
||||||
|
if (!mode)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
||||||
DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
|
DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
|
||||||
}
|
}
|
||||||
@ -1171,7 +1180,7 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector
|
|||||||
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
|
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
|
||||||
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) {
|
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) {
|
||||||
return MODE_OK;
|
return MODE_OK;
|
||||||
} else if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
} else if (connector->display_info.is_hdmi) {
|
||||||
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
||||||
if (mode->clock > 340000)
|
if (mode->clock > 340000)
|
||||||
return MODE_CLOCK_HIGH;
|
return MODE_CLOCK_HIGH;
|
||||||
@ -1463,7 +1472,7 @@ static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector
|
|||||||
(amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
|
(amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
|
||||||
return amdgpu_atombios_dp_mode_valid_helper(connector, mode);
|
return amdgpu_atombios_dp_mode_valid_helper(connector, mode);
|
||||||
} else {
|
} else {
|
||||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
if (connector->display_info.is_hdmi) {
|
||||||
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
||||||
if (mode->clock > 340000)
|
if (mode->clock > 340000)
|
||||||
return MODE_CLOCK_HIGH;
|
return MODE_CLOCK_HIGH;
|
||||||
|
@ -1618,6 +1618,9 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
|||||||
if (!debugfs_initialized())
|
if (!debugfs_initialized())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
debugfs_create_x32("amdgpu_smu_debug", 0600, root,
|
||||||
|
&adev->pm.smu_debug_mask);
|
||||||
|
|
||||||
ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev,
|
ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev,
|
||||||
&fops_ib_preempt);
|
&fops_ib_preempt);
|
||||||
if (IS_ERR(ent)) {
|
if (IS_ERR(ent)) {
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/iommu.h>
|
||||||
|
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
@ -331,7 +332,7 @@ void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_device_vram_access - access vram by vram aperature
|
* amdgpu_device_aper_access - access vram by vram aperature
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
* @pos: offset of the buffer in vram
|
* @pos: offset of the buffer in vram
|
||||||
@ -550,11 +551,11 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
|||||||
trace_amdgpu_device_wreg(adev->pdev->device, reg, v);
|
trace_amdgpu_device_wreg(adev->pdev->device, reg, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* amdgpu_mm_wreg_mmio_rlc - write register either with mmio or with RLC path if in range
|
* amdgpu_mm_wreg_mmio_rlc - write register either with mmio or with RLC path if in range
|
||||||
*
|
*
|
||||||
* this function is invoked only the debugfs register access
|
* this function is invoked only the debugfs register access
|
||||||
* */
|
*/
|
||||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||||
uint32_t reg, uint32_t v)
|
uint32_t reg, uint32_t v)
|
||||||
{
|
{
|
||||||
@ -1100,7 +1101,7 @@ static void amdgpu_device_wb_fini(struct amdgpu_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_device_wb_init- Init Writeback driver info and allocate memory
|
* amdgpu_device_wb_init - Init Writeback driver info and allocate memory
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
*
|
*
|
||||||
@ -2316,6 +2317,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||||||
|
|
||||||
/* need to do gmc hw init early so we can allocate gpu mem */
|
/* need to do gmc hw init early so we can allocate gpu mem */
|
||||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
|
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
|
||||||
|
/* Try to reserve bad pages early */
|
||||||
|
if (amdgpu_sriov_vf(adev))
|
||||||
|
amdgpu_virt_exchange_data(adev);
|
||||||
|
|
||||||
r = amdgpu_device_vram_scratch_init(adev);
|
r = amdgpu_device_vram_scratch_init(adev);
|
||||||
if (r) {
|
if (r) {
|
||||||
DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
|
DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
|
||||||
@ -2347,7 +2352,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (amdgpu_sriov_vf(adev))
|
if (amdgpu_sriov_vf(adev))
|
||||||
amdgpu_virt_init_data_exchange(adev);
|
amdgpu_virt_exchange_data(adev);
|
||||||
|
|
||||||
r = amdgpu_ib_pool_init(adev);
|
r = amdgpu_ib_pool_init(adev);
|
||||||
if (r) {
|
if (r) {
|
||||||
@ -2614,11 +2619,10 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
|||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
|
DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
|
||||||
|
|
||||||
/* For XGMI + passthrough configuration on arcturus, enable light SBR */
|
/* For passthrough configuration on arcturus and aldebaran, enable special handling SBR */
|
||||||
if (adev->asic_type == CHIP_ARCTURUS &&
|
if (amdgpu_passthrough(adev) && ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1)||
|
||||||
amdgpu_passthrough(adev) &&
|
adev->asic_type == CHIP_ALDEBARAN ))
|
||||||
adev->gmc.xgmi.num_physical_nodes > 1)
|
smu_handle_passthrough_sbr(&adev->smu, true);
|
||||||
smu_set_light_sbr(&adev->smu, true);
|
|
||||||
|
|
||||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||||
mutex_lock(&mgpu_info.mutex);
|
mutex_lock(&mgpu_info.mutex);
|
||||||
@ -2657,6 +2661,36 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* amdgpu_device_smu_fini_early - smu hw_fini wrapper
|
||||||
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
|
*
|
||||||
|
* For ASICs need to disable SMC first
|
||||||
|
*/
|
||||||
|
static void amdgpu_device_smu_fini_early(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
if (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||||
|
if (!adev->ip_blocks[i].status.hw)
|
||||||
|
continue;
|
||||||
|
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
|
||||||
|
r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
|
||||||
|
/* XXX handle errors */
|
||||||
|
if (r) {
|
||||||
|
DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
|
||||||
|
adev->ip_blocks[i].version->funcs->name, r);
|
||||||
|
}
|
||||||
|
adev->ip_blocks[i].status.hw = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
@ -2677,21 +2711,8 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
|||||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||||
|
|
||||||
/* need to disable SMC first */
|
/* Workaroud for ASICs need to disable SMC first */
|
||||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
amdgpu_device_smu_fini_early(adev);
|
||||||
if (!adev->ip_blocks[i].status.hw)
|
|
||||||
continue;
|
|
||||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
|
|
||||||
r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
|
|
||||||
/* XXX handle errors */
|
|
||||||
if (r) {
|
|
||||||
DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
|
|
||||||
adev->ip_blocks[i].version->funcs->name, r);
|
|
||||||
}
|
|
||||||
adev->ip_blocks[i].status.hw = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||||
if (!adev->ip_blocks[i].status.hw)
|
if (!adev->ip_blocks[i].status.hw)
|
||||||
@ -2733,8 +2754,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
|||||||
if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
|
if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
|
||||||
amdgpu_virt_release_ras_err_handler_data(adev);
|
amdgpu_virt_release_ras_err_handler_data(adev);
|
||||||
|
|
||||||
amdgpu_ras_pre_fini(adev);
|
|
||||||
|
|
||||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||||
amdgpu_xgmi_remove_device(adev);
|
amdgpu_xgmi_remove_device(adev);
|
||||||
|
|
||||||
@ -3373,6 +3392,22 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* amdgpu_device_check_iommu_direct_map - check if RAM direct mapped to GPU
|
||||||
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
|
*
|
||||||
|
* RAM direct mapped to GPU if IOMMU is not enabled or is pass through mode
|
||||||
|
*/
|
||||||
|
static void amdgpu_device_check_iommu_direct_map(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
struct iommu_domain *domain;
|
||||||
|
|
||||||
|
domain = iommu_get_domain_for_dev(adev->dev);
|
||||||
|
if (!domain || domain->type == IOMMU_DOMAIN_IDENTITY)
|
||||||
|
adev->ram_is_direct_mapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct attribute *amdgpu_dev_attributes[] = {
|
static const struct attribute *amdgpu_dev_attributes[] = {
|
||||||
&dev_attr_product_name.attr,
|
&dev_attr_product_name.attr,
|
||||||
&dev_attr_product_number.attr,
|
&dev_attr_product_number.attr,
|
||||||
@ -3547,6 +3582,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
/* Need to get xgmi info early to decide the reset behavior*/
|
||||||
|
if (adev->gmc.xgmi.supported) {
|
||||||
|
r = adev->gfxhub.funcs->get_xgmi_info(adev);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* enable PCIE atomic ops */
|
/* enable PCIE atomic ops */
|
||||||
if (amdgpu_sriov_vf(adev))
|
if (amdgpu_sriov_vf(adev))
|
||||||
adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
|
adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
|
||||||
@ -3693,8 +3735,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||||||
/* Get a log2 for easy divisions. */
|
/* Get a log2 for easy divisions. */
|
||||||
adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
|
adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
|
||||||
|
|
||||||
amdgpu_fbdev_init(adev);
|
|
||||||
|
|
||||||
r = amdgpu_pm_sysfs_init(adev);
|
r = amdgpu_pm_sysfs_init(adev);
|
||||||
if (r) {
|
if (r) {
|
||||||
adev->pm_sysfs_en = false;
|
adev->pm_sysfs_en = false;
|
||||||
@ -3778,6 +3818,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||||||
queue_delayed_work(system_wq, &mgpu_info.delayed_reset_work,
|
queue_delayed_work(system_wq, &mgpu_info.delayed_reset_work,
|
||||||
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
||||||
|
|
||||||
|
amdgpu_device_check_iommu_direct_map(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
release_ras_con:
|
release_ras_con:
|
||||||
@ -3811,7 +3853,7 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_device_fini - tear down the driver
|
* amdgpu_device_fini_hw - tear down the driver
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
*
|
*
|
||||||
@ -3852,17 +3894,21 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
|||||||
amdgpu_ucode_sysfs_fini(adev);
|
amdgpu_ucode_sysfs_fini(adev);
|
||||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||||
|
|
||||||
amdgpu_fbdev_fini(adev);
|
/* disable ras feature must before hw fini */
|
||||||
|
amdgpu_ras_pre_fini(adev);
|
||||||
|
|
||||||
amdgpu_device_ip_fini_early(adev);
|
amdgpu_device_ip_fini_early(adev);
|
||||||
|
|
||||||
amdgpu_irq_fini_hw(adev);
|
amdgpu_irq_fini_hw(adev);
|
||||||
|
|
||||||
ttm_device_clear_dma_mappings(&adev->mman.bdev);
|
if (adev->mman.initialized)
|
||||||
|
ttm_device_clear_dma_mappings(&adev->mman.bdev);
|
||||||
|
|
||||||
amdgpu_gart_dummy_page_fini(adev);
|
amdgpu_gart_dummy_page_fini(adev);
|
||||||
|
|
||||||
amdgpu_device_unmap_mmio(adev);
|
if (drm_dev_is_unplugged(adev_to_drm(adev)))
|
||||||
|
amdgpu_device_unmap_mmio(adev);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
||||||
@ -3948,7 +3994,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
|||||||
drm_kms_helper_poll_disable(dev);
|
drm_kms_helper_poll_disable(dev);
|
||||||
|
|
||||||
if (fbcon)
|
if (fbcon)
|
||||||
amdgpu_fbdev_set_suspend(adev, 1);
|
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&adev->delayed_init_work);
|
cancel_delayed_work_sync(&adev->delayed_init_work);
|
||||||
|
|
||||||
@ -4025,7 +4071,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
|||||||
flush_delayed_work(&adev->delayed_init_work);
|
flush_delayed_work(&adev->delayed_init_work);
|
||||||
|
|
||||||
if (fbcon)
|
if (fbcon)
|
||||||
amdgpu_fbdev_set_suspend(adev, 0);
|
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
|
||||||
|
|
||||||
drm_kms_helper_poll_enable(dev);
|
drm_kms_helper_poll_enable(dev);
|
||||||
|
|
||||||
@ -4294,6 +4340,9 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||||||
bool from_hypervisor)
|
bool from_hypervisor)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
struct amdgpu_hive_info *hive = NULL;
|
||||||
|
|
||||||
|
amdgpu_amdkfd_pre_reset(adev);
|
||||||
|
|
||||||
amdgpu_amdkfd_pre_reset(adev);
|
amdgpu_amdkfd_pre_reset(adev);
|
||||||
|
|
||||||
@ -4322,9 +4371,19 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||||||
if (r)
|
if (r)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
amdgpu_irq_gpu_reset_resume_helper(adev);
|
hive = amdgpu_get_xgmi_hive(adev);
|
||||||
r = amdgpu_ib_ring_tests(adev);
|
/* Update PSP FW topology after reset */
|
||||||
amdgpu_amdkfd_post_reset(adev);
|
if (hive && adev->gmc.xgmi.num_physical_nodes > 1)
|
||||||
|
r = amdgpu_xgmi_update_topology(hive, adev);
|
||||||
|
|
||||||
|
if (hive)
|
||||||
|
amdgpu_put_xgmi_hive(hive);
|
||||||
|
|
||||||
|
if (!r) {
|
||||||
|
amdgpu_irq_gpu_reset_resume_helper(adev);
|
||||||
|
r = amdgpu_ib_ring_tests(adev);
|
||||||
|
amdgpu_amdkfd_post_reset(adev);
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
|
if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
|
||||||
@ -4650,7 +4709,7 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
|||||||
if (r)
|
if (r)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
amdgpu_fbdev_set_suspend(tmp_adev, 0);
|
drm_fb_helper_set_suspend_unlocked(adev_to_drm(tmp_adev)->fb_helper, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The GPU enters bad state once faulty pages
|
* The GPU enters bad state once faulty pages
|
||||||
@ -4749,7 +4808,7 @@ static int amdgpu_device_lock_hive_adev(struct amdgpu_device *adev, struct amdgp
|
|||||||
{
|
{
|
||||||
struct amdgpu_device *tmp_adev = NULL;
|
struct amdgpu_device *tmp_adev = NULL;
|
||||||
|
|
||||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1)) {
|
||||||
if (!hive) {
|
if (!hive) {
|
||||||
dev_err(adev->dev, "Hive is NULL while device has multiple xgmi nodes");
|
dev_err(adev->dev, "Hive is NULL while device has multiple xgmi nodes");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -4961,7 +5020,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||||||
* We always reset all schedulers for device and all devices for XGMI
|
* We always reset all schedulers for device and all devices for XGMI
|
||||||
* hive so that should take care of them too.
|
* hive so that should take care of them too.
|
||||||
*/
|
*/
|
||||||
hive = amdgpu_get_xgmi_hive(adev);
|
if (!amdgpu_sriov_vf(adev))
|
||||||
|
hive = amdgpu_get_xgmi_hive(adev);
|
||||||
if (hive) {
|
if (hive) {
|
||||||
if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) {
|
if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) {
|
||||||
DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
|
DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
|
||||||
@ -5002,7 +5062,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||||||
* to put adev in the 1st position.
|
* to put adev in the 1st position.
|
||||||
*/
|
*/
|
||||||
INIT_LIST_HEAD(&device_list);
|
INIT_LIST_HEAD(&device_list);
|
||||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1)) {
|
||||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
|
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
|
||||||
list_add_tail(&tmp_adev->reset_list, &device_list);
|
list_add_tail(&tmp_adev->reset_list, &device_list);
|
||||||
if (!list_is_first(&adev->reset_list, &device_list))
|
if (!list_is_first(&adev->reset_list, &device_list))
|
||||||
@ -5041,7 +5101,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||||||
*/
|
*/
|
||||||
amdgpu_unregister_gpu_instance(tmp_adev);
|
amdgpu_unregister_gpu_instance(tmp_adev);
|
||||||
|
|
||||||
amdgpu_fbdev_set_suspend(tmp_adev, 1);
|
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
|
||||||
|
|
||||||
/* disable ras on ALL IPs */
|
/* disable ras on ALL IPs */
|
||||||
if (!need_emergency_restart &&
|
if (!need_emergency_restart &&
|
||||||
@ -5636,3 +5696,42 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
|||||||
|
|
||||||
amdgpu_asic_invalidate_hdp(adev, ring);
|
amdgpu_asic_invalidate_hdp(adev, ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* amdgpu_device_halt() - bring hardware to some kind of halt state
|
||||||
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
|
*
|
||||||
|
* Bring hardware to some kind of halt state so that no one can touch it
|
||||||
|
* any more. It will help to maintain error context when error occurred.
|
||||||
|
* Compare to a simple hang, the system will keep stable at least for SSH
|
||||||
|
* access. Then it should be trivial to inspect the hardware state and
|
||||||
|
* see what's going on. Implemented as following:
|
||||||
|
*
|
||||||
|
* 1. drm_dev_unplug() makes device inaccessible to user space(IOCTLs, etc),
|
||||||
|
* clears all CPU mappings to device, disallows remappings through page faults
|
||||||
|
* 2. amdgpu_irq_disable_all() disables all interrupts
|
||||||
|
* 3. amdgpu_fence_driver_hw_fini() signals all HW fences
|
||||||
|
* 4. set adev->no_hw_access to avoid potential crashes after setp 5
|
||||||
|
* 5. amdgpu_device_unmap_mmio() clears all MMIO mappings
|
||||||
|
* 6. pci_disable_device() and pci_wait_for_pending_transaction()
|
||||||
|
* flush any in flight DMA operations
|
||||||
|
*/
|
||||||
|
void amdgpu_device_halt(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = adev->pdev;
|
||||||
|
struct drm_device *ddev = adev_to_drm(adev);
|
||||||
|
|
||||||
|
drm_dev_unplug(ddev);
|
||||||
|
|
||||||
|
amdgpu_irq_disable_all(adev);
|
||||||
|
|
||||||
|
amdgpu_fence_driver_hw_fini(adev);
|
||||||
|
|
||||||
|
adev->no_hw_access = true;
|
||||||
|
|
||||||
|
amdgpu_device_unmap_mmio(adev);
|
||||||
|
|
||||||
|
pci_disable_device(pdev);
|
||||||
|
pci_wait_for_pending_transaction(pdev);
|
||||||
|
}
|
||||||
|
@ -67,7 +67,8 @@
|
|||||||
#include "smuio_v11_0_6.h"
|
#include "smuio_v11_0_6.h"
|
||||||
#include "smuio_v13_0.h"
|
#include "smuio_v13_0.h"
|
||||||
|
|
||||||
MODULE_FIRMWARE("amdgpu/ip_discovery.bin");
|
#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
|
||||||
|
MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
|
||||||
|
|
||||||
#define mmRCC_CONFIG_MEMSIZE 0xde3
|
#define mmRCC_CONFIG_MEMSIZE 0xde3
|
||||||
#define mmMM_INDEX 0x0
|
#define mmMM_INDEX 0x0
|
||||||
@ -179,7 +180,7 @@ static int hw_id_map[MAX_HWIP] = {
|
|||||||
[DCI_HWIP] = DCI_HWID,
|
[DCI_HWIP] = DCI_HWID,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
|
static int amdgpu_discovery_read_binary_from_vram(struct amdgpu_device *adev, uint8_t *binary)
|
||||||
{
|
{
|
||||||
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||||
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
|
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
|
||||||
@ -189,6 +190,34 @@ static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *bin
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary)
|
||||||
|
{
|
||||||
|
const struct firmware *fw;
|
||||||
|
const char *fw_name;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
switch (amdgpu_discovery) {
|
||||||
|
case 2:
|
||||||
|
fw_name = FIRMWARE_IP_DISCOVERY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_warn(adev->dev, "amdgpu_discovery is not set properly\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = request_firmware(&fw, fw_name, adev->dev);
|
||||||
|
if (r) {
|
||||||
|
dev_err(adev->dev, "can't load firmware \"%s\"\n",
|
||||||
|
fw_name);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((u8 *)binary, (u8 *)fw->data, adev->mman.discovery_tmr_size);
|
||||||
|
release_firmware(fw);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size)
|
static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size)
|
||||||
{
|
{
|
||||||
uint16_t checksum = 0;
|
uint16_t checksum = 0;
|
||||||
@ -206,13 +235,20 @@ static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size
|
|||||||
return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);
|
return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary)
|
||||||
|
{
|
||||||
|
struct binary_header *bhdr;
|
||||||
|
bhdr = (struct binary_header *)binary;
|
||||||
|
|
||||||
|
return (le32_to_cpu(bhdr->binary_signature) == BINARY_SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct table_info *info;
|
struct table_info *info;
|
||||||
struct binary_header *bhdr;
|
struct binary_header *bhdr;
|
||||||
struct ip_discovery_header *ihdr;
|
struct ip_discovery_header *ihdr;
|
||||||
struct gpu_info_header *ghdr;
|
struct gpu_info_header *ghdr;
|
||||||
const struct firmware *fw;
|
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t checksum;
|
uint16_t checksum;
|
||||||
@ -223,31 +259,32 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||||||
if (!adev->mman.discovery_bin)
|
if (!adev->mman.discovery_bin)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (amdgpu_discovery == 2) {
|
r = amdgpu_discovery_read_binary_from_vram(adev, adev->mman.discovery_bin);
|
||||||
r = request_firmware(&fw, "amdgpu/ip_discovery.bin", adev->dev);
|
if (r) {
|
||||||
if (r)
|
dev_err(adev->dev, "failed to read ip discovery binary from vram\n");
|
||||||
goto get_from_vram;
|
r = -EINVAL;
|
||||||
dev_info(adev->dev, "Using IP discovery from file\n");
|
goto out;
|
||||||
memcpy((u8 *)adev->mman.discovery_bin, (u8 *)fw->data,
|
}
|
||||||
adev->mman.discovery_tmr_size);
|
|
||||||
release_firmware(fw);
|
if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
|
||||||
} else {
|
dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n");
|
||||||
get_from_vram:
|
/* retry read ip discovery binary from file */
|
||||||
r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin);
|
r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);
|
||||||
if (r) {
|
if (r) {
|
||||||
DRM_ERROR("failed to read ip discovery binary\n");
|
dev_err(adev->dev, "failed to read ip discovery binary from file\n");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* check the ip discovery binary signature */
|
||||||
|
if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
|
||||||
|
dev_warn(adev->dev, "get invalid ip discovery binary signature from file\n");
|
||||||
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bhdr = (struct binary_header *)adev->mman.discovery_bin;
|
bhdr = (struct binary_header *)adev->mman.discovery_bin;
|
||||||
|
|
||||||
if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) {
|
|
||||||
DRM_ERROR("invalid ip discovery binary signature\n");
|
|
||||||
r = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = offsetof(struct binary_header, binary_checksum) +
|
offset = offsetof(struct binary_header, binary_checksum) +
|
||||||
sizeof(bhdr->binary_checksum);
|
sizeof(bhdr->binary_checksum);
|
||||||
size = le16_to_cpu(bhdr->binary_size) - offset;
|
size = le16_to_cpu(bhdr->binary_size) - offset;
|
||||||
@ -255,7 +292,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||||||
|
|
||||||
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
||||||
size, checksum)) {
|
size, checksum)) {
|
||||||
DRM_ERROR("invalid ip discovery binary checksum\n");
|
dev_err(adev->dev, "invalid ip discovery binary checksum\n");
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -266,14 +303,14 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||||||
ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);
|
ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);
|
||||||
|
|
||||||
if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) {
|
if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) {
|
||||||
DRM_ERROR("invalid ip discovery data table signature\n");
|
dev_err(adev->dev, "invalid ip discovery data table signature\n");
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
||||||
le16_to_cpu(ihdr->size), checksum)) {
|
le16_to_cpu(ihdr->size), checksum)) {
|
||||||
DRM_ERROR("invalid ip discovery data table checksum\n");
|
dev_err(adev->dev, "invalid ip discovery data table checksum\n");
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -285,7 +322,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||||||
|
|
||||||
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
||||||
le32_to_cpu(ghdr->size), checksum)) {
|
le32_to_cpu(ghdr->size), checksum)) {
|
||||||
DRM_ERROR("invalid gc data table checksum\n");
|
dev_err(adev->dev, "invalid gc data table checksum\n");
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -379,8 +416,18 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
|||||||
ip->major, ip->minor,
|
ip->major, ip->minor,
|
||||||
ip->revision);
|
ip->revision);
|
||||||
|
|
||||||
if (le16_to_cpu(ip->hw_id) == VCN_HWID)
|
if (le16_to_cpu(ip->hw_id) == VCN_HWID) {
|
||||||
|
/* Bit [5:0]: original revision value
|
||||||
|
* Bit [7:6]: en/decode capability:
|
||||||
|
* 0b00 : VCN function normally
|
||||||
|
* 0b10 : encode is disabled
|
||||||
|
* 0b01 : decode is disabled
|
||||||
|
*/
|
||||||
|
adev->vcn.vcn_config[adev->vcn.num_vcn_inst] =
|
||||||
|
ip->revision & 0xc0;
|
||||||
|
ip->revision &= ~0xc0;
|
||||||
adev->vcn.num_vcn_inst++;
|
adev->vcn.num_vcn_inst++;
|
||||||
|
}
|
||||||
if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||
|
if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||
|
||||||
le16_to_cpu(ip->hw_id) == SDMA1_HWID ||
|
le16_to_cpu(ip->hw_id) == SDMA1_HWID ||
|
||||||
le16_to_cpu(ip->hw_id) == SDMA2_HWID ||
|
le16_to_cpu(ip->hw_id) == SDMA2_HWID ||
|
||||||
@ -472,14 +519,6 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int n
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance,
|
|
||||||
int *major, int *minor, int *revision)
|
|
||||||
{
|
|
||||||
return amdgpu_discovery_get_ip_version(adev, VCN_HWID,
|
|
||||||
vcn_instance, major, minor, revision);
|
|
||||||
}
|
|
||||||
|
|
||||||
void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct binary_header *bhdr;
|
struct binary_header *bhdr;
|
||||||
@ -949,7 +988,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
|
|||||||
break;
|
break;
|
||||||
case IP_VERSION(3, 0, 0):
|
case IP_VERSION(3, 0, 0):
|
||||||
case IP_VERSION(3, 0, 16):
|
case IP_VERSION(3, 0, 16):
|
||||||
case IP_VERSION(3, 0, 64):
|
|
||||||
case IP_VERSION(3, 1, 1):
|
case IP_VERSION(3, 1, 1):
|
||||||
case IP_VERSION(3, 0, 2):
|
case IP_VERSION(3, 0, 2):
|
||||||
case IP_VERSION(3, 0, 192):
|
case IP_VERSION(3, 0, 192):
|
||||||
@ -986,7 +1024,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
|
|||||||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,6 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev);
|
|||||||
int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance,
|
int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance,
|
||||||
int *major, int *minor, int *revision);
|
int *major, int *minor, int *revision);
|
||||||
|
|
||||||
int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance,
|
|
||||||
int *major, int *minor, int *revision);
|
|
||||||
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev);
|
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev);
|
||||||
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);
|
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);
|
||||||
|
|
||||||
|
@ -83,9 +83,6 @@ static void amdgpu_display_flip_work_func(struct work_struct *__work)
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
int vpos, hpos;
|
int vpos, hpos;
|
||||||
|
|
||||||
if (amdgpu_display_flip_handle_fence(work, &work->excl))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < work->shared_count; ++i)
|
for (i = 0; i < work->shared_count; ++i)
|
||||||
if (amdgpu_display_flip_handle_fence(work, &work->shared[i]))
|
if (amdgpu_display_flip_handle_fence(work, &work->shared[i]))
|
||||||
return;
|
return;
|
||||||
@ -203,7 +200,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||||||
goto unpin;
|
goto unpin;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dma_resv_get_fences(new_abo->tbo.base.resv, &work->excl,
|
r = dma_resv_get_fences(new_abo->tbo.base.resv, NULL,
|
||||||
&work->shared_count, &work->shared);
|
&work->shared_count, &work->shared);
|
||||||
if (unlikely(r != 0)) {
|
if (unlikely(r != 0)) {
|
||||||
DRM_ERROR("failed to get fences for buffer\n");
|
DRM_ERROR("failed to get fences for buffer\n");
|
||||||
@ -253,7 +250,6 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
amdgpu_bo_unref(&work->old_abo);
|
amdgpu_bo_unref(&work->old_abo);
|
||||||
dma_fence_put(work->excl);
|
|
||||||
for (i = 0; i < work->shared_count; ++i)
|
for (i = 0; i < work->shared_count; ++i)
|
||||||
dma_fence_put(work->shared[i]);
|
dma_fence_put(work->shared[i]);
|
||||||
kfree(work->shared);
|
kfree(work->shared);
|
||||||
@ -1364,7 +1360,7 @@ bool amdgpu_display_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
|||||||
if ((!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
|
if ((!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
|
||||||
((amdgpu_encoder->underscan_type == UNDERSCAN_ON) ||
|
((amdgpu_encoder->underscan_type == UNDERSCAN_ON) ||
|
||||||
((amdgpu_encoder->underscan_type == UNDERSCAN_AUTO) &&
|
((amdgpu_encoder->underscan_type == UNDERSCAN_AUTO) &&
|
||||||
drm_detect_hdmi_monitor(amdgpu_connector_edid(connector)) &&
|
connector->display_info.is_hdmi &&
|
||||||
amdgpu_display_is_hdtv_mode(mode)))) {
|
amdgpu_display_is_hdtv_mode(mode)))) {
|
||||||
if (amdgpu_encoder->underscan_hborder != 0)
|
if (amdgpu_encoder->underscan_hborder != 0)
|
||||||
amdgpu_crtc->h_border = amdgpu_encoder->underscan_hborder;
|
amdgpu_crtc->h_border = amdgpu_encoder->underscan_hborder;
|
||||||
@ -1603,13 +1599,10 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||||
/* don't unpin kernel fb objects */
|
r = amdgpu_bo_reserve(robj, true);
|
||||||
if (!amdgpu_fbdev_robj_is_fb(adev, robj)) {
|
if (r == 0) {
|
||||||
r = amdgpu_bo_reserve(robj, true);
|
amdgpu_bo_unpin(robj);
|
||||||
if (r == 0) {
|
amdgpu_bo_unreserve(robj);
|
||||||
amdgpu_bo_unpin(robj);
|
|
||||||
amdgpu_bo_unreserve(robj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -61,9 +61,6 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
|
|||||||
if (pci_p2pdma_distance_many(adev->pdev, &attach->dev, 1, true) < 0)
|
if (pci_p2pdma_distance_many(adev->pdev, &attach->dev, 1, true) < 0)
|
||||||
attach->peer2peer = false;
|
attach->peer2peer = false;
|
||||||
|
|
||||||
if (attach->dev->driver == adev->dev->driver)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "amdgpu_drv.h"
|
#include "amdgpu_drv.h"
|
||||||
|
|
||||||
#include <drm/drm_pciids.h>
|
#include <drm/drm_pciids.h>
|
||||||
#include <linux/console.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/vga_switcheroo.h>
|
#include <linux/vga_switcheroo.h>
|
||||||
@ -315,9 +314,12 @@ module_param_named(dpm, amdgpu_dpm, int, 0444);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* DOC: fw_load_type (int)
|
* DOC: fw_load_type (int)
|
||||||
* Set different firmware loading type for debugging (0 = direct, 1 = SMU, 2 = PSP). The default is -1 (auto).
|
* Set different firmware loading type for debugging, if supported.
|
||||||
|
* Set to 0 to force direct loading if supported by the ASIC. Set
|
||||||
|
* to -1 to select the default loading mode for the ASIC, as defined
|
||||||
|
* by the driver. The default is -1 (auto).
|
||||||
*/
|
*/
|
||||||
MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = direct, 1 = SMU, 2 = PSP, -1 = auto)");
|
MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = force direct if supported, -1 = auto)");
|
||||||
module_param_named(fw_load_type, amdgpu_fw_load_type, int, 0444);
|
module_param_named(fw_load_type, amdgpu_fw_load_type, int, 0444);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2031,6 +2033,19 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
|||||||
goto err_pci;
|
goto err_pci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. don't init fbdev on hw without DCE
|
||||||
|
* 2. don't init fbdev if there are no connectors
|
||||||
|
*/
|
||||||
|
if (adev->mode_info.mode_config_initialized &&
|
||||||
|
!list_empty(&adev_to_drm(adev)->mode_config.connector_list)) {
|
||||||
|
/* select 8 bpp console on low vram cards */
|
||||||
|
if (adev->gmc.real_vram_size <= (32*1024*1024))
|
||||||
|
drm_fbdev_generic_setup(adev_to_drm(adev), 8);
|
||||||
|
else
|
||||||
|
drm_fbdev_generic_setup(adev_to_drm(adev), 32);
|
||||||
|
}
|
||||||
|
|
||||||
ret = amdgpu_debugfs_init(adev);
|
ret = amdgpu_debugfs_init(adev);
|
||||||
if (ret)
|
if (ret)
|
||||||
DRM_ERROR("Creating debugfs files failed (%d).\n", ret);
|
DRM_ERROR("Creating debugfs files failed (%d).\n", ret);
|
||||||
@ -2563,10 +2578,8 @@ static int __init amdgpu_init(void)
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (vgacon_text_force()) {
|
if (drm_firmware_drivers_only())
|
||||||
DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
r = amdgpu_sync_init();
|
r = amdgpu_sync_init();
|
||||||
if (r)
|
if (r)
|
||||||
|
@ -45,4 +45,7 @@
|
|||||||
long amdgpu_drm_ioctl(struct file *filp,
|
long amdgpu_drm_ioctl(struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg);
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
long amdgpu_kms_compat_ioctl(struct file *filp,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,7 +222,7 @@ bool amdgpu_dig_monitor_is_duallink(struct drm_encoder *encoder,
|
|||||||
case DRM_MODE_CONNECTOR_HDMIB:
|
case DRM_MODE_CONNECTOR_HDMIB:
|
||||||
if (amdgpu_connector->use_digital) {
|
if (amdgpu_connector->use_digital) {
|
||||||
/* HDMI 1.3 supports up to 340 Mhz over single link */
|
/* HDMI 1.3 supports up to 340 Mhz over single link */
|
||||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
if (connector->display_info.is_hdmi) {
|
||||||
if (pixel_clock > 340000)
|
if (pixel_clock > 340000)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
@ -244,7 +244,7 @@ bool amdgpu_dig_monitor_is_duallink(struct drm_encoder *encoder,
|
|||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
/* HDMI 1.3 supports up to 340 Mhz over single link */
|
/* HDMI 1.3 supports up to 340 Mhz over single link */
|
||||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
if (connector->display_info.is_hdmi) {
|
||||||
if (pixel_clock > 340000)
|
if (pixel_clock > 340000)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
|
@ -1,388 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2007 David Airlie
|
|
||||||
*
|
|
||||||
* 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 (including the next
|
|
||||||
* paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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:
|
|
||||||
* David Airlie
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/vga_switcheroo.h>
|
|
||||||
|
|
||||||
#include <drm/amdgpu_drm.h>
|
|
||||||
#include <drm/drm_crtc.h>
|
|
||||||
#include <drm/drm_crtc_helper.h>
|
|
||||||
#include <drm/drm_fb_helper.h>
|
|
||||||
#include <drm/drm_fourcc.h>
|
|
||||||
|
|
||||||
#include "amdgpu.h"
|
|
||||||
#include "cikd.h"
|
|
||||||
#include "amdgpu_gem.h"
|
|
||||||
|
|
||||||
#include "amdgpu_display.h"
|
|
||||||
|
|
||||||
/* object hierarchy -
|
|
||||||
this contains a helper + a amdgpu fb
|
|
||||||
the helper contains a pointer to amdgpu framebuffer baseclass.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
amdgpufb_open(struct fb_info *info, int user)
|
|
||||||
{
|
|
||||||
struct drm_fb_helper *fb_helper = info->par;
|
|
||||||
int ret = pm_runtime_get_sync(fb_helper->dev->dev);
|
|
||||||
if (ret < 0 && ret != -EACCES) {
|
|
||||||
pm_runtime_mark_last_busy(fb_helper->dev->dev);
|
|
||||||
pm_runtime_put_autosuspend(fb_helper->dev->dev);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
amdgpufb_release(struct fb_info *info, int user)
|
|
||||||
{
|
|
||||||
struct drm_fb_helper *fb_helper = info->par;
|
|
||||||
|
|
||||||
pm_runtime_mark_last_busy(fb_helper->dev->dev);
|
|
||||||
pm_runtime_put_autosuspend(fb_helper->dev->dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct fb_ops amdgpufb_ops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
DRM_FB_HELPER_DEFAULT_OPS,
|
|
||||||
.fb_open = amdgpufb_open,
|
|
||||||
.fb_release = amdgpufb_release,
|
|
||||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
|
||||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
|
||||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled)
|
|
||||||
{
|
|
||||||
int aligned = width;
|
|
||||||
int pitch_mask = 0;
|
|
||||||
|
|
||||||
switch (cpp) {
|
|
||||||
case 1:
|
|
||||||
pitch_mask = 255;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
pitch_mask = 127;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
pitch_mask = 63;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
aligned += pitch_mask;
|
|
||||||
aligned &= ~pitch_mask;
|
|
||||||
return aligned * cpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
|
|
||||||
{
|
|
||||||
struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = amdgpu_bo_reserve(abo, true);
|
|
||||||
if (likely(ret == 0)) {
|
|
||||||
amdgpu_bo_kunmap(abo);
|
|
||||||
amdgpu_bo_unpin(abo);
|
|
||||||
amdgpu_bo_unreserve(abo);
|
|
||||||
}
|
|
||||||
drm_gem_object_put(gobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
|
|
||||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
|
||||||
struct drm_gem_object **gobj_p)
|
|
||||||
{
|
|
||||||
const struct drm_format_info *info;
|
|
||||||
struct amdgpu_device *adev = rfbdev->adev;
|
|
||||||
struct drm_gem_object *gobj = NULL;
|
|
||||||
struct amdgpu_bo *abo = NULL;
|
|
||||||
bool fb_tiled = false; /* useful for testing */
|
|
||||||
u32 tiling_flags = 0, domain;
|
|
||||||
int ret;
|
|
||||||
int aligned_size, size;
|
|
||||||
int height = mode_cmd->height;
|
|
||||||
u32 cpp;
|
|
||||||
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
|
||||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
|
||||||
AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
|
||||||
|
|
||||||
info = drm_get_format_info(adev_to_drm(adev), mode_cmd);
|
|
||||||
cpp = info->cpp[0];
|
|
||||||
|
|
||||||
/* need to align pitch with crtc limits */
|
|
||||||
mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
|
|
||||||
fb_tiled);
|
|
||||||
domain = amdgpu_display_supported_domains(adev, flags);
|
|
||||||
height = ALIGN(mode_cmd->height, 8);
|
|
||||||
size = mode_cmd->pitches[0] * height;
|
|
||||||
aligned_size = ALIGN(size, PAGE_SIZE);
|
|
||||||
ret = amdgpu_gem_object_create(adev, aligned_size, 0, domain, flags,
|
|
||||||
ttm_bo_type_device, NULL, &gobj);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("failed to allocate framebuffer (%d)\n", aligned_size);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
abo = gem_to_amdgpu_bo(gobj);
|
|
||||||
|
|
||||||
if (fb_tiled)
|
|
||||||
tiling_flags = AMDGPU_TILING_SET(ARRAY_MODE, GRPH_ARRAY_2D_TILED_THIN1);
|
|
||||||
|
|
||||||
ret = amdgpu_bo_reserve(abo, false);
|
|
||||||
if (unlikely(ret != 0))
|
|
||||||
goto out_unref;
|
|
||||||
|
|
||||||
if (tiling_flags) {
|
|
||||||
ret = amdgpu_bo_set_tiling_flags(abo,
|
|
||||||
tiling_flags);
|
|
||||||
if (ret)
|
|
||||||
dev_err(adev->dev, "FB failed to set tiling flags\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = amdgpu_bo_pin(abo, domain);
|
|
||||||
if (ret) {
|
|
||||||
amdgpu_bo_unreserve(abo);
|
|
||||||
goto out_unref;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = amdgpu_ttm_alloc_gart(&abo->tbo);
|
|
||||||
if (ret) {
|
|
||||||
amdgpu_bo_unreserve(abo);
|
|
||||||
dev_err(adev->dev, "%p bind failed\n", abo);
|
|
||||||
goto out_unref;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = amdgpu_bo_kmap(abo, NULL);
|
|
||||||
amdgpu_bo_unreserve(abo);
|
|
||||||
if (ret) {
|
|
||||||
goto out_unref;
|
|
||||||
}
|
|
||||||
|
|
||||||
*gobj_p = gobj;
|
|
||||||
return 0;
|
|
||||||
out_unref:
|
|
||||||
amdgpufb_destroy_pinned_object(gobj);
|
|
||||||
*gobj_p = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdgpufb_create(struct drm_fb_helper *helper,
|
|
||||||
struct drm_fb_helper_surface_size *sizes)
|
|
||||||
{
|
|
||||||
struct amdgpu_fbdev *rfbdev = (struct amdgpu_fbdev *)helper;
|
|
||||||
struct amdgpu_device *adev = rfbdev->adev;
|
|
||||||
struct fb_info *info;
|
|
||||||
struct drm_framebuffer *fb = NULL;
|
|
||||||
struct drm_mode_fb_cmd2 mode_cmd;
|
|
||||||
struct drm_gem_object *gobj = NULL;
|
|
||||||
struct amdgpu_bo *abo = NULL;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
memset(&mode_cmd, 0, sizeof(mode_cmd));
|
|
||||||
mode_cmd.width = sizes->surface_width;
|
|
||||||
mode_cmd.height = sizes->surface_height;
|
|
||||||
|
|
||||||
if (sizes->surface_bpp == 24)
|
|
||||||
sizes->surface_bpp = 32;
|
|
||||||
|
|
||||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
|
||||||
sizes->surface_depth);
|
|
||||||
|
|
||||||
ret = amdgpufb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
|
|
||||||
if (ret) {
|
|
||||||
DRM_ERROR("failed to create fbcon object %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
abo = gem_to_amdgpu_bo(gobj);
|
|
||||||
|
|
||||||
/* okay we have an object now allocate the framebuffer */
|
|
||||||
info = drm_fb_helper_alloc_fbi(helper);
|
|
||||||
if (IS_ERR(info)) {
|
|
||||||
ret = PTR_ERR(info);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = amdgpu_display_gem_fb_init(adev_to_drm(adev), &rfbdev->rfb,
|
|
||||||
&mode_cmd, gobj);
|
|
||||||
if (ret) {
|
|
||||||
DRM_ERROR("failed to initialize framebuffer %d\n", ret);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
fb = &rfbdev->rfb.base;
|
|
||||||
|
|
||||||
/* setup helper */
|
|
||||||
rfbdev->helper.fb = fb;
|
|
||||||
|
|
||||||
info->fbops = &amdgpufb_ops;
|
|
||||||
|
|
||||||
info->fix.smem_start = amdgpu_gmc_vram_cpu_pa(adev, abo);
|
|
||||||
info->fix.smem_len = amdgpu_bo_size(abo);
|
|
||||||
info->screen_base = amdgpu_bo_kptr(abo);
|
|
||||||
info->screen_size = amdgpu_bo_size(abo);
|
|
||||||
|
|
||||||
drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);
|
|
||||||
|
|
||||||
/* setup aperture base/size for vesafb takeover */
|
|
||||||
info->apertures->ranges[0].base = adev_to_drm(adev)->mode_config.fb_base;
|
|
||||||
info->apertures->ranges[0].size = adev->gmc.aper_size;
|
|
||||||
|
|
||||||
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
|
|
||||||
|
|
||||||
if (info->screen_base == NULL) {
|
|
||||||
ret = -ENOSPC;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
|
|
||||||
DRM_INFO("vram apper at 0x%lX\n", (unsigned long)adev->gmc.aper_base);
|
|
||||||
DRM_INFO("size %lu\n", (unsigned long)amdgpu_bo_size(abo));
|
|
||||||
DRM_INFO("fb depth is %d\n", fb->format->depth);
|
|
||||||
DRM_INFO(" pitch is %d\n", fb->pitches[0]);
|
|
||||||
|
|
||||||
vga_switcheroo_client_fb_set(adev->pdev, info);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (fb && ret) {
|
|
||||||
drm_gem_object_put(gobj);
|
|
||||||
drm_framebuffer_unregister_private(fb);
|
|
||||||
drm_framebuffer_cleanup(fb);
|
|
||||||
kfree(fb);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
|
|
||||||
{
|
|
||||||
struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
drm_fb_helper_unregister_fbi(&rfbdev->helper);
|
|
||||||
|
|
||||||
if (rfb->base.obj[0]) {
|
|
||||||
for (i = 0; i < rfb->base.format->num_planes; i++)
|
|
||||||
drm_gem_object_put(rfb->base.obj[0]);
|
|
||||||
amdgpufb_destroy_pinned_object(rfb->base.obj[0]);
|
|
||||||
rfb->base.obj[0] = NULL;
|
|
||||||
drm_framebuffer_unregister_private(&rfb->base);
|
|
||||||
drm_framebuffer_cleanup(&rfb->base);
|
|
||||||
}
|
|
||||||
drm_fb_helper_fini(&rfbdev->helper);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct drm_fb_helper_funcs amdgpu_fb_helper_funcs = {
|
|
||||||
.fb_probe = amdgpufb_create,
|
|
||||||
};
|
|
||||||
|
|
||||||
int amdgpu_fbdev_init(struct amdgpu_device *adev)
|
|
||||||
{
|
|
||||||
struct amdgpu_fbdev *rfbdev;
|
|
||||||
int bpp_sel = 32;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* don't init fbdev on hw without DCE */
|
|
||||||
if (!adev->mode_info.mode_config_initialized)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* don't init fbdev if there are no connectors */
|
|
||||||
if (list_empty(&adev_to_drm(adev)->mode_config.connector_list))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* select 8 bpp console on low vram cards */
|
|
||||||
if (adev->gmc.real_vram_size <= (32*1024*1024))
|
|
||||||
bpp_sel = 8;
|
|
||||||
|
|
||||||
rfbdev = kzalloc(sizeof(struct amdgpu_fbdev), GFP_KERNEL);
|
|
||||||
if (!rfbdev)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
rfbdev->adev = adev;
|
|
||||||
adev->mode_info.rfbdev = rfbdev;
|
|
||||||
|
|
||||||
drm_fb_helper_prepare(adev_to_drm(adev), &rfbdev->helper,
|
|
||||||
&amdgpu_fb_helper_funcs);
|
|
||||||
|
|
||||||
ret = drm_fb_helper_init(adev_to_drm(adev), &rfbdev->helper);
|
|
||||||
if (ret) {
|
|
||||||
kfree(rfbdev);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
|
||||||
if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
|
|
||||||
drm_helper_disable_unused_functions(adev_to_drm(adev));
|
|
||||||
|
|
||||||
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amdgpu_fbdev_fini(struct amdgpu_device *adev)
|
|
||||||
{
|
|
||||||
if (!adev->mode_info.rfbdev)
|
|
||||||
return;
|
|
||||||
|
|
||||||
amdgpu_fbdev_destroy(adev_to_drm(adev), adev->mode_info.rfbdev);
|
|
||||||
kfree(adev->mode_info.rfbdev);
|
|
||||||
adev->mode_info.rfbdev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state)
|
|
||||||
{
|
|
||||||
if (adev->mode_info.rfbdev)
|
|
||||||
drm_fb_helper_set_suspend_unlocked(&adev->mode_info.rfbdev->helper,
|
|
||||||
state);
|
|
||||||
}
|
|
||||||
|
|
||||||
int amdgpu_fbdev_total_size(struct amdgpu_device *adev)
|
|
||||||
{
|
|
||||||
struct amdgpu_bo *robj;
|
|
||||||
int size = 0;
|
|
||||||
|
|
||||||
if (!adev->mode_info.rfbdev)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
robj = gem_to_amdgpu_bo(adev->mode_info.rfbdev->rfb.base.obj[0]);
|
|
||||||
size += amdgpu_bo_size(robj);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
|
|
||||||
{
|
|
||||||
if (!adev->mode_info.rfbdev)
|
|
||||||
return false;
|
|
||||||
if (robj == gem_to_amdgpu_bo(adev->mode_info.rfbdev->rfb.base.obj[0]))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -56,6 +56,9 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
|||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
case CHIP_ALDEBARAN:
|
||||||
|
/* All Aldebaran SKUs have the FRU */
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -88,13 +91,17 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
|||||||
|
|
||||||
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
unsigned char buff[34];
|
unsigned char buff[AMDGPU_PRODUCT_NAME_LEN+2];
|
||||||
u32 addrptr;
|
u32 addrptr;
|
||||||
int size, len;
|
int size, len;
|
||||||
|
int offset = 2;
|
||||||
|
|
||||||
if (!is_fru_eeprom_supported(adev))
|
if (!is_fru_eeprom_supported(adev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (adev->asic_type == CHIP_ALDEBARAN)
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
/* If algo exists, it means that the i2c_adapter's initialized */
|
/* If algo exists, it means that the i2c_adapter's initialized */
|
||||||
if (!adev->pm.smu_i2c.algo) {
|
if (!adev->pm.smu_i2c.algo) {
|
||||||
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
|
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
|
||||||
@ -131,15 +138,13 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = size;
|
len = size;
|
||||||
/* Product name should only be 32 characters. Any more,
|
if (len >= AMDGPU_PRODUCT_NAME_LEN) {
|
||||||
* and something could be wrong. Cap it at 32 to be safe
|
DRM_WARN("FRU Product Name is larger than %d characters. This is likely a mistake",
|
||||||
*/
|
AMDGPU_PRODUCT_NAME_LEN);
|
||||||
if (len >= sizeof(adev->product_name)) {
|
len = AMDGPU_PRODUCT_NAME_LEN - 1;
|
||||||
DRM_WARN("FRU Product Number is larger than 32 characters. This is likely a mistake");
|
|
||||||
len = sizeof(adev->product_name) - 1;
|
|
||||||
}
|
}
|
||||||
/* Start at 2 due to buff using fields 0 and 1 for the address */
|
/* Start at 2 due to buff using fields 0 and 1 for the address */
|
||||||
memcpy(adev->product_name, &buff[2], len);
|
memcpy(adev->product_name, &buff[offset], len);
|
||||||
adev->product_name[len] = '\0';
|
adev->product_name[len] = '\0';
|
||||||
|
|
||||||
addrptr += size + 1;
|
addrptr += size + 1;
|
||||||
@ -157,7 +162,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||||||
DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
|
DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
|
||||||
len = sizeof(adev->product_number) - 1;
|
len = sizeof(adev->product_number) - 1;
|
||||||
}
|
}
|
||||||
memcpy(adev->product_number, &buff[2], len);
|
memcpy(adev->product_number, &buff[offset], len);
|
||||||
adev->product_number[len] = '\0';
|
adev->product_number[len] = '\0';
|
||||||
|
|
||||||
addrptr += size + 1;
|
addrptr += size + 1;
|
||||||
@ -184,7 +189,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||||||
DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
|
DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
|
||||||
len = sizeof(adev->serial) - 1;
|
len = sizeof(adev->serial) - 1;
|
||||||
}
|
}
|
||||||
memcpy(adev->serial, &buff[2], len);
|
memcpy(adev->serial, &buff[offset], len);
|
||||||
adev->serial[len] = '\0';
|
adev->serial[len] = '\0';
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -264,6 +264,9 @@ static int amdgpu_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_str
|
|||||||
!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
|
!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
|
||||||
vma->vm_flags &= ~VM_MAYWRITE;
|
vma->vm_flags &= ~VM_MAYWRITE;
|
||||||
|
|
||||||
|
if (bo->kfd_bo)
|
||||||
|
vma->vm_flags |= VM_DONTCOPY;
|
||||||
|
|
||||||
return drm_gem_ttm_mmap(obj, vma);
|
return drm_gem_ttm_mmap(obj, vma);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,6 +880,32 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amdgpu_gem_align_pitch(struct amdgpu_device *adev,
|
||||||
|
int width,
|
||||||
|
int cpp,
|
||||||
|
bool tiled)
|
||||||
|
{
|
||||||
|
int aligned = width;
|
||||||
|
int pitch_mask = 0;
|
||||||
|
|
||||||
|
switch (cpp) {
|
||||||
|
case 1:
|
||||||
|
pitch_mask = 255;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pitch_mask = 127;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
pitch_mask = 63;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
aligned += pitch_mask;
|
||||||
|
aligned &= ~pitch_mask;
|
||||||
|
return aligned * cpp;
|
||||||
|
}
|
||||||
|
|
||||||
int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
||||||
struct drm_device *dev,
|
struct drm_device *dev,
|
||||||
struct drm_mode_create_dumb *args)
|
struct drm_mode_create_dumb *args)
|
||||||
@ -885,7 +914,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
|||||||
struct drm_gem_object *gobj;
|
struct drm_gem_object *gobj;
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
||||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
AMDGPU_GEM_CREATE_CPU_GTT_USWC |
|
||||||
|
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||||
u32 domain;
|
u32 domain;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -897,8 +927,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
|||||||
if (adev->mman.buffer_funcs_enabled)
|
if (adev->mman.buffer_funcs_enabled)
|
||||||
flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
||||||
|
|
||||||
args->pitch = amdgpu_align_pitch(adev, args->width,
|
args->pitch = amdgpu_gem_align_pitch(adev, args->width,
|
||||||
DIV_ROUND_UP(args->bpp, 8), 0);
|
DIV_ROUND_UP(args->bpp, 8), 0);
|
||||||
args->size = (u64)args->pitch * args->height;
|
args->size = (u64)args->pitch * args->height;
|
||||||
args->size = ALIGN(args->size, PAGE_SIZE);
|
args->size = ALIGN(args->size, PAGE_SIZE);
|
||||||
domain = amdgpu_bo_get_preferred_domain(adev,
|
domain = amdgpu_bo_get_preferred_domain(adev,
|
||||||
|
@ -350,6 +350,7 @@ static inline uint64_t amdgpu_gmc_fault_key(uint64_t addr, uint16_t pasid)
|
|||||||
* amdgpu_gmc_filter_faults - filter VM faults
|
* amdgpu_gmc_filter_faults - filter VM faults
|
||||||
*
|
*
|
||||||
* @adev: amdgpu device structure
|
* @adev: amdgpu device structure
|
||||||
|
* @ih: interrupt ring that the fault received from
|
||||||
* @addr: address of the VM fault
|
* @addr: address of the VM fault
|
||||||
* @pasid: PASID of the process causing the fault
|
* @pasid: PASID of the process causing the fault
|
||||||
* @timestamp: timestamp of the fault
|
* @timestamp: timestamp of the fault
|
||||||
@ -358,7 +359,8 @@ static inline uint64_t amdgpu_gmc_fault_key(uint64_t addr, uint16_t pasid)
|
|||||||
* True if the fault was filtered and should not be processed further.
|
* True if the fault was filtered and should not be processed further.
|
||||||
* False if the fault is a new one and needs to be handled.
|
* False if the fault is a new one and needs to be handled.
|
||||||
*/
|
*/
|
||||||
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
|
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
|
||||||
|
struct amdgpu_ih_ring *ih, uint64_t addr,
|
||||||
uint16_t pasid, uint64_t timestamp)
|
uint16_t pasid, uint64_t timestamp)
|
||||||
{
|
{
|
||||||
struct amdgpu_gmc *gmc = &adev->gmc;
|
struct amdgpu_gmc *gmc = &adev->gmc;
|
||||||
@ -366,6 +368,10 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
|
|||||||
struct amdgpu_gmc_fault *fault;
|
struct amdgpu_gmc_fault *fault;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
|
||||||
|
/* Stale retry fault if timestamp goes backward */
|
||||||
|
if (amdgpu_ih_ts_after(timestamp, ih->processed_timestamp))
|
||||||
|
return true;
|
||||||
|
|
||||||
/* If we don't have space left in the ring buffer return immediately */
|
/* If we don't have space left in the ring buffer return immediately */
|
||||||
stamp = max(timestamp, AMDGPU_GMC_FAULT_TIMEOUT + 1) -
|
stamp = max(timestamp, AMDGPU_GMC_FAULT_TIMEOUT + 1) -
|
||||||
AMDGPU_GMC_FAULT_TIMEOUT;
|
AMDGPU_GMC_FAULT_TIMEOUT;
|
||||||
|
@ -316,7 +316,8 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_gmc *mc);
|
struct amdgpu_gmc *mc);
|
||||||
void amdgpu_gmc_agp_location(struct amdgpu_device *adev,
|
void amdgpu_gmc_agp_location(struct amdgpu_device *adev,
|
||||||
struct amdgpu_gmc *mc);
|
struct amdgpu_gmc *mc);
|
||||||
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
|
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
|
||||||
|
struct amdgpu_ih_ring *ih, uint64_t addr,
|
||||||
uint16_t pasid, uint64_t timestamp);
|
uint16_t pasid, uint64_t timestamp);
|
||||||
void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
|
void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
|
||||||
uint16_t pasid);
|
uint16_t pasid);
|
||||||
|
@ -164,52 +164,32 @@ void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Waiter helper that checks current rptr matches or passes checkpoint wptr */
|
|
||||||
static bool amdgpu_ih_has_checkpoint_processed(struct amdgpu_device *adev,
|
|
||||||
struct amdgpu_ih_ring *ih,
|
|
||||||
uint32_t checkpoint_wptr,
|
|
||||||
uint32_t *prev_rptr)
|
|
||||||
{
|
|
||||||
uint32_t cur_rptr = ih->rptr | (*prev_rptr & ~ih->ptr_mask);
|
|
||||||
|
|
||||||
/* rptr has wrapped. */
|
|
||||||
if (cur_rptr < *prev_rptr)
|
|
||||||
cur_rptr += ih->ptr_mask + 1;
|
|
||||||
*prev_rptr = cur_rptr;
|
|
||||||
|
|
||||||
/* check ring is empty to workaround missing wptr overflow flag */
|
|
||||||
return cur_rptr >= checkpoint_wptr ||
|
|
||||||
(cur_rptr & ih->ptr_mask) == amdgpu_ih_get_wptr(adev, ih);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_ih_wait_on_checkpoint_process - wait to process IVs up to checkpoint
|
* amdgpu_ih_wait_on_checkpoint_process_ts - wait to process IVs up to checkpoint
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
* @ih: ih ring to process
|
* @ih: ih ring to process
|
||||||
*
|
*
|
||||||
* Used to ensure ring has processed IVs up to the checkpoint write pointer.
|
* Used to ensure ring has processed IVs up to the checkpoint write pointer.
|
||||||
*/
|
*/
|
||||||
int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev,
|
int amdgpu_ih_wait_on_checkpoint_process_ts(struct amdgpu_device *adev,
|
||||||
struct amdgpu_ih_ring *ih)
|
struct amdgpu_ih_ring *ih)
|
||||||
{
|
{
|
||||||
uint32_t checkpoint_wptr, rptr;
|
uint32_t checkpoint_wptr;
|
||||||
|
uint64_t checkpoint_ts;
|
||||||
|
long timeout = HZ;
|
||||||
|
|
||||||
if (!ih->enabled || adev->shutdown)
|
if (!ih->enabled || adev->shutdown)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
|
checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
|
||||||
/* Order wptr with rptr. */
|
/* Order wptr with ring data. */
|
||||||
rmb();
|
rmb();
|
||||||
rptr = READ_ONCE(ih->rptr);
|
checkpoint_ts = amdgpu_ih_decode_iv_ts(adev, ih, checkpoint_wptr, -1);
|
||||||
|
|
||||||
/* wptr has wrapped. */
|
return wait_event_interruptible_timeout(ih->wait_process,
|
||||||
if (rptr > checkpoint_wptr)
|
amdgpu_ih_ts_after(checkpoint_ts, ih->processed_timestamp) ||
|
||||||
checkpoint_wptr += ih->ptr_mask + 1;
|
ih->rptr == amdgpu_ih_get_wptr(adev, ih), timeout);
|
||||||
|
|
||||||
return wait_event_interruptible(ih->wait_process,
|
|
||||||
amdgpu_ih_has_checkpoint_processed(adev, ih,
|
|
||||||
checkpoint_wptr, &rptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,3 +279,18 @@ void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
|
|||||||
/* wptr/rptr are in bytes! */
|
/* wptr/rptr are in bytes! */
|
||||||
ih->rptr += 32;
|
ih->rptr += 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t amdgpu_ih_decode_iv_ts_helper(struct amdgpu_ih_ring *ih, u32 rptr,
|
||||||
|
signed int offset)
|
||||||
|
{
|
||||||
|
uint32_t iv_size = 32;
|
||||||
|
uint32_t ring_index;
|
||||||
|
uint32_t dw1, dw2;
|
||||||
|
|
||||||
|
rptr += iv_size * offset;
|
||||||
|
ring_index = (rptr & ih->ptr_mask) >> 2;
|
||||||
|
|
||||||
|
dw1 = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||||
|
dw2 = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||||
|
return dw1 | ((u64)(dw2 & 0xffff) << 32);
|
||||||
|
}
|
||||||
|
@ -68,20 +68,30 @@ struct amdgpu_ih_ring {
|
|||||||
|
|
||||||
/* For waiting on IH processing at checkpoint. */
|
/* For waiting on IH processing at checkpoint. */
|
||||||
wait_queue_head_t wait_process;
|
wait_queue_head_t wait_process;
|
||||||
|
uint64_t processed_timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* return true if time stamp t2 is after t1 with 48bit wrap around */
|
||||||
|
#define amdgpu_ih_ts_after(t1, t2) \
|
||||||
|
(((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL)
|
||||||
|
|
||||||
/* provided by the ih block */
|
/* provided by the ih block */
|
||||||
struct amdgpu_ih_funcs {
|
struct amdgpu_ih_funcs {
|
||||||
/* ring read/write ptr handling, called from interrupt context */
|
/* ring read/write ptr handling, called from interrupt context */
|
||||||
u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||||
void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||||
struct amdgpu_iv_entry *entry);
|
struct amdgpu_iv_entry *entry);
|
||||||
|
uint64_t (*decode_iv_ts)(struct amdgpu_ih_ring *ih, u32 rptr,
|
||||||
|
signed int offset);
|
||||||
void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
|
#define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
|
||||||
#define amdgpu_ih_decode_iv(adev, iv) \
|
#define amdgpu_ih_decode_iv(adev, iv) \
|
||||||
(adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
|
(adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
|
||||||
|
#define amdgpu_ih_decode_iv_ts(adev, ih, rptr, offset) \
|
||||||
|
(WARN_ON_ONCE(!(adev)->irq.ih_funcs->decode_iv_ts) ? 0 : \
|
||||||
|
(adev)->irq.ih_funcs->decode_iv_ts((ih), (rptr), (offset)))
|
||||||
#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))
|
#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))
|
||||||
|
|
||||||
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||||
@ -89,10 +99,12 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||||||
void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||||
void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
|
void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
|
||||||
unsigned int num_dw);
|
unsigned int num_dw);
|
||||||
int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev,
|
int amdgpu_ih_wait_on_checkpoint_process_ts(struct amdgpu_device *adev,
|
||||||
struct amdgpu_ih_ring *ih);
|
struct amdgpu_ih_ring *ih);
|
||||||
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||||
void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
|
void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
|
||||||
struct amdgpu_ih_ring *ih,
|
struct amdgpu_ih_ring *ih,
|
||||||
struct amdgpu_iv_entry *entry);
|
struct amdgpu_iv_entry *entry);
|
||||||
|
uint64_t amdgpu_ih_decode_iv_ts_helper(struct amdgpu_ih_ring *ih, u32 rptr,
|
||||||
|
signed int offset);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/*
|
||||||
* \file amdgpu_ioc32.c
|
* \file amdgpu_ioc32.c
|
||||||
*
|
*
|
||||||
* 32-bit ioctl compatibility routines for the AMDGPU DRM.
|
* 32-bit ioctl compatibility routines for the AMDGPU DRM.
|
||||||
@ -37,12 +37,9 @@
|
|||||||
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (nr < DRM_COMMAND_BASE)
|
if (nr < DRM_COMMAND_BASE)
|
||||||
return drm_compat_ioctl(filp, cmd, arg);
|
return drm_compat_ioctl(filp, cmd, arg);
|
||||||
|
|
||||||
ret = amdgpu_drm_ioctl(filp, cmd, arg);
|
return amdgpu_drm_ioctl(filp, cmd, arg);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||||||
if (!amdgpu_device_has_dc_support(adev)) {
|
if (!amdgpu_device_has_dc_support(adev)) {
|
||||||
if (!adev->enable_virtual_display)
|
if (!adev->enable_virtual_display)
|
||||||
/* Disable vblank IRQs aggressively for power-saving */
|
/* Disable vblank IRQs aggressively for power-saving */
|
||||||
/* XXX: can this be enabled for DC? */
|
|
||||||
adev_to_drm(adev)->vblank_disable_immediate = true;
|
adev_to_drm(adev)->vblank_disable_immediate = true;
|
||||||
|
|
||||||
r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
|
r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
|
||||||
@ -391,7 +390,7 @@ void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_irq_fini - shut down interrupt handling
|
* amdgpu_irq_fini_sw - shut down interrupt handling
|
||||||
*
|
*
|
||||||
* @adev: amdgpu device pointer
|
* @adev: amdgpu device pointer
|
||||||
*
|
*
|
||||||
@ -529,6 +528,9 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
|||||||
/* Send it to amdkfd as well if it isn't already handled */
|
/* Send it to amdkfd as well if it isn't already handled */
|
||||||
if (!handled)
|
if (!handled)
|
||||||
amdgpu_amdkfd_interrupt(adev, entry.iv_entry);
|
amdgpu_amdkfd_interrupt(adev, entry.iv_entry);
|
||||||
|
|
||||||
|
if (amdgpu_ih_ts_after(ih->processed_timestamp, entry.timestamp))
|
||||||
|
ih->processed_timestamp = entry.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,8 +232,6 @@ struct amdgpu_i2c_chan {
|
|||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct amdgpu_fbdev;
|
|
||||||
|
|
||||||
struct amdgpu_afmt {
|
struct amdgpu_afmt {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
int offset;
|
int offset;
|
||||||
@ -309,13 +307,6 @@ struct amdgpu_framebuffer {
|
|||||||
uint64_t address;
|
uint64_t address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct amdgpu_fbdev {
|
|
||||||
struct drm_fb_helper helper;
|
|
||||||
struct amdgpu_framebuffer rfb;
|
|
||||||
struct list_head fbdev_list;
|
|
||||||
struct amdgpu_device *adev;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct amdgpu_mode_info {
|
struct amdgpu_mode_info {
|
||||||
struct atom_context *atom_context;
|
struct atom_context *atom_context;
|
||||||
struct card_info *atom_card_info;
|
struct card_info *atom_card_info;
|
||||||
@ -341,8 +332,6 @@ struct amdgpu_mode_info {
|
|||||||
struct edid *bios_hardcoded_edid;
|
struct edid *bios_hardcoded_edid;
|
||||||
int bios_hardcoded_edid_size;
|
int bios_hardcoded_edid_size;
|
||||||
|
|
||||||
/* pointer to fbdev info structure */
|
|
||||||
struct amdgpu_fbdev *rfbdev;
|
|
||||||
/* firmware flags */
|
/* firmware flags */
|
||||||
u32 firmware_flags;
|
u32 firmware_flags;
|
||||||
/* pointer to backlight encoder */
|
/* pointer to backlight encoder */
|
||||||
@ -631,15 +620,6 @@ bool amdgpu_crtc_get_scanout_position(struct drm_crtc *crtc,
|
|||||||
int *hpos, ktime_t *stime, ktime_t *etime,
|
int *hpos, ktime_t *stime, ktime_t *etime,
|
||||||
const struct drm_display_mode *mode);
|
const struct drm_display_mode *mode);
|
||||||
|
|
||||||
/* fbdev layer */
|
|
||||||
int amdgpu_fbdev_init(struct amdgpu_device *adev);
|
|
||||||
void amdgpu_fbdev_fini(struct amdgpu_device *adev);
|
|
||||||
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
|
|
||||||
int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
|
|
||||||
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj);
|
|
||||||
|
|
||||||
int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tiled);
|
|
||||||
|
|
||||||
/* amdgpu_display.c */
|
/* amdgpu_display.c */
|
||||||
void amdgpu_display_print_display_setup(struct drm_device *dev);
|
void amdgpu_display_print_display_setup(struct drm_device *dev);
|
||||||
int amdgpu_display_modeset_create_props(struct amdgpu_device *adev);
|
int amdgpu_display_modeset_create_props(struct amdgpu_device *adev);
|
||||||
|
@ -1032,9 +1032,14 @@ int amdgpu_bo_init(struct amdgpu_device *adev)
|
|||||||
/* On A+A platform, VRAM can be mapped as WB */
|
/* On A+A platform, VRAM can be mapped as WB */
|
||||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||||
/* reserve PAT memory space to WC for VRAM */
|
/* reserve PAT memory space to WC for VRAM */
|
||||||
arch_io_reserve_memtype_wc(adev->gmc.aper_base,
|
int r = arch_io_reserve_memtype_wc(adev->gmc.aper_base,
|
||||||
adev->gmc.aper_size);
|
adev->gmc.aper_size);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
DRM_ERROR("Unable to set WC memtype for the aperture base\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add an MTRR for the VRAM */
|
/* Add an MTRR for the VRAM */
|
||||||
adev->gmc.vram_mtrr = arch_phys_wc_add(adev->gmc.aper_base,
|
adev->gmc.vram_mtrr = arch_phys_wc_add(adev->gmc.aper_base,
|
||||||
adev->gmc.aper_size);
|
adev->gmc.aper_size);
|
||||||
|
@ -69,6 +69,7 @@ static void amdgpu_pll_reduce_ratio(unsigned *nom, unsigned *den,
|
|||||||
/**
|
/**
|
||||||
* amdgpu_pll_get_fb_ref_div - feedback and ref divider calculation
|
* amdgpu_pll_get_fb_ref_div - feedback and ref divider calculation
|
||||||
*
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
* @nom: nominator
|
* @nom: nominator
|
||||||
* @den: denominator
|
* @den: denominator
|
||||||
* @post_div: post divider
|
* @post_div: post divider
|
||||||
@ -106,6 +107,7 @@ static void amdgpu_pll_get_fb_ref_div(struct amdgpu_device *adev, unsigned int n
|
|||||||
/**
|
/**
|
||||||
* amdgpu_pll_compute - compute PLL paramaters
|
* amdgpu_pll_compute - compute PLL paramaters
|
||||||
*
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
* @pll: information about the PLL
|
* @pll: information about the PLL
|
||||||
* @freq: requested frequency
|
* @freq: requested frequency
|
||||||
* @dot_clock_p: resulting pixel clock
|
* @dot_clock_p: resulting pixel clock
|
||||||
|
@ -233,6 +233,10 @@ static void amdgpu_perf_start(struct perf_event *event, int flags)
|
|||||||
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ((!pe->adev->df.funcs) ||
|
||||||
|
(!pe->adev->df.funcs->pmc_start))
|
||||||
|
return;
|
||||||
|
|
||||||
WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
|
WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
|
||||||
hwc->state = 0;
|
hwc->state = 0;
|
||||||
|
|
||||||
@ -268,6 +272,10 @@ static void amdgpu_perf_read(struct perf_event *event)
|
|||||||
pmu);
|
pmu);
|
||||||
u64 count, prev;
|
u64 count, prev;
|
||||||
|
|
||||||
|
if ((!pe->adev->df.funcs) ||
|
||||||
|
(!pe->adev->df.funcs->pmc_get_count))
|
||||||
|
return;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
prev = local64_read(&hwc->prev_count);
|
prev = local64_read(&hwc->prev_count);
|
||||||
|
|
||||||
@ -297,6 +305,10 @@ static void amdgpu_perf_stop(struct perf_event *event, int flags)
|
|||||||
if (hwc->state & PERF_HES_UPTODATE)
|
if (hwc->state & PERF_HES_UPTODATE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ((!pe->adev->df.funcs) ||
|
||||||
|
(!pe->adev->df.funcs->pmc_stop))
|
||||||
|
return;
|
||||||
|
|
||||||
switch (hwc->config_base) {
|
switch (hwc->config_base) {
|
||||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||||
@ -326,6 +338,10 @@ static int amdgpu_perf_add(struct perf_event *event, int flags)
|
|||||||
struct amdgpu_pmu_entry,
|
struct amdgpu_pmu_entry,
|
||||||
pmu);
|
pmu);
|
||||||
|
|
||||||
|
if ((!pe->adev->df.funcs) ||
|
||||||
|
(!pe->adev->df.funcs->pmc_start))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
switch (pe->pmu_perf_type) {
|
switch (pe->pmu_perf_type) {
|
||||||
case AMDGPU_PMU_PERF_TYPE_DF:
|
case AMDGPU_PMU_PERF_TYPE_DF:
|
||||||
hwc->config_base = AMDGPU_PMU_EVENT_CONFIG_TYPE_DF;
|
hwc->config_base = AMDGPU_PMU_EVENT_CONFIG_TYPE_DF;
|
||||||
@ -371,6 +387,9 @@ static void amdgpu_perf_del(struct perf_event *event, int flags)
|
|||||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||||
struct amdgpu_pmu_entry,
|
struct amdgpu_pmu_entry,
|
||||||
pmu);
|
pmu);
|
||||||
|
if ((!pe->adev->df.funcs) ||
|
||||||
|
(!pe->adev->df.funcs->pmc_stop))
|
||||||
|
return;
|
||||||
|
|
||||||
amdgpu_perf_stop(event, PERF_EF_UPDATE);
|
amdgpu_perf_stop(event, PERF_EF_UPDATE);
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ static DEVICE_ATTR_RO(mem_info_preempt_used);
|
|||||||
* @man: TTM memory type manager
|
* @man: TTM memory type manager
|
||||||
* @tbo: TTM BO we need this range for
|
* @tbo: TTM BO we need this range for
|
||||||
* @place: placement flags and restrictions
|
* @place: placement flags and restrictions
|
||||||
* @mem: the resulting mem object
|
* @res: TTM memory object
|
||||||
*
|
*
|
||||||
* Dummy, just count the space used without allocating resources or any limit.
|
* Dummy, just count the space used without allocating resources or any limit.
|
||||||
*/
|
*/
|
||||||
@ -85,7 +85,7 @@ static int amdgpu_preempt_mgr_new(struct ttm_resource_manager *man,
|
|||||||
* amdgpu_preempt_mgr_del - free ranges
|
* amdgpu_preempt_mgr_del - free ranges
|
||||||
*
|
*
|
||||||
* @man: TTM memory type manager
|
* @man: TTM memory type manager
|
||||||
* @mem: TTM memory object
|
* @res: TTM memory object
|
||||||
*
|
*
|
||||||
* Free the allocated GTT again.
|
* Free the allocated GTT again.
|
||||||
*/
|
*/
|
||||||
|
@ -518,7 +518,7 @@ static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp)
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_psp_cmd_buf(struct psp_context *psp)
|
static void release_psp_cmd_buf(struct psp_context *psp)
|
||||||
{
|
{
|
||||||
mutex_unlock(&psp->mutex);
|
mutex_unlock(&psp->mutex);
|
||||||
}
|
}
|
||||||
@ -2017,12 +2017,16 @@ static int psp_hw_start(struct psp_context *psp)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
|
||||||
|
goto skip_pin_bo;
|
||||||
|
|
||||||
ret = psp_tmr_init(psp);
|
ret = psp_tmr_init(psp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("PSP tmr init failed!\n");
|
DRM_ERROR("PSP tmr init failed!\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_pin_bo:
|
||||||
/*
|
/*
|
||||||
* For ASICs with DF Cstate management centralized
|
* For ASICs with DF Cstate management centralized
|
||||||
* to PMFW, TMR setup should be performed after PMFW
|
* to PMFW, TMR setup should be performed after PMFW
|
||||||
@ -2452,6 +2456,18 @@ static int psp_load_fw(struct amdgpu_device *adev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) {
|
||||||
|
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||||
|
ret = psp_xgmi_initialize(psp, false, true);
|
||||||
|
/* Warning the XGMI seesion initialize failure
|
||||||
|
* Instead of stop driver initialization
|
||||||
|
*/
|
||||||
|
if (ret)
|
||||||
|
dev_err(psp->adev->dev,
|
||||||
|
"XGMI: Failed to initialize XGMI session\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (psp->ta_fw) {
|
if (psp->ta_fw) {
|
||||||
ret = psp_ras_initialize(psp);
|
ret = psp_ras_initialize(psp);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -867,9 +867,9 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev,
|
|||||||
/* feature ctl end */
|
/* feature ctl end */
|
||||||
|
|
||||||
|
|
||||||
void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
static void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
||||||
struct ras_common_if *ras_block,
|
struct ras_common_if *ras_block,
|
||||||
struct ras_err_data *err_data)
|
struct ras_err_data *err_data)
|
||||||
{
|
{
|
||||||
switch (ras_block->sub_block_index) {
|
switch (ras_block->sub_block_index) {
|
||||||
case AMDGPU_RAS_MCA_BLOCK__MP0:
|
case AMDGPU_RAS_MCA_BLOCK__MP0:
|
||||||
@ -892,6 +892,38 @@ void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_data *err_data)
|
||||||
|
{
|
||||||
|
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* choosing right query method according to
|
||||||
|
* whether smu support query error information
|
||||||
|
*/
|
||||||
|
ret = smu_get_ecc_info(&adev->smu, (void *)&(ras->umc_ecc));
|
||||||
|
if (ret == -EOPNOTSUPP) {
|
||||||
|
if (adev->umc.ras_funcs &&
|
||||||
|
adev->umc.ras_funcs->query_ras_error_count)
|
||||||
|
adev->umc.ras_funcs->query_ras_error_count(adev, err_data);
|
||||||
|
|
||||||
|
/* umc query_ras_error_address is also responsible for clearing
|
||||||
|
* error status
|
||||||
|
*/
|
||||||
|
if (adev->umc.ras_funcs &&
|
||||||
|
adev->umc.ras_funcs->query_ras_error_address)
|
||||||
|
adev->umc.ras_funcs->query_ras_error_address(adev, err_data);
|
||||||
|
} else if (!ret) {
|
||||||
|
if (adev->umc.ras_funcs &&
|
||||||
|
adev->umc.ras_funcs->ecc_info_query_ras_error_count)
|
||||||
|
adev->umc.ras_funcs->ecc_info_query_ras_error_count(adev, err_data);
|
||||||
|
|
||||||
|
if (adev->umc.ras_funcs &&
|
||||||
|
adev->umc.ras_funcs->ecc_info_query_ras_error_address)
|
||||||
|
adev->umc.ras_funcs->ecc_info_query_ras_error_address(adev, err_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* query/inject/cure begin */
|
/* query/inject/cure begin */
|
||||||
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||||
struct ras_query_if *info)
|
struct ras_query_if *info)
|
||||||
@ -905,15 +937,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
|||||||
|
|
||||||
switch (info->head.block) {
|
switch (info->head.block) {
|
||||||
case AMDGPU_RAS_BLOCK__UMC:
|
case AMDGPU_RAS_BLOCK__UMC:
|
||||||
if (adev->umc.ras_funcs &&
|
amdgpu_ras_get_ecc_info(adev, &err_data);
|
||||||
adev->umc.ras_funcs->query_ras_error_count)
|
|
||||||
adev->umc.ras_funcs->query_ras_error_count(adev, &err_data);
|
|
||||||
/* umc query_ras_error_address is also responsible for clearing
|
|
||||||
* error status
|
|
||||||
*/
|
|
||||||
if (adev->umc.ras_funcs &&
|
|
||||||
adev->umc.ras_funcs->query_ras_error_address)
|
|
||||||
adev->umc.ras_funcs->query_ras_error_address(adev, &err_data);
|
|
||||||
break;
|
break;
|
||||||
case AMDGPU_RAS_BLOCK__SDMA:
|
case AMDGPU_RAS_BLOCK__SDMA:
|
||||||
if (adev->sdma.funcs->query_ras_error_count) {
|
if (adev->sdma.funcs->query_ras_error_count) {
|
||||||
@ -1137,9 +1161,9 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_ras_query_error_count -- Get error counts of all IPs
|
* amdgpu_ras_query_error_count -- Get error counts of all IPs
|
||||||
* adev: pointer to AMD GPU device
|
* @adev: pointer to AMD GPU device
|
||||||
* ce_count: pointer to an integer to be set to the count of correctible errors.
|
* @ce_count: pointer to an integer to be set to the count of correctible errors.
|
||||||
* ue_count: pointer to an integer to be set to the count of uncorrectible
|
* @ue_count: pointer to an integer to be set to the count of uncorrectible
|
||||||
* errors.
|
* errors.
|
||||||
*
|
*
|
||||||
* If set, @ce_count or @ue_count, count and return the corresponding
|
* If set, @ce_count or @ue_count, count and return the corresponding
|
||||||
@ -1723,6 +1747,16 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
|
|||||||
if (info.head.block == AMDGPU_RAS_BLOCK__PCIE_BIF)
|
if (info.head.block == AMDGPU_RAS_BLOCK__PCIE_BIF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is a workaround for aldebaran, skip send msg to
|
||||||
|
* smu to get ecc_info table due to smu handle get ecc
|
||||||
|
* info table failed temporarily.
|
||||||
|
* should be removed until smu fix handle ecc_info table.
|
||||||
|
*/
|
||||||
|
if ((info.head.block == AMDGPU_RAS_BLOCK__UMC) &&
|
||||||
|
(adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)))
|
||||||
|
continue;
|
||||||
|
|
||||||
amdgpu_ras_query_error_status(adev, &info);
|
amdgpu_ras_query_error_status(adev, &info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1935,9 +1969,11 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
|
|||||||
if (!con || !con->eh_data)
|
if (!con || !con->eh_data)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
mutex_lock(&con->recovery_lock);
|
||||||
control = &con->eeprom_control;
|
control = &con->eeprom_control;
|
||||||
data = con->eh_data;
|
data = con->eh_data;
|
||||||
save_count = data->count - control->ras_num_recs;
|
save_count = data->count - control->ras_num_recs;
|
||||||
|
mutex_unlock(&con->recovery_lock);
|
||||||
/* only new entries are saved */
|
/* only new entries are saved */
|
||||||
if (save_count > 0) {
|
if (save_count > 0) {
|
||||||
if (amdgpu_ras_eeprom_append(control,
|
if (amdgpu_ras_eeprom_append(control,
|
||||||
@ -2336,7 +2372,11 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Init poison supported flag, the default value is false */
|
/* Init poison supported flag, the default value is false */
|
||||||
if (adev->df.funcs &&
|
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||||
|
/* enabled by default when GPU is connected to CPU */
|
||||||
|
con->poison_supported = true;
|
||||||
|
}
|
||||||
|
else if (adev->df.funcs &&
|
||||||
adev->df.funcs->query_ras_poison_mode &&
|
adev->df.funcs->query_ras_poison_mode &&
|
||||||
adev->umc.ras_funcs &&
|
adev->umc.ras_funcs &&
|
||||||
adev->umc.ras_funcs->query_ras_poison_mode) {
|
adev->umc.ras_funcs->query_ras_poison_mode) {
|
||||||
@ -2477,7 +2517,6 @@ void amdgpu_ras_late_fini(struct amdgpu_device *adev,
|
|||||||
amdgpu_ras_sysfs_remove(adev, ras_block);
|
amdgpu_ras_sysfs_remove(adev, ras_block);
|
||||||
if (ih_info->cb)
|
if (ih_info->cb)
|
||||||
amdgpu_ras_interrupt_remove_handler(adev, ih_info);
|
amdgpu_ras_interrupt_remove_handler(adev, ih_info);
|
||||||
amdgpu_ras_feature_enable(adev, ras_block, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do some init work after IP late init as dependence.
|
/* do some init work after IP late init as dependence.
|
||||||
|
@ -319,6 +319,19 @@ struct ras_common_if {
|
|||||||
char name[32];
|
char name[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_UMC_CHANNEL_NUM 32
|
||||||
|
|
||||||
|
struct ecc_info_per_ch {
|
||||||
|
uint16_t ce_count_lo_chip;
|
||||||
|
uint16_t ce_count_hi_chip;
|
||||||
|
uint64_t mca_umc_status;
|
||||||
|
uint64_t mca_umc_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct umc_ecc_info {
|
||||||
|
struct ecc_info_per_ch ecc[MAX_UMC_CHANNEL_NUM];
|
||||||
|
};
|
||||||
|
|
||||||
struct amdgpu_ras {
|
struct amdgpu_ras {
|
||||||
/* ras infrastructure */
|
/* ras infrastructure */
|
||||||
/* for ras itself. */
|
/* for ras itself. */
|
||||||
@ -358,6 +371,9 @@ struct amdgpu_ras {
|
|||||||
struct delayed_work ras_counte_delay_work;
|
struct delayed_work ras_counte_delay_work;
|
||||||
atomic_t ras_ue_count;
|
atomic_t ras_ue_count;
|
||||||
atomic_t ras_ce_count;
|
atomic_t ras_ce_count;
|
||||||
|
|
||||||
|
/* record umc error info queried from smu */
|
||||||
|
struct umc_ecc_info umc_ecc;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ras_fs_data {
|
struct ras_fs_data {
|
||||||
|
@ -252,41 +252,25 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
|
|||||||
struct dma_resv *resv, enum amdgpu_sync_mode mode,
|
struct dma_resv *resv, enum amdgpu_sync_mode mode,
|
||||||
void *owner)
|
void *owner)
|
||||||
{
|
{
|
||||||
struct dma_resv_list *flist;
|
struct dma_resv_iter cursor;
|
||||||
struct dma_fence *f;
|
struct dma_fence *f;
|
||||||
unsigned i;
|
int r;
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
if (resv == NULL)
|
if (resv == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* always sync to the exclusive fence */
|
dma_resv_for_each_fence(&cursor, resv, true, f) {
|
||||||
f = dma_resv_excl_fence(resv);
|
dma_fence_chain_for_each(f, f) {
|
||||||
dma_fence_chain_for_each(f, f) {
|
struct dma_fence_chain *chain = to_dma_fence_chain(f);
|
||||||
struct dma_fence_chain *chain = to_dma_fence_chain(f);
|
|
||||||
|
|
||||||
if (amdgpu_sync_test_fence(adev, mode, owner, chain ?
|
if (amdgpu_sync_test_fence(adev, mode, owner, chain ?
|
||||||
chain->fence : f)) {
|
chain->fence : f)) {
|
||||||
r = amdgpu_sync_fence(sync, f);
|
r = amdgpu_sync_fence(sync, f);
|
||||||
dma_fence_put(f);
|
dma_fence_put(f);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
flist = dma_resv_shared_list(resv);
|
|
||||||
if (!flist)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < flist->shared_count; ++i) {
|
|
||||||
f = rcu_dereference_protected(flist->shared[i],
|
|
||||||
dma_resv_held(resv));
|
|
||||||
|
|
||||||
if (amdgpu_sync_test_fence(adev, mode, owner, f)) {
|
|
||||||
r = amdgpu_sync_fence(sync, f);
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user