mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
Merge 1d36dffa5d ("Merge tag 'drm-next-2020-12-11' of git://anongit.freedesktop.org/drm/drm") into android-mainline
Steps on the way to 5.11-rc1. Required resolutions in: include/linux/dma-buf.h drivers/dma-buf/heaps/system_heap.c drivers/staging/android/ion/ion_dma_buf.c drivers/dma-buf/heaps/heap-helpers.c Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ic546af62c7f61b5c754ece178c32f45878013c3a
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright 2019 Analogix Semiconductor, Inc.
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/display/bridge/analogix,anx7625.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Analogix ANX7625 SlimPort (4K Mobile HD Transmitter)
|
||||
|
||||
maintainers:
|
||||
- Xin Ji <xji@analogixsemi.com>
|
||||
|
||||
description: |
|
||||
The ANX7625 is an ultra-low power 4K Mobile HD Transmitter
|
||||
designed for portable devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: analogix,anx7625
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description: used for interrupt pin B8.
|
||||
maxItems: 1
|
||||
|
||||
enable-gpios:
|
||||
description: used for power on chip control, POWER_EN pin D2.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: used for reset chip control, RESET_N pin B7.
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
description:
|
||||
Video port for MIPI DSI input.
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
description:
|
||||
Video port for panel or connector.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
encoder@58 {
|
||||
compatible = "analogix,anx7625";
|
||||
reg = <0x58>;
|
||||
enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mipi2dp_bridge_in: port@0 {
|
||||
reg = <0>;
|
||||
anx7625_in: endpoint {
|
||||
remote-endpoint = <&mipi_dsi>;
|
||||
};
|
||||
};
|
||||
|
||||
mipi2dp_bridge_out: port@1 {
|
||||
reg = <1>;
|
||||
anx7625_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,101 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/intel,keembay-dsi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Devicetree bindings for Intel Keem Bay mipi dsi controller
|
||||
|
||||
maintainers:
|
||||
- Anitha Chrisanthus <anitha.chrisanthus@intel.com>
|
||||
- Edmond J Dea <edmund.j.dea@intel.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,keembay-dsi
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: MIPI registers range
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: mipi
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: MIPI DSI clock
|
||||
- description: MIPI DSI econfig clock
|
||||
- description: MIPI DSI config clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: clk_mipi
|
||||
- const: clk_mipi_ecfg
|
||||
- const: clk_mipi_cfg
|
||||
|
||||
ports:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
description: MIPI DSI input port.
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
description: DSI output port.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
mipi-dsi@20900000 {
|
||||
compatible = "intel,keembay-dsi";
|
||||
reg = <0x20900000 0x4000>;
|
||||
reg-names = "mipi";
|
||||
clocks = <&scmi_clk 0x86>,
|
||||
<&scmi_clk 0x88>,
|
||||
<&scmi_clk 0x89>;
|
||||
clock-names = "clk_mipi", "clk_mipi_ecfg",
|
||||
"clk_mipi_cfg";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi_in: endpoint {
|
||||
remote-endpoint = <&disp_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dsi_out: endpoint {
|
||||
remote-endpoint = <&adv7535_input>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -4,18 +4,19 @@
|
||||
$id: http://devicetree.org/schemas/display/bridge/lontium,lt9611.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Lontium LT9611 2 Port MIPI to HDMI Bridge
|
||||
title: Lontium LT9611(UXC) 2 Port MIPI to HDMI Bridge
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description: |
|
||||
The LT9611 is a bridge device which converts DSI to HDMI
|
||||
The LT9611 and LT9611UXC are bridge devices which convert DSI to HDMI
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- lontium,lt9611
|
||||
- lontium,lt9611uxc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -8,6 +8,8 @@ Optional properties:
|
||||
- interrupts: describe the interrupt line used to inform the host
|
||||
about hotplug events.
|
||||
- reset-gpios: OF device-tree gpio specification for RST_N pin.
|
||||
- iovcc-supply: I/O Supply Voltage (1.8V or 3.3V)
|
||||
- cvcc12-supply: Digital Core Supply Voltage (1.2V)
|
||||
|
||||
HDMI audio properties:
|
||||
- #sound-dai-cells: <0> or <1>. <0> if only i2s or spdif pin
|
||||
@@ -54,6 +56,8 @@ Example:
|
||||
compatible = "sil,sii9022";
|
||||
reg = <0x39>;
|
||||
reset-gpios = <&pioA 1 0>;
|
||||
iovcc-supply = <&v3v3_hdmi>;
|
||||
cvcc12-supply = <&v1v2_hdmi>;
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
sil,i2s-data-lanes = < 0 1 2 >;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/intel,keembay-display.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Devicetree bindings for Intel Keem Bay display controller
|
||||
|
||||
maintainers:
|
||||
- Anitha Chrisanthus <anitha.chrisanthus@intel.com>
|
||||
- Edmond J Dea <edmund.j.dea@intel.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,keembay-display
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: LCD registers range
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: lcd
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: LCD controller clock
|
||||
- description: pll0 clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: clk_lcd
|
||||
- const: clk_pll0
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: Display output node to DSI.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
display@20930000 {
|
||||
compatible = "intel,keembay-display";
|
||||
reg = <0x20930000 0x3000>;
|
||||
reg-names = "lcd";
|
||||
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&scmi_clk 0x83>,
|
||||
<&scmi_clk 0x0>;
|
||||
clock-names = "clk_lcd", "clk_pll0";
|
||||
|
||||
port {
|
||||
disp_out: endpoint {
|
||||
remote-endpoint = <&dsi_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/intel,keembay-msscam.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Devicetree bindings for Intel Keem Bay MSSCAM
|
||||
|
||||
maintainers:
|
||||
- Anitha Chrisanthus <anitha.chrisanthus@intel.com>
|
||||
- Edmond J Dea <edmund.j.dea@intel.com>
|
||||
|
||||
description: |
|
||||
MSSCAM controls local clocks in the display subsystem namely LCD clocks and
|
||||
MIPI DSI clocks. It also configures the interconnect between LCD and
|
||||
MIPI DSI.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: intel,keembay-msscam
|
||||
- const: syscon
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reg-io-width:
|
||||
const: 4
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-io-width
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
msscam:msscam@20910000 {
|
||||
compatible = "intel,keembay-msscam", "syscon";
|
||||
reg = <0x20910000 0x30>;
|
||||
reg-io-width = <4>;
|
||||
};
|
||||
@@ -43,7 +43,7 @@ Required properties (all function blocks):
|
||||
"mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt
|
||||
"mediatek,<chip>-disp-mutex" - display mutex
|
||||
"mediatek,<chip>-disp-od" - overdrive
|
||||
the supported chips are mt2701, mt7623, mt2712 and mt8173.
|
||||
the supported chips are mt2701, mt7623, mt2712, mt8167 and mt8173.
|
||||
- reg: Physical base address and length of the function block register space
|
||||
- interrupts: The interrupt signal from the function block (required, except for
|
||||
merge and split function blocks).
|
||||
@@ -59,7 +59,7 @@ Required properties (DMA function blocks):
|
||||
"mediatek,<chip>-disp-ovl"
|
||||
"mediatek,<chip>-disp-rdma"
|
||||
"mediatek,<chip>-disp-wdma"
|
||||
the supported chips are mt2701 and mt8173.
|
||||
the supported chips are mt2701, mt8167 and mt8173.
|
||||
- larb: Should contain a phandle pointing to the local arbiter device as defined
|
||||
in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
|
||||
- iommus: Should point to the respective IOMMU block with master port as
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
Mediatek DPI Device
|
||||
===================
|
||||
|
||||
The Mediatek DPI function block is a sink of the display subsystem and
|
||||
provides 8-bit RGB/YUV444 or 8/10/10-bit YUV422 pixel data on a parallel
|
||||
output bus.
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,<chip>-dpi"
|
||||
the supported chips are mt2701, mt7623, mt8173 and mt8183.
|
||||
- reg: Physical base address and length of the controller's registers
|
||||
- interrupts: The interrupt signal from the function block.
|
||||
- clocks: device clocks
|
||||
See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
|
||||
- clock-names: must contain "pixel", "engine", and "pll"
|
||||
- port: Output port node with endpoint definitions as described in
|
||||
Documentation/devicetree/bindings/graph.txt. This port should be connected
|
||||
to the input port of an attached HDMI or LVDS encoder chip.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names: Contain "default" and "sleep".
|
||||
|
||||
Example:
|
||||
|
||||
dpi0: dpi@1401d000 {
|
||||
compatible = "mediatek,mt8173-dpi";
|
||||
reg = <0 0x1401d000 0 0x1000>;
|
||||
interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
|
||||
clocks = <&mmsys CLK_MM_DPI_PIXEL>,
|
||||
<&mmsys CLK_MM_DPI_ENGINE>,
|
||||
<&apmixedsys CLK_APMIXED_TVDPLL>;
|
||||
clock-names = "pixel", "engine", "pll";
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&dpi_pin_func>;
|
||||
pinctrl-1 = <&dpi_pin_idle>;
|
||||
|
||||
port {
|
||||
dpi0_out: endpoint {
|
||||
remote-endpoint = <&hdmi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/mediatek/mediatek,dpi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: mediatek DPI Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- CK Hu <ck.hu@mediatek.com>
|
||||
- Jitao shi <jitao.shi@mediatek.com>
|
||||
|
||||
description: |
|
||||
The Mediatek DPI function block is a sink of the display subsystem and
|
||||
provides 8-bit RGB/YUV444 or 8/10/10-bit YUV422 pixel data on a parallel
|
||||
output bus.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt2701-dpi
|
||||
- mediatek,mt7623-dpi
|
||||
- mediatek,mt8173-dpi
|
||||
- mediatek,mt8183-dpi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Pixel Clock
|
||||
- description: Engine Clock
|
||||
- description: DPI PLL
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pixel
|
||||
- const: engine
|
||||
- const: pll
|
||||
|
||||
pinctrl-0: true
|
||||
pinctrl-1: true
|
||||
|
||||
pinctrl-names:
|
||||
items:
|
||||
- const: default
|
||||
- const: sleep
|
||||
|
||||
port:
|
||||
type: object
|
||||
description:
|
||||
Output port node with endpoint definitions as described in
|
||||
Documentation/devicetree/bindings/graph.txt. This port should be connected
|
||||
to the input port of an attached HDMI or LVDS encoder chip.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/mt8173-clk.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
dpi0: dpi@1401d000 {
|
||||
compatible = "mediatek,mt8173-dpi";
|
||||
reg = <0x1401d000 0x1000>;
|
||||
interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
|
||||
clocks = <&mmsys CLK_MM_DPI_PIXEL>,
|
||||
<&mmsys CLK_MM_DPI_ENGINE>,
|
||||
<&apmixedsys CLK_APMIXED_TVDPLL>;
|
||||
clock-names = "pixel", "engine", "pll";
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&dpi_pin_func>;
|
||||
pinctrl-1 = <&dpi_pin_idle>;
|
||||
|
||||
port {
|
||||
dpi0_out: endpoint {
|
||||
remote-endpoint = <&hdmi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -39,6 +39,10 @@ Required properties:
|
||||
a4xx Snapdragon SoCs. See
|
||||
Documentation/devicetree/bindings/sram/qcom,ocmem.yaml.
|
||||
|
||||
Optional properties:
|
||||
- #cooling-cells: The value must be 2. For details, please refer
|
||||
Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml.
|
||||
|
||||
Example 3xx/4xx:
|
||||
|
||||
/ {
|
||||
@@ -61,6 +65,7 @@ Example 3xx/4xx:
|
||||
power-domains = <&mmcc OXILICX_GDSC>;
|
||||
operating-points-v2 = <&gpu_opp_table>;
|
||||
iommus = <&gpu_iommu 0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
gpu_sram: ocmem@fdd00000 {
|
||||
@@ -98,6 +103,8 @@ Example a6xx (with GMU):
|
||||
reg = <0x5000000 0x40000>, <0x509e000 0x10>;
|
||||
reg-names = "kgsl_3d0_reg_memory", "cx_mem";
|
||||
|
||||
#cooling-cells = <2>;
|
||||
|
||||
/*
|
||||
* Look ma, no clocks! The GPU clocks and power are
|
||||
* controlled entirely by the GMU
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/abt,y030xx067a.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Asia Better Technology 3.0" (320x480 pixels) 24-bit IPS LCD panel
|
||||
|
||||
description: |
|
||||
The panel must obey the rules for a SPI slave device as specified in
|
||||
spi/spi-controller.yaml
|
||||
|
||||
maintainers:
|
||||
- Paul Cercueil <paul@crapouillou.net>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: abt,y030xx067a
|
||||
|
||||
backlight: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- power-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "abt,y030xx067a";
|
||||
reg = <0>;
|
||||
|
||||
spi-max-frequency = <3125000>;
|
||||
|
||||
reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
power-supply = <&vcc>;
|
||||
|
||||
port {
|
||||
panel_input: endpoint {
|
||||
remote-endpoint = <&panel_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/novatek,nt36672a.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Novatek NT36672A based DSI display Panels
|
||||
|
||||
maintainers:
|
||||
- Sumit Semwal <sumit.semwal@linaro.org>
|
||||
|
||||
description: |
|
||||
The nt36672a IC from Novatek is a generic DSI Panel IC used to drive dsi
|
||||
panels.
|
||||
Right now, support is added only for a Tianma FHD+ LCD display panel with a
|
||||
resolution of 1080x2246. It is a video mode DSI panel.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- tianma,fhd-video
|
||||
- const: novatek,nt36672a
|
||||
description: This indicates the panel manufacturer of the panel that is
|
||||
in turn using the NT36672A panel driver. This compatible string
|
||||
determines how the NT36672A panel driver is configured for the indicated
|
||||
panel. The novatek,nt36672a compatible shall always be provided as a fallback.
|
||||
|
||||
reset-gpios:
|
||||
description: phandle of gpio for reset line - This should be 8mA, gpio
|
||||
can be configured using mux, pinctrl, pinctrl-names (active high)
|
||||
|
||||
vddio-supply:
|
||||
description: phandle of the regulator that provides the supply voltage
|
||||
Power IC supply
|
||||
|
||||
vddpos-supply:
|
||||
description: phandle of the positive boost supply regulator
|
||||
|
||||
vddneg-supply:
|
||||
description: phandle of the negative boost supply regulator
|
||||
|
||||
reg: true
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vddi0-supply
|
||||
- vddpos-supply
|
||||
- vddneg-supply
|
||||
- reset-gpios
|
||||
- port
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |+
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "tianma,fhd-video", "novatek,nt36672a";
|
||||
reg = <0>;
|
||||
vddi0-supply = <&vreg_l14a_1p88>;
|
||||
vddpos-supply = <&lab>;
|
||||
vddneg-supply = <&ibb>;
|
||||
|
||||
reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port {
|
||||
tianma_nt36672a_in_0: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -47,6 +47,12 @@ properties:
|
||||
- panasonic,vvx10f004b00
|
||||
# Panasonic 10" WUXGA TFT LCD panel
|
||||
- panasonic,vvx10f034n00
|
||||
# Samsung s6e3fc2x01 1080x2340 AMOLED panel
|
||||
- samsung,s6e3fc2x01
|
||||
# Samsung sofef00 1080x2280 AMOLED panel
|
||||
- samsung,sofef00
|
||||
# Shangai Top Display Optoelectronics 7" TL070WSH30 1024x600 TFT LCD panel
|
||||
- tdo,tl070wsh30
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -54,6 +60,7 @@ properties:
|
||||
|
||||
backlight: true
|
||||
enable-gpios: true
|
||||
reset-gpios: true
|
||||
port: true
|
||||
power-supply: true
|
||||
|
||||
|
||||
@@ -282,6 +282,8 @@ properties:
|
||||
- vxt,vl050-8048nt-c01
|
||||
# Winstar Display Corporation 3.5" QVGA (320x240) TFT LCD panel
|
||||
- winstar,wf35ltiacd
|
||||
# Yes Optoelectronics YTC700TLAG-05-201C 7" TFT LCD panel
|
||||
- yes-optoelectronics,ytc700tlag-05-201c
|
||||
|
||||
backlight: true
|
||||
enable-gpios: true
|
||||
|
||||
@@ -55,6 +55,14 @@ properties:
|
||||
- const: vp1
|
||||
- const: vp2
|
||||
|
||||
assigned-clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
assigned-clock-parents:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
@@ -62,6 +70,9 @@ properties:
|
||||
maxItems: 1
|
||||
description: phandle to the associated power domain
|
||||
|
||||
dma-coherent:
|
||||
type: boolean
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
|
||||
@@ -77,6 +77,14 @@ properties:
|
||||
- const: vp3
|
||||
- const: vp4
|
||||
|
||||
assigned-clocks:
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
|
||||
assigned-clock-parents:
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: common_m DSS Master common
|
||||
@@ -95,6 +103,9 @@ properties:
|
||||
maxItems: 1
|
||||
description: phandle to the associated power domain
|
||||
|
||||
dma-coherent:
|
||||
type: boolean
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
|
||||
@@ -29,6 +29,8 @@ patternProperties:
|
||||
description: Abilis Systems
|
||||
"^abracon,.*":
|
||||
description: Abracon Corporation
|
||||
"^abt,.*":
|
||||
description: ShenZhen Asia Better Technology Ltd.
|
||||
"^acer,.*":
|
||||
description: Acer Inc.
|
||||
"^acme,.*":
|
||||
@@ -1053,6 +1055,8 @@ patternProperties:
|
||||
description: Trusted Computing Group
|
||||
"^tcl,.*":
|
||||
description: Toby Churchill Ltd.
|
||||
"^tdo,.*":
|
||||
description: Shangai Top Display Optoelectronics Co., Ltd
|
||||
"^technexion,.*":
|
||||
description: TechNexion
|
||||
"^technologic,.*":
|
||||
@@ -1210,6 +1214,8 @@ patternProperties:
|
||||
description: Shenzhen Xunlong Software CO.,Limited
|
||||
"^xylon,.*":
|
||||
description: Xylon
|
||||
"^yes-optoelectronics,.*":
|
||||
description: Yes Optoelectronics Co.,Ltd.
|
||||
"^ylm,.*":
|
||||
description: Shenzhen Yangliming Electronic Technology Co., Ltd.
|
||||
"^yna,.*":
|
||||
|
||||
@@ -115,6 +115,15 @@ Kernel Functions and Structures Reference
|
||||
.. kernel-doc:: include/linux/dma-buf.h
|
||||
:internal:
|
||||
|
||||
Buffer Mapping Helpers
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: include/linux/dma-buf-map.h
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/linux/dma-buf-map.h
|
||||
:internal:
|
||||
|
||||
Reservation Objects
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -182,11 +182,11 @@ acquired and release by calling drm_gem_object_get() and drm_gem_object_put()
|
||||
respectively.
|
||||
|
||||
When the last reference to a GEM object is released the GEM core calls
|
||||
the :c:type:`struct drm_driver <drm_driver>` gem_free_object_unlocked
|
||||
the :c:type:`struct drm_gem_object_funcs <gem_object_funcs>` free
|
||||
operation. That operation is mandatory for GEM-enabled drivers and must
|
||||
free the GEM object and all associated resources.
|
||||
|
||||
void (\*gem_free_object) (struct drm_gem_object \*obj); Drivers are
|
||||
void (\*free) (struct drm_gem_object \*obj); Drivers are
|
||||
responsible for freeing all GEM object resources. This includes the
|
||||
resources created by the GEM core, which need to be released with
|
||||
drm_gem_object_release().
|
||||
|
||||
@@ -118,6 +118,12 @@ Atomic Plane Helpers
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_atomic_plane.c
|
||||
:internal:
|
||||
|
||||
Asynchronous Page Flip
|
||||
----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_display.c
|
||||
:doc: asynchronous flip implementation
|
||||
|
||||
Output Probing
|
||||
--------------
|
||||
|
||||
|
||||
@@ -105,6 +105,10 @@ converted over to the new infrastructure.
|
||||
One issue with the helpers is that they require that drivers handle completion
|
||||
events for atomic commits correctly. But fixing these bugs is good anyway.
|
||||
|
||||
Somewhat related is the legacy_cursor_update hack, which should be replaced with
|
||||
the new atomic_async_check/commit functionality in the helpers in drivers that
|
||||
still look at that flag.
|
||||
|
||||
Contact: Daniel Vetter, respective driver maintainers
|
||||
|
||||
Level: Advanced
|
||||
@@ -149,7 +153,7 @@ have to keep track of that lock and either call ``unreference`` or
|
||||
``unreference_locked`` depending upon context.
|
||||
|
||||
Core GEM doesn't have a need for ``struct_mutex`` any more since kernel 4.8,
|
||||
and there's a ``gem_free_object_unlocked`` callback for any drivers which are
|
||||
and there's a GEM object ``free`` callback for any drivers which are
|
||||
entirely ``struct_mutex`` free.
|
||||
|
||||
For drivers that need ``struct_mutex`` it should be replaced with a driver-
|
||||
@@ -197,13 +201,28 @@ Convert drivers to use drm_fbdev_generic_setup()
|
||||
------------------------------------------------
|
||||
|
||||
Most drivers can use drm_fbdev_generic_setup(). Driver have to implement
|
||||
atomic modesetting and GEM vmap support. Current generic fbdev emulation
|
||||
expects the framebuffer in system memory (or system-like memory).
|
||||
atomic modesetting and GEM vmap support. Historically, generic fbdev emulation
|
||||
expected the framebuffer in system memory or system-like memory. By employing
|
||||
struct dma_buf_map, drivers with frambuffers in I/O memory can be supported
|
||||
as well.
|
||||
|
||||
Contact: Maintainer of the driver you plan to convert
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Reimplement functions in drm_fbdev_fb_ops without fbdev
|
||||
-------------------------------------------------------
|
||||
|
||||
A number of callback functions in drm_fbdev_fb_ops could benefit from
|
||||
being rewritten without dependencies on the fbdev module. Some of the
|
||||
helpers could further benefit from using struct dma_buf_map instead of
|
||||
raw pointers.
|
||||
|
||||
Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter
|
||||
|
||||
Level: Advanced
|
||||
|
||||
|
||||
drm_framebuffer_funcs and drm_mode_config_funcs.fb_create cleanup
|
||||
-----------------------------------------------------------------
|
||||
|
||||
@@ -273,6 +292,27 @@ Contact: Daniel Vetter, Noralf Tronnes
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Garbage collect fbdev scrolling acceleration
|
||||
--------------------------------------------
|
||||
|
||||
Scroll acceleration is disabled in fbcon by hard-wiring p->scrollmode =
|
||||
SCROLL_REDRAW. There's a ton of code this will allow us to remove:
|
||||
|
||||
- lots of code in fbcon.c
|
||||
|
||||
- a bunch of the hooks in fbcon_ops, maybe the remaining hooks could be called
|
||||
directly instead of the function table (with a switch on p->rotate)
|
||||
|
||||
- fb_copyarea is unused after this, and can be deleted from all drivers
|
||||
|
||||
Note that not all acceleration code can be deleted, since clearing and cursor
|
||||
support is still accelerated, which might be good candidates for further
|
||||
deletion projects.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
idr_init_base()
|
||||
---------------
|
||||
|
||||
@@ -289,11 +329,8 @@ struct drm_gem_object_funcs
|
||||
---------------------------
|
||||
|
||||
GEM objects can now have a function table instead of having the callbacks on the
|
||||
DRM driver struct. This is now the preferred way and drivers can be moved over.
|
||||
|
||||
We also need a 2nd version of the CMA define that doesn't require the
|
||||
vmapping to be present (different hook for prime importing). Plus this needs to
|
||||
be rolled out to all drivers using their own implementations, too.
|
||||
DRM driver struct. This is now the preferred way. Callbacks in drivers have been
|
||||
converted, except for struct drm_driver.gem_prime_mmap.
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
@@ -449,6 +486,24 @@ Contact: Ville Syrjälä, Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Use struct dma_buf_map throughout codebase
|
||||
------------------------------------------
|
||||
|
||||
Pointers to shared device memory are stored in struct dma_buf_map. Each
|
||||
instance knows whether it refers to system or I/O memory. Most of the DRM-wide
|
||||
interface have been converted to use struct dma_buf_map, but implementations
|
||||
often still use raw pointers.
|
||||
|
||||
The task is to use struct dma_buf_map where it makes sense.
|
||||
|
||||
* Memory managers should use struct dma_buf_map for dma-buf-imported buffers.
|
||||
* TTM might benefit from using struct dma_buf_map internally.
|
||||
* Framebuffer copying and blitting helpers should operate on struct dma_buf_map.
|
||||
|
||||
Contact: Thomas Zimmermann <tzimmermann@suse.de>, Christian König, Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
@@ -518,9 +573,6 @@ There's a bunch of issues with it:
|
||||
this (together with the drm_minor->drm_device move) would allow us to remove
|
||||
debugfs_init.
|
||||
|
||||
- Drop the return code and error checking from all debugfs functions. Greg KH is
|
||||
working on this already.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
@@ -10,36 +10,24 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
CRC API Improvements
|
||||
--------------------
|
||||
If you want to do any of the items listed below, please share your interest
|
||||
with VKMS maintainers.
|
||||
|
||||
- Optimize CRC computation ``compute_crc()`` and plane blending ``blend()``
|
||||
IGT better support
|
||||
------------------
|
||||
|
||||
- Use the alpha value to blend vaddr_src with vaddr_dst instead of
|
||||
overwriting it in ``blend()``.
|
||||
- Investigate: (1) test cases on kms_plane that are failing due to timeout on
|
||||
capturing CRC; (2) when running kms_flip test cases in sequence, some
|
||||
successful individual test cases are failing randomly.
|
||||
|
||||
- Add igt test to check cleared alpha value for XRGB plane format.
|
||||
|
||||
- Add igt test to check extreme alpha values i.e. fully opaque and fully
|
||||
transparent (intermediate values are affected by hw-specific rounding modes).
|
||||
|
||||
Runtime Configuration
|
||||
---------------------
|
||||
|
||||
We want to be able to reconfigure vkms instance without having to reload the
|
||||
module. Use/Test-cases:
|
||||
|
||||
- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling of
|
||||
compositors).
|
||||
|
||||
- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of
|
||||
them first).
|
||||
|
||||
- Change output configuration: Plug/unplug screens, change EDID, allow changing
|
||||
the refresh rate.
|
||||
|
||||
The currently proposed solution is to expose vkms configuration through
|
||||
configfs. All existing module options should be supported through configfs too.
|
||||
- VKMS already has support for vblanks simulated via hrtimers, which can be
|
||||
tested with kms_flip test; in some way, we can say that VKMS already mimics
|
||||
the real hardware vblank. However, we also have virtual hardware that does
|
||||
not support vblank interrupt and completes page_flip events right away; in
|
||||
this case, compositor developers may end up creating a busy loop on virtual
|
||||
hardware. It would be useful to support Virtual Hardware behavior in VKMS
|
||||
because this can help compositor developers to test their features in
|
||||
multiple scenarios.
|
||||
|
||||
Add Plane Features
|
||||
------------------
|
||||
@@ -55,33 +43,49 @@ There's lots of plane features we could add support for:
|
||||
- Additional buffer formats, especially YUV formats for video like NV12.
|
||||
Low/high bpp RGB formats would also be interesting.
|
||||
|
||||
- Async updates (currently only possible on cursor plane using the legacy cursor
|
||||
api).
|
||||
- Async updates (currently only possible on cursor plane using the legacy
|
||||
cursor api).
|
||||
|
||||
For all of these, we also want to review the igt test coverage and make sure all
|
||||
relevant igt testcases work on vkms.
|
||||
|
||||
Writeback support
|
||||
-----------------
|
||||
|
||||
Currently vkms only computes a CRC for each frame. Once we have additional plane
|
||||
features, we could write back the entire composited frame, and expose it as:
|
||||
|
||||
- Writeback connector. This is useful for testing compositors if you don't have
|
||||
hardware with writeback support.
|
||||
|
||||
- As a v4l device. This is useful for debugging compositors on special vkms
|
||||
configurations, so that developers see what's really going on.
|
||||
For all of these, we also want to review the igt test coverage and make sure
|
||||
all relevant igt testcases work on vkms.
|
||||
|
||||
Prime Buffer Sharing
|
||||
--------------------
|
||||
|
||||
We already have vgem, which is a gem driver for testing rendering, similar to
|
||||
how vkms is for testing the modeset side. Adding buffer sharing support to vkms
|
||||
allows us to test them together, to test synchronization and lots of other
|
||||
features. Also, this allows compositors to test whether they work correctly on
|
||||
SoC chips, where the display and rendering is very often split between 2
|
||||
drivers.
|
||||
- Syzbot report - WARNING in vkms_gem_free_object:
|
||||
https://syzkaller.appspot.com/bug?extid=e7ad70d406e74d8fc9d0
|
||||
|
||||
Runtime Configuration
|
||||
---------------------
|
||||
|
||||
We want to be able to reconfigure vkms instance without having to reload the
|
||||
module. Use/Test-cases:
|
||||
|
||||
- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling
|
||||
of compositors).
|
||||
|
||||
- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of
|
||||
them first).
|
||||
|
||||
- Change output configuration: Plug/unplug screens, change EDID, allow changing
|
||||
the refresh rate.
|
||||
|
||||
The currently proposed solution is to expose vkms configuration through
|
||||
configfs. All existing module options should be supported through configfs
|
||||
too.
|
||||
|
||||
Writeback support
|
||||
-----------------
|
||||
|
||||
- The writeback and CRC capture operations share the use of composer_enabled
|
||||
boolean to ensure vblanks. Probably, when these operations work together,
|
||||
composer_enabled needs to refcounting the composer state to proper work.
|
||||
|
||||
- Add support for cloned writeback outputs and related test cases using a
|
||||
cloned output in the IGT kms_writeback.
|
||||
|
||||
- As a v4l device. This is useful for debugging compositors on special vkms
|
||||
configurations, so that developers see what's really going on.
|
||||
|
||||
Output Features
|
||||
---------------
|
||||
@@ -93,7 +97,10 @@ Output Features
|
||||
- Add support for link status, so that compositors can validate their runtime
|
||||
fallbacks when e.g. a Display Port link goes bad.
|
||||
|
||||
- All the hotplug handling describe under "Runtime Configuration".
|
||||
CRC API Improvements
|
||||
--------------------
|
||||
|
||||
- Optimize CRC computation ``compute_crc()`` and plane blending ``blend()``
|
||||
|
||||
Atomic Check using eBPF
|
||||
-----------------------
|
||||
|
||||
19
MAINTAINERS
19
MAINTAINERS
@@ -5588,6 +5588,13 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt35510.c
|
||||
|
||||
DRM DRIVER FOR NOVATEK NT36672A PANELS
|
||||
M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
|
||||
|
||||
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
|
||||
M: Ben Skeggs <bskeggs@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
@@ -5875,6 +5882,7 @@ S: Supported
|
||||
F: Documentation/devicetree/bindings/display/mediatek/
|
||||
F: drivers/gpu/drm/mediatek/
|
||||
F: drivers/phy/mediatek/phy-mtk-hdmi*
|
||||
F: drivers/phy/mediatek/phy-mtk-mipi*
|
||||
|
||||
DRM DRIVERS FOR NVIDIA TEGRA
|
||||
M: Thierry Reding <thierry.reding@gmail.com>
|
||||
@@ -5967,6 +5975,7 @@ F: include/uapi/drm/v3d_drm.h
|
||||
|
||||
DRM DRIVERS FOR VC4
|
||||
M: Eric Anholt <eric@anholt.net>
|
||||
M: Maxime Ripard <mripard@kernel.org>
|
||||
S: Supported
|
||||
T: git git://github.com/anholt/linux
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
@@ -6924,10 +6933,9 @@ F: drivers/net/wan/dlci.c
|
||||
F: drivers/net/wan/sdla.c
|
||||
|
||||
FRAMEBUFFER LAYER
|
||||
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
Q: http://patchwork.kernel.org/project/linux-fbdev/list/
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/fb/
|
||||
@@ -8974,6 +8982,13 @@ M: Deepak Saxena <dsaxena@plexity.net>
|
||||
S: Maintained
|
||||
F: drivers/char/hw_random/ixp4xx-rng.c
|
||||
|
||||
INTEL KEEMBAY DRM DRIVER
|
||||
M: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
|
||||
M: Edmund Dea <edmund.j.dea@intel.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/intel,kmb_display.yaml
|
||||
F: drivers/gpu/drm/kmb/
|
||||
|
||||
INTEL MANAGEMENT ENGINE (mei)
|
||||
M: Tomas Winkler <tomas.winkler@intel.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
|
||||
@@ -135,3 +135,7 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mali {
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
@@ -851,6 +851,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unpin);
|
||||
* Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
|
||||
* on error. May return -EINTR if it is interrupted by a signal.
|
||||
*
|
||||
* On success, the DMA addresses and lengths in the returned scatterlist are
|
||||
* PAGE_SIZE aligned.
|
||||
*
|
||||
* A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
|
||||
* the underlying backing storage is pinned for as long as a mapping exists,
|
||||
* therefore users/importers should not hold onto a mapping for undue amounts of
|
||||
@@ -904,6 +907,24 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
|
||||
attach->dir = direction;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DMA_API_DEBUG
|
||||
if (!IS_ERR(sg_table)) {
|
||||
struct scatterlist *sg;
|
||||
u64 addr;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
for_each_sgtable_dma_sg(sg_table, sg, i) {
|
||||
addr = sg_dma_address(sg);
|
||||
len = sg_dma_len(sg);
|
||||
if (!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(len)) {
|
||||
pr_debug("%s: addr %llx or len %x is not page aligned!\n",
|
||||
__func__, addr, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_DMA_API_DEBUG */
|
||||
|
||||
return sg_table;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
|
||||
@@ -1227,68 +1248,72 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
|
||||
* dma_buf_vmap - Create virtual mapping for the buffer object into kernel
|
||||
* address space. Same restrictions as for vmap and friends apply.
|
||||
* @dmabuf: [in] buffer to vmap
|
||||
* @map: [out] returns the vmap pointer
|
||||
*
|
||||
* This call may fail due to lack of virtual mapping address space.
|
||||
* These calls are optional in drivers. The intended use for them
|
||||
* is for mapping objects linear in kernel space for high use objects.
|
||||
* Please attempt to use kmap/kunmap before thinking about these interfaces.
|
||||
*
|
||||
* Returns NULL on error.
|
||||
* Returns 0 on success, or a negative errno code otherwise.
|
||||
*/
|
||||
void *dma_buf_vmap(struct dma_buf *dmabuf)
|
||||
int dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
|
||||
{
|
||||
void *ptr;
|
||||
struct dma_buf_map ptr;
|
||||
int ret = 0;
|
||||
|
||||
dma_buf_map_clear(map);
|
||||
|
||||
if (WARN_ON(!dmabuf))
|
||||
return NULL;
|
||||
return -EINVAL;
|
||||
|
||||
if (!dmabuf->ops->vmap)
|
||||
return NULL;
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dmabuf->lock);
|
||||
if (dmabuf->vmapping_counter) {
|
||||
dmabuf->vmapping_counter++;
|
||||
BUG_ON(!dmabuf->vmap_ptr);
|
||||
ptr = dmabuf->vmap_ptr;
|
||||
BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr));
|
||||
*map = dmabuf->vmap_ptr;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
BUG_ON(dmabuf->vmap_ptr);
|
||||
BUG_ON(dma_buf_map_is_set(&dmabuf->vmap_ptr));
|
||||
|
||||
ptr = dmabuf->ops->vmap(dmabuf);
|
||||
if (WARN_ON_ONCE(IS_ERR(ptr)))
|
||||
ptr = NULL;
|
||||
if (!ptr)
|
||||
ret = dmabuf->ops->vmap(dmabuf, &ptr);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
goto out_unlock;
|
||||
|
||||
dmabuf->vmap_ptr = ptr;
|
||||
dmabuf->vmapping_counter = 1;
|
||||
|
||||
*map = dmabuf->vmap_ptr;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&dmabuf->lock);
|
||||
return ptr;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_vmap);
|
||||
|
||||
/**
|
||||
* dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
|
||||
* @dmabuf: [in] buffer to vunmap
|
||||
* @vaddr: [in] vmap to vunmap
|
||||
* @map: [in] vmap pointer to vunmap
|
||||
*/
|
||||
void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
|
||||
void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
|
||||
{
|
||||
if (WARN_ON(!dmabuf))
|
||||
return;
|
||||
|
||||
BUG_ON(!dmabuf->vmap_ptr);
|
||||
BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr));
|
||||
BUG_ON(dmabuf->vmapping_counter == 0);
|
||||
BUG_ON(dmabuf->vmap_ptr != vaddr);
|
||||
BUG_ON(!dma_buf_map_is_equal(&dmabuf->vmap_ptr, map));
|
||||
|
||||
mutex_lock(&dmabuf->lock);
|
||||
if (--dmabuf->vmapping_counter == 0) {
|
||||
if (dmabuf->ops->vunmap)
|
||||
dmabuf->ops->vunmap(dmabuf, vaddr);
|
||||
dmabuf->vmap_ptr = NULL;
|
||||
dmabuf->ops->vunmap(dmabuf, map);
|
||||
dma_buf_map_clear(&dmabuf->vmap_ptr);
|
||||
}
|
||||
mutex_unlock(&dmabuf->lock);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ static struct dma_resv_list *dma_resv_list_alloc(unsigned int shared_max)
|
||||
{
|
||||
struct dma_resv_list *list;
|
||||
|
||||
list = kmalloc(offsetof(typeof(*list), shared[shared_max]), GFP_KERNEL);
|
||||
list = kmalloc(struct_size(list, shared, shared_max), GFP_KERNEL);
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ static void *system_heap_do_vmap(struct system_heap_buffer *buffer)
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
static void *system_heap_vmap(struct dma_buf *dmabuf)
|
||||
static int system_heap_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
|
||||
{
|
||||
struct system_heap_buffer *buffer = dmabuf->priv;
|
||||
void *vaddr;
|
||||
@@ -253,18 +253,21 @@ static void *system_heap_vmap(struct dma_buf *dmabuf)
|
||||
}
|
||||
|
||||
vaddr = system_heap_do_vmap(buffer);
|
||||
if (IS_ERR(vaddr))
|
||||
goto out;
|
||||
if (IS_ERR(vaddr)) {
|
||||
mutex_unlock(&buffer->lock);
|
||||
return PTR_ERR(vaddr);
|
||||
}
|
||||
|
||||
buffer->vaddr = vaddr;
|
||||
buffer->vmap_cnt++;
|
||||
out:
|
||||
mutex_unlock(&buffer->lock);
|
||||
|
||||
return vaddr;
|
||||
dma_buf_map_set_vaddr(map, vaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void system_heap_vunmap(struct dma_buf *dmabuf, void *vaddr)
|
||||
static void system_heap_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
|
||||
{
|
||||
struct system_heap_buffer *buffer = dmabuf->priv;
|
||||
|
||||
|
||||
@@ -182,13 +182,6 @@ config DRM_TTM
|
||||
GPU memory types. Will be enabled automatically if a device driver
|
||||
uses it.
|
||||
|
||||
config DRM_TTM_DMA_PAGE_POOL
|
||||
bool
|
||||
depends on DRM_TTM && (SWIOTLB || INTEL_IOMMU)
|
||||
default y
|
||||
help
|
||||
Choose this if you need the TTM dma page pool
|
||||
|
||||
config DRM_VRAM_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
@@ -239,6 +232,7 @@ config DRM_RADEON
|
||||
select FW_LOADER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_TTM
|
||||
select DRM_TTM_HELPER
|
||||
select POWER_SUPPLY
|
||||
select HWMON
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
@@ -259,6 +253,7 @@ config DRM_AMDGPU
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_SCHED
|
||||
select DRM_TTM
|
||||
select DRM_TTM_HELPER
|
||||
select POWER_SUPPLY
|
||||
select HWMON
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
@@ -275,6 +270,8 @@ source "drivers/gpu/drm/nouveau/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/i915/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/kmb/Kconfig"
|
||||
|
||||
config DRM_VGEM
|
||||
tristate "Virtual GEM provider"
|
||||
depends on DRM
|
||||
@@ -287,6 +284,7 @@ config DRM_VKMS
|
||||
tristate "Virtual KMS (EXPERIMENTAL)"
|
||||
depends on DRM
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_SHMEM_HELPER
|
||||
select CRC32
|
||||
default n
|
||||
help
|
||||
|
||||
@@ -71,6 +71,7 @@ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
|
||||
obj-$(CONFIG_DRM_MGA) += mga/
|
||||
obj-$(CONFIG_DRM_I810) += i810/
|
||||
obj-$(CONFIG_DRM_I915) += i915/
|
||||
obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/
|
||||
obj-$(CONFIG_DRM_MGAG200) += mgag200/
|
||||
obj-$(CONFIG_DRM_V3D) += v3d/
|
||||
obj-$(CONFIG_DRM_VC4) += vc4/
|
||||
|
||||
@@ -55,7 +55,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
|
||||
amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \
|
||||
amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
|
||||
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
|
||||
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o
|
||||
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
|
||||
amdgpu_fw_attestation.o
|
||||
|
||||
amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
|
||||
|
||||
@@ -69,7 +70,8 @@ amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce
|
||||
amdgpu-y += \
|
||||
vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \
|
||||
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \
|
||||
arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o
|
||||
arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \
|
||||
nbio_v7_2.o dimgrey_cavefish_reg_init.o
|
||||
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
@@ -81,7 +83,7 @@ amdgpu-y += \
|
||||
gmc_v7_0.o \
|
||||
gmc_v8_0.o \
|
||||
gfxhub_v1_0.o mmhub_v1_0.o gmc_v9_0.o gfxhub_v1_1.o mmhub_v9_4.o \
|
||||
gfxhub_v2_0.o mmhub_v2_0.o gmc_v10_0.o gfxhub_v2_1.o
|
||||
gfxhub_v2_0.o mmhub_v2_0.o gmc_v10_0.o gfxhub_v2_1.o mmhub_v2_3.o
|
||||
|
||||
# add UMC block
|
||||
amdgpu-y += \
|
||||
@@ -165,6 +167,11 @@ amdgpu-y += \
|
||||
athub_v2_0.o \
|
||||
athub_v2_1.o
|
||||
|
||||
# add SMUIO block
|
||||
amdgpu-y += \
|
||||
smuio_v9_0.o \
|
||||
smuio_v11_0.o
|
||||
|
||||
# add amdkfd interfaces
|
||||
amdgpu-y += amdgpu_amdkfd.o
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
#include "amdgpu_mmhub.h"
|
||||
#include "amdgpu_gfxhub.h"
|
||||
#include "amdgpu_df.h"
|
||||
#include "amdgpu_smuio.h"
|
||||
|
||||
#define MAX_GPU_INSTANCE 16
|
||||
|
||||
@@ -193,9 +194,9 @@ extern int sched_policy;
|
||||
extern bool debug_evictions;
|
||||
extern bool no_system_mem_limit;
|
||||
#else
|
||||
static const int sched_policy = KFD_SCHED_POLICY_HWS;
|
||||
static const bool debug_evictions; /* = false */
|
||||
static const bool no_system_mem_limit;
|
||||
static const int __maybe_unused sched_policy = KFD_SCHED_POLICY_HWS;
|
||||
static const bool __maybe_unused debug_evictions; /* = false */
|
||||
static const bool __maybe_unused no_system_mem_limit;
|
||||
#endif
|
||||
|
||||
extern int amdgpu_tmz;
|
||||
@@ -623,6 +624,8 @@ struct amdgpu_asic_funcs {
|
||||
bool (*supports_baco)(struct amdgpu_device *adev);
|
||||
/* pre asic_init quirks */
|
||||
void (*pre_asic_init)(struct amdgpu_device *adev);
|
||||
/* enter/exit umd stable pstate */
|
||||
int (*update_umd_stable_pstate)(struct amdgpu_device *adev, bool enter);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -723,6 +726,45 @@ struct amd_powerplay {
|
||||
const struct amd_pm_funcs *pp_funcs;
|
||||
};
|
||||
|
||||
/* polaris10 kickers */
|
||||
#define ASICID_IS_P20(did, rid) (((did == 0x67DF) && \
|
||||
((rid == 0xE3) || \
|
||||
(rid == 0xE4) || \
|
||||
(rid == 0xE5) || \
|
||||
(rid == 0xE7) || \
|
||||
(rid == 0xEF))) || \
|
||||
((did == 0x6FDF) && \
|
||||
((rid == 0xE7) || \
|
||||
(rid == 0xEF) || \
|
||||
(rid == 0xFF))))
|
||||
|
||||
#define ASICID_IS_P30(did, rid) ((did == 0x67DF) && \
|
||||
((rid == 0xE1) || \
|
||||
(rid == 0xF7)))
|
||||
|
||||
/* polaris11 kickers */
|
||||
#define ASICID_IS_P21(did, rid) (((did == 0x67EF) && \
|
||||
((rid == 0xE0) || \
|
||||
(rid == 0xE5))) || \
|
||||
((did == 0x67FF) && \
|
||||
((rid == 0xCF) || \
|
||||
(rid == 0xEF) || \
|
||||
(rid == 0xFF))))
|
||||
|
||||
#define ASICID_IS_P31(did, rid) ((did == 0x67EF) && \
|
||||
((rid == 0xE2)))
|
||||
|
||||
/* polaris12 kickers */
|
||||
#define ASICID_IS_P23(did, rid) (((did == 0x6987) && \
|
||||
((rid == 0xC0) || \
|
||||
(rid == 0xC1) || \
|
||||
(rid == 0xC3) || \
|
||||
(rid == 0xC7))) || \
|
||||
((did == 0x6981) && \
|
||||
((rid == 0x00) || \
|
||||
(rid == 0x01) || \
|
||||
(rid == 0x10))))
|
||||
|
||||
#define AMDGPU_RESET_MAGIC_NUM 64
|
||||
#define AMDGPU_MAX_DF_PERFMONS 4
|
||||
struct amdgpu_device {
|
||||
@@ -879,6 +921,9 @@ struct amdgpu_device {
|
||||
/* nbio */
|
||||
struct amdgpu_nbio nbio;
|
||||
|
||||
/* smuio */
|
||||
struct amdgpu_smuio smuio;
|
||||
|
||||
/* mmhub */
|
||||
struct amdgpu_mmhub mmhub;
|
||||
|
||||
@@ -1165,6 +1210,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
#define amdgpu_asic_get_pcie_replay_count(adev) ((adev)->asic_funcs->get_pcie_replay_count((adev)))
|
||||
#define amdgpu_asic_supports_baco(adev) (adev)->asic_funcs->supports_baco((adev))
|
||||
#define amdgpu_asic_pre_asic_init(adev) (adev)->asic_funcs->pre_asic_init((adev))
|
||||
#define amdgpu_asic_update_umd_stable_pstate(adev, enter) \
|
||||
((adev)->asic_funcs->update_umd_stable_pstate ? (adev)->asic_funcs->update_umd_stable_pstate((adev), (enter)) : 0)
|
||||
|
||||
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
|
||||
|
||||
@@ -1264,9 +1311,11 @@ int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
|
||||
struct amdgpu_dm_backlight_caps *caps);
|
||||
bool amdgpu_acpi_is_s0ix_supported(void);
|
||||
#else
|
||||
static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
|
||||
static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
|
||||
static inline bool amdgpu_acpi_is_s0ix_supported(void) { return false; }
|
||||
#endif
|
||||
|
||||
int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
|
||||
@@ -1294,19 +1343,6 @@ bool amdgpu_device_load_pci_state(struct pci_dev *pdev);
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
|
||||
/* used by df_v3_6.c and amdgpu_pmu.c */
|
||||
#define AMDGPU_PMU_ATTR(_name, _object) \
|
||||
static ssize_t \
|
||||
_name##_show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *page) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(_object) >= PAGE_SIZE - 1); \
|
||||
return sprintf(page, _object "\n"); \
|
||||
} \
|
||||
\
|
||||
static struct device_attribute pmu_attr_##_name = __ATTR_RO(_name)
|
||||
|
||||
static inline bool amdgpu_is_tmz(struct amdgpu_device *adev)
|
||||
{
|
||||
return adev->gmc.tmz_enabled;
|
||||
|
||||
@@ -36,17 +36,17 @@
|
||||
|
||||
#include "acp_gfx_if.h"
|
||||
|
||||
#define ACP_TILE_ON_MASK 0x03
|
||||
#define ACP_TILE_OFF_MASK 0x02
|
||||
#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f
|
||||
#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20
|
||||
#define ACP_TILE_ON_MASK 0x03
|
||||
#define ACP_TILE_OFF_MASK 0x02
|
||||
#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f
|
||||
#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20
|
||||
|
||||
#define ACP_TILE_P1_MASK 0x3e
|
||||
#define ACP_TILE_P2_MASK 0x3d
|
||||
#define ACP_TILE_DSP0_MASK 0x3b
|
||||
#define ACP_TILE_DSP1_MASK 0x37
|
||||
#define ACP_TILE_P1_MASK 0x3e
|
||||
#define ACP_TILE_P2_MASK 0x3d
|
||||
#define ACP_TILE_DSP0_MASK 0x3b
|
||||
#define ACP_TILE_DSP1_MASK 0x37
|
||||
|
||||
#define ACP_TILE_DSP2_MASK 0x2f
|
||||
#define ACP_TILE_DSP2_MASK 0x2f
|
||||
|
||||
#define ACP_DMA_REGS_END 0x146c0
|
||||
#define ACP_I2S_PLAY_REGS_START 0x14840
|
||||
@@ -75,8 +75,8 @@
|
||||
#define mmACP_CONTROL 0x5131
|
||||
#define mmACP_STATUS 0x5133
|
||||
#define mmACP_SOFT_RESET 0x5134
|
||||
#define ACP_CONTROL__ClkEn_MASK 0x1
|
||||
#define ACP_SOFT_RESET__SoftResetAud_MASK 0x100
|
||||
#define ACP_CONTROL__ClkEn_MASK 0x1
|
||||
#define ACP_SOFT_RESET__SoftResetAud_MASK 0x100
|
||||
#define ACP_SOFT_RESET__SoftResetAudDone_MASK 0x1000000
|
||||
#define ACP_CLOCK_EN_TIME_OUT_VALUE 0x000000FF
|
||||
#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF
|
||||
@@ -176,7 +176,7 @@ static struct device *get_mfd_cell_dev(const char *device_name, int r)
|
||||
/**
|
||||
* acp_hw_init - start and test ACP block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @handle: handle used to pass amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
static int acp_hw_init(void *handle)
|
||||
@@ -405,7 +405,7 @@ failure:
|
||||
/**
|
||||
* acp_hw_fini - stop the hardware block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @handle: handle used to pass amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
static int acp_hw_fini(void *handle)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <acpi/video.h>
|
||||
#include <acpi/actbl.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include "amdgpu.h"
|
||||
@@ -894,3 +895,16 @@ void amdgpu_acpi_fini(struct amdgpu_device *adev)
|
||||
unregister_acpi_notifier(&adev->acpi_nb);
|
||||
kfree(adev->atif);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_acpi_is_s0ix_supported
|
||||
*
|
||||
* returns true if supported, false if not.
|
||||
*/
|
||||
bool amdgpu_acpi_is_s0ix_supported(void)
|
||||
{
|
||||
if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -390,23 +390,17 @@ void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
||||
struct kfd_local_mem_info *mem_info)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
uint64_t address_mask = adev->dev->dma_mask ? ~*adev->dev->dma_mask :
|
||||
~((1ULL << 32) - 1);
|
||||
resource_size_t aper_limit = adev->gmc.aper_base + adev->gmc.aper_size;
|
||||
|
||||
memset(mem_info, 0, sizeof(*mem_info));
|
||||
if (!(adev->gmc.aper_base & address_mask || aper_limit & address_mask)) {
|
||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size -
|
||||
adev->gmc.visible_vram_size;
|
||||
} else {
|
||||
mem_info->local_mem_size_public = 0;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size;
|
||||
}
|
||||
|
||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size -
|
||||
adev->gmc.visible_vram_size;
|
||||
|
||||
mem_info->vram_width = adev->gmc.vram_width;
|
||||
|
||||
pr_debug("Address base: %pap limit %pap public 0x%llx private 0x%llx\n",
|
||||
&adev->gmc.aper_base, &aper_limit,
|
||||
pr_debug("Address base: %pap public 0x%llx private 0x%llx\n",
|
||||
&adev->gmc.aper_base,
|
||||
mem_info->local_mem_size_public,
|
||||
mem_info->local_mem_size_private);
|
||||
|
||||
@@ -648,6 +642,13 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
/* Temp workaround to fix the soft hang observed in certain compute
|
||||
* applications if GFXOFF is enabled.
|
||||
*/
|
||||
if (adev->asic_type == CHIP_SIENNA_CICHLID) {
|
||||
pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled");
|
||||
amdgpu_gfx_off_ctrl(adev, idle);
|
||||
}
|
||||
amdgpu_dpm_switch_power_profile(adev,
|
||||
PP_SMC_POWER_PROFILE_COMPUTE,
|
||||
!idle);
|
||||
|
||||
@@ -304,4 +304,5 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = {
|
||||
kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
|
||||
.set_vm_context_page_table_base =
|
||||
kgd_gfx_v9_set_vm_context_page_table_base,
|
||||
.get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "soc15.h"
|
||||
#include "soc15d.h"
|
||||
#include "gfx_v9_0.h"
|
||||
#include "amdgpu_amdkfd_gfx_v9.h"
|
||||
|
||||
enum hqd_dequeue_request_type {
|
||||
NO_ACTION = 0,
|
||||
@@ -799,7 +800,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
||||
*
|
||||
* Reading registers referenced above involves programming GRBM appropriately
|
||||
*/
|
||||
static void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
||||
int *pasid_wave_cnt, int *max_waves_per_cu)
|
||||
{
|
||||
int qidx;
|
||||
|
||||
@@ -63,3 +63,5 @@ bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
||||
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd,
|
||||
uint32_t vmid, uint64_t page_table_base);
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
||||
int *pasid_wave_cnt, int *max_waves_per_cu);
|
||||
|
||||
@@ -239,8 +239,7 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
|
||||
if (!old)
|
||||
return 0;
|
||||
|
||||
new = kmalloc(offsetof(typeof(*new), shared[old->shared_max]),
|
||||
GFP_KERNEL);
|
||||
new = kmalloc(struct_size(new, shared, old->shared_max), GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1115,19 +1114,19 @@ void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm)
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *vm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_vm *avm = (struct amdgpu_vm *)vm;
|
||||
struct amdgpu_vm *avm = (struct amdgpu_vm *)vm;
|
||||
|
||||
if (WARN_ON(!kgd || !vm))
|
||||
return;
|
||||
return;
|
||||
|
||||
pr_debug("Releasing process vm %p\n", vm);
|
||||
pr_debug("Releasing process vm %p\n", vm);
|
||||
|
||||
/* The original pasid of amdgpu vm has already been
|
||||
* released during making a amdgpu vm to a compute vm
|
||||
* The current pasid is managed by kfd and will be
|
||||
* released on kfd process destroy. Set amdgpu pasid
|
||||
* to 0 to avoid duplicate release.
|
||||
*/
|
||||
/* The original pasid of amdgpu vm has already been
|
||||
* released during making a amdgpu vm to a compute vm
|
||||
* The current pasid is managed by kfd and will be
|
||||
* released on kfd process destroy. Set amdgpu pasid
|
||||
* to 0 to avoid duplicate release.
|
||||
*/
|
||||
amdgpu_vm_release_compute(adev, avm);
|
||||
}
|
||||
|
||||
@@ -1288,7 +1287,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
struct ttm_validate_buffer *bo_list_entry;
|
||||
unsigned int mapped_to_gpu_memory;
|
||||
int ret;
|
||||
bool is_imported = 0;
|
||||
bool is_imported = false;
|
||||
|
||||
mutex_lock(&mem->lock);
|
||||
mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
|
||||
@@ -1479,7 +1478,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
}
|
||||
}
|
||||
|
||||
if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->pin_count)
|
||||
if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->tbo.pin_count)
|
||||
amdgpu_bo_fence(bo,
|
||||
&avm->process_info->eviction_fence->base,
|
||||
true);
|
||||
@@ -1558,7 +1557,8 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
* required.
|
||||
*/
|
||||
if (mem->mapped_to_gpu_memory == 0 &&
|
||||
!amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) && !mem->bo->pin_count)
|
||||
!amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) &&
|
||||
!mem->bo->tbo.pin_count)
|
||||
amdgpu_amdkfd_remove_eviction_fence(mem->bo,
|
||||
process_info->eviction_fence);
|
||||
|
||||
@@ -1694,7 +1694,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
||||
|
||||
INIT_LIST_HEAD(&(*mem)->bo_va_list);
|
||||
mutex_init(&(*mem)->lock);
|
||||
|
||||
|
||||
(*mem)->alloc_flags =
|
||||
((bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_VRAM : KFD_IOC_ALLOC_MEM_FLAGS_GTT)
|
||||
@@ -2043,6 +2043,8 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
|
||||
int ret = 0, i;
|
||||
struct list_head duplicate_save;
|
||||
struct amdgpu_sync sync_obj;
|
||||
unsigned long failed_size = 0;
|
||||
unsigned long total_size = 0;
|
||||
|
||||
INIT_LIST_HEAD(&duplicate_save);
|
||||
INIT_LIST_HEAD(&ctx.list);
|
||||
@@ -2099,10 +2101,18 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
|
||||
uint32_t domain = mem->domain;
|
||||
struct kfd_bo_va_list *bo_va_entry;
|
||||
|
||||
total_size += amdgpu_bo_size(bo);
|
||||
|
||||
ret = amdgpu_amdkfd_bo_validate(bo, domain, false);
|
||||
if (ret) {
|
||||
pr_debug("Memory eviction: Validate BOs failed. Try again\n");
|
||||
goto validate_map_fail;
|
||||
pr_debug("Memory eviction: Validate BOs failed\n");
|
||||
failed_size += amdgpu_bo_size(bo);
|
||||
ret = amdgpu_amdkfd_bo_validate(bo,
|
||||
AMDGPU_GEM_DOMAIN_GTT, false);
|
||||
if (ret) {
|
||||
pr_debug("Memory eviction: Try again\n");
|
||||
goto validate_map_fail;
|
||||
}
|
||||
}
|
||||
ret = amdgpu_sync_fence(&sync_obj, bo->tbo.moving);
|
||||
if (ret) {
|
||||
@@ -2122,6 +2132,9 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
|
||||
}
|
||||
}
|
||||
|
||||
if (failed_size)
|
||||
pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
|
||||
|
||||
/* Update page directories */
|
||||
ret = process_update_pds(process_info, &sync_obj);
|
||||
if (ret) {
|
||||
|
||||
@@ -1401,7 +1401,7 @@ static ATOM_VOLTAGE_OBJECT_V3 *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOL
|
||||
{
|
||||
u32 size = le16_to_cpu(v3->sHeader.usStructureSize);
|
||||
u32 offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]);
|
||||
u8 *start = (u8*)v3;
|
||||
u8 *start = (u8 *)v3;
|
||||
|
||||
while (offset < size) {
|
||||
ATOM_VOLTAGE_OBJECT_V3 *vo = (ATOM_VOLTAGE_OBJECT_V3 *)(start + offset);
|
||||
|
||||
@@ -70,7 +70,7 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
|
||||
struct atom_context *ctx = adev->mode_info.atom_context;
|
||||
int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
vram_usagebyfirmware);
|
||||
struct vram_usagebyfirmware_v2_1 * firmware_usage;
|
||||
struct vram_usagebyfirmware_v2_1 *firmware_usage;
|
||||
uint32_t start_addr, size;
|
||||
uint16_t data_offset;
|
||||
int usage_bytes = 0;
|
||||
@@ -149,6 +149,10 @@ static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,
|
||||
case LpDdr4MemType:
|
||||
vram_type = AMDGPU_VRAM_TYPE_DDR4;
|
||||
break;
|
||||
case Ddr5MemType:
|
||||
case LpDdr5MemType:
|
||||
vram_type = AMDGPU_VRAM_TYPE_DDR5;
|
||||
break;
|
||||
default:
|
||||
vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
|
||||
break;
|
||||
@@ -544,6 +548,7 @@ int amdgpu_mem_train_support(struct amdgpu_device *adev)
|
||||
case HW_REV(11, 0, 5):
|
||||
case HW_REV(11, 0, 7):
|
||||
case HW_REV(11, 0, 11):
|
||||
case HW_REV(11, 0, 12):
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -352,17 +352,10 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
|
||||
break;
|
||||
case CHIP_POLARIS11:
|
||||
if (type == CGS_UCODE_ID_SMU) {
|
||||
if (((adev->pdev->device == 0x67ef) &&
|
||||
((adev->pdev->revision == 0xe0) ||
|
||||
(adev->pdev->revision == 0xe5))) ||
|
||||
((adev->pdev->device == 0x67ff) &&
|
||||
((adev->pdev->revision == 0xcf) ||
|
||||
(adev->pdev->revision == 0xef) ||
|
||||
(adev->pdev->revision == 0xff)))) {
|
||||
if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) {
|
||||
info->is_kicker = true;
|
||||
strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
|
||||
} else if ((adev->pdev->device == 0x67ef) &&
|
||||
(adev->pdev->revision == 0xe2)) {
|
||||
} else if (ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
|
||||
info->is_kicker = true;
|
||||
strcpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
|
||||
} else {
|
||||
@@ -374,21 +367,10 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
|
||||
break;
|
||||
case CHIP_POLARIS10:
|
||||
if (type == CGS_UCODE_ID_SMU) {
|
||||
if (((adev->pdev->device == 0x67df) &&
|
||||
((adev->pdev->revision == 0xe0) ||
|
||||
(adev->pdev->revision == 0xe3) ||
|
||||
(adev->pdev->revision == 0xe4) ||
|
||||
(adev->pdev->revision == 0xe5) ||
|
||||
(adev->pdev->revision == 0xe7) ||
|
||||
(adev->pdev->revision == 0xef))) ||
|
||||
((adev->pdev->device == 0x6fdf) &&
|
||||
((adev->pdev->revision == 0xef) ||
|
||||
(adev->pdev->revision == 0xff)))) {
|
||||
if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) {
|
||||
info->is_kicker = true;
|
||||
strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
|
||||
} else if ((adev->pdev->device == 0x67df) &&
|
||||
((adev->pdev->revision == 0xe1) ||
|
||||
(adev->pdev->revision == 0xf7))) {
|
||||
} else if (ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
|
||||
info->is_kicker = true;
|
||||
strcpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
|
||||
} else {
|
||||
@@ -399,13 +381,7 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
|
||||
}
|
||||
break;
|
||||
case CHIP_POLARIS12:
|
||||
if (((adev->pdev->device == 0x6987) &&
|
||||
((adev->pdev->revision == 0xc0) ||
|
||||
(adev->pdev->revision == 0xc3))) ||
|
||||
((adev->pdev->device == 0x6981) &&
|
||||
((adev->pdev->revision == 0x00) ||
|
||||
(adev->pdev->revision == 0x01) ||
|
||||
(adev->pdev->revision == 0x10)))) {
|
||||
if (ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) {
|
||||
info->is_kicker = true;
|
||||
strcpy(fw_name, "amdgpu/polaris12_k_smc.bin");
|
||||
} else {
|
||||
|
||||
@@ -326,7 +326,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev,
|
||||
increment_us = time_us - adev->mm_stats.last_update_us;
|
||||
adev->mm_stats.last_update_us = time_us;
|
||||
adev->mm_stats.accum_us = min(adev->mm_stats.accum_us + increment_us,
|
||||
us_upper_bound);
|
||||
us_upper_bound);
|
||||
|
||||
/* This prevents the short period of low performance when the VRAM
|
||||
* usage is low and the driver is in debt or doesn't have enough
|
||||
@@ -404,13 +404,12 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = true,
|
||||
.no_wait_gpu = false,
|
||||
.resv = bo->tbo.base.resv,
|
||||
.flags = 0
|
||||
.resv = bo->tbo.base.resv
|
||||
};
|
||||
uint32_t domain;
|
||||
int r;
|
||||
|
||||
if (bo->pin_count)
|
||||
if (bo->tbo.pin_count)
|
||||
return 0;
|
||||
|
||||
/* Don't move this buffer if we have depleted our allowance
|
||||
@@ -677,6 +676,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
|
||||
* cs_parser_fini() - clean parser states
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @error: error number
|
||||
* @backoff: indicator to backoff the reservation
|
||||
*
|
||||
* If error is set than unvalidate buffer, otherwise just free memory
|
||||
* used by parsing context.
|
||||
@@ -1461,7 +1461,7 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
|
||||
dma_fence_put(fence);
|
||||
if (r)
|
||||
return r;
|
||||
r = drm_syncobj_get_fd(syncobj, (int*)&info->out.handle);
|
||||
r = drm_syncobj_get_fd(syncobj, (int *)&info->out.handle);
|
||||
drm_syncobj_put(syncobj);
|
||||
return r;
|
||||
|
||||
@@ -1645,6 +1645,7 @@ err_free_fences:
|
||||
* @parser: command submission parser context
|
||||
* @addr: VM address
|
||||
* @bo: resulting BO of the mapping found
|
||||
* @map: Placeholder to return found BO mapping
|
||||
*
|
||||
* Search the buffer objects in the command submission context for a certain
|
||||
* virtual memory address. Returns allocation structure when found, NULL
|
||||
|
||||
@@ -37,10 +37,9 @@ uint64_t amdgpu_csa_vaddr(struct amdgpu_device *adev)
|
||||
int amdgpu_allocate_static_csa(struct amdgpu_device *adev, struct amdgpu_bo **bo,
|
||||
u32 domain, uint32_t size)
|
||||
{
|
||||
int r;
|
||||
void *ptr;
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
|
||||
amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
|
||||
domain, bo,
|
||||
NULL, &ptr);
|
||||
if (!*bo)
|
||||
|
||||
@@ -100,7 +100,7 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
|
||||
enum drm_sched_priority priority;
|
||||
int r;
|
||||
|
||||
entity = kcalloc(1, offsetof(typeof(*entity), fences[amdgpu_sched_jobs]),
|
||||
entity = kzalloc(struct_size(entity, fences, amdgpu_sched_jobs),
|
||||
GFP_KERNEL);
|
||||
if (!entity)
|
||||
return -ENOMEM;
|
||||
@@ -450,7 +450,7 @@ int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
|
||||
|
||||
void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
|
||||
struct drm_sched_entity *entity,
|
||||
struct dma_fence *fence, uint64_t* handle)
|
||||
struct dma_fence *fence, uint64_t *handle)
|
||||
{
|
||||
struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
|
||||
uint64_t seq = centity->sequence;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "amdgpu_dm_debugfs.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_rap.h"
|
||||
#include "amdgpu_fw_attestation.h"
|
||||
|
||||
/**
|
||||
* amdgpu_debugfs_add_files - Add simple debugfs entries
|
||||
@@ -169,14 +170,14 @@ static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev)
|
||||
*
|
||||
* Bit 62: Indicates a GRBM bank switch is needed
|
||||
* Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is
|
||||
* zero)
|
||||
* zero)
|
||||
* Bits 24..33: The SE or ME selector if needed
|
||||
* Bits 34..43: The SH (or SA) or PIPE selector if needed
|
||||
* Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed
|
||||
*
|
||||
* Bit 23: Indicates that the PM power gating lock should be held
|
||||
* This is necessary to read registers that might be
|
||||
* unreliable during a power gating transistion.
|
||||
* This is necessary to read registers that might be
|
||||
* unreliable during a power gating transistion.
|
||||
*
|
||||
* The lower bits are the BYTE offset of the register to read. This
|
||||
* allows reading multiple registers in a single call and having
|
||||
@@ -299,7 +300,7 @@ end:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_debugfs_regs_read - Callback for reading MMIO registers
|
||||
*/
|
||||
static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
|
||||
@@ -308,7 +309,7 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
|
||||
return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_debugfs_regs_write - Callback for writing MMIO registers
|
||||
*/
|
||||
static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
|
||||
@@ -864,7 +865,7 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
|
||||
{
|
||||
struct amdgpu_device *adev = f->f_inode->i_private;
|
||||
int r, x;
|
||||
ssize_t result=0;
|
||||
ssize_t result = 0;
|
||||
uint32_t offset, se, sh, cu, wave, simd, data[32];
|
||||
|
||||
if (size & 3 || *pos & 3)
|
||||
@@ -1210,7 +1211,7 @@ static const char *debugfs_regs_names[] = {
|
||||
|
||||
/**
|
||||
* amdgpu_debugfs_regs_init - Initialize debugfs entries that provide
|
||||
* register access.
|
||||
* register access.
|
||||
*
|
||||
* @adev: The device to attach the debugfs entries to
|
||||
*/
|
||||
@@ -1319,6 +1320,7 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data)
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct ttm_resource_manager *man;
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(dev->dev);
|
||||
@@ -1327,7 +1329,9 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data)
|
||||
return r;
|
||||
}
|
||||
|
||||
seq_printf(m, "(%d)\n", ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_TT));
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
r = ttm_resource_manager_evict_all(&adev->mman.bdev, man);
|
||||
seq_printf(m, "(%d)\n", r);
|
||||
|
||||
pm_runtime_mark_last_busy(dev->dev);
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
@@ -1335,11 +1339,41 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_debugfs_vm_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_file *file;
|
||||
int r;
|
||||
|
||||
r = mutex_lock_interruptible(&dev->filelist_mutex);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
list_for_each_entry(file, &dev->filelist, lhead) {
|
||||
struct amdgpu_fpriv *fpriv = file->driver_priv;
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
|
||||
seq_printf(m, "pid:%d\tProcess:%s ----------\n",
|
||||
vm->task_info.pid, vm->task_info.process_name);
|
||||
r = amdgpu_bo_reserve(vm->root.base.bo, true);
|
||||
if (r)
|
||||
break;
|
||||
amdgpu_debugfs_vm_bo_info(vm, m);
|
||||
amdgpu_bo_unreserve(vm->root.base.bo);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->filelist_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct drm_info_list amdgpu_debugfs_list[] = {
|
||||
{"amdgpu_vbios", amdgpu_debugfs_get_vbios_dump},
|
||||
{"amdgpu_test_ib", &amdgpu_debugfs_test_ib},
|
||||
{"amdgpu_evict_vram", &amdgpu_debugfs_evict_vram},
|
||||
{"amdgpu_evict_gtt", &amdgpu_debugfs_evict_gtt},
|
||||
{"amdgpu_vm_info", &amdgpu_debugfs_vm_info},
|
||||
};
|
||||
|
||||
static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring,
|
||||
@@ -1635,6 +1669,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_rap_debugfs_init(adev);
|
||||
|
||||
amdgpu_fw_attestation_debugfs_init(adev);
|
||||
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list,
|
||||
ARRAY_SIZE(amdgpu_debugfs_list));
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vangogh_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/green_sardine_gpu_info.bin");
|
||||
|
||||
#define AMDGPU_RESUME_MS 2000
|
||||
@@ -115,6 +116,8 @@ const char *amdgpu_asic_name[] = {
|
||||
"NAVI12",
|
||||
"SIENNA_CICHLID",
|
||||
"NAVY_FLOUNDER",
|
||||
"VANGOGH",
|
||||
"DIMGREY_CAVEFISH",
|
||||
"LAST",
|
||||
};
|
||||
|
||||
@@ -582,6 +585,7 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v)
|
||||
* @adev: amdgpu_device pointer
|
||||
* @pcie_index: mmio register offset
|
||||
* @pcie_data: mmio register offset
|
||||
* @reg_addr: indirect register address to read from
|
||||
*
|
||||
* Returns the value of indirect register @reg_addr
|
||||
*/
|
||||
@@ -612,6 +616,7 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
|
||||
* @adev: amdgpu_device pointer
|
||||
* @pcie_index: mmio register offset
|
||||
* @pcie_data: mmio register offset
|
||||
* @reg_addr: indirect register address to read from
|
||||
*
|
||||
* Returns the value of indirect register @reg_addr
|
||||
*/
|
||||
@@ -1373,13 +1378,6 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_gmc_tmz_set(adev);
|
||||
|
||||
if (amdgpu_num_kcq == -1) {
|
||||
amdgpu_num_kcq = 8;
|
||||
} else if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) {
|
||||
amdgpu_num_kcq = 8;
|
||||
dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid parameter provided by user\n");
|
||||
}
|
||||
|
||||
amdgpu_gmc_noretry_set(adev);
|
||||
|
||||
return 0;
|
||||
@@ -1786,6 +1784,7 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
default:
|
||||
return 0;
|
||||
case CHIP_VEGA10:
|
||||
@@ -1820,6 +1819,9 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI12:
|
||||
chip_name = "navi12";
|
||||
break;
|
||||
case CHIP_VANGOGH:
|
||||
chip_name = "vangogh";
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
|
||||
@@ -1994,7 +1996,12 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
adev->family = AMDGPU_FAMILY_NV;
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
case CHIP_VANGOGH:
|
||||
if (adev->asic_type == CHIP_VANGOGH)
|
||||
adev->family = AMDGPU_FAMILY_VGH;
|
||||
else
|
||||
adev->family = AMDGPU_FAMILY_NV;
|
||||
|
||||
r = nv_set_ip_blocks(adev);
|
||||
if (r)
|
||||
@@ -2643,8 +2650,10 @@ static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
if (!amdgpu_acpi_is_s0ix_supported() || amdgpu_in_reset(adev)) {
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
}
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
@@ -2999,10 +3008,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_RENOIR:
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
case CHIP_VANGOGH:
|
||||
#endif
|
||||
return amdgpu_dc != 0;
|
||||
#endif
|
||||
@@ -3337,7 +3346,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
/* if we have > 1 VGA cards, then disable the amdgpu VGA resources */
|
||||
/* this will fail for cards that aren't VGA class devices, just
|
||||
* ignore it */
|
||||
vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
|
||||
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
|
||||
vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
|
||||
|
||||
if (amdgpu_device_supports_boco(ddev))
|
||||
boco = true;
|
||||
@@ -3596,7 +3606,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
vga_switcheroo_unregister_client(adev->pdev);
|
||||
if (amdgpu_device_supports_boco(adev_to_drm(adev)))
|
||||
vga_switcheroo_fini_domain_pm_ops(adev->dev);
|
||||
vga_client_register(adev->pdev, NULL, NULL, NULL);
|
||||
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
|
||||
vga_client_register(adev->pdev, NULL, NULL, NULL);
|
||||
if (adev->rio_mem)
|
||||
pci_iounmap(adev->pdev, adev->rio_mem);
|
||||
adev->rio_mem = NULL;
|
||||
@@ -3699,8 +3710,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
|
||||
amdgpu_fence_driver_suspend(adev);
|
||||
|
||||
r = amdgpu_device_ip_suspend_phase2(adev);
|
||||
|
||||
if (!amdgpu_acpi_is_s0ix_supported() || amdgpu_in_reset(adev))
|
||||
r = amdgpu_device_ip_suspend_phase2(adev);
|
||||
else
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry);
|
||||
/* evict remaining vram memory
|
||||
* This second call to evict vram is to evict the gart page table
|
||||
* using the CPU.
|
||||
@@ -3731,6 +3744,9 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
if (amdgpu_acpi_is_s0ix_supported())
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D0Entry);
|
||||
|
||||
/* post card */
|
||||
if (amdgpu_device_need_post(adev)) {
|
||||
r = amdgpu_device_asic_init(adev);
|
||||
|
||||
@@ -44,11 +44,11 @@ struct amdgpu_df_funcs {
|
||||
void (*enable_ecc_force_par_wr_rmw)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
int (*pmc_start)(struct amdgpu_device *adev, uint64_t config,
|
||||
int is_add);
|
||||
int counter_idx, int is_add);
|
||||
int (*pmc_stop)(struct amdgpu_device *adev, uint64_t config,
|
||||
int is_remove);
|
||||
int counter_idx, int is_remove);
|
||||
void (*pmc_get_count)(struct amdgpu_device *adev, uint64_t config,
|
||||
uint64_t *count);
|
||||
int counter_idx, uint64_t *count);
|
||||
uint64_t (*get_fica)(struct amdgpu_device *adev, uint32_t ficaa_val);
|
||||
void (*set_fica)(struct amdgpu_device *adev, uint32_t ficaa_val,
|
||||
uint32_t ficadl_val, uint32_t ficadh_val);
|
||||
|
||||
@@ -128,6 +128,7 @@ static int hw_id_map[MAX_HWIP] = {
|
||||
[NBIF_HWIP] = NBIF_HWID,
|
||||
[THM_HWIP] = THM_HWID,
|
||||
[CLK_HWIP] = CLKA_HWID,
|
||||
[UMC_HWIP] = UMC_HWID,
|
||||
};
|
||||
|
||||
static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
static void amdgpu_display_flip_callback(struct dma_fence *f,
|
||||
@@ -132,10 +133,7 @@ static void amdgpu_display_unpin_work_func(struct work_struct *__work)
|
||||
/* unpin of the old buffer */
|
||||
r = amdgpu_bo_reserve(work->old_abo, true);
|
||||
if (likely(r == 0)) {
|
||||
r = amdgpu_bo_unpin(work->old_abo);
|
||||
if (unlikely(r != 0)) {
|
||||
DRM_ERROR("failed to unpin buffer after flip\n");
|
||||
}
|
||||
amdgpu_bo_unpin(work->old_abo);
|
||||
amdgpu_bo_unreserve(work->old_abo);
|
||||
} else
|
||||
DRM_ERROR("failed to reserve buffer after flip\n");
|
||||
@@ -249,8 +247,7 @@ pflip_cleanup:
|
||||
}
|
||||
unpin:
|
||||
if (!adev->enable_virtual_display)
|
||||
if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
|
||||
DRM_ERROR("failed to unpin new abo in error path\n");
|
||||
amdgpu_bo_unpin(new_abo);
|
||||
|
||||
unreserve:
|
||||
amdgpu_bo_unreserve(new_abo);
|
||||
@@ -444,10 +441,6 @@ void amdgpu_display_print_display_setup(struct drm_device *dev)
|
||||
drm_connector_list_iter_end(&iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_display_ddc_probe
|
||||
*
|
||||
*/
|
||||
bool amdgpu_display_ddc_probe(struct amdgpu_connector *amdgpu_connector,
|
||||
bool use_aux)
|
||||
{
|
||||
@@ -512,7 +505,7 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
|
||||
* to avoid hang caused by placement of scanout BO in GTT on certain
|
||||
* APUs. So force the BO placement to VRAM in case this architecture
|
||||
* will not allow USWC mappings.
|
||||
* Also, don't allow GTT domain if the BO doens't have USWC falg set.
|
||||
* Also, don't allow GTT domain if the BO doesn't have USWC flag set.
|
||||
*/
|
||||
if ((bo_flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) &&
|
||||
amdgpu_bo_support_uswc(bo_flags) &&
|
||||
@@ -528,6 +521,11 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
|
||||
(adev->apu_flags & AMD_APU_IS_PICASSO))
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
case CHIP_RENOIR:
|
||||
case CHIP_VANGOGH:
|
||||
domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -537,20 +535,390 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
|
||||
return domain;
|
||||
}
|
||||
|
||||
static const struct drm_format_info dcc_formats[] = {
|
||||
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
|
||||
.cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 2,
|
||||
.cpp = { 2, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
};
|
||||
|
||||
static const struct drm_format_info dcc_retile_formats[] = {
|
||||
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
{ .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 3,
|
||||
.cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
|
||||
.has_alpha = true, },
|
||||
{ .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 3,
|
||||
.cpp = { 2, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
|
||||
};
|
||||
|
||||
static const struct drm_format_info *
|
||||
lookup_format_info(const struct drm_format_info formats[],
|
||||
int num_formats, u32 format)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_formats; i++) {
|
||||
if (formats[i].format == format)
|
||||
return &formats[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct drm_format_info *
|
||||
amdgpu_lookup_format_info(u32 format, uint64_t modifier)
|
||||
{
|
||||
if (!IS_AMD_FMT_MOD(modifier))
|
||||
return NULL;
|
||||
|
||||
if (AMD_FMT_MOD_GET(DCC_RETILE, modifier))
|
||||
return lookup_format_info(dcc_retile_formats,
|
||||
ARRAY_SIZE(dcc_retile_formats),
|
||||
format);
|
||||
|
||||
if (AMD_FMT_MOD_GET(DCC, modifier))
|
||||
return lookup_format_info(dcc_formats, ARRAY_SIZE(dcc_formats),
|
||||
format);
|
||||
|
||||
/* returning NULL will cause the default format structs to be used. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tries to extract the renderable DCC offset from the opaque metadata attached
|
||||
* to the buffer.
|
||||
*/
|
||||
static int
|
||||
extract_render_dcc_offset(struct amdgpu_device *adev,
|
||||
struct drm_gem_object *obj,
|
||||
uint64_t *offset)
|
||||
{
|
||||
struct amdgpu_bo *rbo;
|
||||
int r = 0;
|
||||
uint32_t metadata[10]; /* Something that fits a descriptor + header. */
|
||||
uint32_t size;
|
||||
|
||||
rbo = gem_to_amdgpu_bo(obj);
|
||||
r = amdgpu_bo_reserve(rbo, false);
|
||||
|
||||
if (unlikely(r)) {
|
||||
/* Don't show error message when returning -ERESTARTSYS */
|
||||
if (r != -ERESTARTSYS)
|
||||
DRM_ERROR("Unable to reserve buffer: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_get_metadata(rbo, metadata, sizeof(metadata), &size, NULL);
|
||||
amdgpu_bo_unreserve(rbo);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* The first word is the metadata version, and we need space for at least
|
||||
* the version + pci vendor+device id + 8 words for a descriptor.
|
||||
*/
|
||||
if (size < 40 || metadata[0] != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (adev->family >= AMDGPU_FAMILY_NV) {
|
||||
/* resource word 6/7 META_DATA_ADDRESS{_LO} */
|
||||
*offset = ((u64)metadata[9] << 16u) |
|
||||
((metadata[8] & 0xFF000000u) >> 16);
|
||||
} else {
|
||||
/* resource word 5/7 META_DATA_ADDRESS */
|
||||
*offset = ((u64)metadata[9] << 8u) |
|
||||
((u64)(metadata[7] & 0x1FE0000u) << 23);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(afb->base.dev);
|
||||
uint64_t modifier = 0;
|
||||
|
||||
if (!afb->tiling_flags || !AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE)) {
|
||||
modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
} else {
|
||||
int swizzle = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE);
|
||||
bool has_xor = swizzle >= 16;
|
||||
int block_size_bits;
|
||||
int version;
|
||||
int pipe_xor_bits = 0;
|
||||
int bank_xor_bits = 0;
|
||||
int packers = 0;
|
||||
int rb = 0;
|
||||
int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
|
||||
uint32_t dcc_offset = AMDGPU_TILING_GET(afb->tiling_flags, DCC_OFFSET_256B);
|
||||
|
||||
switch (swizzle >> 2) {
|
||||
case 0: /* 256B */
|
||||
block_size_bits = 8;
|
||||
break;
|
||||
case 1: /* 4KiB */
|
||||
case 5: /* 4KiB _X */
|
||||
block_size_bits = 12;
|
||||
break;
|
||||
case 2: /* 64KiB */
|
||||
case 4: /* 64 KiB _T */
|
||||
case 6: /* 64 KiB _X */
|
||||
block_size_bits = 16;
|
||||
break;
|
||||
default:
|
||||
/* RESERVED or VAR */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (adev->asic_type >= CHIP_SIENNA_CICHLID)
|
||||
version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS;
|
||||
else if (adev->family == AMDGPU_FAMILY_NV)
|
||||
version = AMD_FMT_MOD_TILE_VER_GFX10;
|
||||
else
|
||||
version = AMD_FMT_MOD_TILE_VER_GFX9;
|
||||
|
||||
switch (swizzle & 3) {
|
||||
case 0: /* Z microtiling */
|
||||
return -EINVAL;
|
||||
case 1: /* S microtiling */
|
||||
if (!has_xor)
|
||||
version = AMD_FMT_MOD_TILE_VER_GFX9;
|
||||
break;
|
||||
case 2:
|
||||
if (!has_xor && afb->base.format->cpp[0] != 4)
|
||||
version = AMD_FMT_MOD_TILE_VER_GFX9;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_xor) {
|
||||
switch (version) {
|
||||
case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS:
|
||||
pipe_xor_bits = min(block_size_bits - 8, pipes);
|
||||
packers = min(block_size_bits - 8 - pipe_xor_bits,
|
||||
ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs));
|
||||
break;
|
||||
case AMD_FMT_MOD_TILE_VER_GFX10:
|
||||
pipe_xor_bits = min(block_size_bits - 8, pipes);
|
||||
break;
|
||||
case AMD_FMT_MOD_TILE_VER_GFX9:
|
||||
rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
|
||||
ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
|
||||
pipe_xor_bits = min(block_size_bits - 8, pipes +
|
||||
ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
|
||||
bank_xor_bits = min(block_size_bits - 8 - pipe_xor_bits,
|
||||
ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
modifier = AMD_FMT_MOD |
|
||||
AMD_FMT_MOD_SET(TILE, AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE)) |
|
||||
AMD_FMT_MOD_SET(TILE_VERSION, version) |
|
||||
AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
|
||||
AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
|
||||
AMD_FMT_MOD_SET(PACKERS, packers);
|
||||
|
||||
if (dcc_offset != 0) {
|
||||
bool dcc_i64b = AMDGPU_TILING_GET(afb->tiling_flags, DCC_INDEPENDENT_64B) != 0;
|
||||
bool dcc_i128b = version >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS;
|
||||
const struct drm_format_info *format_info;
|
||||
u64 render_dcc_offset;
|
||||
|
||||
/* Enable constant encode on RAVEN2 and later. */
|
||||
bool dcc_constant_encode = adev->asic_type > CHIP_RAVEN ||
|
||||
(adev->asic_type == CHIP_RAVEN &&
|
||||
adev->external_rev_id >= 0x81);
|
||||
|
||||
int max_cblock_size = dcc_i64b ? AMD_FMT_MOD_DCC_BLOCK_64B :
|
||||
dcc_i128b ? AMD_FMT_MOD_DCC_BLOCK_128B :
|
||||
AMD_FMT_MOD_DCC_BLOCK_256B;
|
||||
|
||||
modifier |= AMD_FMT_MOD_SET(DCC, 1) |
|
||||
AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, dcc_constant_encode) |
|
||||
AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, dcc_i64b) |
|
||||
AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, dcc_i128b) |
|
||||
AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_cblock_size);
|
||||
|
||||
afb->base.offsets[1] = dcc_offset * 256 + afb->base.offsets[0];
|
||||
afb->base.pitches[1] =
|
||||
AMDGPU_TILING_GET(afb->tiling_flags, DCC_PITCH_MAX) + 1;
|
||||
|
||||
/*
|
||||
* If the userspace driver uses retiling the tiling flags do not contain
|
||||
* info on the renderable DCC buffer. Luckily the opaque metadata contains
|
||||
* the info so we can try to extract it. The kernel does not use this info
|
||||
* but we should convert it to a modifier plane for getfb2, so the
|
||||
* userspace driver that gets it doesn't have to juggle around another DCC
|
||||
* plane internally.
|
||||
*/
|
||||
if (extract_render_dcc_offset(adev, afb->base.obj[0],
|
||||
&render_dcc_offset) == 0 &&
|
||||
render_dcc_offset != 0 &&
|
||||
render_dcc_offset != afb->base.offsets[1] &&
|
||||
render_dcc_offset < UINT_MAX) {
|
||||
uint32_t dcc_block_bits; /* of base surface data */
|
||||
|
||||
modifier |= AMD_FMT_MOD_SET(DCC_RETILE, 1);
|
||||
afb->base.offsets[2] = render_dcc_offset;
|
||||
|
||||
if (adev->family >= AMDGPU_FAMILY_NV) {
|
||||
int extra_pipe = 0;
|
||||
|
||||
if (adev->asic_type >= CHIP_SIENNA_CICHLID &&
|
||||
pipes == packers && pipes > 1)
|
||||
extra_pipe = 1;
|
||||
|
||||
dcc_block_bits = max(20, 16 + pipes + extra_pipe);
|
||||
} else {
|
||||
modifier |= AMD_FMT_MOD_SET(RB, rb) |
|
||||
AMD_FMT_MOD_SET(PIPE, pipes);
|
||||
dcc_block_bits = max(20, 18 + rb);
|
||||
}
|
||||
|
||||
dcc_block_bits -= ilog2(afb->base.format->cpp[0]);
|
||||
afb->base.pitches[2] = ALIGN(afb->base.width,
|
||||
1u << ((dcc_block_bits + 1) / 2));
|
||||
}
|
||||
format_info = amdgpu_lookup_format_info(afb->base.format->format,
|
||||
modifier);
|
||||
if (!format_info)
|
||||
return -EINVAL;
|
||||
|
||||
afb->base.format = format_info;
|
||||
}
|
||||
}
|
||||
|
||||
afb->base.modifier = modifier;
|
||||
afb->base.flags |= DRM_MODE_FB_MODIFIERS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
|
||||
uint64_t *tiling_flags, bool *tmz_surface)
|
||||
{
|
||||
struct amdgpu_bo *rbo;
|
||||
int r;
|
||||
|
||||
if (!amdgpu_fb) {
|
||||
*tiling_flags = 0;
|
||||
*tmz_surface = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]);
|
||||
r = amdgpu_bo_reserve(rbo, false);
|
||||
|
||||
if (unlikely(r)) {
|
||||
/* Don't show error message when returning -ERESTARTSYS */
|
||||
if (r != -ERESTARTSYS)
|
||||
DRM_ERROR("Unable to reserve buffer: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (tiling_flags)
|
||||
amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
|
||||
|
||||
if (tmz_surface)
|
||||
*tmz_surface = amdgpu_bo_encrypted(rbo);
|
||||
|
||||
amdgpu_bo_unreserve(rbo);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_display_framebuffer_init(struct drm_device *dev,
|
||||
struct amdgpu_framebuffer *rfb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
int ret, i;
|
||||
rfb->base.obj[0] = obj;
|
||||
drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd);
|
||||
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
|
||||
if (ret) {
|
||||
rfb->base.obj[0] = NULL;
|
||||
return ret;
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* This needs to happen before modifier conversion as that might change
|
||||
* the number of planes.
|
||||
*/
|
||||
for (i = 1; i < rfb->base.format->num_planes; ++i) {
|
||||
if (mode_cmd->handles[i] != mode_cmd->handles[0]) {
|
||||
drm_dbg_kms(dev, "Plane 0 and %d have different BOs: %u vs. %u\n",
|
||||
i, mode_cmd->handles[0], mode_cmd->handles[i]);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ret = amdgpu_display_get_fb_info(rfb, &rfb->tiling_flags, &rfb->tmz_surface);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (dev->mode_config.allow_fb_modifiers &&
|
||||
!(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) {
|
||||
ret = convert_tiling_flags_to_modifier(rfb);
|
||||
if (ret) {
|
||||
drm_dbg_kms(dev, "Failed to convert tiling flags 0x%llX to a modifier",
|
||||
rfb->tiling_flags);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < rfb->base.format->num_planes; ++i) {
|
||||
rfb->base.obj[i] = rfb->base.obj[0];
|
||||
drm_gem_object_get(rfb->base.obj[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
rfb->base.obj[0] = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_framebuffer *
|
||||
@@ -564,14 +932,14 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
||||
|
||||
obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
|
||||
if (obj == NULL) {
|
||||
dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
|
||||
"can't create framebuffer\n", mode_cmd->handles[0]);
|
||||
drm_dbg_kms(dev, "No GEM object associated to handle 0x%08X, "
|
||||
"can't create framebuffer\n", mode_cmd->handles[0]);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */
|
||||
if (obj->import_attach) {
|
||||
DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n");
|
||||
drm_dbg_kms(dev, "Cannot create framebuffer from imported dma_buf\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,5 +44,7 @@ struct drm_framebuffer *
|
||||
amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
const struct drm_format_info *
|
||||
amdgpu_lookup_format_info(u32 format, uint64_t modifier);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,42 +41,6 @@
|
||||
#include <linux/dma-fence-array.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
|
||||
/**
|
||||
* amdgpu_gem_prime_vmap - &dma_buf_ops.vmap implementation
|
||||
* @obj: GEM BO
|
||||
*
|
||||
* Sets up an in-kernel virtual mapping of the BO's memory.
|
||||
*
|
||||
* Returns:
|
||||
* The virtual address of the mapping or an error pointer.
|
||||
*/
|
||||
void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj)
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages,
|
||||
&bo->dma_buf_vmap);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return bo->dma_buf_vmap.virtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gem_prime_vunmap - &dma_buf_ops.vunmap implementation
|
||||
* @obj: GEM BO
|
||||
* @vaddr: Virtual address (unused)
|
||||
*
|
||||
* Tears down the in-kernel virtual mapping of the BO's memory.
|
||||
*/
|
||||
void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
ttm_bo_kunmap(&bo->dma_buf_vmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
|
||||
* @obj: GEM BO
|
||||
@@ -281,7 +245,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt;
|
||||
long r;
|
||||
|
||||
if (!bo->pin_count) {
|
||||
if (!bo->tbo.pin_count) {
|
||||
/* move buffer into GTT or VRAM */
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
unsigned domains = AMDGPU_GEM_DOMAIN_GTT;
|
||||
@@ -390,7 +354,8 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
|
||||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
|
||||
if (!bo->pin_count && (bo->allowed_domains & AMDGPU_GEM_DOMAIN_GTT)) {
|
||||
if (!bo->tbo.pin_count &&
|
||||
(bo->allowed_domains & AMDGPU_GEM_DOMAIN_GTT)) {
|
||||
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf);
|
||||
bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo *bo);
|
||||
void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj);
|
||||
void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
|
||||
int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
|
||||
struct vm_area_struct *vma);
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_irq.h"
|
||||
#include "amdgpu_dma_buf.h"
|
||||
#include "amdgpu_sched.h"
|
||||
|
||||
#include "amdgpu_amdkfd.h"
|
||||
|
||||
@@ -94,16 +95,16 @@
|
||||
#define KMS_DRIVER_MINOR 40
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
|
||||
int amdgpu_vram_limit = 0;
|
||||
int amdgpu_vis_vram_limit = 0;
|
||||
int amdgpu_vram_limit;
|
||||
int amdgpu_vis_vram_limit;
|
||||
int amdgpu_gart_size = -1; /* auto */
|
||||
int amdgpu_gtt_size = -1; /* auto */
|
||||
int amdgpu_moverate = -1; /* auto */
|
||||
int amdgpu_benchmarking = 0;
|
||||
int amdgpu_testing = 0;
|
||||
int amdgpu_benchmarking;
|
||||
int amdgpu_testing;
|
||||
int amdgpu_audio = -1;
|
||||
int amdgpu_disp_priority = 0;
|
||||
int amdgpu_hw_i2c = 0;
|
||||
int amdgpu_disp_priority;
|
||||
int amdgpu_hw_i2c;
|
||||
int amdgpu_pcie_gen2 = -1;
|
||||
int amdgpu_msi = -1;
|
||||
char amdgpu_lockup_timeout[AMDGPU_MAX_TIMEOUT_PARAM_LENGTH];
|
||||
@@ -113,19 +114,19 @@ int amdgpu_aspm = -1;
|
||||
int amdgpu_runtime_pm = -1;
|
||||
uint amdgpu_ip_block_mask = 0xffffffff;
|
||||
int amdgpu_bapm = -1;
|
||||
int amdgpu_deep_color = 0;
|
||||
int amdgpu_deep_color;
|
||||
int amdgpu_vm_size = -1;
|
||||
int amdgpu_vm_fragment_size = -1;
|
||||
int amdgpu_vm_block_size = -1;
|
||||
int amdgpu_vm_fault_stop = 0;
|
||||
int amdgpu_vm_debug = 0;
|
||||
int amdgpu_vm_fault_stop;
|
||||
int amdgpu_vm_debug;
|
||||
int amdgpu_vm_update_mode = -1;
|
||||
int amdgpu_exp_hw_support = 0;
|
||||
int amdgpu_exp_hw_support;
|
||||
int amdgpu_dc = -1;
|
||||
int amdgpu_sched_jobs = 32;
|
||||
int amdgpu_sched_hw_submission = 2;
|
||||
uint amdgpu_pcie_gen_cap = 0;
|
||||
uint amdgpu_pcie_lane_cap = 0;
|
||||
uint amdgpu_pcie_gen_cap;
|
||||
uint amdgpu_pcie_lane_cap;
|
||||
uint amdgpu_cg_mask = 0xffffffff;
|
||||
uint amdgpu_pg_mask = 0xffffffff;
|
||||
uint amdgpu_sdma_phase_quantum = 32;
|
||||
@@ -133,23 +134,31 @@ char *amdgpu_disable_cu = NULL;
|
||||
char *amdgpu_virtual_display = NULL;
|
||||
/* OverDrive(bit 14) disabled by default*/
|
||||
uint amdgpu_pp_feature_mask = 0xffffbfff;
|
||||
uint amdgpu_force_long_training = 0;
|
||||
int amdgpu_job_hang_limit = 0;
|
||||
uint amdgpu_force_long_training;
|
||||
int amdgpu_job_hang_limit;
|
||||
int amdgpu_lbpw = -1;
|
||||
int amdgpu_compute_multipipe = -1;
|
||||
int amdgpu_gpu_recovery = -1; /* auto */
|
||||
int amdgpu_emu_mode = 0;
|
||||
uint amdgpu_smu_memory_pool_size = 0;
|
||||
/* FBC (bit 0) disabled by default*/
|
||||
uint amdgpu_dc_feature_mask = 0;
|
||||
uint amdgpu_dc_debug_mask = 0;
|
||||
int amdgpu_emu_mode;
|
||||
uint amdgpu_smu_memory_pool_size;
|
||||
/*
|
||||
* FBC (bit 0) disabled by default
|
||||
* MULTI_MON_PP_MCLK_SWITCH (bit 1) enabled by default
|
||||
* - With this, for multiple monitors in sync(e.g. with the same model),
|
||||
* mclk switching will be allowed. And the mclk will be not foced to the
|
||||
* highest. That helps saving some idle power.
|
||||
* DISABLE_FRACTIONAL_PWM (bit 2) disabled by default
|
||||
* PSR (bit 3) disabled by default
|
||||
*/
|
||||
uint amdgpu_dc_feature_mask = 2;
|
||||
uint amdgpu_dc_debug_mask;
|
||||
int amdgpu_async_gfx_ring = 1;
|
||||
int amdgpu_mcbp = 0;
|
||||
int amdgpu_mcbp;
|
||||
int amdgpu_discovery = -1;
|
||||
int amdgpu_mes = 0;
|
||||
int amdgpu_mes;
|
||||
int amdgpu_noretry = -1;
|
||||
int amdgpu_force_asic_type = -1;
|
||||
int amdgpu_tmz = 0;
|
||||
int amdgpu_tmz;
|
||||
int amdgpu_reset_method = -1; /* auto */
|
||||
int amdgpu_num_kcq = -1;
|
||||
|
||||
@@ -271,7 +280,7 @@ module_param_string(lockup_timeout, amdgpu_lockup_timeout, sizeof(amdgpu_lockup_
|
||||
/**
|
||||
* DOC: dpm (int)
|
||||
* Override for dynamic power management setting
|
||||
* (0 = disable, 1 = enable, 2 = enable sw smu driver for vega20)
|
||||
* (0 = disable, 1 = enable)
|
||||
* The default is -1 (auto).
|
||||
*/
|
||||
MODULE_PARM_DESC(dpm, "DPM support (1 = enable, 0 = disable, -1 = auto)");
|
||||
@@ -296,7 +305,7 @@ module_param_named(aspm, amdgpu_aspm, int, 0444);
|
||||
* Override for runtime power management control for dGPUs in PX/HG laptops. The amdgpu driver can dynamically power down
|
||||
* the dGPU on PX/HG laptops when it is idle. The default is -1 (auto enable). Setting the value to 0 disables this functionality.
|
||||
*/
|
||||
MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 = PX only default)");
|
||||
MODULE_PARM_DESC(runpm, "PX runtime pm (2 = force enable with BAMACO, 1 = force enable with BACO, 0 = disable, -1 = PX only default)");
|
||||
module_param_named(runpm, amdgpu_runtime_pm, int, 0444);
|
||||
|
||||
/**
|
||||
@@ -764,7 +773,7 @@ module_param_named(dcdebugmask, amdgpu_dc_debug_mask, uint, 0444);
|
||||
* Defaults to 0, or disabled. Userspace can still override this level later
|
||||
* after boot.
|
||||
*/
|
||||
uint amdgpu_dm_abm_level = 0;
|
||||
uint amdgpu_dm_abm_level;
|
||||
MODULE_PARM_DESC(abmlevel, "ABM level (0 = off (default), 1-4 = backlight reduction level) ");
|
||||
module_param_named(abmlevel, amdgpu_dm_abm_level, uint, 0444);
|
||||
|
||||
@@ -782,7 +791,7 @@ module_param_named(tmz, amdgpu_tmz, int, 0444);
|
||||
* DOC: reset_method (int)
|
||||
* GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)
|
||||
*/
|
||||
MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)");
|
||||
MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco/bamaco)");
|
||||
module_param_named(reset_method, amdgpu_reset_method, int, 0444);
|
||||
|
||||
/**
|
||||
@@ -1089,12 +1098,27 @@ static const struct pci_device_id pciidlist[] = {
|
||||
{0x1002, 0x73AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
|
||||
/* Van Gogh */
|
||||
{0x1002, 0x163F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VANGOGH|AMD_IS_APU},
|
||||
|
||||
/* Navy_Flounder */
|
||||
{0x1002, 0x73C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
|
||||
{0x1002, 0x73C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
|
||||
{0x1002, 0x73C3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
|
||||
{0x1002, 0x73DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVY_FLOUNDER},
|
||||
|
||||
/* DIMGREY_CAVEFISH */
|
||||
{0x1002, 0x73E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||
{0x1002, 0x73E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||
{0x1002, 0x73E2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||
{0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH},
|
||||
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pciidlist);
|
||||
|
||||
static struct drm_driver kms_driver;
|
||||
static const struct drm_driver amdgpu_kms_driver;
|
||||
|
||||
static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
@@ -1165,7 +1189,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
adev = devm_drm_dev_alloc(&pdev->dev, &kms_driver, typeof(*adev), ddev);
|
||||
adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);
|
||||
if (IS_ERR(adev))
|
||||
return PTR_ERR(adev);
|
||||
|
||||
@@ -1495,7 +1519,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
|
||||
|
||||
int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv)
|
||||
{
|
||||
struct drm_file *file;
|
||||
struct drm_file *file;
|
||||
|
||||
if (!filp)
|
||||
return -EINVAL;
|
||||
@@ -1509,7 +1533,29 @@ int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_driver kms_driver = {
|
||||
int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
|
||||
|
||||
const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_VM, amdgpu_vm_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_SCHED, amdgpu_sched_ioctl, DRM_MASTER),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_BO_LIST, amdgpu_bo_list_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_FENCE_TO_HANDLE, amdgpu_cs_fence_to_handle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
/* KMS */
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_MMAP, amdgpu_gem_mmap_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_WAIT_IDLE, amdgpu_gem_wait_idle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_FENCES, amdgpu_cs_wait_fences_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static const struct drm_driver amdgpu_kms_driver = {
|
||||
.driver_features =
|
||||
DRIVER_ATOMIC |
|
||||
DRIVER_GEM |
|
||||
@@ -1520,19 +1566,14 @@ static struct drm_driver kms_driver = {
|
||||
.lastclose = amdgpu_driver_lastclose_kms,
|
||||
.irq_handler = amdgpu_irq_handler,
|
||||
.ioctls = amdgpu_ioctls_kms,
|
||||
.gem_free_object_unlocked = amdgpu_gem_object_free,
|
||||
.gem_open_object = amdgpu_gem_object_open,
|
||||
.gem_close_object = amdgpu_gem_object_close,
|
||||
.num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms),
|
||||
.dumb_create = amdgpu_mode_dumb_create,
|
||||
.dumb_map_offset = amdgpu_mode_dumb_mmap,
|
||||
.fops = &amdgpu_driver_kms_fops,
|
||||
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_export = amdgpu_gem_prime_export,
|
||||
.gem_prime_import = amdgpu_gem_prime_import,
|
||||
.gem_prime_vmap = amdgpu_gem_prime_vmap,
|
||||
.gem_prime_vunmap = amdgpu_gem_prime_vunmap,
|
||||
.gem_prime_mmap = amdgpu_gem_prime_mmap,
|
||||
|
||||
.name = DRIVER_NAME,
|
||||
@@ -1578,7 +1619,6 @@ static int __init amdgpu_init(void)
|
||||
goto error_fence;
|
||||
|
||||
DRM_INFO("amdgpu kernel modesetting enabled.\n");
|
||||
kms_driver.num_ioctls = amdgpu_max_kms_ioctl;
|
||||
amdgpu_register_atpx_handler();
|
||||
|
||||
/* Ignore KFD init failures. Normal when CONFIG_HSA_AMD is not set. */
|
||||
|
||||
@@ -207,6 +207,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
int ret;
|
||||
unsigned long tmp;
|
||||
|
||||
memset(&mode_cmd, 0, sizeof(mode_cmd));
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
|
||||
*
|
||||
* @ring: ring the fence is associated with
|
||||
* @f: resulting fence object
|
||||
* @flags: flags to pass into the subordinate .emit_fence() call
|
||||
*
|
||||
* Emits a fence command on the requested ring (all asics).
|
||||
* Returns 0 on success, -ENOMEM on failure.
|
||||
@@ -187,6 +188,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
|
||||
*
|
||||
* @ring: ring the fence is associated with
|
||||
* @s: resulting sequence number
|
||||
* @timeout: the timeout for waiting in usecs
|
||||
*
|
||||
* Emits a fence command on the requested ring (all asics).
|
||||
* Used For polling fence.
|
||||
@@ -294,7 +296,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
|
||||
/**
|
||||
* amdgpu_fence_fallback - fallback for hardware interrupts
|
||||
*
|
||||
* @work: delayed work item
|
||||
* @t: timer context used to obtain the pointer to ring structure
|
||||
*
|
||||
* Checks for fence activity.
|
||||
*/
|
||||
@@ -310,7 +312,6 @@ static void amdgpu_fence_fallback(struct timer_list *t)
|
||||
/**
|
||||
* amdgpu_fence_wait_empty - wait for all fences to signal
|
||||
*
|
||||
* @adev: amdgpu device pointer
|
||||
* @ring: ring index the fence is associated with
|
||||
*
|
||||
* Wait for all fences on the requested ring to signal (all asics).
|
||||
@@ -639,7 +640,7 @@ static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f)
|
||||
|
||||
/**
|
||||
* amdgpu_fence_enable_signaling - enable signalling on fence
|
||||
* @fence: fence
|
||||
* @f: fence
|
||||
*
|
||||
* This function is called with fence_queue lock held, and adds a callback
|
||||
* to fence_queue that checks if this fence is signaled, and if so it
|
||||
@@ -675,7 +676,7 @@ static void amdgpu_fence_free(struct rcu_head *rcu)
|
||||
/**
|
||||
* amdgpu_fence_release - callback that fence can be freed
|
||||
*
|
||||
* @fence: fence
|
||||
* @f: fence
|
||||
*
|
||||
* This function is called when the reference count becomes zero.
|
||||
* It just RCU schedules freeing up the fence.
|
||||
@@ -740,7 +741,7 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_debugfs_gpu_recover - manually trigger a gpu reset & recover
|
||||
*
|
||||
* Manually trigger a gpu reset at the next fence wait.
|
||||
|
||||
141
drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.c
Normal file
141
drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_fw_attestation.h"
|
||||
#include "amdgpu_psp.h"
|
||||
#include "amdgpu_ucode.h"
|
||||
#include "soc15_common.h"
|
||||
|
||||
#define FW_ATTESTATION_DB_COOKIE 0x143b6a37
|
||||
#define FW_ATTESTATION_RECORD_VALID 1
|
||||
#define FW_ATTESTATION_MAX_SIZE 4096
|
||||
|
||||
typedef struct FW_ATT_DB_HEADER
|
||||
{
|
||||
uint32_t AttDbVersion; /* version of the fwar feature */
|
||||
uint32_t AttDbCookie; /* cookie as an extra check for corrupt data */
|
||||
} FW_ATT_DB_HEADER;
|
||||
|
||||
typedef struct FW_ATT_RECORD
|
||||
{
|
||||
uint16_t AttFwIdV1; /* Legacy FW Type field */
|
||||
uint16_t AttFwIdV2; /* V2 FW ID field */
|
||||
uint32_t AttFWVersion; /* FW Version */
|
||||
uint16_t AttFWActiveFunctionID; /* The VF ID (only in VF Attestation Table) */
|
||||
uint16_t AttSource; /* FW source indicator */
|
||||
uint16_t RecordValid; /* Indicates whether the record is a valid entry */
|
||||
uint8_t AttFwTaId; /* Ta ID (only in TA Attestation Table) */
|
||||
uint8_t Reserved;
|
||||
} FW_ATT_RECORD;
|
||||
|
||||
static ssize_t amdgpu_fw_attestation_debugfs_read(struct file *f,
|
||||
char __user *buf,
|
||||
size_t size,
|
||||
loff_t *pos)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
|
||||
uint64_t records_addr = 0;
|
||||
uint64_t vram_pos = 0;
|
||||
FW_ATT_DB_HEADER fw_att_hdr = {0};
|
||||
FW_ATT_RECORD fw_att_record = {0};
|
||||
|
||||
if (size < sizeof(FW_ATT_RECORD)) {
|
||||
DRM_WARN("FW attestation input buffer not enough memory");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((*pos + sizeof(FW_ATT_DB_HEADER)) >= FW_ATTESTATION_MAX_SIZE) {
|
||||
DRM_WARN("FW attestation out of bounds");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (psp_get_fw_attestation_records_addr(&adev->psp, &records_addr)) {
|
||||
DRM_WARN("Failed to get FW attestation record address");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vram_pos = records_addr - adev->gmc.vram_start;
|
||||
|
||||
if (*pos == 0) {
|
||||
amdgpu_device_vram_access(adev,
|
||||
vram_pos,
|
||||
(uint32_t*)&fw_att_hdr,
|
||||
sizeof(FW_ATT_DB_HEADER),
|
||||
false);
|
||||
|
||||
if (fw_att_hdr.AttDbCookie != FW_ATTESTATION_DB_COOKIE) {
|
||||
DRM_WARN("Invalid FW attestation cookie");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_INFO("FW attestation version = 0x%X", fw_att_hdr.AttDbVersion);
|
||||
}
|
||||
|
||||
amdgpu_device_vram_access(adev,
|
||||
vram_pos + sizeof(FW_ATT_DB_HEADER) + *pos,
|
||||
(uint32_t*)&fw_att_record,
|
||||
sizeof(FW_ATT_RECORD),
|
||||
false);
|
||||
|
||||
if (fw_att_record.RecordValid != FW_ATTESTATION_RECORD_VALID)
|
||||
return 0;
|
||||
|
||||
if (copy_to_user(buf, (void*)&fw_att_record, sizeof(FW_ATT_RECORD)))
|
||||
return -EINVAL;
|
||||
|
||||
*pos += sizeof(FW_ATT_RECORD);
|
||||
|
||||
return sizeof(FW_ATT_RECORD);
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_fw_attestation_debugfs_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = amdgpu_fw_attestation_debugfs_read,
|
||||
.write = NULL,
|
||||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
static int amdgpu_is_fw_attestation_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->asic_type >= CHIP_SIENNA_CICHLID)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!amdgpu_is_fw_attestation_supported(adev))
|
||||
return;
|
||||
|
||||
debugfs_create_file("amdgpu_fw_attestation",
|
||||
S_IRUSR,
|
||||
adev_to_drm(adev)->primary->debugfs_root,
|
||||
adev,
|
||||
&amdgpu_fw_attestation_debugfs_ops);
|
||||
}
|
||||
30
drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.h
Normal file
30
drivers/gpu/drm/amd/amdgpu/amdgpu_fw_attestation.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef _AMDGPU_FW_ATTESTATION_H
|
||||
#define _AMDGPU_FW_ATTESTATION_H
|
||||
|
||||
#include "amdgpu.h"
|
||||
|
||||
void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev);
|
||||
#endif
|
||||
@@ -75,9 +75,9 @@ static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
|
||||
|
||||
if (adev->dummy_page_addr)
|
||||
return 0;
|
||||
adev->dummy_page_addr = pci_map_page(adev->pdev, dummy_page, 0,
|
||||
adev->dummy_page_addr = dma_map_page(&adev->pdev->dev, dummy_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(adev->pdev, adev->dummy_page_addr)) {
|
||||
if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) {
|
||||
dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n");
|
||||
adev->dummy_page_addr = 0;
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -33,12 +33,16 @@
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_gem_ttm_helper.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_display.h"
|
||||
#include "amdgpu_dma_buf.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
|
||||
void amdgpu_gem_object_free(struct drm_gem_object *gobj)
|
||||
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs;
|
||||
|
||||
static void amdgpu_gem_object_free(struct drm_gem_object *gobj)
|
||||
{
|
||||
struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj);
|
||||
|
||||
@@ -73,6 +77,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
|
||||
return r;
|
||||
|
||||
*obj = &bo->tbo.base;
|
||||
(*obj)->funcs = &amdgpu_gem_object_funcs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -105,8 +110,8 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
|
||||
* Call from drm_gem_handle_create which appear in both new and open ioctl
|
||||
* case.
|
||||
*/
|
||||
int amdgpu_gem_object_open(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv)
|
||||
static int amdgpu_gem_object_open(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct amdgpu_bo *abo = gem_to_amdgpu_bo(obj);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
|
||||
@@ -138,8 +143,8 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv)
|
||||
static void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
@@ -197,6 +202,15 @@ out_unlock:
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
}
|
||||
|
||||
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = {
|
||||
.free = amdgpu_gem_object_free,
|
||||
.open = amdgpu_gem_object_open,
|
||||
.close = amdgpu_gem_object_close,
|
||||
.export = amdgpu_gem_prime_export,
|
||||
.vmap = drm_gem_ttm_vmap,
|
||||
.vunmap = drm_gem_ttm_vunmap,
|
||||
};
|
||||
|
||||
/*
|
||||
* GEM ioctls.
|
||||
*/
|
||||
@@ -841,67 +855,6 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
#define amdgpu_debugfs_gem_bo_print_flag(m, bo, flag) \
|
||||
if (bo->flags & (AMDGPU_GEM_CREATE_ ## flag)) { \
|
||||
seq_printf((m), " " #flag); \
|
||||
}
|
||||
|
||||
static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data)
|
||||
{
|
||||
struct drm_gem_object *gobj = ptr;
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
|
||||
struct seq_file *m = data;
|
||||
|
||||
struct dma_buf_attachment *attachment;
|
||||
struct dma_buf *dma_buf;
|
||||
unsigned domain;
|
||||
const char *placement;
|
||||
unsigned pin_count;
|
||||
|
||||
domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
|
||||
switch (domain) {
|
||||
case AMDGPU_GEM_DOMAIN_VRAM:
|
||||
placement = "VRAM";
|
||||
break;
|
||||
case AMDGPU_GEM_DOMAIN_GTT:
|
||||
placement = " GTT";
|
||||
break;
|
||||
case AMDGPU_GEM_DOMAIN_CPU:
|
||||
default:
|
||||
placement = " CPU";
|
||||
break;
|
||||
}
|
||||
seq_printf(m, "\t0x%08x: %12ld byte %s",
|
||||
id, amdgpu_bo_size(bo), placement);
|
||||
|
||||
pin_count = READ_ONCE(bo->pin_count);
|
||||
if (pin_count)
|
||||
seq_printf(m, " pin count %d", pin_count);
|
||||
|
||||
dma_buf = READ_ONCE(bo->tbo.base.dma_buf);
|
||||
attachment = READ_ONCE(bo->tbo.base.import_attach);
|
||||
|
||||
if (attachment)
|
||||
seq_printf(m, " imported from %p%s", dma_buf,
|
||||
attachment->peer2peer ? " P2P" : "");
|
||||
else if (dma_buf)
|
||||
seq_printf(m, " exported as %p", dma_buf);
|
||||
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, CPU_ACCESS_REQUIRED);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, NO_CPU_ACCESS);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, CPU_GTT_USWC);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, VRAM_CLEARED);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, SHADOW);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, VRAM_CONTIGUOUS);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, VM_ALWAYS_VALID);
|
||||
amdgpu_debugfs_gem_bo_print_flag(m, bo, EXPLICIT_SYNC);
|
||||
|
||||
seq_printf(m, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
@@ -915,6 +868,8 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
|
||||
|
||||
list_for_each_entry(file, &dev->filelist, lhead) {
|
||||
struct task_struct *task;
|
||||
struct drm_gem_object *gobj;
|
||||
int id;
|
||||
|
||||
/*
|
||||
* Although we have a valid reference on file->pid, that does
|
||||
@@ -929,7 +884,11 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
|
||||
rcu_read_unlock();
|
||||
|
||||
spin_lock(&file->table_lock);
|
||||
idr_for_each(&file->object_idr, amdgpu_debugfs_gem_bo_info, m);
|
||||
idr_for_each_entry(&file->object_idr, gobj, id) {
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
|
||||
|
||||
amdgpu_bo_print_info(id, bo, m);
|
||||
}
|
||||
spin_unlock(&file->table_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,6 @@
|
||||
#define AMDGPU_GEM_DOMAIN_MAX 0x3
|
||||
#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, tbo.base)
|
||||
|
||||
void amdgpu_gem_object_free(struct drm_gem_object *obj);
|
||||
int amdgpu_gem_object_open(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv);
|
||||
void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
||||
struct drm_file *file_priv);
|
||||
unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
|
||||
|
||||
/*
|
||||
|
||||
@@ -193,10 +193,14 @@ static bool amdgpu_gfx_is_multipipe_capable(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
bool amdgpu_gfx_is_high_priority_compute_queue(struct amdgpu_device *adev,
|
||||
int queue)
|
||||
int pipe, int queue)
|
||||
{
|
||||
/* Policy: make queue 0 of each pipe as high priority compute queue */
|
||||
return (queue == 0);
|
||||
bool multipipe_policy = amdgpu_gfx_is_multipipe_capable(adev);
|
||||
int cond;
|
||||
/* Policy: alternate between normal and high priority */
|
||||
cond = multipipe_policy ? pipe : queue;
|
||||
|
||||
return ((cond % 2) != 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -804,3 +808,34 @@ failed_undo:
|
||||
failed_kiq_write:
|
||||
dev_err(adev->dev, "failed to write reg:%x\n", reg);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_num_kcq == -1) {
|
||||
return 8;
|
||||
} else if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) {
|
||||
dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid parameter provided by user\n");
|
||||
return 8;
|
||||
}
|
||||
return amdgpu_num_kcq;
|
||||
}
|
||||
|
||||
/* amdgpu_gfx_state_change_set - Handle gfx power state change set
|
||||
* @adev: amdgpu_device pointer
|
||||
* @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry)
|
||||
*
|
||||
*/
|
||||
|
||||
void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state)
|
||||
{
|
||||
if (is_support_sw_smu(adev)) {
|
||||
smu_gfx_state_change_set(&adev->smu, state);
|
||||
} else {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->gfx_state_change_set)
|
||||
((adev)->powerplay.pp_funcs->gfx_state_change_set(
|
||||
(adev)->powerplay.pp_handle, state));
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,12 @@ enum gfx_pipe_priority {
|
||||
AMDGPU_GFX_PIPE_PRIO_MAX
|
||||
};
|
||||
|
||||
/* Argument for PPSMC_MSG_GpuChangeState */
|
||||
enum gfx_change_state {
|
||||
sGpuChangeState_D0Entry = 1,
|
||||
sGpuChangeState_D3Entry,
|
||||
};
|
||||
|
||||
#define AMDGPU_GFX_QUEUE_PRIORITY_MINIMUM 0
|
||||
#define AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM 15
|
||||
|
||||
@@ -218,6 +224,7 @@ struct amdgpu_gfx_funcs {
|
||||
void (*reset_ras_error_count) (struct amdgpu_device *adev);
|
||||
void (*init_spm_golden)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_status) (struct amdgpu_device *adev);
|
||||
void (*update_perfmon_mgcg)(struct amdgpu_device *adev, bool enable);
|
||||
};
|
||||
|
||||
struct sq_work {
|
||||
@@ -373,7 +380,7 @@ void amdgpu_queue_mask_bit_to_mec_queue(struct amdgpu_device *adev, int bit,
|
||||
bool amdgpu_gfx_is_mec_queue_enabled(struct amdgpu_device *adev, int mec,
|
||||
int pipe, int queue);
|
||||
bool amdgpu_gfx_is_high_priority_compute_queue(struct amdgpu_device *adev,
|
||||
int queue);
|
||||
int pipe, int queue);
|
||||
int amdgpu_gfx_me_queue_to_bit(struct amdgpu_device *adev, int me,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_bit_to_me_queue(struct amdgpu_device *adev, int bit,
|
||||
@@ -392,4 +399,6 @@ int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
|
||||
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v);
|
||||
int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state);
|
||||
#endif
|
||||
|
||||
@@ -45,12 +45,10 @@ void amdgpu_gmc_get_pde_for_bo(struct amdgpu_bo *bo, int level,
|
||||
uint64_t *addr, uint64_t *flags)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct ttm_dma_tt *ttm;
|
||||
|
||||
switch (bo->tbo.mem.mem_type) {
|
||||
case TTM_PL_TT:
|
||||
ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm);
|
||||
*addr = ttm->dma_address[0];
|
||||
*addr = bo->tbo.ttm->dma_address[0];
|
||||
break;
|
||||
case TTM_PL_VRAM:
|
||||
*addr = amdgpu_bo_gpu_offset(bo);
|
||||
@@ -63,9 +61,8 @@ void amdgpu_gmc_get_pde_for_bo(struct amdgpu_bo *bo, int level,
|
||||
amdgpu_gmc_get_vm_pde(adev, level, addr, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_gmc_pd_addr - return the address of the root directory
|
||||
*
|
||||
*/
|
||||
uint64_t amdgpu_gmc_pd_addr(struct amdgpu_bo *bo)
|
||||
{
|
||||
@@ -114,7 +111,7 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
|
||||
/**
|
||||
* amdgpu_gmc_agp_addr - return the address in the AGP address space
|
||||
*
|
||||
* @tbo: TTM BO which needs the address, must be in GTT domain
|
||||
* @bo: TTM BO which needs the address, must be in GTT domain
|
||||
*
|
||||
* Tries to figure out how to access the BO through the AGP aperture. Returns
|
||||
* AMDGPU_BO_INVALID_OFFSET if that is not possible.
|
||||
@@ -122,16 +119,14 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
|
||||
uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
struct ttm_dma_tt *ttm;
|
||||
|
||||
if (bo->num_pages != 1 || bo->ttm->caching_state == tt_cached)
|
||||
if (bo->num_pages != 1 || bo->ttm->caching == ttm_cached)
|
||||
return AMDGPU_BO_INVALID_OFFSET;
|
||||
|
||||
ttm = container_of(bo->ttm, struct ttm_dma_tt, ttm);
|
||||
if (ttm->dma_address[0] + PAGE_SIZE >= adev->gmc.agp_size)
|
||||
if (bo->ttm->dma_address[0] + PAGE_SIZE >= adev->gmc.agp_size)
|
||||
return AMDGPU_BO_INVALID_OFFSET;
|
||||
|
||||
return adev->gmc.agp_start + ttm->dma_address[0];
|
||||
return adev->gmc.agp_start + bo->ttm->dma_address[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,6 +388,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_VANGOGH:
|
||||
/* Don't enable it by default yet.
|
||||
*/
|
||||
if (amdgpu_tmz < 1) {
|
||||
@@ -425,20 +421,26 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
||||
struct amdgpu_gmc *gmc = &adev->gmc;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA20:
|
||||
/*
|
||||
* noretry = 0 will cause kfd page fault tests fail
|
||||
* for some ASICs, so set default to 1 for these ASICs.
|
||||
*/
|
||||
if (amdgpu_noretry == -1)
|
||||
gmc->noretry = 1;
|
||||
else
|
||||
gmc->noretry = amdgpu_noretry;
|
||||
break;
|
||||
case CHIP_RAVEN:
|
||||
default:
|
||||
/* Raven currently has issues with noretry
|
||||
* regardless of what we decide for other
|
||||
* asics, we should leave raven with
|
||||
* noretry = 0 until we root cause the
|
||||
* issues.
|
||||
*/
|
||||
if (amdgpu_noretry == -1)
|
||||
gmc->noretry = 0;
|
||||
else
|
||||
gmc->noretry = amdgpu_noretry;
|
||||
break;
|
||||
default:
|
||||
/* default this to 0 for now, but we may want
|
||||
*
|
||||
* default this to 0 for now, but we may want
|
||||
* to change this in the future for certain
|
||||
* GPUs as it can increase performance in
|
||||
* certain cases.
|
||||
|
||||
@@ -136,7 +136,7 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev)
|
||||
|
||||
ttm_resource_manager_set_used(man, false);
|
||||
|
||||
ret = ttm_resource_manager_force_list_clean(&adev->mman.bdev, man);
|
||||
ret = ttm_resource_manager_evict_all(&adev->mman.bdev, man);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
|
||||
@@ -52,8 +52,10 @@
|
||||
/**
|
||||
* amdgpu_ib_get - request an IB (Indirect Buffer)
|
||||
*
|
||||
* @ring: ring index the IB is associated with
|
||||
* @adev: amdgpu_device pointer
|
||||
* @vm: amdgpu_vm pointer
|
||||
* @size: requested IB size
|
||||
* @pool_type: IB pool type (delayed, immediate, direct)
|
||||
* @ib: IB object returned
|
||||
*
|
||||
* Request an IB (all asics). IBs are allocated using the
|
||||
@@ -101,9 +103,10 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
|
||||
/**
|
||||
* amdgpu_ib_schedule - schedule an IB (Indirect Buffer) on the ring
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: ring index the IB is associated with
|
||||
* @num_ibs: number of IBs to schedule
|
||||
* @ibs: IB objects to schedule
|
||||
* @job: job to schedule
|
||||
* @f: fence created during this submission
|
||||
*
|
||||
* Schedule an IB on the associated ring (all asics).
|
||||
|
||||
@@ -208,7 +208,7 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
|
||||
if (ring->vmid_wait && !dma_fence_is_signaled(ring->vmid_wait))
|
||||
return amdgpu_sync_fence(sync, ring->vmid_wait);
|
||||
|
||||
fences = kmalloc_array(sizeof(void *), id_mgr->num_ids, GFP_KERNEL);
|
||||
fences = kmalloc_array(id_mgr->num_ids, sizeof(void *), GFP_KERNEL);
|
||||
if (!fences)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -259,6 +259,7 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
|
||||
* @sync: sync object where we add dependencies
|
||||
* @fence: fence protecting ID from reuse
|
||||
* @job: job who wants to use the VMID
|
||||
* @id: resulting VMID
|
||||
*
|
||||
* Try to assign a reserved VMID.
|
||||
*/
|
||||
@@ -514,6 +515,7 @@ void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
|
||||
* amdgpu_vmid_reset - reset VMID to zero
|
||||
*
|
||||
* @adev: amdgpu device structure
|
||||
* @vmhub: vmhub type
|
||||
* @vmid: vmid number to use
|
||||
*
|
||||
* Reset saved GDW, GWS and OA to force switch on next flush.
|
||||
|
||||
@@ -131,6 +131,35 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ih_ring_write - write IV to the ring buffer
|
||||
*
|
||||
* @ih: ih ring to write to
|
||||
* @iv: the iv to write
|
||||
* @num_dw: size of the iv in dw
|
||||
*
|
||||
* Writes an IV to the ring buffer using the CPU and increment the wptr.
|
||||
* Used for testing and delegating IVs to a software ring.
|
||||
*/
|
||||
void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
|
||||
unsigned int num_dw)
|
||||
{
|
||||
uint32_t wptr = le32_to_cpu(*ih->wptr_cpu) >> 2;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_dw; ++i)
|
||||
ih->ring[wptr++] = cpu_to_le32(iv[i]);
|
||||
|
||||
wptr <<= 2;
|
||||
wptr &= ih->ptr_mask;
|
||||
|
||||
/* Only commit the new wptr if we don't overflow */
|
||||
if (wptr != READ_ONCE(ih->rptr)) {
|
||||
wmb();
|
||||
WRITE_ONCE(*ih->wptr_cpu, cpu_to_le32(wptr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ih_process - interrupt handler
|
||||
*
|
||||
|
||||
@@ -72,6 +72,8 @@ struct amdgpu_ih_funcs {
|
||||
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
unsigned ring_size, bool use_bus_addr);
|
||||
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,
|
||||
unsigned int num_dw);
|
||||
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -206,6 +206,21 @@ static void amdgpu_irq_handle_ih2(struct work_struct *work)
|
||||
amdgpu_ih_process(adev, &adev->irq.ih2);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_handle_ih_soft - kick of processing for ih_soft
|
||||
*
|
||||
* @work: work structure in struct amdgpu_irq
|
||||
*
|
||||
* Kick of processing IH soft ring.
|
||||
*/
|
||||
static void amdgpu_irq_handle_ih_soft(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
|
||||
irq.ih_soft_work);
|
||||
|
||||
amdgpu_ih_process(adev, &adev->irq.ih_soft);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_msi_ok - check whether MSI functionality is enabled
|
||||
*
|
||||
@@ -281,6 +296,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
||||
|
||||
INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
|
||||
INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
|
||||
INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft);
|
||||
|
||||
adev->irq.installed = true;
|
||||
/* Use vector 0 for MSI-X */
|
||||
@@ -413,6 +429,7 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
||||
bool handled = false;
|
||||
int r;
|
||||
|
||||
entry.ih = ih;
|
||||
entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
|
||||
amdgpu_ih_decode_iv(adev, &entry);
|
||||
|
||||
@@ -450,6 +467,24 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
||||
amdgpu_amdkfd_interrupt(adev, entry.iv_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_delegate - delegate IV to soft IH ring
|
||||
*
|
||||
* @adev: amdgpu device pointer
|
||||
* @entry: IV entry
|
||||
* @num_dw: size of IV
|
||||
*
|
||||
* Delegate the IV to the soft IH ring and schedule processing of it. Used
|
||||
* if the hardware delegation to IH1 or IH2 doesn't work for some reason.
|
||||
*/
|
||||
void amdgpu_irq_delegate(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry,
|
||||
unsigned int num_dw)
|
||||
{
|
||||
amdgpu_ih_ring_write(&adev->irq.ih_soft, entry->iv_entry, num_dw);
|
||||
schedule_work(&adev->irq.ih_soft_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_update - update hardware interrupt state
|
||||
*
|
||||
|
||||
@@ -44,6 +44,7 @@ enum amdgpu_interrupt_state {
|
||||
};
|
||||
|
||||
struct amdgpu_iv_entry {
|
||||
struct amdgpu_ih_ring *ih;
|
||||
unsigned client_id;
|
||||
unsigned src_id;
|
||||
unsigned ring_id;
|
||||
@@ -88,9 +89,9 @@ struct amdgpu_irq {
|
||||
bool msi_enabled; /* msi enabled */
|
||||
|
||||
/* interrupt rings */
|
||||
struct amdgpu_ih_ring ih, ih1, ih2;
|
||||
struct amdgpu_ih_ring ih, ih1, ih2, ih_soft;
|
||||
const struct amdgpu_ih_funcs *ih_funcs;
|
||||
struct work_struct ih1_work, ih2_work;
|
||||
struct work_struct ih1_work, ih2_work, ih_soft_work;
|
||||
struct amdgpu_irq_src self_irq;
|
||||
|
||||
/* gen irq stuff */
|
||||
@@ -109,6 +110,9 @@ int amdgpu_irq_add_id(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source);
|
||||
void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih);
|
||||
void amdgpu_irq_delegate(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry,
|
||||
unsigned int num_dw);
|
||||
int amdgpu_irq_update(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
|
||||
unsigned type);
|
||||
int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "amdgpu.h"
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include "amdgpu_sched.h"
|
||||
#include "amdgpu_uvd.h"
|
||||
#include "amdgpu_vce.h"
|
||||
#include "atom.h"
|
||||
@@ -163,10 +162,6 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
||||
} else if (amdgpu_device_supports_baco(dev) &&
|
||||
(amdgpu_runtime_pm != 0)) {
|
||||
switch (adev->asic_type) {
|
||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||
case CHIP_BONAIRE:
|
||||
case CHIP_HAWAII:
|
||||
#endif
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
@@ -181,7 +176,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
||||
adev->runpm = true;
|
||||
break;
|
||||
default:
|
||||
/* enable runpm on VI+ */
|
||||
/* enable runpm on CI+ */
|
||||
adev->runpm = true;
|
||||
break;
|
||||
}
|
||||
@@ -325,6 +320,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
|
||||
fw_info->ver = adev->dm.dmcub_fw_version;
|
||||
fw_info->feature = 0;
|
||||
break;
|
||||
case AMDGPU_INFO_FW_TOC:
|
||||
fw_info->ver = adev->psp.toc_fw_version;
|
||||
fw_info->feature = adev->psp.toc_feature_version;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -471,7 +470,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
|
||||
/**
|
||||
* amdgpu_info_ioctl - answer a device specific request.
|
||||
*
|
||||
* @adev: amdgpu device pointer
|
||||
* @dev: drm device pointer
|
||||
* @data: request object
|
||||
* @filp: drm filp
|
||||
*
|
||||
@@ -480,7 +479,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
|
||||
* etc. (all asics).
|
||||
* Returns 0 on success, -EINVAL on failure.
|
||||
*/
|
||||
static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct drm_amdgpu_info *info = data;
|
||||
@@ -717,38 +716,42 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
||||
return n ? -EFAULT : 0;
|
||||
}
|
||||
case AMDGPU_INFO_DEV_INFO: {
|
||||
struct drm_amdgpu_info_device dev_info;
|
||||
struct drm_amdgpu_info_device *dev_info;
|
||||
uint64_t vm_size;
|
||||
int ret;
|
||||
|
||||
memset(&dev_info, 0, sizeof(dev_info));
|
||||
dev_info.device_id = dev->pdev->device;
|
||||
dev_info.chip_rev = adev->rev_id;
|
||||
dev_info.external_rev = adev->external_rev_id;
|
||||
dev_info.pci_rev = dev->pdev->revision;
|
||||
dev_info.family = adev->family;
|
||||
dev_info.num_shader_engines = adev->gfx.config.max_shader_engines;
|
||||
dev_info.num_shader_arrays_per_engine = adev->gfx.config.max_sh_per_se;
|
||||
dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
|
||||
if (!dev_info)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_info->device_id = dev->pdev->device;
|
||||
dev_info->chip_rev = adev->rev_id;
|
||||
dev_info->external_rev = adev->external_rev_id;
|
||||
dev_info->pci_rev = dev->pdev->revision;
|
||||
dev_info->family = adev->family;
|
||||
dev_info->num_shader_engines = adev->gfx.config.max_shader_engines;
|
||||
dev_info->num_shader_arrays_per_engine = adev->gfx.config.max_sh_per_se;
|
||||
/* return all clocks in KHz */
|
||||
dev_info.gpu_counter_freq = amdgpu_asic_get_xclk(adev) * 10;
|
||||
dev_info->gpu_counter_freq = amdgpu_asic_get_xclk(adev) * 10;
|
||||
if (adev->pm.dpm_enabled) {
|
||||
dev_info.max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
|
||||
dev_info.max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
|
||||
dev_info->max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
|
||||
dev_info->max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
|
||||
} else {
|
||||
dev_info.max_engine_clock = adev->clock.default_sclk * 10;
|
||||
dev_info.max_memory_clock = adev->clock.default_mclk * 10;
|
||||
dev_info->max_engine_clock = adev->clock.default_sclk * 10;
|
||||
dev_info->max_memory_clock = adev->clock.default_mclk * 10;
|
||||
}
|
||||
dev_info.enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
|
||||
dev_info.num_rb_pipes = adev->gfx.config.max_backends_per_se *
|
||||
dev_info->enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
|
||||
dev_info->num_rb_pipes = adev->gfx.config.max_backends_per_se *
|
||||
adev->gfx.config.max_shader_engines;
|
||||
dev_info.num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;
|
||||
dev_info._pad = 0;
|
||||
dev_info.ids_flags = 0;
|
||||
dev_info->num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;
|
||||
dev_info->_pad = 0;
|
||||
dev_info->ids_flags = 0;
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
|
||||
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev))
|
||||
dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
|
||||
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
|
||||
if (amdgpu_is_tmz(adev))
|
||||
dev_info.ids_flags |= AMDGPU_IDS_FLAGS_TMZ;
|
||||
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ;
|
||||
|
||||
vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
|
||||
vm_size -= AMDGPU_VA_RESERVED_SIZE;
|
||||
@@ -758,45 +761,47 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
||||
adev->vce.fw_version < AMDGPU_VCE_FW_53_45)
|
||||
vm_size = min(vm_size, 1ULL << 40);
|
||||
|
||||
dev_info.virtual_address_offset = AMDGPU_VA_RESERVED_SIZE;
|
||||
dev_info.virtual_address_max =
|
||||
dev_info->virtual_address_offset = AMDGPU_VA_RESERVED_SIZE;
|
||||
dev_info->virtual_address_max =
|
||||
min(vm_size, AMDGPU_GMC_HOLE_START);
|
||||
|
||||
if (vm_size > AMDGPU_GMC_HOLE_START) {
|
||||
dev_info.high_va_offset = AMDGPU_GMC_HOLE_END;
|
||||
dev_info.high_va_max = AMDGPU_GMC_HOLE_END | vm_size;
|
||||
dev_info->high_va_offset = AMDGPU_GMC_HOLE_END;
|
||||
dev_info->high_va_max = AMDGPU_GMC_HOLE_END | vm_size;
|
||||
}
|
||||
dev_info.virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
|
||||
dev_info.pte_fragment_size = (1 << adev->vm_manager.fragment_size) * AMDGPU_GPU_PAGE_SIZE;
|
||||
dev_info.gart_page_size = AMDGPU_GPU_PAGE_SIZE;
|
||||
dev_info.cu_active_number = adev->gfx.cu_info.number;
|
||||
dev_info.cu_ao_mask = adev->gfx.cu_info.ao_cu_mask;
|
||||
dev_info.ce_ram_size = adev->gfx.ce_ram_size;
|
||||
memcpy(&dev_info.cu_ao_bitmap[0], &adev->gfx.cu_info.ao_cu_bitmap[0],
|
||||
dev_info->virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
|
||||
dev_info->pte_fragment_size = (1 << adev->vm_manager.fragment_size) * AMDGPU_GPU_PAGE_SIZE;
|
||||
dev_info->gart_page_size = AMDGPU_GPU_PAGE_SIZE;
|
||||
dev_info->cu_active_number = adev->gfx.cu_info.number;
|
||||
dev_info->cu_ao_mask = adev->gfx.cu_info.ao_cu_mask;
|
||||
dev_info->ce_ram_size = adev->gfx.ce_ram_size;
|
||||
memcpy(&dev_info->cu_ao_bitmap[0], &adev->gfx.cu_info.ao_cu_bitmap[0],
|
||||
sizeof(adev->gfx.cu_info.ao_cu_bitmap));
|
||||
memcpy(&dev_info.cu_bitmap[0], &adev->gfx.cu_info.bitmap[0],
|
||||
memcpy(&dev_info->cu_bitmap[0], &adev->gfx.cu_info.bitmap[0],
|
||||
sizeof(adev->gfx.cu_info.bitmap));
|
||||
dev_info.vram_type = adev->gmc.vram_type;
|
||||
dev_info.vram_bit_width = adev->gmc.vram_width;
|
||||
dev_info.vce_harvest_config = adev->vce.harvest_config;
|
||||
dev_info.gc_double_offchip_lds_buf =
|
||||
dev_info->vram_type = adev->gmc.vram_type;
|
||||
dev_info->vram_bit_width = adev->gmc.vram_width;
|
||||
dev_info->vce_harvest_config = adev->vce.harvest_config;
|
||||
dev_info->gc_double_offchip_lds_buf =
|
||||
adev->gfx.config.double_offchip_lds_buf;
|
||||
dev_info.wave_front_size = adev->gfx.cu_info.wave_front_size;
|
||||
dev_info.num_shader_visible_vgprs = adev->gfx.config.max_gprs;
|
||||
dev_info.num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
|
||||
dev_info.num_tcc_blocks = adev->gfx.config.max_texture_channel_caches;
|
||||
dev_info.gs_vgt_table_depth = adev->gfx.config.gs_vgt_table_depth;
|
||||
dev_info.gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth;
|
||||
dev_info.max_gs_waves_per_vgt = adev->gfx.config.max_gs_threads;
|
||||
dev_info->wave_front_size = adev->gfx.cu_info.wave_front_size;
|
||||
dev_info->num_shader_visible_vgprs = adev->gfx.config.max_gprs;
|
||||
dev_info->num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
|
||||
dev_info->num_tcc_blocks = adev->gfx.config.max_texture_channel_caches;
|
||||
dev_info->gs_vgt_table_depth = adev->gfx.config.gs_vgt_table_depth;
|
||||
dev_info->gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth;
|
||||
dev_info->max_gs_waves_per_vgt = adev->gfx.config.max_gs_threads;
|
||||
|
||||
if (adev->family >= AMDGPU_FAMILY_NV)
|
||||
dev_info.pa_sc_tile_steering_override =
|
||||
dev_info->pa_sc_tile_steering_override =
|
||||
adev->gfx.config.pa_sc_tile_steering_override;
|
||||
|
||||
dev_info.tcc_disabled_mask = adev->gfx.config.tcc_disabled_mask;
|
||||
dev_info->tcc_disabled_mask = adev->gfx.config.tcc_disabled_mask;
|
||||
|
||||
return copy_to_user(out, &dev_info,
|
||||
min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
|
||||
ret = copy_to_user(out, dev_info,
|
||||
min((size_t)size, sizeof(*dev_info))) ? -EFAULT : 0;
|
||||
kfree(dev_info);
|
||||
return ret;
|
||||
}
|
||||
case AMDGPU_INFO_VCE_CLOCK_TABLE: {
|
||||
unsigned i;
|
||||
@@ -1243,27 +1248,6 @@ void amdgpu_disable_vblank_kms(struct drm_crtc *crtc)
|
||||
amdgpu_irq_put(adev, &adev->crtc_irq, idx);
|
||||
}
|
||||
|
||||
const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_VM, amdgpu_vm_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_SCHED, amdgpu_sched_ioctl, DRM_MASTER),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_BO_LIST, amdgpu_bo_list_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_FENCE_TO_HANDLE, amdgpu_cs_fence_to_handle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
/* KMS */
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_MMAP, amdgpu_gem_mmap_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_WAIT_IDLE, amdgpu_gem_wait_idle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_FENCES, amdgpu_cs_wait_fences_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW)
|
||||
};
|
||||
const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms);
|
||||
|
||||
/*
|
||||
* Debugfs info
|
||||
*/
|
||||
@@ -1466,6 +1450,13 @@ static int amdgpu_debugfs_firmware_info(struct seq_file *m, void *data)
|
||||
seq_printf(m, "DMCUB feature version: %u, firmware version: 0x%08x\n",
|
||||
fw_info.feature, fw_info.ver);
|
||||
|
||||
/* TOC */
|
||||
query_fw.fw_type = AMDGPU_INFO_FW_TOC;
|
||||
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
seq_printf(m, "TOC feature version: %u, firmware version: 0x%08x\n",
|
||||
fw_info.feature, fw_info.ver);
|
||||
|
||||
seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);
|
||||
|
||||
|
||||
@@ -302,6 +302,9 @@ struct amdgpu_display_funcs {
|
||||
struct amdgpu_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
|
||||
uint64_t tiling_flags;
|
||||
bool tmz_surface;
|
||||
|
||||
/* caching for later use */
|
||||
uint64_t address;
|
||||
};
|
||||
|
||||
@@ -53,6 +53,8 @@ struct amdgpu_nbio_funcs {
|
||||
u32 (*get_hdp_flush_done_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_pcie_index_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_pcie_data_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_pcie_port_index_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_pcie_port_data_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_rev_id)(struct amdgpu_device *adev);
|
||||
void (*mc_access_enable)(struct amdgpu_device *adev, bool enable);
|
||||
void (*hdp_flush)(struct amdgpu_device *adev, struct amdgpu_ring *ring);
|
||||
@@ -85,6 +87,8 @@ struct amdgpu_nbio_funcs {
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*enable_aspm)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
};
|
||||
|
||||
struct amdgpu_nbio {
|
||||
|
||||
@@ -78,7 +78,7 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
|
||||
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
|
||||
|
||||
if (bo->pin_count > 0)
|
||||
if (bo->tbo.pin_count > 0)
|
||||
amdgpu_bo_subtract_pin_size(bo);
|
||||
|
||||
amdgpu_bo_kunmap(bo);
|
||||
@@ -137,7 +137,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].fpfn = 0;
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = TTM_PL_VRAM;
|
||||
places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
|
||||
places[c].flags = 0;
|
||||
|
||||
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
|
||||
places[c].lpfn = visible_pfn;
|
||||
@@ -154,11 +154,6 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = TTM_PL_TT;
|
||||
places[c].flags = 0;
|
||||
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
|
||||
places[c].flags |= TTM_PL_FLAG_WC |
|
||||
TTM_PL_FLAG_UNCACHED;
|
||||
else
|
||||
places[c].flags |= TTM_PL_FLAG_CACHED;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -167,11 +162,6 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = TTM_PL_SYSTEM;
|
||||
places[c].flags = 0;
|
||||
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
|
||||
places[c].flags |= TTM_PL_FLAG_WC |
|
||||
TTM_PL_FLAG_UNCACHED;
|
||||
else
|
||||
places[c].flags |= TTM_PL_FLAG_CACHED;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -179,7 +169,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].fpfn = 0;
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = AMDGPU_PL_GDS;
|
||||
places[c].flags = TTM_PL_FLAG_UNCACHED;
|
||||
places[c].flags = 0;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -187,7 +177,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].fpfn = 0;
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = AMDGPU_PL_GWS;
|
||||
places[c].flags = TTM_PL_FLAG_UNCACHED;
|
||||
places[c].flags = 0;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -195,7 +185,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].fpfn = 0;
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = AMDGPU_PL_OA;
|
||||
places[c].flags = TTM_PL_FLAG_UNCACHED;
|
||||
places[c].flags = 0;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -203,7 +193,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
||||
places[c].fpfn = 0;
|
||||
places[c].lpfn = 0;
|
||||
places[c].mem_type = TTM_PL_SYSTEM;
|
||||
places[c].flags = TTM_PL_MASK_CACHING;
|
||||
places[c].flags = 0;
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -526,9 +516,10 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = (bp->type != ttm_bo_type_kernel),
|
||||
.no_wait_gpu = bp->no_wait_gpu,
|
||||
.resv = bp->resv,
|
||||
.flags = bp->type != ttm_bo_type_kernel ?
|
||||
TTM_OPT_FLAG_ALLOW_RES_EVICT : 0
|
||||
/* We opt to avoid OOM on system pages allocations */
|
||||
.gfp_retry_mayfail = true,
|
||||
.allow_res_evict = bp->type != ttm_bo_type_kernel,
|
||||
.resv = bp->resv
|
||||
};
|
||||
struct amdgpu_bo *bo;
|
||||
unsigned long page_align, size = bp->size;
|
||||
@@ -721,7 +712,7 @@ int amdgpu_bo_validate(struct amdgpu_bo *bo)
|
||||
uint32_t domain;
|
||||
int r;
|
||||
|
||||
if (bo->pin_count)
|
||||
if (bo->tbo.pin_count)
|
||||
return 0;
|
||||
|
||||
domain = bo->preferred_domains;
|
||||
@@ -918,13 +909,13 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
||||
*/
|
||||
domain = amdgpu_bo_get_preferred_pin_domain(adev, domain);
|
||||
|
||||
if (bo->pin_count) {
|
||||
if (bo->tbo.pin_count) {
|
||||
uint32_t mem_type = bo->tbo.mem.mem_type;
|
||||
|
||||
if (!(domain & amdgpu_mem_type_to_domain(mem_type)))
|
||||
return -EINVAL;
|
||||
|
||||
bo->pin_count++;
|
||||
ttm_bo_pin(&bo->tbo);
|
||||
|
||||
if (max_offset != 0) {
|
||||
u64 domain_start = amdgpu_ttm_domain_start(adev,
|
||||
@@ -955,7 +946,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
||||
if (!bo->placements[i].lpfn ||
|
||||
(lpfn && lpfn < bo->placements[i].lpfn))
|
||||
bo->placements[i].lpfn = lpfn;
|
||||
bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
|
||||
}
|
||||
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
@@ -964,7 +954,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
||||
goto error;
|
||||
}
|
||||
|
||||
bo->pin_count = 1;
|
||||
ttm_bo_pin(&bo->tbo);
|
||||
|
||||
domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
|
||||
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
|
||||
@@ -1006,34 +996,16 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain)
|
||||
* Returns:
|
||||
* 0 for success or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_bo_unpin(struct amdgpu_bo *bo)
|
||||
void amdgpu_bo_unpin(struct amdgpu_bo *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
int r, i;
|
||||
|
||||
if (WARN_ON_ONCE(!bo->pin_count)) {
|
||||
dev_warn(adev->dev, "%p unpin not necessary\n", bo);
|
||||
return 0;
|
||||
}
|
||||
bo->pin_count--;
|
||||
if (bo->pin_count)
|
||||
return 0;
|
||||
ttm_bo_unpin(&bo->tbo);
|
||||
if (bo->tbo.pin_count)
|
||||
return;
|
||||
|
||||
amdgpu_bo_subtract_pin_size(bo);
|
||||
|
||||
if (bo->tbo.base.import_attach)
|
||||
dma_buf_unpin(bo->tbo.base.import_attach);
|
||||
|
||||
for (i = 0; i < bo->placement.num_placement; i++) {
|
||||
bo->placements[i].lpfn = 0;
|
||||
bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
|
||||
}
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
if (unlikely(r))
|
||||
dev_err(adev->dev, "%p validate failed for unpin\n", bo);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1048,6 +1020,8 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
|
||||
*/
|
||||
int amdgpu_bo_evict_vram(struct amdgpu_device *adev)
|
||||
{
|
||||
struct ttm_resource_manager *man;
|
||||
|
||||
/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
|
||||
#ifndef CONFIG_HIBERNATION
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
@@ -1055,7 +1029,9 @@ int amdgpu_bo_evict_vram(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
return ttm_resource_manager_evict_all(&adev->mman.bdev, man);
|
||||
}
|
||||
|
||||
static const char *amdgpu_vram_names[] = {
|
||||
@@ -1069,6 +1045,7 @@ static const char *amdgpu_vram_names[] = {
|
||||
"DDR3",
|
||||
"DDR4",
|
||||
"GDDR6",
|
||||
"DDR5"
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1097,23 +1074,6 @@ int amdgpu_bo_init(struct amdgpu_device *adev)
|
||||
return amdgpu_ttm_init(adev);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_bo_late_init - late init
|
||||
* @adev: amdgpu device object
|
||||
*
|
||||
* Calls amdgpu_ttm_late_init() to free resources used earlier during
|
||||
* initialization.
|
||||
*
|
||||
* Returns:
|
||||
* 0 for success or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_bo_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_ttm_late_init(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_bo_fini - tear down memory manager
|
||||
* @adev: amdgpu device object
|
||||
@@ -1360,19 +1320,14 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
||||
* Returns:
|
||||
* 0 for success or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
|
||||
vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct amdgpu_bo *abo;
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
|
||||
unsigned long offset, size;
|
||||
int r;
|
||||
|
||||
if (!amdgpu_bo_is_amdgpu_bo(bo))
|
||||
return 0;
|
||||
|
||||
abo = ttm_to_amdgpu_bo(bo);
|
||||
|
||||
/* Remember that this BO was accessed by the CPU */
|
||||
abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
|
||||
|
||||
@@ -1385,8 +1340,8 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
|
||||
return 0;
|
||||
|
||||
/* Can't move a pinned BO to visible VRAM */
|
||||
if (abo->pin_count > 0)
|
||||
return -EINVAL;
|
||||
if (abo->tbo.pin_count > 0)
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
/* hurrah the memory is not visible ! */
|
||||
atomic64_inc(&adev->num_vram_cpu_page_faults);
|
||||
@@ -1398,15 +1353,18 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
|
||||
abo->placement.busy_placement = &abo->placements[1];
|
||||
|
||||
r = ttm_bo_validate(bo, &abo->placement, &ctx);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
if (unlikely(r == -EBUSY || r == -ERESTARTSYS))
|
||||
return VM_FAULT_NOPAGE;
|
||||
else if (unlikely(r))
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
offset = bo->mem.start << PAGE_SHIFT;
|
||||
/* this should never happen */
|
||||
if (bo->mem.mem_type == TTM_PL_VRAM &&
|
||||
(offset + size) > adev->gmc.visible_vram_size)
|
||||
return -EINVAL;
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
ttm_bo_move_to_lru_tail_unlocked(bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1489,7 +1447,7 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
|
||||
{
|
||||
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
|
||||
WARN_ON_ONCE(!dma_resv_is_locked(bo->tbo.base.resv) &&
|
||||
!bo->pin_count && bo->tbo.type != ttm_bo_type_kernel);
|
||||
!bo->tbo.pin_count && bo->tbo.type != ttm_bo_type_kernel);
|
||||
WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET);
|
||||
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM &&
|
||||
!(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS));
|
||||
@@ -1533,3 +1491,77 @@ uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev,
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
#define amdgpu_bo_print_flag(m, bo, flag) \
|
||||
do { \
|
||||
if (bo->flags & (AMDGPU_GEM_CREATE_ ## flag)) { \
|
||||
seq_printf((m), " " #flag); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* amdgpu_bo_print_info - print BO info in debugfs file
|
||||
*
|
||||
* @id: Index or Id of the BO
|
||||
* @bo: Requested BO for printing info
|
||||
* @m: debugfs file
|
||||
*
|
||||
* Print BO information in debugfs file
|
||||
*
|
||||
* Returns:
|
||||
* Size of the BO in bytes.
|
||||
*/
|
||||
u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
|
||||
{
|
||||
struct dma_buf_attachment *attachment;
|
||||
struct dma_buf *dma_buf;
|
||||
unsigned int domain;
|
||||
const char *placement;
|
||||
unsigned int pin_count;
|
||||
u64 size;
|
||||
|
||||
domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
|
||||
switch (domain) {
|
||||
case AMDGPU_GEM_DOMAIN_VRAM:
|
||||
placement = "VRAM";
|
||||
break;
|
||||
case AMDGPU_GEM_DOMAIN_GTT:
|
||||
placement = " GTT";
|
||||
break;
|
||||
case AMDGPU_GEM_DOMAIN_CPU:
|
||||
default:
|
||||
placement = " CPU";
|
||||
break;
|
||||
}
|
||||
|
||||
size = amdgpu_bo_size(bo);
|
||||
seq_printf(m, "\t\t0x%08x: %12lld byte %s",
|
||||
id, size, placement);
|
||||
|
||||
pin_count = READ_ONCE(bo->tbo.pin_count);
|
||||
if (pin_count)
|
||||
seq_printf(m, " pin count %d", pin_count);
|
||||
|
||||
dma_buf = READ_ONCE(bo->tbo.base.dma_buf);
|
||||
attachment = READ_ONCE(bo->tbo.base.import_attach);
|
||||
|
||||
if (attachment)
|
||||
seq_printf(m, " imported from %p", dma_buf);
|
||||
else if (dma_buf)
|
||||
seq_printf(m, " exported as %p", dma_buf);
|
||||
|
||||
amdgpu_bo_print_flag(m, bo, CPU_ACCESS_REQUIRED);
|
||||
amdgpu_bo_print_flag(m, bo, NO_CPU_ACCESS);
|
||||
amdgpu_bo_print_flag(m, bo, CPU_GTT_USWC);
|
||||
amdgpu_bo_print_flag(m, bo, VRAM_CLEARED);
|
||||
amdgpu_bo_print_flag(m, bo, SHADOW);
|
||||
amdgpu_bo_print_flag(m, bo, VRAM_CONTIGUOUS);
|
||||
amdgpu_bo_print_flag(m, bo, VM_ALWAYS_VALID);
|
||||
amdgpu_bo_print_flag(m, bo, EXPLICIT_SYNC);
|
||||
|
||||
seq_puts(m, "\n");
|
||||
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -89,7 +89,6 @@ struct amdgpu_bo {
|
||||
struct ttm_buffer_object tbo;
|
||||
struct ttm_bo_kmap_obj kmap;
|
||||
u64 flags;
|
||||
unsigned pin_count;
|
||||
u64 tiling_flags;
|
||||
u64 metadata_flags;
|
||||
void *metadata;
|
||||
@@ -101,7 +100,6 @@ struct amdgpu_bo {
|
||||
struct amdgpu_bo *parent;
|
||||
struct amdgpu_bo *shadow;
|
||||
|
||||
struct ttm_bo_kmap_obj dma_buf_vmap;
|
||||
struct amdgpu_mn *mn;
|
||||
|
||||
|
||||
@@ -267,10 +265,9 @@ void amdgpu_bo_unref(struct amdgpu_bo **bo);
|
||||
int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain);
|
||||
int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
||||
u64 min_offset, u64 max_offset);
|
||||
int amdgpu_bo_unpin(struct amdgpu_bo *bo);
|
||||
void amdgpu_bo_unpin(struct amdgpu_bo *bo);
|
||||
int amdgpu_bo_evict_vram(struct amdgpu_device *adev);
|
||||
int amdgpu_bo_init(struct amdgpu_device *adev);
|
||||
int amdgpu_bo_late_init(struct amdgpu_device *adev);
|
||||
void amdgpu_bo_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
|
||||
struct vm_area_struct *vma);
|
||||
@@ -285,7 +282,7 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
|
||||
bool evict,
|
||||
struct ttm_resource *new_mem);
|
||||
void amdgpu_bo_release_notify(struct ttm_buffer_object *bo);
|
||||
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
|
||||
vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
|
||||
void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
|
||||
bool shared);
|
||||
int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv,
|
||||
@@ -330,6 +327,7 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev,
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
|
||||
struct seq_file *m);
|
||||
u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m);
|
||||
#endif
|
||||
int amdgpu_debugfs_sa_init(struct amdgpu_device *adev);
|
||||
|
||||
|
||||
@@ -102,11 +102,12 @@ static void amdgpu_pll_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_
|
||||
* amdgpu_pll_compute - compute PLL paramaters
|
||||
*
|
||||
* @pll: information about the PLL
|
||||
* @freq: requested frequency
|
||||
* @dot_clock_p: resulting pixel clock
|
||||
* fb_div_p: resulting feedback divider
|
||||
* frac_fb_div_p: fractional part of the feedback divider
|
||||
* ref_div_p: resulting reference divider
|
||||
* post_div_p: resulting reference divider
|
||||
* @fb_div_p: resulting feedback divider
|
||||
* @frac_fb_div_p: fractional part of the feedback divider
|
||||
* @ref_div_p: resulting reference divider
|
||||
* @post_div_p: resulting reference divider
|
||||
*
|
||||
* Try to calculate the PLL parameters to generate the given frequency:
|
||||
* dot_clock = (ref_freq * feedback_div) / (ref_div * post_div)
|
||||
@@ -308,7 +309,6 @@ int amdgpu_pll_get_shared_dp_ppll(struct drm_crtc *crtc)
|
||||
* amdgpu_pll_get_shared_nondp_ppll - return the PPLL used by another non-DP crtc
|
||||
*
|
||||
* @crtc: drm crtc
|
||||
* @encoder: drm encoder
|
||||
*
|
||||
* Returns the PPLL (Pixel PLL) used by another non-DP crtc/encoder which can
|
||||
* be shared (i.e., same clock).
|
||||
|
||||
@@ -19,17 +19,29 @@
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Jonathan Kim <jonathan.kim@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/init.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_pmu.h"
|
||||
#include "df_v3_6.h"
|
||||
|
||||
#define PMU_NAME_SIZE 32
|
||||
#define NUM_FORMATS_AMDGPU_PMU 4
|
||||
#define NUM_FORMATS_DF_VEGA20 3
|
||||
#define NUM_EVENTS_DF_VEGA20 8
|
||||
#define NUM_EVENT_TYPES_VEGA20 1
|
||||
#define NUM_EVENTS_VEGA20_XGMI 2
|
||||
#define NUM_EVENTS_VEGA20_MAX NUM_EVENTS_VEGA20_XGMI
|
||||
#define NUM_EVENT_TYPES_ARCTURUS 1
|
||||
#define NUM_EVENTS_ARCTURUS_XGMI 6
|
||||
#define NUM_EVENTS_ARCTURUS_MAX NUM_EVENTS_ARCTURUS_XGMI
|
||||
|
||||
struct amdgpu_pmu_event_attribute {
|
||||
struct device_attribute attr;
|
||||
const char *event_str;
|
||||
unsigned int type;
|
||||
};
|
||||
|
||||
/* record to keep track of pmu entry per pmu type per device */
|
||||
struct amdgpu_pmu_entry {
|
||||
@@ -37,11 +49,162 @@ struct amdgpu_pmu_entry {
|
||||
struct amdgpu_device *adev;
|
||||
struct pmu pmu;
|
||||
unsigned int pmu_perf_type;
|
||||
char *pmu_type_name;
|
||||
char *pmu_file_prefix;
|
||||
struct attribute_group fmt_attr_group;
|
||||
struct amdgpu_pmu_event_attribute *fmt_attr;
|
||||
struct attribute_group evt_attr_group;
|
||||
struct amdgpu_pmu_event_attribute *evt_attr;
|
||||
};
|
||||
|
||||
static ssize_t amdgpu_pmu_event_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct amdgpu_pmu_event_attribute *amdgpu_pmu_attr;
|
||||
|
||||
amdgpu_pmu_attr = container_of(attr, struct amdgpu_pmu_event_attribute,
|
||||
attr);
|
||||
|
||||
if (!amdgpu_pmu_attr->type)
|
||||
return sprintf(buf, "%s\n", amdgpu_pmu_attr->event_str);
|
||||
|
||||
return sprintf(buf, "%s,type=0x%x\n",
|
||||
amdgpu_pmu_attr->event_str, amdgpu_pmu_attr->type);
|
||||
}
|
||||
|
||||
static LIST_HEAD(amdgpu_pmu_list);
|
||||
|
||||
|
||||
struct amdgpu_pmu_attr {
|
||||
const char *name;
|
||||
const char *config;
|
||||
};
|
||||
|
||||
struct amdgpu_pmu_type {
|
||||
const unsigned int type;
|
||||
const unsigned int num_of_type;
|
||||
};
|
||||
|
||||
struct amdgpu_pmu_config {
|
||||
struct amdgpu_pmu_attr *formats;
|
||||
unsigned int num_formats;
|
||||
struct amdgpu_pmu_attr *events;
|
||||
unsigned int num_events;
|
||||
struct amdgpu_pmu_type *types;
|
||||
unsigned int num_types;
|
||||
};
|
||||
|
||||
/*
|
||||
* Events fall under two categories:
|
||||
* - PMU typed
|
||||
* Events in /sys/bus/event_source/devices/amdgpu_<pmu_type>_<dev_num> have
|
||||
* performance counter operations handled by one IP <pmu_type>. Formats and
|
||||
* events should be defined by <pmu_type>_<asic_type>_formats and
|
||||
* <pmu_type>_<asic_type>_events respectively.
|
||||
*
|
||||
* - Event config typed
|
||||
* Events in /sys/bus/event_source/devices/amdgpu_<dev_num> have performance
|
||||
* counter operations that can be handled by multiple IPs dictated by their
|
||||
* "type" format field. Formats and events should be defined by
|
||||
* amdgpu_pmu_formats and <asic_type>_events respectively. Format field
|
||||
* "type" is generated in amdgpu_pmu_event_show and defined in
|
||||
* <asic_type>_event_config_types.
|
||||
*/
|
||||
|
||||
static struct amdgpu_pmu_attr amdgpu_pmu_formats[NUM_FORMATS_AMDGPU_PMU] = {
|
||||
{ .name = "event", .config = "config:0-7" },
|
||||
{ .name = "instance", .config = "config:8-15" },
|
||||
{ .name = "umask", .config = "config:16-23"},
|
||||
{ .name = "type", .config = "config:56-63"}
|
||||
};
|
||||
|
||||
/* Vega20 events */
|
||||
static struct amdgpu_pmu_attr vega20_events[NUM_EVENTS_VEGA20_MAX] = {
|
||||
{ .name = "xgmi_link0_data_outbound",
|
||||
.config = "event=0x7,instance=0x46,umask=0x2" },
|
||||
{ .name = "xgmi_link1_data_outbound",
|
||||
.config = "event=0x7,instance=0x47,umask=0x2" }
|
||||
};
|
||||
|
||||
static struct amdgpu_pmu_type vega20_types[NUM_EVENT_TYPES_VEGA20] = {
|
||||
{ .type = AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI,
|
||||
.num_of_type = NUM_EVENTS_VEGA20_XGMI }
|
||||
};
|
||||
|
||||
static struct amdgpu_pmu_config vega20_config = {
|
||||
.formats = amdgpu_pmu_formats,
|
||||
.num_formats = ARRAY_SIZE(amdgpu_pmu_formats),
|
||||
.events = vega20_events,
|
||||
.num_events = ARRAY_SIZE(vega20_events),
|
||||
.types = vega20_types,
|
||||
.num_types = ARRAY_SIZE(vega20_types)
|
||||
};
|
||||
|
||||
/* Vega20 data fabric (DF) events */
|
||||
static struct amdgpu_pmu_attr df_vega20_formats[NUM_FORMATS_DF_VEGA20] = {
|
||||
{ .name = "event", .config = "config:0-7" },
|
||||
{ .name = "instance", .config = "config:8-15" },
|
||||
{ .name = "umask", .config = "config:16-23"}
|
||||
};
|
||||
|
||||
static struct amdgpu_pmu_attr df_vega20_events[NUM_EVENTS_DF_VEGA20] = {
|
||||
{ .name = "cake0_pcsout_txdata",
|
||||
.config = "event=0x7,instance=0x46,umask=0x2" },
|
||||
{ .name = "cake1_pcsout_txdata",
|
||||
.config = "event=0x7,instance=0x47,umask=0x2" },
|
||||
{ .name = "cake0_pcsout_txmeta",
|
||||
.config = "event=0x7,instance=0x46,umask=0x4" },
|
||||
{ .name = "cake1_pcsout_txmeta",
|
||||
.config = "event=0x7,instance=0x47,umask=0x4" },
|
||||
{ .name = "cake0_ftiinstat_reqalloc",
|
||||
.config = "event=0xb,instance=0x46,umask=0x4" },
|
||||
{ .name = "cake1_ftiinstat_reqalloc",
|
||||
.config = "event=0xb,instance=0x47,umask=0x4" },
|
||||
{ .name = "cake0_ftiinstat_rspalloc",
|
||||
.config = "event=0xb,instance=0x46,umask=0x8" },
|
||||
{ .name = "cake1_ftiinstat_rspalloc",
|
||||
.config = "event=0xb,instance=0x47,umask=0x8" }
|
||||
};
|
||||
|
||||
static struct amdgpu_pmu_config df_vega20_config = {
|
||||
.formats = df_vega20_formats,
|
||||
.num_formats = ARRAY_SIZE(df_vega20_formats),
|
||||
.events = df_vega20_events,
|
||||
.num_events = ARRAY_SIZE(df_vega20_events),
|
||||
.types = NULL,
|
||||
.num_types = 0
|
||||
};
|
||||
|
||||
/* Arcturus events */
|
||||
static struct amdgpu_pmu_attr arcturus_events[NUM_EVENTS_ARCTURUS_MAX] = {
|
||||
{ .name = "xgmi_link0_data_outbound",
|
||||
.config = "event=0x7,instance=0x4b,umask=0x2" },
|
||||
{ .name = "xgmi_link1_data_outbound",
|
||||
.config = "event=0x7,instance=0x4c,umask=0x2" },
|
||||
{ .name = "xgmi_link2_data_outbound",
|
||||
.config = "event=0x7,instance=0x4d,umask=0x2" },
|
||||
{ .name = "xgmi_link3_data_outbound",
|
||||
.config = "event=0x7,instance=0x4e,umask=0x2" },
|
||||
{ .name = "xgmi_link4_data_outbound",
|
||||
.config = "event=0x7,instance=0x4f,umask=0x2" },
|
||||
{ .name = "xgmi_link5_data_outbound",
|
||||
.config = "event=0x7,instance=0x50,umask=0x2" }
|
||||
};
|
||||
|
||||
static struct amdgpu_pmu_type arcturus_types[NUM_EVENT_TYPES_ARCTURUS] = {
|
||||
{ .type = AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI,
|
||||
.num_of_type = NUM_EVENTS_ARCTURUS_XGMI }
|
||||
};
|
||||
|
||||
static struct amdgpu_pmu_config arcturus_config = {
|
||||
.formats = amdgpu_pmu_formats,
|
||||
.num_formats = ARRAY_SIZE(amdgpu_pmu_formats),
|
||||
.events = arcturus_events,
|
||||
.num_events = ARRAY_SIZE(arcturus_events),
|
||||
.types = arcturus_types,
|
||||
.num_types = ARRAY_SIZE(arcturus_types)
|
||||
};
|
||||
|
||||
/* initialize perf counter */
|
||||
static int amdgpu_perf_event_init(struct perf_event *event)
|
||||
{
|
||||
@@ -53,6 +216,7 @@ static int amdgpu_perf_event_init(struct perf_event *event)
|
||||
|
||||
/* update the hw_perf_event struct with config data */
|
||||
hwc->config = event->attr.config;
|
||||
hwc->config_base = AMDGPU_PMU_PERF_TYPE_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -64,6 +228,7 @@ static void amdgpu_perf_start(struct perf_event *event, int flags)
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
int target_cntr = 0;
|
||||
|
||||
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
||||
return;
|
||||
@@ -71,19 +236,27 @@ static void amdgpu_perf_start(struct perf_event *event, int flags)
|
||||
WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
|
||||
hwc->state = 0;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
if (!(flags & PERF_EF_RELOAD))
|
||||
pe->adev->df.funcs->pmc_start(pe->adev, hwc->config, 1);
|
||||
switch (hwc->config_base) {
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||
if (!(flags & PERF_EF_RELOAD)) {
|
||||
target_cntr = pe->adev->df.funcs->pmc_start(pe->adev,
|
||||
hwc->config, 0 /* unused */,
|
||||
1 /* add counter */);
|
||||
if (target_cntr < 0)
|
||||
break;
|
||||
|
||||
pe->adev->df.funcs->pmc_start(pe->adev, hwc->config, 0);
|
||||
hwc->idx = target_cntr;
|
||||
}
|
||||
|
||||
pe->adev->df.funcs->pmc_start(pe->adev, hwc->config,
|
||||
hwc->idx, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
|
||||
}
|
||||
|
||||
/* read perf counter */
|
||||
@@ -93,16 +266,16 @@ static void amdgpu_perf_read(struct perf_event *event)
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
u64 count, prev;
|
||||
|
||||
do {
|
||||
prev = local64_read(&hwc->prev_count);
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
pe->adev->df.funcs->pmc_get_count(pe->adev, hwc->config,
|
||||
&count);
|
||||
switch (hwc->config_base) {
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||
pe->adev->df.funcs->pmc_get_count(pe->adev,
|
||||
hwc->config, hwc->idx, &count);
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
@@ -124,9 +297,11 @@ static void amdgpu_perf_stop(struct perf_event *event, int flags)
|
||||
if (hwc->state & PERF_HES_UPTODATE)
|
||||
return;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, 0);
|
||||
switch (hwc->config_base) {
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||
pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, hwc->idx,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -142,22 +317,39 @@ static void amdgpu_perf_stop(struct perf_event *event, int flags)
|
||||
hwc->state |= PERF_HES_UPTODATE;
|
||||
}
|
||||
|
||||
/* add perf counter */
|
||||
/* add perf counter */
|
||||
static int amdgpu_perf_add(struct perf_event *event, int flags)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int retval;
|
||||
|
||||
int retval = 0, target_cntr;
|
||||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case AMDGPU_PMU_PERF_TYPE_DF:
|
||||
hwc->config_base = AMDGPU_PMU_EVENT_CONFIG_TYPE_DF;
|
||||
break;
|
||||
case AMDGPU_PMU_PERF_TYPE_ALL:
|
||||
hwc->config_base = (hwc->config >>
|
||||
AMDGPU_PMU_EVENT_CONFIG_TYPE_SHIFT) &
|
||||
AMDGPU_PMU_EVENT_CONFIG_TYPE_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
retval = pe->adev->df.funcs->pmc_start(pe->adev,
|
||||
hwc->config, 1);
|
||||
switch (hwc->config_base) {
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||
target_cntr = pe->adev->df.funcs->pmc_start(pe->adev,
|
||||
hwc->config, 0 /* unused */,
|
||||
1 /* add counter */);
|
||||
if (target_cntr < 0)
|
||||
retval = target_cntr;
|
||||
else
|
||||
hwc->idx = target_cntr;
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
@@ -170,7 +362,6 @@ static int amdgpu_perf_add(struct perf_event *event, int flags)
|
||||
amdgpu_perf_start(event, PERF_EF_RELOAD);
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
/* delete perf counter */
|
||||
@@ -183,9 +374,11 @@ static void amdgpu_perf_del(struct perf_event *event, int flags)
|
||||
|
||||
amdgpu_perf_stop(event, PERF_EF_UPDATE);
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case PERF_TYPE_AMDGPU_DF:
|
||||
pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, 1);
|
||||
switch (hwc->config_base) {
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||
pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, hwc->idx,
|
||||
1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -194,25 +387,92 @@ static void amdgpu_perf_del(struct perf_event *event, int flags)
|
||||
perf_event_update_userpage(event);
|
||||
}
|
||||
|
||||
/* vega20 pmus */
|
||||
|
||||
/* init pmu tracking per pmu type */
|
||||
static int init_pmu_by_type(struct amdgpu_device *adev,
|
||||
const struct attribute_group *attr_groups[],
|
||||
char *pmu_type_name, char *pmu_file_prefix,
|
||||
unsigned int pmu_perf_type,
|
||||
unsigned int num_counters)
|
||||
static void amdgpu_pmu_create_event_attrs_by_type(
|
||||
struct attribute_group *attr_group,
|
||||
struct amdgpu_pmu_event_attribute *pmu_attr,
|
||||
struct amdgpu_pmu_attr events[],
|
||||
int s_offset,
|
||||
int e_offset,
|
||||
unsigned int type)
|
||||
{
|
||||
char pmu_name[PMU_NAME_SIZE];
|
||||
struct amdgpu_pmu_entry *pmu_entry;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
pmu_entry = kzalloc(sizeof(struct amdgpu_pmu_entry), GFP_KERNEL);
|
||||
pmu_attr += s_offset;
|
||||
|
||||
if (!pmu_entry)
|
||||
for (i = s_offset; i < e_offset; i++) {
|
||||
attr_group->attrs[i] = &pmu_attr->attr.attr;
|
||||
sysfs_attr_init(&pmu_attr->attr.attr);
|
||||
pmu_attr->attr.attr.name = events[i].name;
|
||||
pmu_attr->attr.attr.mode = 0444;
|
||||
pmu_attr->attr.show = amdgpu_pmu_event_show;
|
||||
pmu_attr->event_str = events[i].config;
|
||||
pmu_attr->type = type;
|
||||
pmu_attr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void amdgpu_pmu_create_attrs(struct attribute_group *attr_group,
|
||||
struct amdgpu_pmu_event_attribute *pmu_attr,
|
||||
struct amdgpu_pmu_attr events[],
|
||||
int num_events)
|
||||
{
|
||||
amdgpu_pmu_create_event_attrs_by_type(attr_group, pmu_attr, events, 0,
|
||||
num_events, AMDGPU_PMU_EVENT_CONFIG_TYPE_NONE);
|
||||
}
|
||||
|
||||
|
||||
static int amdgpu_pmu_alloc_pmu_attrs(
|
||||
struct attribute_group *fmt_attr_group,
|
||||
struct amdgpu_pmu_event_attribute **fmt_attr,
|
||||
struct attribute_group *evt_attr_group,
|
||||
struct amdgpu_pmu_event_attribute **evt_attr,
|
||||
struct amdgpu_pmu_config *config)
|
||||
{
|
||||
*fmt_attr = kcalloc(config->num_formats, sizeof(**fmt_attr),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!(*fmt_attr))
|
||||
return -ENOMEM;
|
||||
|
||||
pmu_entry->adev = adev;
|
||||
fmt_attr_group->attrs = kcalloc(config->num_formats + 1,
|
||||
sizeof(*fmt_attr_group->attrs), GFP_KERNEL);
|
||||
|
||||
if (!fmt_attr_group->attrs)
|
||||
goto err_fmt_attr_grp;
|
||||
|
||||
*evt_attr = kcalloc(config->num_events, sizeof(**evt_attr), GFP_KERNEL);
|
||||
|
||||
if (!(*evt_attr))
|
||||
goto err_evt_attr;
|
||||
|
||||
evt_attr_group->attrs = kcalloc(config->num_events + 1,
|
||||
sizeof(*evt_attr_group->attrs), GFP_KERNEL);
|
||||
|
||||
if (!evt_attr_group->attrs)
|
||||
goto err_evt_attr_grp;
|
||||
|
||||
return 0;
|
||||
err_evt_attr_grp:
|
||||
kfree(*evt_attr);
|
||||
err_evt_attr:
|
||||
kfree(fmt_attr_group->attrs);
|
||||
err_fmt_attr_grp:
|
||||
kfree(*fmt_attr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* init pmu tracking per pmu type */
|
||||
static int init_pmu_entry_by_type_and_add(struct amdgpu_pmu_entry *pmu_entry,
|
||||
struct amdgpu_pmu_config *config)
|
||||
{
|
||||
const struct attribute_group *attr_groups[] = {
|
||||
&pmu_entry->fmt_attr_group,
|
||||
&pmu_entry->evt_attr_group,
|
||||
NULL
|
||||
};
|
||||
char pmu_name[PMU_NAME_SIZE];
|
||||
int ret = 0, total_num_events = 0;
|
||||
|
||||
pmu_entry->pmu = (struct pmu){
|
||||
.event_init = amdgpu_perf_event_init,
|
||||
.add = amdgpu_perf_add,
|
||||
@@ -223,59 +483,178 @@ static int init_pmu_by_type(struct amdgpu_device *adev,
|
||||
.task_ctx_nr = perf_invalid_context,
|
||||
};
|
||||
|
||||
pmu_entry->pmu.attr_groups = attr_groups;
|
||||
pmu_entry->pmu_perf_type = pmu_perf_type;
|
||||
snprintf(pmu_name, PMU_NAME_SIZE, "%s_%d",
|
||||
pmu_file_prefix, adev_to_drm(adev)->primary->index);
|
||||
ret = amdgpu_pmu_alloc_pmu_attrs(&pmu_entry->fmt_attr_group,
|
||||
&pmu_entry->fmt_attr,
|
||||
&pmu_entry->evt_attr_group,
|
||||
&pmu_entry->evt_attr,
|
||||
config);
|
||||
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
amdgpu_pmu_create_attrs(&pmu_entry->fmt_attr_group, pmu_entry->fmt_attr,
|
||||
config->formats, config->num_formats);
|
||||
|
||||
if (pmu_entry->pmu_perf_type == AMDGPU_PMU_PERF_TYPE_ALL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config->num_types; i++) {
|
||||
amdgpu_pmu_create_event_attrs_by_type(
|
||||
&pmu_entry->evt_attr_group,
|
||||
pmu_entry->evt_attr,
|
||||
config->events,
|
||||
total_num_events,
|
||||
total_num_events +
|
||||
config->types[i].num_of_type,
|
||||
config->types[i].type);
|
||||
total_num_events += config->types[i].num_of_type;
|
||||
}
|
||||
} else {
|
||||
amdgpu_pmu_create_attrs(&pmu_entry->evt_attr_group,
|
||||
pmu_entry->evt_attr,
|
||||
config->events, config->num_events);
|
||||
total_num_events = config->num_events;
|
||||
}
|
||||
|
||||
pmu_entry->pmu.attr_groups = kmemdup(attr_groups, sizeof(attr_groups),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!pmu_entry->pmu.attr_groups)
|
||||
goto err_attr_group;
|
||||
|
||||
snprintf(pmu_name, PMU_NAME_SIZE, "%s_%d", pmu_entry->pmu_file_prefix,
|
||||
adev_to_drm(pmu_entry->adev)->primary->index);
|
||||
|
||||
ret = perf_pmu_register(&pmu_entry->pmu, pmu_name, -1);
|
||||
|
||||
if (ret) {
|
||||
kfree(pmu_entry);
|
||||
pr_warn("Error initializing AMDGPU %s PMUs.\n", pmu_type_name);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_register;
|
||||
|
||||
if (pmu_entry->pmu_perf_type != AMDGPU_PMU_PERF_TYPE_ALL)
|
||||
pr_info("Detected AMDGPU %s Counters. # of Counters = %d.\n",
|
||||
pmu_entry->pmu_type_name, total_num_events);
|
||||
else
|
||||
pr_info("Detected AMDGPU %d Perf Events.\n", total_num_events);
|
||||
|
||||
pr_info("Detected AMDGPU %s Counters. # of Counters = %d.\n",
|
||||
pmu_type_name, num_counters);
|
||||
|
||||
list_add_tail(&pmu_entry->entry, &amdgpu_pmu_list);
|
||||
|
||||
return 0;
|
||||
err_register:
|
||||
kfree(pmu_entry->pmu.attr_groups);
|
||||
err_attr_group:
|
||||
kfree(pmu_entry->fmt_attr_group.attrs);
|
||||
kfree(pmu_entry->fmt_attr);
|
||||
kfree(pmu_entry->evt_attr_group.attrs);
|
||||
kfree(pmu_entry->evt_attr);
|
||||
err_out:
|
||||
pr_warn("Error initializing AMDGPU %s PMUs.\n",
|
||||
pmu_entry->pmu_type_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* init amdgpu_pmu */
|
||||
int amdgpu_pmu_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
/* init df */
|
||||
ret = init_pmu_by_type(adev, df_v3_6_attr_groups,
|
||||
"DF", "amdgpu_df", PERF_TYPE_AMDGPU_DF,
|
||||
DF_V3_6_MAX_COUNTERS);
|
||||
|
||||
/* other pmu types go here*/
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* destroy all pmu data associated with target device */
|
||||
void amdgpu_pmu_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_pmu_entry *pe, *temp;
|
||||
|
||||
list_for_each_entry_safe(pe, temp, &amdgpu_pmu_list, entry) {
|
||||
if (pe->adev == adev) {
|
||||
list_del(&pe->entry);
|
||||
perf_pmu_unregister(&pe->pmu);
|
||||
kfree(pe);
|
||||
}
|
||||
if (pe->adev != adev)
|
||||
continue;
|
||||
list_del(&pe->entry);
|
||||
perf_pmu_unregister(&pe->pmu);
|
||||
kfree(pe->pmu.attr_groups);
|
||||
kfree(pe->fmt_attr_group.attrs);
|
||||
kfree(pe->fmt_attr);
|
||||
kfree(pe->evt_attr_group.attrs);
|
||||
kfree(pe->evt_attr);
|
||||
kfree(pe);
|
||||
}
|
||||
}
|
||||
|
||||
static struct amdgpu_pmu_entry *create_pmu_entry(struct amdgpu_device *adev,
|
||||
unsigned int pmu_type,
|
||||
char *pmu_type_name,
|
||||
char *pmu_file_prefix)
|
||||
{
|
||||
struct amdgpu_pmu_entry *pmu_entry;
|
||||
|
||||
pmu_entry = kzalloc(sizeof(struct amdgpu_pmu_entry), GFP_KERNEL);
|
||||
|
||||
if (!pmu_entry)
|
||||
return pmu_entry;
|
||||
|
||||
pmu_entry->adev = adev;
|
||||
pmu_entry->fmt_attr_group.name = "format";
|
||||
pmu_entry->fmt_attr_group.attrs = NULL;
|
||||
pmu_entry->evt_attr_group.name = "events";
|
||||
pmu_entry->evt_attr_group.attrs = NULL;
|
||||
pmu_entry->pmu_perf_type = pmu_type;
|
||||
pmu_entry->pmu_type_name = pmu_type_name;
|
||||
pmu_entry->pmu_file_prefix = pmu_file_prefix;
|
||||
|
||||
return pmu_entry;
|
||||
}
|
||||
|
||||
/* init amdgpu_pmu */
|
||||
int amdgpu_pmu_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct amdgpu_pmu_entry *pmu_entry, *pmu_entry_df;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
pmu_entry_df = create_pmu_entry(adev, AMDGPU_PMU_PERF_TYPE_DF,
|
||||
"DF", "amdgpu_df");
|
||||
|
||||
if (!pmu_entry_df)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = init_pmu_entry_by_type_and_add(pmu_entry_df,
|
||||
&df_vega20_config);
|
||||
|
||||
if (ret) {
|
||||
kfree(pmu_entry_df);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pmu_entry = create_pmu_entry(adev, AMDGPU_PMU_PERF_TYPE_ALL,
|
||||
"", "amdgpu");
|
||||
|
||||
if (!pmu_entry) {
|
||||
amdgpu_pmu_fini(adev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = init_pmu_entry_by_type_and_add(pmu_entry,
|
||||
&vega20_config);
|
||||
|
||||
if (ret) {
|
||||
kfree(pmu_entry);
|
||||
amdgpu_pmu_fini(adev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
pmu_entry = create_pmu_entry(adev, AMDGPU_PMU_PERF_TYPE_ALL,
|
||||
"", "amdgpu");
|
||||
if (!pmu_entry)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = init_pmu_entry_by_type_and_add(pmu_entry,
|
||||
&arcturus_config);
|
||||
|
||||
if (ret) {
|
||||
kfree(pmu_entry);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,38 @@
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Jonathan Kim <jonathan.kim@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AMDGPU_PMU_H_
|
||||
#define _AMDGPU_PMU_H_
|
||||
|
||||
/* PMU types. */
|
||||
enum amdgpu_pmu_perf_type {
|
||||
PERF_TYPE_AMDGPU_DF = 0,
|
||||
PERF_TYPE_AMDGPU_MAX
|
||||
AMDGPU_PMU_PERF_TYPE_NONE = 0,
|
||||
AMDGPU_PMU_PERF_TYPE_DF,
|
||||
AMDGPU_PMU_PERF_TYPE_ALL
|
||||
};
|
||||
|
||||
/*
|
||||
* PMU type AMDGPU_PMU_PERF_TYPE_ALL can hold events of different "type"
|
||||
* configurations. Event config types are parsed from the 64-bit raw
|
||||
* config (See EVENT_CONFIG_TYPE_SHIFT and EVENT_CONFIG_TYPE_MASK) and
|
||||
* are registered into the HW perf events config_base.
|
||||
*
|
||||
* PMU types with only a single event configuration type
|
||||
* (non-AMDGPU_PMU_PERF_TYPE_ALL) have their event config type auto generated
|
||||
* when the performance counter is added.
|
||||
*/
|
||||
enum amdgpu_pmu_event_config_type {
|
||||
AMDGPU_PMU_EVENT_CONFIG_TYPE_NONE = 0,
|
||||
AMDGPU_PMU_EVENT_CONFIG_TYPE_DF,
|
||||
AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI,
|
||||
AMDGPU_PMU_EVENT_CONFIG_TYPE_MAX
|
||||
};
|
||||
|
||||
#define AMDGPU_PMU_EVENT_CONFIG_TYPE_SHIFT 56
|
||||
#define AMDGPU_PMU_EVENT_CONFIG_TYPE_MASK 0xff
|
||||
|
||||
int amdgpu_pmu_init(struct amdgpu_device *adev);
|
||||
void amdgpu_pmu_fini(struct amdgpu_device *adev);
|
||||
|
||||
|
||||
@@ -100,6 +100,8 @@ static int psp_early_init(void *handle)
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
case CHIP_VANGOGH:
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
psp_v11_0_set_psp_funcs(psp);
|
||||
psp->autoload_supported = true;
|
||||
break;
|
||||
@@ -288,6 +290,8 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED ||
|
||||
psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev);
|
||||
|
||||
memcpy((void*)&cmd->resp, (void*)&psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp));
|
||||
|
||||
/* In some cases, psp response status is not 0 even there is no
|
||||
* problem while the command is submitted. Some version of PSP FW
|
||||
* doesn't write 0 to that field.
|
||||
@@ -308,9 +312,6 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
}
|
||||
}
|
||||
|
||||
/* get xGMI session id from response buffer */
|
||||
cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id;
|
||||
|
||||
if (ucode) {
|
||||
ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;
|
||||
ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;
|
||||
@@ -509,6 +510,37 @@ static int psp_tmr_terminate(struct psp_context *psp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
|
||||
uint64_t *output_ptr)
|
||||
{
|
||||
int ret;
|
||||
struct psp_gfx_cmd_resp *cmd;
|
||||
|
||||
if (!output_ptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_sriov_vf(psp->adev))
|
||||
return 0;
|
||||
|
||||
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION;
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
|
||||
if (!ret) {
|
||||
*output_ptr = ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_lo) +
|
||||
((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32);
|
||||
}
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint64_t asd_mc, uint32_t size)
|
||||
{
|
||||
@@ -624,14 +656,14 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint64_t ta_shared_mc,
|
||||
uint32_t ta_shared_size)
|
||||
{
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_TA;
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_TA;
|
||||
cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc);
|
||||
cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc);
|
||||
cmd->cmd.cmd_load_ta.app_len = ta_bin_size;
|
||||
cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc);
|
||||
cmd->cmd.cmd_load_ta.app_len = ta_bin_size;
|
||||
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(ta_shared_mc);
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(ta_shared_mc);
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size;
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size;
|
||||
}
|
||||
|
||||
static int psp_xgmi_init_shared_buf(struct psp_context *psp)
|
||||
@@ -655,9 +687,9 @@ static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint32_t ta_cmd_id,
|
||||
uint32_t session_id)
|
||||
{
|
||||
cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
|
||||
cmd->cmd.cmd_invoke_cmd.session_id = session_id;
|
||||
cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
|
||||
cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
|
||||
cmd->cmd.cmd_invoke_cmd.session_id = session_id;
|
||||
cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
|
||||
}
|
||||
|
||||
static int psp_ta_invoke(struct psp_context *psp,
|
||||
@@ -806,7 +838,7 @@ int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id)
|
||||
struct ta_xgmi_shared_memory *xgmi_cmd;
|
||||
int ret;
|
||||
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory*)psp->xgmi_context.xgmi_shared_buf;
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
|
||||
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
|
||||
|
||||
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID;
|
||||
@@ -826,7 +858,7 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
|
||||
struct ta_xgmi_shared_memory *xgmi_cmd;
|
||||
int ret;
|
||||
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory*)psp->xgmi_context.xgmi_shared_buf;
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
|
||||
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
|
||||
|
||||
xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID;
|
||||
@@ -854,7 +886,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
|
||||
if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES)
|
||||
return -EINVAL;
|
||||
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory*)psp->xgmi_context.xgmi_shared_buf;
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
|
||||
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
|
||||
|
||||
/* Fill in the shared memory with topology information as input */
|
||||
@@ -898,7 +930,7 @@ int psp_xgmi_set_topology_info(struct psp_context *psp,
|
||||
if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES)
|
||||
return -EINVAL;
|
||||
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory*)psp->xgmi_context.xgmi_shared_buf;
|
||||
xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf;
|
||||
memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
|
||||
|
||||
topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info;
|
||||
@@ -962,7 +994,7 @@ static int psp_ras_load(struct psp_context *psp)
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
|
||||
ras_cmd = (struct ta_ras_shared_memory*)psp->ras.ras_shared_buf;
|
||||
ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
|
||||
|
||||
if (!ret) {
|
||||
psp->ras.session_id = cmd->resp.session_id;
|
||||
@@ -1884,7 +1916,7 @@ static int psp_execute_np_fw_load(struct psp_context *psp,
|
||||
static int psp_load_smu_fw(struct psp_context *psp)
|
||||
{
|
||||
int ret;
|
||||
struct amdgpu_device* adev = psp->adev;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
struct amdgpu_firmware_info *ucode =
|
||||
&adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
|
||||
struct amdgpu_ras *ras = psp->ras.ras;
|
||||
@@ -1893,7 +1925,8 @@ static int psp_load_smu_fw(struct psp_context *psp)
|
||||
return 0;
|
||||
|
||||
|
||||
if (amdgpu_in_reset(adev) && ras && ras->supported) {
|
||||
if (amdgpu_in_reset(adev) && ras && ras->supported &&
|
||||
adev->asic_type == CHIP_ARCTURUS) {
|
||||
ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
|
||||
if (ret) {
|
||||
DRM_WARN("Failed to set MP1 state prepare for reload\n");
|
||||
@@ -1950,7 +1983,7 @@ static int psp_np_fw_load(struct psp_context *psp)
|
||||
{
|
||||
int i, ret;
|
||||
struct amdgpu_firmware_info *ucode;
|
||||
struct amdgpu_device* adev = psp->adev;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp->autoload_supported &&
|
||||
!psp->pmfw_centralized_cstate_management) {
|
||||
@@ -1974,8 +2007,8 @@ static int psp_np_fw_load(struct psp_context *psp)
|
||||
continue;
|
||||
|
||||
if (psp->autoload_supported &&
|
||||
(adev->asic_type == CHIP_SIENNA_CICHLID ||
|
||||
adev->asic_type == CHIP_NAVY_FLOUNDER) &&
|
||||
(adev->asic_type >= CHIP_SIENNA_CICHLID &&
|
||||
adev->asic_type <= CHIP_DIMGREY_CAVEFISH) &&
|
||||
(ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 ||
|
||||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 ||
|
||||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3))
|
||||
@@ -2390,7 +2423,7 @@ int psp_init_asd_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[30];
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *asd_hdr;
|
||||
int err = 0;
|
||||
|
||||
@@ -2422,11 +2455,47 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int psp_init_sos_microcode(struct psp_context *psp,
|
||||
int psp_init_toc_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[30];
|
||||
const struct psp_firmware_header_v1_0 *toc_hdr;
|
||||
int err = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for toc microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.toc_fw, fw_name, adev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.toc_fw);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data;
|
||||
adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
|
||||
adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->ucode_feature_version);
|
||||
adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
|
||||
adev->psp.toc_start_addr = (uint8_t *)toc_hdr +
|
||||
le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
|
||||
return 0;
|
||||
out:
|
||||
dev_err(adev->dev, "fail to request/validate toc microcode\n");
|
||||
release_firmware(adev->psp.toc_fw);
|
||||
adev->psp.toc_fw = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
int psp_init_sos_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *sos_hdr;
|
||||
const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
|
||||
const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
|
||||
@@ -2505,9 +2574,9 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int parse_ta_bin_descriptor(struct psp_context *psp,
|
||||
const struct ta_fw_bin_desc *desc,
|
||||
const struct ta_firmware_header_v2_0 *ta_hdr)
|
||||
static int parse_ta_bin_descriptor(struct psp_context *psp,
|
||||
const struct ta_fw_bin_desc *desc,
|
||||
const struct ta_firmware_header_v2_0 *ta_hdr)
|
||||
{
|
||||
uint8_t *ucode_start_addr = NULL;
|
||||
|
||||
@@ -2520,9 +2589,9 @@ int parse_ta_bin_descriptor(struct psp_context *psp,
|
||||
|
||||
switch (desc->fw_type) {
|
||||
case TA_FW_TYPE_PSP_ASD:
|
||||
psp->asd_fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->asd_fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->asd_feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->asd_ucode_size = le32_to_cpu(desc->size_bytes);
|
||||
psp->asd_ucode_size = le32_to_cpu(desc->size_bytes);
|
||||
psp->asd_start_addr = ucode_start_addr;
|
||||
psp->asd_fw = psp->ta_fw;
|
||||
break;
|
||||
@@ -2563,7 +2632,7 @@ int psp_init_ta_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[30];
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct ta_firmware_header_v2_0 *ta_hdr;
|
||||
int err = 0;
|
||||
int ta_index = 0;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define PSP_DTM_SHARED_MEM_SIZE 0x4000
|
||||
#define PSP_RAP_SHARED_MEM_SIZE 0x4000
|
||||
#define PSP_SHARED_MEM_SIZE 0x4000
|
||||
#define PSP_FW_NAME_LEN 0x24
|
||||
|
||||
struct psp_context;
|
||||
struct psp_xgmi_node_info;
|
||||
@@ -253,6 +254,11 @@ struct psp_context
|
||||
uint32_t asd_ucode_size;
|
||||
uint8_t *asd_start_addr;
|
||||
|
||||
/* toc firmware */
|
||||
const struct firmware *toc_fw;
|
||||
uint32_t toc_fw_version;
|
||||
uint32_t toc_feature_version;
|
||||
|
||||
/* fence buffer */
|
||||
struct amdgpu_bo *fence_buf_bo;
|
||||
uint64_t fence_buf_mc_addr;
|
||||
@@ -386,8 +392,12 @@ int psp_ring_cmd_submit(struct psp_context *psp,
|
||||
int index);
|
||||
int psp_init_asd_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_init_toc_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_init_sos_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_init_ta_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
|
||||
uint64_t *output_ptr);
|
||||
#endif
|
||||
|
||||
@@ -80,6 +80,8 @@ enum amdgpu_ras_retire_page_reservation {
|
||||
|
||||
atomic_t amdgpu_ras_in_intr = ATOMIC_INIT(0);
|
||||
|
||||
static bool amdgpu_ras_check_bad_page_unlock(struct amdgpu_ras *con,
|
||||
uint64_t addr);
|
||||
static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
|
||||
uint64_t addr);
|
||||
|
||||
@@ -516,9 +518,9 @@ struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
|
||||
/* obj end */
|
||||
|
||||
static void amdgpu_ras_parse_status_code(struct amdgpu_device *adev,
|
||||
const char* invoke_type,
|
||||
const char* block_name,
|
||||
enum ta_ras_status ret)
|
||||
const char* invoke_type,
|
||||
const char* block_name,
|
||||
enum ta_ras_status ret)
|
||||
{
|
||||
switch (ret) {
|
||||
case TA_RAS_STATUS__SUCCESS:
|
||||
@@ -607,7 +609,7 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
|
||||
if (!con)
|
||||
return -EINVAL;
|
||||
|
||||
info = kzalloc(sizeof(union ta_ras_cmd_input), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(union ta_ras_cmd_input), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -903,13 +905,6 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_ras_error_cure(struct amdgpu_device *adev,
|
||||
struct ras_cure_if *info)
|
||||
{
|
||||
/* psp fw has no cure interface for now. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the total error counts on all IPs */
|
||||
unsigned long amdgpu_ras_query_error_count(struct amdgpu_device *adev,
|
||||
bool is_ce)
|
||||
@@ -953,7 +948,7 @@ static char *amdgpu_ras_badpage_flags_str(unsigned int flags)
|
||||
case AMDGPU_RAS_RETIRE_PAGE_FAULT:
|
||||
default:
|
||||
return "F";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1474,8 +1469,8 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
/* Parse RdRspStatus and WrRspStatus */
|
||||
void amdgpu_ras_error_status_query(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info)
|
||||
static void amdgpu_ras_error_status_query(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info)
|
||||
{
|
||||
/*
|
||||
* Only two block need to query read/write
|
||||
@@ -1548,10 +1543,12 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev,
|
||||
.size = AMDGPU_GPU_PAGE_SIZE,
|
||||
.flags = AMDGPU_RAS_RETIRE_PAGE_RESERVED,
|
||||
};
|
||||
|
||||
if (data->last_reserved <= i)
|
||||
ret = amdgpu_vram_mgr_query_page_status(
|
||||
ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM),
|
||||
data->bps[i].retired_page);
|
||||
if (ret == -EBUSY)
|
||||
(*bps)[i].flags = AMDGPU_RAS_RETIRE_PAGE_PENDING;
|
||||
else if (data->bps_bo[i] == NULL)
|
||||
else if (ret == -ENOENT)
|
||||
(*bps)[i].flags = AMDGPU_RAS_RETIRE_PAGE_FAULT;
|
||||
}
|
||||
|
||||
@@ -1603,12 +1600,9 @@ static int amdgpu_ras_realloc_eh_data_space(struct amdgpu_device *adev,
|
||||
unsigned int new_space = old_space + pages;
|
||||
unsigned int align_space = ALIGN(new_space, 512);
|
||||
void *bps = kmalloc(align_space * sizeof(*data->bps), GFP_KERNEL);
|
||||
struct amdgpu_bo **bps_bo =
|
||||
kmalloc(align_space * sizeof(*data->bps_bo), GFP_KERNEL);
|
||||
|
||||
if (!bps || !bps_bo) {
|
||||
if (!bps) {
|
||||
kfree(bps);
|
||||
kfree(bps_bo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -1617,14 +1611,8 @@ static int amdgpu_ras_realloc_eh_data_space(struct amdgpu_device *adev,
|
||||
data->count * sizeof(*data->bps));
|
||||
kfree(data->bps);
|
||||
}
|
||||
if (data->bps_bo) {
|
||||
memcpy(bps_bo, data->bps_bo,
|
||||
data->count * sizeof(*data->bps_bo));
|
||||
kfree(data->bps_bo);
|
||||
}
|
||||
|
||||
data->bps = bps;
|
||||
data->bps_bo = bps_bo;
|
||||
data->space_left += align_space - old_space;
|
||||
return 0;
|
||||
}
|
||||
@@ -1636,6 +1624,7 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data;
|
||||
int ret = 0;
|
||||
uint32_t i;
|
||||
|
||||
if (!con || !con->eh_data || !bps || pages <= 0)
|
||||
return 0;
|
||||
@@ -1645,16 +1634,26 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
||||
if (!data)
|
||||
goto out;
|
||||
|
||||
if (data->space_left <= pages)
|
||||
if (amdgpu_ras_realloc_eh_data_space(adev, data, pages)) {
|
||||
for (i = 0; i < pages; i++) {
|
||||
if (amdgpu_ras_check_bad_page_unlock(con,
|
||||
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT))
|
||||
continue;
|
||||
|
||||
if (!data->space_left &&
|
||||
amdgpu_ras_realloc_eh_data_space(adev, data, 256)) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&data->bps[data->count], bps, pages * sizeof(*data->bps));
|
||||
data->count += pages;
|
||||
data->space_left -= pages;
|
||||
amdgpu_vram_mgr_reserve_range(
|
||||
ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM),
|
||||
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT,
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
memcpy(&data->bps[data->count], &bps[i], sizeof(*data->bps));
|
||||
data->count++;
|
||||
data->space_left--;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
|
||||
@@ -1665,7 +1664,7 @@ out:
|
||||
* write error record array to eeprom, the function should be
|
||||
* protected by recovery_lock
|
||||
*/
|
||||
static int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
|
||||
int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data;
|
||||
@@ -1727,6 +1726,20 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool amdgpu_ras_check_bad_page_unlock(struct amdgpu_ras *con,
|
||||
uint64_t addr)
|
||||
{
|
||||
struct ras_err_handler_data *data = con->eh_data;
|
||||
int i;
|
||||
|
||||
addr >>= AMDGPU_GPU_PAGE_SHIFT;
|
||||
for (i = 0; i < data->count; i++)
|
||||
if (addr == data->bps[i].retired_page)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if an address belongs to bad page
|
||||
*
|
||||
@@ -1736,26 +1749,13 @@ static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
|
||||
uint64_t addr)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data;
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
||||
if (!con || !con->eh_data)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
data = con->eh_data;
|
||||
if (!data)
|
||||
goto out;
|
||||
|
||||
addr >>= AMDGPU_GPU_PAGE_SHIFT;
|
||||
for (i = 0; i < data->count; i++)
|
||||
if (addr == data->bps[i].retired_page) {
|
||||
ret = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
ret = amdgpu_ras_check_bad_page_unlock(con, addr);
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -1801,80 +1801,6 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
/* called in gpu recovery/init */
|
||||
int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data;
|
||||
uint64_t bp;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
int i, ret = 0;
|
||||
|
||||
/* Not reserve bad page when amdgpu_bad_page_threshold == 0. */
|
||||
if (!con || !con->eh_data || (amdgpu_bad_page_threshold == 0))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
data = con->eh_data;
|
||||
if (!data)
|
||||
goto out;
|
||||
/* reserve vram at driver post stage. */
|
||||
for (i = data->last_reserved; i < data->count; i++) {
|
||||
bp = data->bps[i].retired_page;
|
||||
|
||||
/* There are two cases of reserve error should be ignored:
|
||||
* 1) a ras bad page has been allocated (used by someone);
|
||||
* 2) a ras bad page has been reserved (duplicate error injection
|
||||
* for one page);
|
||||
*/
|
||||
if (amdgpu_bo_create_kernel_at(adev, bp << AMDGPU_GPU_PAGE_SHIFT,
|
||||
AMDGPU_GPU_PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&bo, NULL))
|
||||
dev_warn(adev->dev, "RAS WARN: reserve vram for "
|
||||
"retired page %llx fail\n", bp);
|
||||
|
||||
data->bps_bo[i] = bo;
|
||||
data->last_reserved = i + 1;
|
||||
bo = NULL;
|
||||
}
|
||||
|
||||
/* continue to save bad pages to eeprom even reesrve_vram fails */
|
||||
ret = amdgpu_ras_save_bad_pages(adev);
|
||||
out:
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* called when driver unload */
|
||||
static int amdgpu_ras_release_bad_pages(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_err_handler_data *data;
|
||||
struct amdgpu_bo *bo;
|
||||
int i;
|
||||
|
||||
if (!con || !con->eh_data)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
data = con->eh_data;
|
||||
if (!data)
|
||||
goto out;
|
||||
|
||||
for (i = data->last_reserved - 1; i >= 0; i--) {
|
||||
bo = data->bps_bo[i];
|
||||
|
||||
amdgpu_bo_free_kernel(&bo, NULL, NULL);
|
||||
|
||||
data->bps_bo[i] = bo;
|
||||
data->last_reserved = i;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
@@ -1914,18 +1840,12 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
||||
ret = amdgpu_ras_load_bad_pages(adev);
|
||||
if (ret)
|
||||
goto free;
|
||||
ret = amdgpu_ras_reserve_bad_pages(adev);
|
||||
if (ret)
|
||||
goto release;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
release:
|
||||
amdgpu_ras_release_bad_pages(adev);
|
||||
free:
|
||||
kfree((*data)->bps);
|
||||
kfree((*data)->bps_bo);
|
||||
kfree(*data);
|
||||
con->eh_data = NULL;
|
||||
out:
|
||||
@@ -1953,12 +1873,10 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
|
||||
cancel_work_sync(&con->recovery_work);
|
||||
amdgpu_ras_release_bad_pages(adev);
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
con->eh_data = NULL;
|
||||
kfree(data->bps);
|
||||
kfree(data->bps_bo);
|
||||
kfree(data);
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
|
||||
@@ -2153,7 +2071,7 @@ void amdgpu_ras_late_fini(struct amdgpu_device *adev,
|
||||
|
||||
amdgpu_ras_sysfs_remove(adev, ras_block);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0)
|
||||
#define AMDGPU_RAS_FLAG_INIT_NEED_RESET (0x1 << 1)
|
||||
#define AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV (0x1 << 2)
|
||||
|
||||
enum amdgpu_ras_block {
|
||||
AMDGPU_RAS_BLOCK__UMC = 0,
|
||||
@@ -363,14 +362,10 @@ struct ras_err_data {
|
||||
struct ras_err_handler_data {
|
||||
/* point to bad page records array */
|
||||
struct eeprom_table_record *bps;
|
||||
/* point to reserved bo array */
|
||||
struct amdgpu_bo **bps_bo;
|
||||
/* the count of entries */
|
||||
int count;
|
||||
/* the space can place new entries */
|
||||
int space_left;
|
||||
/* last reserved entry's index + 1 */
|
||||
int last_reserved;
|
||||
};
|
||||
|
||||
typedef int (*ras_ih_cb)(struct amdgpu_device *adev,
|
||||
@@ -506,22 +501,12 @@ bool amdgpu_ras_check_err_threshold(struct amdgpu_device *adev);
|
||||
int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
||||
struct eeprom_table_record *bps, int pages);
|
||||
|
||||
int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev);
|
||||
int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev);
|
||||
|
||||
static inline int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
/*
|
||||
* Save bad page to eeprom before gpu reset, i2c may be unstable
|
||||
* in gpu reset.
|
||||
*
|
||||
* Also, exclude the case when ras recovery issuer is
|
||||
* eeprom page write itself.
|
||||
*/
|
||||
if (!(ras->flags & AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV) && in_task())
|
||||
amdgpu_ras_reserve_bad_pages(adev);
|
||||
|
||||
if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0)
|
||||
schedule_work(&ras->recovery_work);
|
||||
return 0;
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include <linux/bits.h>
|
||||
#include "atom.h"
|
||||
|
||||
#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0
|
||||
#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0
|
||||
|
||||
/*
|
||||
* The 2 macros bellow represent the actual size in bytes that
|
||||
@@ -124,11 +124,11 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade
|
||||
{
|
||||
uint32_t *pp = (uint32_t *)buff;
|
||||
|
||||
hdr->header = le32_to_cpu(pp[0]);
|
||||
hdr->version = le32_to_cpu(pp[1]);
|
||||
hdr->header = le32_to_cpu(pp[0]);
|
||||
hdr->version = le32_to_cpu(pp[1]);
|
||||
hdr->first_rec_offset = le32_to_cpu(pp[2]);
|
||||
hdr->tbl_size = le32_to_cpu(pp[3]);
|
||||
hdr->checksum = le32_to_cpu(pp[4]);
|
||||
hdr->tbl_size = le32_to_cpu(pp[3]);
|
||||
hdr->checksum = le32_to_cpu(pp[4]);
|
||||
}
|
||||
|
||||
static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
|
||||
@@ -149,7 +149,11 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
|
||||
|
||||
msg.addr = control->i2c_address;
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1);
|
||||
up_read(&adev->reset_sem);
|
||||
|
||||
if (ret < 1)
|
||||
DRM_ERROR("Failed to write EEPROM table header, ret:%d", ret);
|
||||
|
||||
@@ -475,7 +479,6 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
|
||||
int i, ret = 0;
|
||||
struct i2c_msg *msgs, *msg;
|
||||
unsigned char *buffs, *buff;
|
||||
bool sched_ras_recovery = false;
|
||||
struct eeprom_table_record *record;
|
||||
struct amdgpu_device *adev = to_amdgpu_device(control);
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
@@ -513,7 +516,6 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
|
||||
"Saved bad pages(%d) reaches threshold value(%d).\n",
|
||||
control->num_recs + num, ras->bad_page_cnt_threshold);
|
||||
control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD;
|
||||
sched_ras_recovery = true;
|
||||
}
|
||||
|
||||
/* In case of overflow just start from beginning to not lose newest records */
|
||||
@@ -557,7 +559,11 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
|
||||
control->next_addr += EEPROM_TABLE_RECORD_SIZE;
|
||||
}
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
ret = i2c_transfer(&adev->pm.smu_i2c, msgs, num);
|
||||
up_read(&adev->reset_sem);
|
||||
|
||||
if (ret < 1) {
|
||||
DRM_ERROR("Failed to process EEPROM table records, ret:%d", ret);
|
||||
|
||||
@@ -595,20 +601,6 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
|
||||
__update_tbl_checksum(control, records, num, old_hdr_byte_sum);
|
||||
|
||||
__update_table_header(control, buffs);
|
||||
|
||||
if (sched_ras_recovery) {
|
||||
/*
|
||||
* Before scheduling ras recovery, assert the related
|
||||
* flag first, which shall bypass common bad page
|
||||
* reservation execution in amdgpu_ras_reset_gpu.
|
||||
*/
|
||||
amdgpu_ras_get_context(adev)->flags |=
|
||||
AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV;
|
||||
|
||||
dev_warn(adev->dev, "Conduct ras recovery due to bad "
|
||||
"page threshold reached.\n");
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
} else if (!__validate_tbl_checksum(control, records, num)) {
|
||||
DRM_WARN("EEPROM Table checksum mismatch!");
|
||||
/* TODO Uncomment when EEPROM read/write is relliable */
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
/**
|
||||
* amdgpu_ring_alloc - allocate space on the ring buffer
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: amdgpu_ring structure holding ring information
|
||||
* @ndw: number of dwords to allocate in the ring buffer
|
||||
*
|
||||
@@ -95,7 +94,8 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
|
||||
amdgpu_ring_write(ring, ring->funcs->nop);
|
||||
}
|
||||
|
||||
/** amdgpu_ring_generic_pad_ib - pad IB with NOP packets
|
||||
/**
|
||||
* amdgpu_ring_generic_pad_ib - pad IB with NOP packets
|
||||
*
|
||||
* @ring: amdgpu_ring structure holding ring information
|
||||
* @ib: IB to add NOP packets to
|
||||
@@ -112,7 +112,6 @@ void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib)
|
||||
* amdgpu_ring_commit - tell the GPU to execute the new
|
||||
* commands on the ring buffer
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: amdgpu_ring structure holding ring information
|
||||
*
|
||||
* Update the wptr (write pointer) to tell the GPU to
|
||||
@@ -155,8 +154,10 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring)
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: amdgpu_ring structure holding ring information
|
||||
* @max_ndw: maximum number of dw for ring alloc
|
||||
* @nop: nop packet for this ring
|
||||
* @max_dw: maximum number of dw for ring alloc
|
||||
* @irq_src: interrupt source to use for this ring
|
||||
* @irq_type: interrupt type to use for this ring
|
||||
* @hw_prio: ring priority (NORMAL/HIGH)
|
||||
*
|
||||
* Initialize the driver information for the selected ring (all asics).
|
||||
* Returns 0 on success, error on failure.
|
||||
@@ -276,7 +277,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
||||
/**
|
||||
* amdgpu_ring_fini - tear down the driver ring struct.
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: amdgpu_ring structure holding ring information
|
||||
*
|
||||
* Tear down the driver information for the selected ring (all asics).
|
||||
@@ -310,7 +310,7 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
|
||||
/**
|
||||
* amdgpu_ring_emit_reg_write_reg_wait_helper - ring helper
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: ring to write to
|
||||
* @reg0: register to write
|
||||
* @reg1: register to wait on
|
||||
* @ref: reference value to write/wait on
|
||||
@@ -396,7 +396,7 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
|
||||
return result;
|
||||
|
||||
value = ring->ring[(*pos - 12)/4];
|
||||
r = put_user(value, (uint32_t*)buf);
|
||||
r = put_user(value, (uint32_t *)buf);
|
||||
if (r)
|
||||
return r;
|
||||
buf += 4;
|
||||
|
||||
@@ -75,7 +75,7 @@ int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev,
|
||||
struct amdgpu_sa_manager *sa_manager)
|
||||
struct amdgpu_sa_manager *sa_manager)
|
||||
{
|
||||
struct amdgpu_sa_bo *sa_bo, *tmp;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <drm/amdgpu_drm.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
|
||||
#include "amdgpu_sched.h"
|
||||
#include "amdgpu_vm.h"
|
||||
|
||||
int amdgpu_to_sched_priority(int amdgpu_priority,
|
||||
|
||||
@@ -126,7 +126,7 @@ int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev,
|
||||
goto free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
late_fini:
|
||||
amdgpu_ras_late_fini(adev, adev->sdma.ras_if, ih_info);
|
||||
|
||||
37
drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
Normal file
37
drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef __AMDGPU_SMUIO_H__
|
||||
#define __AMDGPU_SMUIO_H__
|
||||
|
||||
struct amdgpu_smuio_funcs {
|
||||
u32 (*get_rom_index_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_rom_data_offset)(struct amdgpu_device *adev);
|
||||
void (*update_rom_clock_gating)(struct amdgpu_device *adev, bool enable);
|
||||
void (*get_clock_gating_state)(struct amdgpu_device *adev, u32 *flags);
|
||||
};
|
||||
|
||||
struct amdgpu_smuio {
|
||||
const struct amdgpu_smuio_funcs *funcs;
|
||||
};
|
||||
|
||||
#endif /* __AMDGPU_SMUIO_H__ */
|
||||
@@ -78,7 +78,7 @@ static bool amdgpu_sync_same_dev(struct amdgpu_device *adev,
|
||||
/**
|
||||
* amdgpu_sync_get_owner - extract the owner of a fence
|
||||
*
|
||||
* @fence: fence get the owner from
|
||||
* @f: fence get the owner from
|
||||
*
|
||||
* Extract who originally created the fence.
|
||||
*/
|
||||
@@ -172,7 +172,6 @@ int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f)
|
||||
/**
|
||||
* amdgpu_sync_vm_fence - remember to sync to this VM fence
|
||||
*
|
||||
* @adev: amdgpu device
|
||||
* @sync: sync object to add fence to
|
||||
* @fence: the VM fence to add
|
||||
*
|
||||
@@ -190,6 +189,7 @@ int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence)
|
||||
/**
|
||||
* amdgpu_sync_resv - sync to a reservation object
|
||||
*
|
||||
* @adev: amdgpu device
|
||||
* @sync: sync object to add fences from reservation object to
|
||||
* @resv: reservation object with embedded fence
|
||||
* @mode: how owner affects which fences we sync to
|
||||
|
||||
@@ -42,16 +42,11 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
|
||||
size = 1024 * 1024;
|
||||
|
||||
/* Number of tests =
|
||||
* (Total GTT - IB pool - writeback page - ring buffers) / test size
|
||||
* (Total GTT - gart_pin_size - (2 transfer windows for buffer moves)) / test size
|
||||
*/
|
||||
n = adev->gmc.gart_size - AMDGPU_IB_POOL_SIZE;
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
|
||||
if (adev->rings[i])
|
||||
n -= adev->rings[i]->ring_size;
|
||||
if (adev->wb.wb_obj)
|
||||
n -= AMDGPU_GPU_PAGE_SIZE;
|
||||
if (adev->irq.ih.ring_obj)
|
||||
n -= adev->irq.ih.ring_size;
|
||||
n = adev->gmc.gart_size - atomic64_read(&adev->gart_pin_size);
|
||||
n -= AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS *
|
||||
AMDGPU_GPU_PAGE_SIZE;
|
||||
n /= size;
|
||||
|
||||
gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL);
|
||||
@@ -157,10 +152,10 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
|
||||
i, *vram_start, gart_start,
|
||||
(unsigned long long)
|
||||
(gart_addr - adev->gmc.gart_start +
|
||||
(void*)gart_start - gtt_map),
|
||||
(void *)gart_start - gtt_map),
|
||||
(unsigned long long)
|
||||
(vram_addr - adev->gmc.vram_start +
|
||||
(void*)gart_start - gtt_map));
|
||||
(void *)gart_start - gtt_map));
|
||||
amdgpu_bo_kunmap(vram_obj);
|
||||
goto out_lclean_unpin;
|
||||
}
|
||||
@@ -203,10 +198,10 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
|
||||
i, *gart_start, vram_start,
|
||||
(unsigned long long)
|
||||
(vram_addr - adev->gmc.vram_start +
|
||||
(void*)vram_start - vram_map),
|
||||
(void *)vram_start - vram_map),
|
||||
(unsigned long long)
|
||||
(gart_addr - adev->gmc.gart_start +
|
||||
(void*)vram_start - vram_map));
|
||||
(void *)vram_start - vram_map));
|
||||
amdgpu_bo_kunmap(gtt_obj[i]);
|
||||
goto out_lclean_unpin;
|
||||
}
|
||||
|
||||
@@ -366,15 +366,15 @@ TRACE_EVENT(amdgpu_vm_update_ptes,
|
||||
|
||||
TRACE_EVENT(amdgpu_vm_set_ptes,
|
||||
TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
|
||||
uint32_t incr, uint64_t flags, bool direct),
|
||||
TP_ARGS(pe, addr, count, incr, flags, direct),
|
||||
uint32_t incr, uint64_t flags, bool immediate),
|
||||
TP_ARGS(pe, addr, count, incr, flags, immediate),
|
||||
TP_STRUCT__entry(
|
||||
__field(u64, pe)
|
||||
__field(u64, addr)
|
||||
__field(u32, count)
|
||||
__field(u32, incr)
|
||||
__field(u64, flags)
|
||||
__field(bool, direct)
|
||||
__field(bool, immediate)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
@@ -383,32 +383,32 @@ TRACE_EVENT(amdgpu_vm_set_ptes,
|
||||
__entry->count = count;
|
||||
__entry->incr = incr;
|
||||
__entry->flags = flags;
|
||||
__entry->direct = direct;
|
||||
__entry->immediate = immediate;
|
||||
),
|
||||
TP_printk("pe=%010Lx, addr=%010Lx, incr=%u, flags=%llx, count=%u, "
|
||||
"direct=%d", __entry->pe, __entry->addr, __entry->incr,
|
||||
__entry->flags, __entry->count, __entry->direct)
|
||||
"immediate=%d", __entry->pe, __entry->addr, __entry->incr,
|
||||
__entry->flags, __entry->count, __entry->immediate)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_vm_copy_ptes,
|
||||
TP_PROTO(uint64_t pe, uint64_t src, unsigned count, bool direct),
|
||||
TP_ARGS(pe, src, count, direct),
|
||||
TP_PROTO(uint64_t pe, uint64_t src, unsigned count, bool immediate),
|
||||
TP_ARGS(pe, src, count, immediate),
|
||||
TP_STRUCT__entry(
|
||||
__field(u64, pe)
|
||||
__field(u64, src)
|
||||
__field(u32, count)
|
||||
__field(bool, direct)
|
||||
__field(bool, immediate)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->pe = pe;
|
||||
__entry->src = src;
|
||||
__entry->count = count;
|
||||
__entry->direct = direct;
|
||||
__entry->immediate = immediate;
|
||||
),
|
||||
TP_printk("pe=%010Lx, src=%010Lx, count=%u, direct=%d",
|
||||
TP_printk("pe=%010Lx, src=%010Lx, count=%u, immediate=%d",
|
||||
__entry->pe, __entry->src, __entry->count,
|
||||
__entry->direct)
|
||||
__entry->immediate)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_vm_flush,
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
#include <drm/ttm/ttm_page_alloc.h>
|
||||
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
@@ -66,6 +65,8 @@
|
||||
static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev,
|
||||
struct ttm_tt *ttm,
|
||||
struct ttm_resource *bo_mem);
|
||||
static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev,
|
||||
struct ttm_tt *ttm);
|
||||
|
||||
static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev,
|
||||
unsigned int type,
|
||||
@@ -92,7 +93,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
|
||||
.fpfn = 0,
|
||||
.lpfn = 0,
|
||||
.mem_type = TTM_PL_SYSTEM,
|
||||
.flags = TTM_PL_MASK_CACHING
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
/* Don't handle scatter gather BOs */
|
||||
@@ -292,11 +293,9 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
||||
cpu_addr = &job->ibs[0].ptr[num_dw];
|
||||
|
||||
if (mem->mem_type == TTM_PL_TT) {
|
||||
struct ttm_dma_tt *dma;
|
||||
dma_addr_t *dma_address;
|
||||
|
||||
dma = container_of(bo->ttm, struct ttm_dma_tt, ttm);
|
||||
dma_address = &dma->dma_address[offset >> PAGE_SHIFT];
|
||||
dma_address = &bo->ttm->dma_address[offset >> PAGE_SHIFT];
|
||||
r = amdgpu_gart_map(adev, 0, num_pages, dma_address, flags,
|
||||
cpu_addr);
|
||||
if (r)
|
||||
@@ -452,7 +451,7 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_move_blit - Copy an entire buffer to another buffer
|
||||
*
|
||||
* This is a helper called by amdgpu_bo_move() and amdgpu_move_vram_ram() to
|
||||
@@ -513,116 +512,7 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_move_vram_ram - Copy VRAM buffer to RAM buffer
|
||||
*
|
||||
* Called by amdgpu_bo_move().
|
||||
*/
|
||||
static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
struct ttm_resource *new_mem)
|
||||
{
|
||||
struct ttm_resource *old_mem = &bo->mem;
|
||||
struct ttm_resource tmp_mem;
|
||||
struct ttm_place placements;
|
||||
struct ttm_placement placement;
|
||||
int r;
|
||||
|
||||
/* create space/pages for new_mem in GTT space */
|
||||
tmp_mem = *new_mem;
|
||||
tmp_mem.mm_node = NULL;
|
||||
placement.num_placement = 1;
|
||||
placement.placement = &placements;
|
||||
placement.num_busy_placement = 1;
|
||||
placement.busy_placement = &placements;
|
||||
placements.fpfn = 0;
|
||||
placements.lpfn = 0;
|
||||
placements.mem_type = TTM_PL_TT;
|
||||
placements.flags = TTM_PL_MASK_CACHING;
|
||||
r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx);
|
||||
if (unlikely(r)) {
|
||||
pr_err("Failed to find GTT space for blit from VRAM\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* set caching flags */
|
||||
r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement);
|
||||
if (unlikely(r)) {
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
r = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
|
||||
if (unlikely(r))
|
||||
goto out_cleanup;
|
||||
|
||||
/* Bind the memory to the GTT space */
|
||||
r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, &tmp_mem);
|
||||
if (unlikely(r)) {
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
/* blit VRAM to GTT */
|
||||
r = amdgpu_move_blit(bo, evict, &tmp_mem, old_mem);
|
||||
if (unlikely(r)) {
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
/* move BO (in tmp_mem) to new_mem */
|
||||
r = ttm_bo_move_ttm(bo, ctx, new_mem);
|
||||
out_cleanup:
|
||||
ttm_resource_free(bo, &tmp_mem);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_move_ram_vram - Copy buffer from RAM to VRAM
|
||||
*
|
||||
* Called by amdgpu_bo_move().
|
||||
*/
|
||||
static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
struct ttm_resource *new_mem)
|
||||
{
|
||||
struct ttm_resource *old_mem = &bo->mem;
|
||||
struct ttm_resource tmp_mem;
|
||||
struct ttm_placement placement;
|
||||
struct ttm_place placements;
|
||||
int r;
|
||||
|
||||
/* make space in GTT for old_mem buffer */
|
||||
tmp_mem = *new_mem;
|
||||
tmp_mem.mm_node = NULL;
|
||||
placement.num_placement = 1;
|
||||
placement.placement = &placements;
|
||||
placement.num_busy_placement = 1;
|
||||
placement.busy_placement = &placements;
|
||||
placements.fpfn = 0;
|
||||
placements.lpfn = 0;
|
||||
placements.mem_type = TTM_PL_TT;
|
||||
placements.flags = TTM_PL_MASK_CACHING;
|
||||
r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx);
|
||||
if (unlikely(r)) {
|
||||
pr_err("Failed to find GTT space for blit to VRAM\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* move/bind old memory to GTT space */
|
||||
r = ttm_bo_move_ttm(bo, ctx, &tmp_mem);
|
||||
if (unlikely(r)) {
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
/* copy to VRAM */
|
||||
r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
|
||||
if (unlikely(r)) {
|
||||
goto out_cleanup;
|
||||
}
|
||||
out_cleanup:
|
||||
ttm_resource_free(bo, &tmp_mem);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy
|
||||
*
|
||||
* Called by amdgpu_bo_move()
|
||||
@@ -646,23 +536,43 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev,
|
||||
<= adev->gmc.visible_vram_size;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_bo_move - Move a buffer object to a new memory location
|
||||
*
|
||||
* Called by ttm_bo_handle_move_mem()
|
||||
*/
|
||||
static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
struct ttm_resource *new_mem)
|
||||
struct ttm_resource *new_mem,
|
||||
struct ttm_place *hop)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct amdgpu_bo *abo;
|
||||
struct ttm_resource *old_mem = &bo->mem;
|
||||
int r;
|
||||
|
||||
if ((old_mem->mem_type == TTM_PL_SYSTEM &&
|
||||
new_mem->mem_type == TTM_PL_VRAM) ||
|
||||
(old_mem->mem_type == TTM_PL_VRAM &&
|
||||
new_mem->mem_type == TTM_PL_SYSTEM)) {
|
||||
hop->fpfn = 0;
|
||||
hop->lpfn = 0;
|
||||
hop->mem_type = TTM_PL_TT;
|
||||
hop->flags = 0;
|
||||
return -EMULTIHOP;
|
||||
}
|
||||
|
||||
if (new_mem->mem_type == TTM_PL_TT) {
|
||||
r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
amdgpu_bo_move_notify(bo, evict, new_mem);
|
||||
|
||||
/* Can't move a pinned BO */
|
||||
abo = ttm_to_amdgpu_bo(bo);
|
||||
if (WARN_ON_ONCE(abo->pin_count > 0))
|
||||
if (WARN_ON_ONCE(abo->tbo.pin_count > 0))
|
||||
return -EINVAL;
|
||||
|
||||
adev = amdgpu_ttm_adev(bo->bdev);
|
||||
@@ -671,14 +581,24 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
ttm_bo_move_null(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
if ((old_mem->mem_type == TTM_PL_TT &&
|
||||
new_mem->mem_type == TTM_PL_SYSTEM) ||
|
||||
(old_mem->mem_type == TTM_PL_SYSTEM &&
|
||||
new_mem->mem_type == TTM_PL_TT)) {
|
||||
/* bind is enough */
|
||||
if (old_mem->mem_type == TTM_PL_SYSTEM &&
|
||||
new_mem->mem_type == TTM_PL_TT) {
|
||||
ttm_bo_move_null(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (old_mem->mem_type == TTM_PL_TT &&
|
||||
new_mem->mem_type == TTM_PL_SYSTEM) {
|
||||
r = ttm_bo_wait_ctx(bo, ctx);
|
||||
if (r)
|
||||
goto fail;
|
||||
|
||||
amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
|
||||
ttm_resource_free(bo, &bo->mem);
|
||||
ttm_bo_assign_mem(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (old_mem->mem_type == AMDGPU_PL_GDS ||
|
||||
old_mem->mem_type == AMDGPU_PL_GWS ||
|
||||
old_mem->mem_type == AMDGPU_PL_OA ||
|
||||
@@ -695,29 +615,19 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
goto memcpy;
|
||||
}
|
||||
|
||||
if (old_mem->mem_type == TTM_PL_VRAM &&
|
||||
new_mem->mem_type == TTM_PL_SYSTEM) {
|
||||
r = amdgpu_move_vram_ram(bo, evict, ctx, new_mem);
|
||||
} else if (old_mem->mem_type == TTM_PL_SYSTEM &&
|
||||
new_mem->mem_type == TTM_PL_VRAM) {
|
||||
r = amdgpu_move_ram_vram(bo, evict, ctx, new_mem);
|
||||
} else {
|
||||
r = amdgpu_move_blit(bo, evict,
|
||||
new_mem, old_mem);
|
||||
}
|
||||
|
||||
r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
|
||||
if (r) {
|
||||
memcpy:
|
||||
/* Check that all memory is CPU accessible */
|
||||
if (!amdgpu_mem_visible(adev, old_mem) ||
|
||||
!amdgpu_mem_visible(adev, new_mem)) {
|
||||
pr_err("Move buffer fallback to memcpy unavailable\n");
|
||||
return r;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = ttm_bo_move_memcpy(bo, ctx, new_mem);
|
||||
if (r)
|
||||
return r;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (bo->type == ttm_bo_type_device &&
|
||||
@@ -732,9 +642,14 @@ memcpy:
|
||||
/* update statistics */
|
||||
atomic64_add((u64)bo->num_pages << PAGE_SHIFT, &adev->num_bytes_moved);
|
||||
return 0;
|
||||
fail:
|
||||
swap(*new_mem, bo->mem);
|
||||
amdgpu_bo_move_notify(bo, false, new_mem);
|
||||
swap(*new_mem, bo->mem);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_io_mem_reserve - Reserve a block of memory during a fault
|
||||
*
|
||||
* Called by ttm_mem_io_reserve() ultimately via ttm_bo_vm_fault()
|
||||
@@ -767,6 +682,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso
|
||||
|
||||
mem->bus.offset += adev->gmc.aper_base;
|
||||
mem->bus.is_iomem = true;
|
||||
mem->bus.caching = ttm_write_combined;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -811,7 +727,7 @@ uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type)
|
||||
* TTM backend functions.
|
||||
*/
|
||||
struct amdgpu_ttm_tt {
|
||||
struct ttm_dma_tt ttm;
|
||||
struct ttm_tt ttm;
|
||||
struct drm_gem_object *gobj;
|
||||
u64 offset;
|
||||
uint64_t userptr;
|
||||
@@ -824,7 +740,7 @@ struct amdgpu_ttm_tt {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_USERPTR
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_get_user_pages - get device accessible pages that back user
|
||||
* memory and start HMM tracking CPU page table update
|
||||
*
|
||||
@@ -929,7 +845,7 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_userptr_range_done - stop HMM track the CPU page table change
|
||||
* Check if the pages backing this ttm range have been invalidated
|
||||
*
|
||||
@@ -943,7 +859,7 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm)
|
||||
if (!gtt || !gtt->userptr)
|
||||
return false;
|
||||
|
||||
DRM_DEBUG_DRIVER("user_pages_done 0x%llx pages 0x%lx\n",
|
||||
DRM_DEBUG_DRIVER("user_pages_done 0x%llx pages 0x%x\n",
|
||||
gtt->userptr, ttm->num_pages);
|
||||
|
||||
WARN_ONCE(!gtt->range || !gtt->range->hmm_pfns,
|
||||
@@ -965,7 +881,7 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_set_user_pages - Copy pages in, putting old pages as necessary.
|
||||
*
|
||||
* Called by amdgpu_cs_list_validate(). This creates the page list
|
||||
@@ -980,8 +896,8 @@ void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages)
|
||||
ttm->pages[i] = pages ? pages[i] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_tt_pin_userptr - prepare the sg table with the user pages
|
||||
/*
|
||||
* amdgpu_ttm_tt_pin_userptr - prepare the sg table with the user pages
|
||||
*
|
||||
* Called by amdgpu_ttm_backend_bind()
|
||||
**/
|
||||
@@ -1020,7 +936,7 @@ release_sg:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_unpin_userptr - Unpin and unmap userptr pages
|
||||
*/
|
||||
static void amdgpu_ttm_tt_unpin_userptr(struct ttm_bo_device *bdev,
|
||||
@@ -1095,13 +1011,13 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
|
||||
|
||||
gart_bind_fail:
|
||||
if (r)
|
||||
DRM_ERROR("failed to bind %lu pages at 0x%08llX\n",
|
||||
DRM_ERROR("failed to bind %u pages at 0x%08llX\n",
|
||||
ttm->num_pages, gtt->offset);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_backend_bind - Bind GTT memory
|
||||
*
|
||||
* Called by ttm_tt_bind() on behalf of ttm_bo_handle_move_mem().
|
||||
@@ -1130,7 +1046,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev,
|
||||
}
|
||||
}
|
||||
if (!ttm->num_pages) {
|
||||
WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
|
||||
WARN(1, "nothing to bind %u pages for mreg %p back %p!\n",
|
||||
ttm->num_pages, bo_mem, ttm);
|
||||
}
|
||||
|
||||
@@ -1153,13 +1069,13 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev,
|
||||
ttm->pages, gtt->ttm.dma_address, flags);
|
||||
|
||||
if (r)
|
||||
DRM_ERROR("failed to bind %lu pages at 0x%08llX\n",
|
||||
DRM_ERROR("failed to bind %u pages at 0x%08llX\n",
|
||||
ttm->num_pages, gtt->offset);
|
||||
gtt->bound = true;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_alloc_gart - Make sure buffer object is accessible either
|
||||
* through AGP or GART aperture.
|
||||
*
|
||||
@@ -1171,7 +1087,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct amdgpu_ttm_tt *gtt = (void*)bo->ttm;
|
||||
struct amdgpu_ttm_tt *gtt = (void *)bo->ttm;
|
||||
struct ttm_resource tmp;
|
||||
struct ttm_placement placement;
|
||||
struct ttm_place placements;
|
||||
@@ -1220,7 +1136,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_recover_gart - Rebind GTT pages
|
||||
*
|
||||
* Called by amdgpu_gtt_mgr_recover() from amdgpu_device_reset() to
|
||||
@@ -1241,7 +1157,7 @@ int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo)
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_backend_unbind - Unbind GTT mapped pages
|
||||
*
|
||||
* Called by ttm_tt_unbind() on behalf of ttm_bo_move_ttm() and
|
||||
@@ -1267,8 +1183,8 @@ static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev,
|
||||
/* unbind shouldn't be done for GDS/GWS/OA in ttm_bo_clean_mm */
|
||||
r = amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages);
|
||||
if (r)
|
||||
DRM_ERROR("failed to unbind %lu pages at 0x%08llX\n",
|
||||
gtt->ttm.ttm.num_pages, gtt->offset);
|
||||
DRM_ERROR("failed to unbind %u pages at 0x%08llX\n",
|
||||
gtt->ttm.num_pages, gtt->offset);
|
||||
gtt->bound = false;
|
||||
}
|
||||
|
||||
@@ -1282,7 +1198,7 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev,
|
||||
if (gtt->usertask)
|
||||
put_task_struct(gtt->usertask);
|
||||
|
||||
ttm_dma_tt_fini(>t->ttm);
|
||||
ttm_tt_fini(>t->ttm);
|
||||
kfree(gtt);
|
||||
}
|
||||
|
||||
@@ -1290,13 +1206,16 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev,
|
||||
* amdgpu_ttm_tt_create - Create a ttm_tt object for a given BO
|
||||
*
|
||||
* @bo: The buffer object to create a GTT ttm_tt object around
|
||||
* @page_flags: Page flags to be added to the ttm_tt object
|
||||
*
|
||||
* Called by ttm_tt_create().
|
||||
*/
|
||||
static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
|
||||
uint32_t page_flags)
|
||||
{
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
|
||||
struct amdgpu_ttm_tt *gtt;
|
||||
enum ttm_caching caching;
|
||||
|
||||
gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL);
|
||||
if (gtt == NULL) {
|
||||
@@ -1304,15 +1223,20 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
|
||||
}
|
||||
gtt->gobj = &bo->base;
|
||||
|
||||
if (abo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
|
||||
caching = ttm_write_combined;
|
||||
else
|
||||
caching = ttm_cached;
|
||||
|
||||
/* allocate space for the uninitialized page entries */
|
||||
if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) {
|
||||
if (ttm_sg_tt_init(>t->ttm, bo, page_flags, caching)) {
|
||||
kfree(gtt);
|
||||
return NULL;
|
||||
}
|
||||
return >t->ttm.ttm;
|
||||
return >t->ttm;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_populate - Map GTT pages visible to the device
|
||||
*
|
||||
* Map the pages of a ttm_tt object to an address space visible
|
||||
@@ -1332,7 +1256,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev,
|
||||
return -ENOMEM;
|
||||
|
||||
ttm->page_flags |= TTM_PAGE_FLAG_SG;
|
||||
ttm_tt_set_populated(ttm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1352,28 +1275,20 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev,
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
|
||||
gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
ttm_tt_set_populated(ttm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (adev->need_swiotlb && swiotlb_nr_tbl()) {
|
||||
return ttm_dma_populate(>t->ttm, adev->dev, ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fall back to generic helper to populate the page array
|
||||
* and map them to the device */
|
||||
return ttm_populate_and_map_pages(adev->dev, >t->ttm, ctx);
|
||||
return ttm_pool_alloc(&adev->mman.bdev.pool, ttm, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_unpopulate - unmap GTT pages and unpopulate page arrays
|
||||
*
|
||||
* Unmaps pages of a ttm_tt object from the device address space and
|
||||
* unpopulates the page array backing it.
|
||||
*/
|
||||
static void amdgpu_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
|
||||
static void amdgpu_ttm_tt_unpopulate(struct ttm_bo_device *bdev,
|
||||
struct ttm_tt *ttm)
|
||||
{
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
struct amdgpu_device *adev;
|
||||
@@ -1398,16 +1313,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *
|
||||
return;
|
||||
|
||||
adev = amdgpu_ttm_adev(bdev);
|
||||
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (adev->need_swiotlb && swiotlb_nr_tbl()) {
|
||||
ttm_dma_unpopulate(>t->ttm, adev->dev);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fall back to generic helper to unmap and unpopulate array */
|
||||
ttm_unmap_and_unpopulate_pages(adev->dev, >t->ttm);
|
||||
return ttm_pool_free(&adev->mman.bdev.pool, ttm);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1433,7 +1339,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
gtt = (void*)bo->ttm;
|
||||
gtt = (void *)bo->ttm;
|
||||
gtt->userptr = addr;
|
||||
gtt->userflags = flags;
|
||||
|
||||
@@ -1445,7 +1351,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_get_usermm - Return memory manager for ttm_tt object
|
||||
*/
|
||||
struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm)
|
||||
@@ -1461,7 +1367,7 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm)
|
||||
return gtt->usertask->mm;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_affect_userptr - Determine if a ttm_tt object lays inside an
|
||||
* address range for the current task.
|
||||
*
|
||||
@@ -1478,14 +1384,14 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
|
||||
/* Return false if no part of the ttm_tt object lies within
|
||||
* the range
|
||||
*/
|
||||
size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE;
|
||||
size = (unsigned long)gtt->ttm.num_pages * PAGE_SIZE;
|
||||
if (gtt->userptr > end || gtt->userptr + size <= start)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_is_userptr - Have the pages backing by userptr?
|
||||
*/
|
||||
bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm)
|
||||
@@ -1498,7 +1404,7 @@ bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_tt_is_readonly - Is the ttm_tt object read only?
|
||||
*/
|
||||
bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm)
|
||||
@@ -1529,7 +1435,7 @@ uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem)
|
||||
if (mem && mem->mem_type == TTM_PL_TT) {
|
||||
flags |= AMDGPU_PTE_SYSTEM;
|
||||
|
||||
if (ttm->caching_state == tt_cached)
|
||||
if (ttm->caching == ttm_cached)
|
||||
flags |= AMDGPU_PTE_SNOOPED;
|
||||
}
|
||||
|
||||
@@ -1539,9 +1445,10 @@ uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem)
|
||||
/**
|
||||
* amdgpu_ttm_tt_pte_flags - Compute PTE flags for ttm_tt object
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ttm: The ttm_tt object to compute the flags for
|
||||
* @mem: The memory registry backing this ttm_tt object
|
||||
|
||||
*
|
||||
* Figure out the flags to use for a VM PTE (Page Table Entry).
|
||||
*/
|
||||
uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
|
||||
@@ -1558,7 +1465,7 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_bo_eviction_valuable - Check to see if we can evict a buffer
|
||||
* object.
|
||||
*
|
||||
@@ -1699,20 +1606,23 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo)
|
||||
{
|
||||
amdgpu_bo_move_notify(bo, false, NULL);
|
||||
}
|
||||
|
||||
static struct ttm_bo_driver amdgpu_bo_driver = {
|
||||
.ttm_tt_create = &amdgpu_ttm_tt_create,
|
||||
.ttm_tt_populate = &amdgpu_ttm_tt_populate,
|
||||
.ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate,
|
||||
.ttm_tt_bind = &amdgpu_ttm_backend_bind,
|
||||
.ttm_tt_unbind = &amdgpu_ttm_backend_unbind,
|
||||
.ttm_tt_destroy = &amdgpu_ttm_backend_destroy,
|
||||
.eviction_valuable = amdgpu_ttm_bo_eviction_valuable,
|
||||
.evict_flags = &amdgpu_evict_flags,
|
||||
.move = &amdgpu_bo_move,
|
||||
.verify_access = &amdgpu_verify_access,
|
||||
.move_notify = &amdgpu_bo_move_notify,
|
||||
.delete_mem_notify = &amdgpu_bo_delete_mem_notify,
|
||||
.release_notify = &amdgpu_bo_release_notify,
|
||||
.fault_reserve_notify = &amdgpu_bo_fault_reserve_notify,
|
||||
.io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
|
||||
.io_mem_pfn = amdgpu_ttm_io_mem_pfn,
|
||||
.access_memory = &amdgpu_ttm_access_memory,
|
||||
@@ -1866,7 +1776,7 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_init - Init the memory management (ttm) as well as various
|
||||
* gtt/vram related fields.
|
||||
*
|
||||
@@ -1884,10 +1794,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
mutex_init(&adev->mman.gtt_window_lock);
|
||||
|
||||
/* No others user of address space so set it to 0 */
|
||||
r = ttm_bo_device_init(&adev->mman.bdev,
|
||||
&amdgpu_bo_driver,
|
||||
r = ttm_bo_device_init(&adev->mman.bdev, &amdgpu_bo_driver, adev->dev,
|
||||
adev_to_drm(adev)->anon_inode->i_mapping,
|
||||
adev_to_drm(adev)->vma_offset_manager,
|
||||
adev->need_swiotlb,
|
||||
dma_addressing_limited(adev->dev));
|
||||
if (r) {
|
||||
DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
|
||||
@@ -1895,9 +1805,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
}
|
||||
adev->mman.initialized = true;
|
||||
|
||||
/* We opt to avoid OOM on system pages allocations */
|
||||
adev->mman.bdev.no_retry = true;
|
||||
|
||||
/* Initialize VRAM pool with all of VRAM divided into pages */
|
||||
r = amdgpu_vram_mgr_init(adev);
|
||||
if (r) {
|
||||
@@ -2003,18 +1910,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_late_init - Handle any late initialization for amdgpu_ttm
|
||||
*/
|
||||
void amdgpu_ttm_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
/* return the VGA stolen memory (if any) back to VRAM */
|
||||
if (!adev->mman.keep_stolen_vga_memory)
|
||||
amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
|
||||
amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_fini - De-initialize the TTM memory pools
|
||||
*/
|
||||
void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
||||
@@ -2024,8 +1920,8 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_ttm_training_reserve_vram_fini(adev);
|
||||
/* return the stolen vga memory back to VRAM */
|
||||
if (adev->mman.keep_stolen_vga_memory)
|
||||
amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
|
||||
amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL);
|
||||
amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL);
|
||||
/* return the IP Discovery TMR memory back to VRAM */
|
||||
amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL);
|
||||
amdgpu_ttm_fw_reserve_vram_fini(adev);
|
||||
@@ -2092,15 +1988,48 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
||||
adev->mman.buffer_funcs_enabled = enable;
|
||||
}
|
||||
|
||||
static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct ttm_buffer_object *bo = vmf->vma->vm_private_data;
|
||||
vm_fault_t ret;
|
||||
|
||||
ret = ttm_bo_vm_reserve(bo, vmf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = amdgpu_bo_fault_reserve_notify(bo);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
|
||||
TTM_BO_VM_NUM_PREFAULT, 1);
|
||||
if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
|
||||
return ret;
|
||||
|
||||
unlock:
|
||||
dma_resv_unlock(bo->base.resv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct amdgpu_ttm_vm_ops = {
|
||||
.fault = amdgpu_ttm_fault,
|
||||
.open = ttm_bo_vm_open,
|
||||
.close = ttm_bo_vm_close,
|
||||
.access = ttm_bo_vm_access
|
||||
};
|
||||
|
||||
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev);
|
||||
int r;
|
||||
|
||||
if (adev == NULL)
|
||||
return -EINVAL;
|
||||
r = ttm_bo_mmap(filp, vma, &adev->mman.bdev);
|
||||
if (unlikely(r != 0))
|
||||
return r;
|
||||
|
||||
return ttm_bo_mmap(filp, vma, &adev->mman.bdev);
|
||||
vma->vm_ops = &amdgpu_ttm_vm_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
||||
@@ -2284,19 +2213,25 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ttm_pool_debugfs(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
return ttm_pool_debugfs(&adev->mman.bdev.pool, m);
|
||||
}
|
||||
|
||||
static const struct drm_info_list amdgpu_ttm_debugfs_list[] = {
|
||||
{"amdgpu_vram_mm", amdgpu_mm_dump_table, 0, (void *)TTM_PL_VRAM},
|
||||
{"amdgpu_gtt_mm", amdgpu_mm_dump_table, 0, (void *)TTM_PL_TT},
|
||||
{"amdgpu_gds_mm", amdgpu_mm_dump_table, 0, (void *)AMDGPU_PL_GDS},
|
||||
{"amdgpu_gws_mm", amdgpu_mm_dump_table, 0, (void *)AMDGPU_PL_GWS},
|
||||
{"amdgpu_oa_mm", amdgpu_mm_dump_table, 0, (void *)AMDGPU_PL_OA},
|
||||
{"ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL},
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
{"ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL}
|
||||
#endif
|
||||
{"ttm_page_pool", amdgpu_ttm_pool_debugfs, 0, NULL},
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_vram_read - Linear read access to VRAM
|
||||
*
|
||||
* Accesses VRAM via MMIO for debugging purposes.
|
||||
@@ -2331,7 +2266,7 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_vram_write - Linear write access to VRAM
|
||||
*
|
||||
* Accesses VRAM via MMIO for debugging purposes.
|
||||
@@ -2384,7 +2319,7 @@ static const struct file_operations amdgpu_ttm_vram_fops = {
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_ttm_gtt_read - Linear read access to GTT memory
|
||||
*/
|
||||
static ssize_t amdgpu_ttm_gtt_read(struct file *f, char __user *buf,
|
||||
@@ -2434,7 +2369,7 @@ static const struct file_operations amdgpu_ttm_gtt_fops = {
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_iomem_read - Virtual read access to GPU mapped memory
|
||||
*
|
||||
* This function is used to read memory that has been mapped to the
|
||||
@@ -2490,7 +2425,7 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_iomem_write - Virtual write access to GPU mapped memory
|
||||
*
|
||||
* This function is used to write memory that has been mapped to the
|
||||
@@ -2586,12 +2521,6 @@ int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
count = ARRAY_SIZE(amdgpu_ttm_debugfs_list);
|
||||
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (!(adev->need_swiotlb && swiotlb_nr_tbl()))
|
||||
--count;
|
||||
#endif
|
||||
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_ttm_debugfs_list, count);
|
||||
#else
|
||||
return 0;
|
||||
|
||||
@@ -37,10 +37,17 @@
|
||||
|
||||
#define AMDGPU_POISON 0xd0bed0be
|
||||
|
||||
struct amdgpu_vram_reservation {
|
||||
struct list_head node;
|
||||
struct drm_mm_node mm_node;
|
||||
};
|
||||
|
||||
struct amdgpu_vram_mgr {
|
||||
struct ttm_resource_manager manager;
|
||||
struct drm_mm mm;
|
||||
spinlock_t lock;
|
||||
struct list_head reservations_pending;
|
||||
struct list_head reserved_pages;
|
||||
atomic64_t usage;
|
||||
atomic64_t vis_usage;
|
||||
};
|
||||
@@ -54,7 +61,6 @@ struct amdgpu_gtt_mgr {
|
||||
|
||||
struct amdgpu_mman {
|
||||
struct ttm_bo_device bdev;
|
||||
bool mem_global_referenced;
|
||||
bool initialized;
|
||||
void __iomem *aper_base_kaddr;
|
||||
|
||||
@@ -119,9 +125,12 @@ void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev,
|
||||
struct sg_table *sgt);
|
||||
uint64_t amdgpu_vram_mgr_usage(struct ttm_resource_manager *man);
|
||||
uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_resource_manager *man);
|
||||
int amdgpu_vram_mgr_reserve_range(struct ttm_resource_manager *man,
|
||||
uint64_t start, uint64_t size);
|
||||
int amdgpu_vram_mgr_query_page_status(struct ttm_resource_manager *man,
|
||||
uint64_t start);
|
||||
|
||||
int amdgpu_ttm_init(struct amdgpu_device *adev);
|
||||
void amdgpu_ttm_late_init(struct amdgpu_device *adev);
|
||||
void amdgpu_ttm_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
|
||||
@@ -68,23 +68,32 @@ void amdgpu_ucode_print_smc_hdr(const struct common_firmware_header *hdr)
|
||||
{
|
||||
uint16_t version_major = le16_to_cpu(hdr->header_version_major);
|
||||
uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
|
||||
const struct smc_firmware_header_v1_0 *v1_0_hdr;
|
||||
const struct smc_firmware_header_v2_0 *v2_0_hdr;
|
||||
const struct smc_firmware_header_v2_1 *v2_1_hdr;
|
||||
|
||||
DRM_DEBUG("SMC\n");
|
||||
amdgpu_ucode_print_common_hdr(hdr);
|
||||
|
||||
if (version_major == 1) {
|
||||
const struct smc_firmware_header_v1_0 *smc_hdr =
|
||||
container_of(hdr, struct smc_firmware_header_v1_0, header);
|
||||
|
||||
DRM_DEBUG("ucode_start_addr: %u\n", le32_to_cpu(smc_hdr->ucode_start_addr));
|
||||
v1_0_hdr = container_of(hdr, struct smc_firmware_header_v1_0, header);
|
||||
DRM_DEBUG("ucode_start_addr: %u\n", le32_to_cpu(v1_0_hdr->ucode_start_addr));
|
||||
} else if (version_major == 2) {
|
||||
const struct smc_firmware_header_v1_0 *v1_hdr =
|
||||
container_of(hdr, struct smc_firmware_header_v1_0, header);
|
||||
const struct smc_firmware_header_v2_0 *v2_hdr =
|
||||
container_of(v1_hdr, struct smc_firmware_header_v2_0, v1_0);
|
||||
switch (version_minor) {
|
||||
case 0:
|
||||
v2_0_hdr = container_of(hdr, struct smc_firmware_header_v2_0, v1_0.header);
|
||||
DRM_DEBUG("ppt_offset_bytes: %u\n", le32_to_cpu(v2_0_hdr->ppt_offset_bytes));
|
||||
DRM_DEBUG("ppt_size_bytes: %u\n", le32_to_cpu(v2_0_hdr->ppt_size_bytes));
|
||||
break;
|
||||
case 1:
|
||||
v2_1_hdr = container_of(hdr, struct smc_firmware_header_v2_1, v1_0.header);
|
||||
DRM_DEBUG("pptable_count: %u\n", le32_to_cpu(v2_1_hdr->pptable_count));
|
||||
DRM_DEBUG("pptable_entry_offset: %u\n", le32_to_cpu(v2_1_hdr->pptable_entry_offset));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DRM_DEBUG("ppt_offset_bytes: %u\n", le32_to_cpu(v2_hdr->ppt_offset_bytes));
|
||||
DRM_DEBUG("ppt_size_bytes: %u\n", le32_to_cpu(v2_hdr->ppt_size_bytes));
|
||||
} else {
|
||||
DRM_ERROR("Unknown SMC ucode version: %u.%u\n", version_major, version_minor);
|
||||
}
|
||||
@@ -391,6 +400,8 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
case CHIP_VANGOGH:
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
if (!load_type)
|
||||
return AMDGPU_FW_LOAD_DIRECT;
|
||||
else
|
||||
@@ -586,8 +597,8 @@ static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode,
|
||||
{
|
||||
const struct gfx_firmware_header_v1_0 *header = NULL;
|
||||
const struct common_firmware_header *comm_hdr = NULL;
|
||||
uint8_t* src_addr = NULL;
|
||||
uint8_t* dst_addr = NULL;
|
||||
uint8_t *src_addr = NULL;
|
||||
uint8_t *dst_addr = NULL;
|
||||
|
||||
if (NULL == ucode->fw)
|
||||
return 0;
|
||||
|
||||
@@ -126,10 +126,11 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
err_data->ue_count);
|
||||
|
||||
if ((amdgpu_bad_page_threshold != 0) &&
|
||||
err_data->err_addr_cnt &&
|
||||
err_data->err_addr_cnt) {
|
||||
amdgpu_ras_add_bad_pages(adev, err_data->err_addr,
|
||||
err_data->err_addr_cnt))
|
||||
dev_warn(adev->dev, "Failed to add ras bad page!\n");
|
||||
err_data->err_addr_cnt);
|
||||
amdgpu_ras_save_bad_pages(adev);
|
||||
}
|
||||
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
#define UVD_NO_OP 0x03ff
|
||||
#define UVD_BASE_SI 0x3800
|
||||
|
||||
/**
|
||||
/*
|
||||
* amdgpu_uvd_cs_ctx - Command submission parser context
|
||||
*
|
||||
* Used for emulating virtual memory support on UVD 4.2.
|
||||
@@ -545,8 +545,9 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
|
||||
/**
|
||||
* amdgpu_uvd_cs_msg_decode - handle UVD decode message
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @msg: pointer to message structure
|
||||
* @buf_sizes: returned buffer sizes
|
||||
* @buf_sizes: placeholder to put the different buffer lengths
|
||||
*
|
||||
* Peek into the decode message and calculate the necessary buffer sizes.
|
||||
*/
|
||||
@@ -1005,6 +1006,7 @@ static int amdgpu_uvd_cs_packets(struct amdgpu_uvd_cs_ctx *ctx,
|
||||
* amdgpu_uvd_ring_parse_cs - UVD command submission parser
|
||||
*
|
||||
* @parser: Command submission parser context
|
||||
* @ib_idx: Which indirect buffer to use
|
||||
*
|
||||
* Parse the command stream, patch in addresses as necessary.
|
||||
*/
|
||||
@@ -1279,6 +1281,7 @@ void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring)
|
||||
* amdgpu_uvd_ring_test_ib - test ib execution
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @timeout: timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
|
||||
*
|
||||
* Test if we can successfully execute an IB
|
||||
*/
|
||||
|
||||
@@ -90,6 +90,7 @@ static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
|
||||
* amdgpu_vce_init - allocate memory, load vce firmware
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @size: size for the new BO
|
||||
*
|
||||
* First step to get VCE online, allocate memory and load the firmware
|
||||
*/
|
||||
@@ -428,9 +429,9 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
|
||||
/**
|
||||
* amdgpu_vce_get_create_msg - generate a VCE create msg
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: ring we should submit the msg to
|
||||
* @handle: VCE session handle to use
|
||||
* @bo: amdgpu object for which we query the offset
|
||||
* @fence: optional fence to return
|
||||
*
|
||||
* Open up a stream for HW test
|
||||
@@ -509,9 +510,9 @@ err:
|
||||
/**
|
||||
* amdgpu_vce_get_destroy_msg - generate a VCE destroy msg
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ring: ring we should submit the msg to
|
||||
* @handle: VCE session handle to use
|
||||
* @direct: direct or delayed pool
|
||||
* @fence: optional fence to return
|
||||
*
|
||||
* Close up a stream for HW test or if userspace failed to do so
|
||||
@@ -576,6 +577,7 @@ err:
|
||||
* amdgpu_vce_cs_validate_bo - make sure not to cross 4GB boundary
|
||||
*
|
||||
* @p: parser context
|
||||
* @ib_idx: indirect buffer to use
|
||||
* @lo: address of lower dword
|
||||
* @hi: address of higher dword
|
||||
* @size: minimum size
|
||||
@@ -625,9 +627,11 @@ static int amdgpu_vce_validate_bo(struct amdgpu_cs_parser *p, uint32_t ib_idx,
|
||||
* amdgpu_vce_cs_reloc - command submission relocation
|
||||
*
|
||||
* @p: parser context
|
||||
* @ib_idx: indirect buffer to use
|
||||
* @lo: address of lower dword
|
||||
* @hi: address of higher dword
|
||||
* @size: minimum size
|
||||
* @index: bs/fb index
|
||||
*
|
||||
* Patch relocation inside command stream with real buffer address
|
||||
*/
|
||||
@@ -714,7 +718,7 @@ static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p,
|
||||
* amdgpu_vce_cs_parse - parse and validate the command stream
|
||||
*
|
||||
* @p: parser context
|
||||
*
|
||||
* @ib_idx: indirect buffer to use
|
||||
*/
|
||||
int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
|
||||
{
|
||||
@@ -950,7 +954,7 @@ out:
|
||||
* amdgpu_vce_cs_parse_vm - parse the command stream in VM mode
|
||||
*
|
||||
* @p: parser context
|
||||
*
|
||||
* @ib_idx: indirect buffer to use
|
||||
*/
|
||||
int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx)
|
||||
{
|
||||
@@ -1040,7 +1044,9 @@ out:
|
||||
* amdgpu_vce_ring_emit_ib - execute indirect buffer
|
||||
*
|
||||
* @ring: engine to use
|
||||
* @job: job to retrieve vmid from
|
||||
* @ib: the IB to execute
|
||||
* @flags: unused
|
||||
*
|
||||
*/
|
||||
void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
@@ -1058,7 +1064,9 @@ void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
* amdgpu_vce_ring_emit_fence - add a fence command to the ring
|
||||
*
|
||||
* @ring: engine to use
|
||||
* @fence: the fence
|
||||
* @addr: address
|
||||
* @seq: sequence number
|
||||
* @flags: fence related flags
|
||||
*
|
||||
*/
|
||||
void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
@@ -1116,6 +1124,7 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
|
||||
* amdgpu_vce_ring_test_ib - test if VCE IBs are working
|
||||
*
|
||||
* @ring: the engine to test on
|
||||
* @timeout: timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
|
||||
*
|
||||
*/
|
||||
int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
|
||||
@@ -37,14 +37,16 @@
|
||||
#define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin"
|
||||
#define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"
|
||||
#define FIRMWARE_RAVEN2 "amdgpu/raven2_vcn.bin"
|
||||
#define FIRMWARE_ARCTURUS "amdgpu/arcturus_vcn.bin"
|
||||
#define FIRMWARE_RENOIR "amdgpu/renoir_vcn.bin"
|
||||
#define FIRMWARE_GREEN_SARDINE "amdgpu/green_sardine_vcn.bin"
|
||||
#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"
|
||||
#define FIRMWARE_NAVI14 "amdgpu/navi14_vcn.bin"
|
||||
#define FIRMWARE_NAVI12 "amdgpu/navi12_vcn.bin"
|
||||
#define FIRMWARE_SIENNA_CICHLID "amdgpu/sienna_cichlid_vcn.bin"
|
||||
#define FIRMWARE_NAVY_FLOUNDER "amdgpu/navy_flounder_vcn.bin"
|
||||
#define FIRMWARE_ARCTURUS "amdgpu/arcturus_vcn.bin"
|
||||
#define FIRMWARE_RENOIR "amdgpu/renoir_vcn.bin"
|
||||
#define FIRMWARE_GREEN_SARDINE "amdgpu/green_sardine_vcn.bin"
|
||||
#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"
|
||||
#define FIRMWARE_NAVI14 "amdgpu/navi14_vcn.bin"
|
||||
#define FIRMWARE_NAVI12 "amdgpu/navi12_vcn.bin"
|
||||
#define FIRMWARE_SIENNA_CICHLID "amdgpu/sienna_cichlid_vcn.bin"
|
||||
#define FIRMWARE_NAVY_FLOUNDER "amdgpu/navy_flounder_vcn.bin"
|
||||
#define FIRMWARE_VANGOGH "amdgpu/vangogh_vcn.bin"
|
||||
#define FIRMWARE_DIMGREY_CAVEFISH "amdgpu/dimgrey_cavefish_vcn.bin"
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE_RAVEN);
|
||||
MODULE_FIRMWARE(FIRMWARE_PICASSO);
|
||||
@@ -57,6 +59,8 @@ MODULE_FIRMWARE(FIRMWARE_NAVI14);
|
||||
MODULE_FIRMWARE(FIRMWARE_NAVI12);
|
||||
MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID);
|
||||
MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER);
|
||||
MODULE_FIRMWARE(FIRMWARE_VANGOGH);
|
||||
MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH);
|
||||
|
||||
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
|
||||
|
||||
@@ -130,6 +134,15 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case CHIP_VANGOGH:
|
||||
fw_name = FIRMWARE_VANGOGH;
|
||||
break;
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
fw_name = FIRMWARE_DIMGREY_CAVEFISH;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -319,6 +332,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
container_of(work, struct amdgpu_device, vcn.idle_work.work);
|
||||
unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
|
||||
unsigned int i, j;
|
||||
int r = 0;
|
||||
|
||||
for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
|
||||
if (adev->vcn.harvest_config & (1 << j))
|
||||
@@ -345,8 +359,13 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) {
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
AMD_PG_STATE_GATE);
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
|
||||
} else {
|
||||
schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
|
||||
}
|
||||
@@ -355,9 +374,17 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
int r = 0;
|
||||
|
||||
atomic_inc(&adev->vcn.total_submission_cnt);
|
||||
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
||||
|
||||
if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) {
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
|
||||
}
|
||||
|
||||
mutex_lock(&adev->vcn.vcn_pg_lock);
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
@@ -429,6 +456,37 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t rptr;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
r = amdgpu_ring_alloc(ring, 16);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
rptr = amdgpu_ring_get_rptr(ring);
|
||||
|
||||
amdgpu_ring_write(ring, VCN_DEC_SW_CMD_END);
|
||||
amdgpu_ring_commit(ring);
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (amdgpu_ring_get_rptr(ring) != rptr)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
|
||||
struct amdgpu_bo *bo,
|
||||
struct dma_fence **fence)
|
||||
@@ -483,16 +541,16 @@ err:
|
||||
}
|
||||
|
||||
static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
|
||||
struct dma_fence **fence)
|
||||
struct amdgpu_bo **bo)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
uint32_t *msg;
|
||||
int r, i;
|
||||
|
||||
*bo = NULL;
|
||||
r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&bo, NULL, (void **)&msg);
|
||||
bo, NULL, (void **)&msg);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -513,20 +571,20 @@ static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
||||
for (i = 14; i < 1024; ++i)
|
||||
msg[i] = cpu_to_le32(0x0);
|
||||
|
||||
return amdgpu_vcn_dec_send_msg(ring, bo, fence);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
|
||||
struct dma_fence **fence)
|
||||
struct amdgpu_bo **bo)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
uint32_t *msg;
|
||||
int r, i;
|
||||
|
||||
*bo = NULL;
|
||||
r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&bo, NULL, (void **)&msg);
|
||||
bo, NULL, (void **)&msg);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -539,19 +597,117 @@ static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
||||
for (i = 6; i < 1024; ++i)
|
||||
msg[i] = cpu_to_le32(0x0);
|
||||
|
||||
return amdgpu_vcn_dec_send_msg(ring, bo, fence);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
{
|
||||
struct dma_fence *fence;
|
||||
struct dma_fence *fence = NULL;
|
||||
struct amdgpu_bo *bo;
|
||||
long r;
|
||||
|
||||
r = amdgpu_vcn_dec_get_create_msg(ring, 1, NULL);
|
||||
r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &fence);
|
||||
r = amdgpu_vcn_dec_send_msg(ring, bo, NULL);
|
||||
if (r)
|
||||
goto error;
|
||||
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_vcn_dec_send_msg(ring, bo, &fence);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = dma_fence_wait_timeout(fence, false, timeout);
|
||||
if (r == 0)
|
||||
r = -ETIMEDOUT;
|
||||
else if (r > 0)
|
||||
r = 0;
|
||||
|
||||
dma_fence_put(fence);
|
||||
error:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
||||
struct amdgpu_bo *bo,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_vcn_decode_buffer *decode_buffer = NULL;
|
||||
const unsigned int ib_size_dw = 64;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct dma_fence *f = NULL;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
uint64_t addr;
|
||||
int i, r;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4,
|
||||
AMDGPU_IB_POOL_DIRECT, &job);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
addr = amdgpu_bo_gpu_offset(bo);
|
||||
ib->length_dw = 0;
|
||||
|
||||
ib->ptr[ib->length_dw++] = sizeof(struct amdgpu_vcn_decode_buffer) + 8;
|
||||
ib->ptr[ib->length_dw++] = cpu_to_le32(AMDGPU_VCN_IB_FLAG_DECODE_BUFFER);
|
||||
decode_buffer = (struct amdgpu_vcn_decode_buffer *)&(ib->ptr[ib->length_dw]);
|
||||
ib->length_dw += sizeof(struct amdgpu_vcn_decode_buffer) / 4;
|
||||
memset(decode_buffer, 0, sizeof(struct amdgpu_vcn_decode_buffer));
|
||||
|
||||
decode_buffer->valid_buf_flag |= cpu_to_le32(AMDGPU_VCN_CMD_FLAG_MSG_BUFFER);
|
||||
decode_buffer->msg_buffer_address_hi = cpu_to_le32(addr >> 32);
|
||||
decode_buffer->msg_buffer_address_lo = cpu_to_le32(addr);
|
||||
|
||||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
if (r)
|
||||
goto err_free;
|
||||
|
||||
amdgpu_bo_fence(bo, f, false);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
|
||||
if (fence)
|
||||
*fence = dma_fence_get(f);
|
||||
dma_fence_put(f);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
amdgpu_job_free(job);
|
||||
|
||||
err:
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
{
|
||||
struct dma_fence *fence = NULL;
|
||||
struct amdgpu_bo *bo;
|
||||
long r;
|
||||
|
||||
r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_vcn_dec_sw_send_msg(ring, bo, NULL);
|
||||
if (r)
|
||||
goto error;
|
||||
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_vcn_dec_sw_send_msg(ring, bo, &fence);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
|
||||
@@ -44,6 +44,17 @@
|
||||
#define VCN_DEC_CMD_PACKET_START 0x0000000a
|
||||
#define VCN_DEC_CMD_PACKET_END 0x0000000b
|
||||
|
||||
#define VCN_DEC_SW_CMD_NO_OP 0x00000000
|
||||
#define VCN_DEC_SW_CMD_END 0x00000001
|
||||
#define VCN_DEC_SW_CMD_IB 0x00000002
|
||||
#define VCN_DEC_SW_CMD_FENCE 0x00000003
|
||||
#define VCN_DEC_SW_CMD_TRAP 0x00000004
|
||||
#define VCN_DEC_SW_CMD_IB_AUTO 0x00000005
|
||||
#define VCN_DEC_SW_CMD_SEMAPHORE 0x00000006
|
||||
#define VCN_DEC_SW_CMD_PREEMPT_FENCE 0x00000009
|
||||
#define VCN_DEC_SW_CMD_REG_WRITE 0x0000000b
|
||||
#define VCN_DEC_SW_CMD_REG_WAIT 0x0000000c
|
||||
|
||||
#define VCN_ENC_CMD_NO_OP 0x00000000
|
||||
#define VCN_ENC_CMD_END 0x00000001
|
||||
#define VCN_ENC_CMD_IB 0x00000002
|
||||
@@ -145,6 +156,10 @@
|
||||
} while (0)
|
||||
|
||||
#define AMDGPU_VCN_MULTI_QUEUE_FLAG (1 << 8)
|
||||
#define AMDGPU_VCN_SW_RING_FLAG (1 << 9)
|
||||
|
||||
#define AMDGPU_VCN_IB_FLAG_DECODE_BUFFER 0x00000001
|
||||
#define AMDGPU_VCN_CMD_FLAG_MSG_BUFFER 0x00000001
|
||||
|
||||
enum fw_queue_mode {
|
||||
FW_QUEUE_RING_RESET = 1,
|
||||
@@ -236,12 +251,25 @@ struct amdgpu_fw_shared_multi_queue {
|
||||
uint8_t padding[4];
|
||||
};
|
||||
|
||||
struct amdgpu_fw_shared_sw_ring {
|
||||
uint8_t is_enabled;
|
||||
uint8_t padding[3];
|
||||
};
|
||||
|
||||
struct amdgpu_fw_shared {
|
||||
uint32_t present_flag_0;
|
||||
uint8_t pad[53];
|
||||
struct amdgpu_fw_shared_multi_queue multi_queue;
|
||||
struct amdgpu_fw_shared_sw_ring sw_ring;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct amdgpu_vcn_decode_buffer {
|
||||
uint32_t valid_buf_flag;
|
||||
uint32_t msg_buffer_address_hi;
|
||||
uint32_t msg_buffer_address_lo;
|
||||
uint32_t pad[30];
|
||||
};
|
||||
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_suspend(struct amdgpu_device *adev);
|
||||
@@ -251,6 +279,8 @@ void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring);
|
||||
|
||||
int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
|
||||
int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
|
||||
@@ -59,7 +59,7 @@ void amdgpu_vf_error_trans_all(struct amdgpu_device *adev)
|
||||
return;
|
||||
}
|
||||
/*
|
||||
TODO: Enable these code when pv2vf_info is merged
|
||||
TODO: Enable these code when pv2vf_info is merged
|
||||
AMDGPU_FW_VRAM_PF2VF_READ (adev, feature_flags, &pf2vf_flags);
|
||||
if (!(pf2vf_flags & AMDGIM_FEATURE_ERROR_LOG_COLLECT)) {
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user