drm for 5.11-rc1

core:
 - documentation updates
 - deprecate DRM_FORMAT_MOD_NONE
 - atomic crtc enable/disable rework
 - GEM convert drivers to gem object functions
 - remove SCATTER_LIST_MAX_SEGMENT
 
 sched:
 - avoid infinite waits
 
 ttm:
 - remove AGP support
 - don't modify caching for swapout
 - ttm pinning rework
 - major TTM reworks
 - new backend allocator
 - multihop support
 
 vram-helper:
 - top down BO placement fix
 - TTM changes
 - GEM object support
 
 displayport:
 - DP 2.0 DPCD prep work
 - DP MST extended DPCD caps
 
 fbdev:
 - mark as orphaned
 
 amdgpu:
 - Initial Vangogh support
 - Green Sardine support
 - Dimgrey Cavefish support
 - SG display support for renoir
 - SMU7 improvements
 - gfx9+ modiifier support
 - CI BACO fixes
 
 radeon:
 - expose voltage via hwmon on SUMO
 
 amdkfd:
 - fix unique id handling
 
 i915:
 - more DG1 enablement
 - bigjoiner support
 - integer scaling filter support
 - async flip support
 - ICL+ DSI command mode
 - Improve display shutdown
 - Display refactoring
 - eLLC machine fbdev loading fix
 - dma scatterlist fixes
 - TGL hang fixes
 - eLLC display buffer caching on SKL+
 - MOCS PTE seeting for gen9+
 
 msm:
 - Shutdown hook
 - GPU cooling device support
 - DSI 7nm and 10nm phy/pll updates
 - sm8150/sm2850 DPU support
 - GEM locking re-work
 - LLCC system cache support
 
 aspeed:
 - sysfs output config support
 
 ast:
 - LUT fix
 - new display mode
 
 gma500:
 - remove 2d framebuffer accel
 
 panfrost:
 - move gpu reset to a worker
 
 exynos:
 - new HDMI mode support
 
 mediatek:
 - MT8167 support
 - yaml bindings
 - MIPI DSI phy code moved
 
 etnaviv:
 - new perf counter
 - more lockdep annotation
 
 hibmc:
 - i2c DDC support
 
 ingenic:
 - pixel clock reset fix
 - reserved memory support
 - allow both DMA channels at once
 - different pixel format support
 - 30/24/8-bit palette modes
 
 tilcdc:
 - don't keep vblank irq enabled
 
 vc4:
 - new maintainer added
 - DSI registration fix
 
 virtio:
 - blob resource support
 - host visible and cross-device support
 - uuid api support
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJf0upGAAoJEAx081l5xIa+1EoP/2OkZnl5d9S26qPja15EoRFl
 S69OjNci331Br9Y111jD2OCtyqA7w3ppnvCmzpHOBK1IZjhkxOVNC6PSUFSV4M3V
 oVOxZK0KaMHpLU2p90NbURWHa2TOktj7IWb9FrhPaEeBECbFuORZ2TbloFhaoyyt
 9auEAwqYRPgF8CSYOjQGGZJ85MQN4ImExTdY13+BZgQlGLiSPHfpnLVJ1Q5TPt6A
 BLgcU/DFcqOZqyjeu+CuA+LZSHjHeVJxTOGRX65PoTtU3Xus8TRZ/qL4r8e6mAI1
 boFLmsevvQlzaQ9GFohc+l9QR/dtnm6SpZxuEelewh7sQvsz2GI+SNF+OHcwHCph
 TYIEtyZNaz1bf7ip75FGbhEVaWh2PUMn3zkGlYt+zqAtznYB+dFPc31hhuVn3o5X
 c8UwLDUUJLzTePKPZ0UtzIu4Gm2RYTyRsnUAP0OKP/0WaZRyxnoQMYm5Llg7RBe0
 5ZJSWjJPBlv1YMWAHQ0YMZ+MhnFE8k4eV/8WfBQnb2INosgzKfJXEmu6ffAkPqSq
 jxBsrVQwtOMF2P9VEfdQDv3fs0GKDuZN5ezTFuW59Dt4VYfCUe2FTssSwFBIp5X9
 erPJ/nk883rcI6F0PdArNYvWpwPlVSDJyfTxQbYYxVAf8X1ARJCU3PT6iBnGO3i4
 d5tveSc8HoOXr4W3eIjn
 =c9rl
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2020-12-11' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "Not a huge amount of big things here, AMD has support for a few new HW
  variants (vangogh, green sardine, dimgrey cavefish), Intel has some
  more DG1 enablement. We have a few big reworks of the TTM layers and
  interfaces, GEM and atomic internal API reworks cross tree. fbdev is
  marked orphaned in here as well to reflect the current reality.

  core:
   - documentation updates
   - deprecate DRM_FORMAT_MOD_NONE
   - atomic crtc enable/disable rework
   - GEM convert drivers to gem object functions
   - remove SCATTER_LIST_MAX_SEGMENT

  sched:
   - avoid infinite waits

  ttm:
   - remove AGP support
   - don't modify caching for swapout
   - ttm pinning rework
   - major TTM reworks
   - new backend allocator
   - multihop support

  vram-helper:
   - top down BO placement fix
   - TTM changes
   - GEM object support

  displayport:
   - DP 2.0 DPCD prep work
   - DP MST extended DPCD caps

  fbdev:
   - mark as orphaned

  amdgpu:
   - Initial Vangogh support
   - Green Sardine support
   - Dimgrey Cavefish support
   - SG display support for renoir
   - SMU7 improvements
   - gfx9+ modiifier support
   - CI BACO fixes

  radeon:
   - expose voltage via hwmon on SUMO

  amdkfd:
   - fix unique id handling

  i915:
   - more DG1 enablement
   - bigjoiner support
   - integer scaling filter support
   - async flip support
   - ICL+ DSI command mode
   - Improve display shutdown
   - Display refactoring
   - eLLC machine fbdev loading fix
   - dma scatterlist fixes
   - TGL hang fixes
   - eLLC display buffer caching on SKL+
   - MOCS PTE seeting for gen9+

  msm:
   - Shutdown hook
   - GPU cooling device support
   - DSI 7nm and 10nm phy/pll updates
   - sm8150/sm2850 DPU support
   - GEM locking re-work
   - LLCC system cache support

  aspeed:
   - sysfs output config support

  ast:
   - LUT fix
   - new display mode

  gma500:
   - remove 2d framebuffer accel

  panfrost:
   - move gpu reset to a worker

  exynos:
   - new HDMI mode support

  mediatek:
   - MT8167 support
   - yaml bindings
   - MIPI DSI phy code moved

  etnaviv:
   - new perf counter
   - more lockdep annotation

  hibmc:
   - i2c DDC support

  ingenic:
   - pixel clock reset fix
   - reserved memory support
   - allow both DMA channels at once
   - different pixel format support
   - 30/24/8-bit palette modes

  tilcdc:
   - don't keep vblank irq enabled

  vc4:
   - new maintainer added
   - DSI registration fix

  virtio:
   - blob resource support
   - host visible and cross-device support
   - uuid api support"

* tag 'drm-next-2020-12-11' of git://anongit.freedesktop.org/drm/drm: (1754 commits)
  drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs
  drm/amdgpu: fix size calculation with stolen vga memory
  drm/amdgpu: remove amdgpu_ttm_late_init  and amdgpu_bo_late_init
  drm/amdgpu: free the pre-OS console framebuffer after the first modeset
  drm/amdgpu: enable runtime pm using BACO on CI dGPUs
  drm/amdgpu/cik: enable BACO reset on Bonaire
  drm/amd/pm: update smu10.h WORKLOAD_PPLIB setting for raven
  drm/amd/pm: remove one unsupported smu function for vangogh
  drm/amd/display: setup system context for APUs
  drm/amd/display: add S/G support for Vangogh
  drm/amdkfd: Fix leak in dmabuf import
  drm/amdgpu: use AMDGPU_NUM_VMID when possible
  drm/amdgpu: fix sdma instance fw version and feature version init
  drm/amd/pm: update driver if version for dimgrey_cavefish
  drm/amd/display: 3.2.115
  drm/amd/display: [FW Promotion] Release 0.0.45
  drm/amd/display: Revert DCN2.1 dram_clock_change_latency update
  drm/amd/display: Enable gpu_vm_support for dcn3.01
  drm/amd/display: Fixed the audio noise during mode switching with HDCP mode on
  drm/amd/display: Add wm table for Renoir
  ...
This commit is contained in:
Linus Torvalds 2020-12-14 11:07:56 -08:00
commit 1d36dffa5d
1323 changed files with 397128 additions and 18672 deletions

View File

@ -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>;
};
};
};
};
};

View File

@ -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>;
};
};
};
};

View File

@ -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

View File

@ -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 >;

View File

@ -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>;
};
};
};

View File

@ -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>;
};

View File

@ -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

View File

@ -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>;
};
};
};

View File

@ -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>;
};
};
};
...

View File

@ -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

View File

@ -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>;
};
};
};
};

View File

@ -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>;
};
};
};
};
...

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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,.*":

View File

@ -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
-------------------

View File

@ -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().

View File

@ -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
--------------

View File

@ -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

View File

@ -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
-----------------------

View File

@ -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/
@ -8967,6 +8975,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

View File

@ -135,3 +135,7 @@
};
};
};
&mali {
dma-coherent;
};

View File

@ -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);
@ -1188,68 +1209,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);
}

View File

@ -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;

View File

@ -235,7 +235,7 @@ static int dma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
return 0;
}
static void *dma_heap_dma_buf_vmap(struct dma_buf *dmabuf)
static int dma_heap_dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
{
struct heap_helper_buffer *buffer = dmabuf->priv;
void *vaddr;
@ -244,10 +244,14 @@ static void *dma_heap_dma_buf_vmap(struct dma_buf *dmabuf)
vaddr = dma_heap_buffer_vmap_get(buffer);
mutex_unlock(&buffer->lock);
return vaddr;
if (!vaddr)
return -ENOMEM;
dma_buf_map_set_vaddr(map, vaddr);
return 0;
}
static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
{
struct heap_helper_buffer *buffer = dmabuf->priv;

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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
};

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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:

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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));
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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. */

View File

@ -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;

View File

@ -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.

View 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);
}

View 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

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
/*

View File

@ -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);
}
}

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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).

View File

@ -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.

View File

@ -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
*

View File

@ -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

View File

@ -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
*

View File

@ -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,

View File

@ -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);

View File

@ -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;
};

View File

@ -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 {

View File

@ -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

View File

@ -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);

View File

@ -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).

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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);

View 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__ */

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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(&gtt->ttm);
ttm_tt_fini(&gtt->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(&gtt->ttm, bo, page_flags)) {
if (ttm_sg_tt_init(&gtt->ttm, bo, page_flags, caching)) {
kfree(gtt);
return NULL;
}
return &gtt->ttm.ttm;
return &gtt->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(&gtt->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, &gtt->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(&gtt->ttm, adev->dev);
return;
}
#endif
/* fall back to generic helper to unmap and unpopulate array */
ttm_unmap_and_unpopulate_pages(adev->dev, &gtt->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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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
*/

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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