drm for 5.16-rc1

core:
 - improve dma_fence, lease and resv documentation
 - shmem-helpers: allocate WC pages on x86, use vmf_insert_pin
 - sched fixes/improvements
 - allow empty drm leases
 - add dma resv iterator
 - add more DP 2.0 headers
 - DP MST helper improvements for DP2.0
 
 dma-buf:
 - avoid warnings, remove fence trace macros
 
 bridge:
 - new helper to get rid of panels
 - probe improvements for it66121
 - enable DSI EOTP for anx7625
 
 fbdev:
 - efifb: release runtime PM on destroy
 
 ttm:
 - kerneldoc switch
 - helper to clear all DMA mappings
 - pool shrinker optimizaton
 - remove ttm_tt_destroy_common
 - update ttm_move_memcpy for async use
 
 panel:
 - add new panel-edp driver
 
 amdgpu:
  - Initial DP 2.0 support
  - Initial USB4 DP tunnelling support
  - Aldebaran MCE support
  - Modifier support for DCC image stores for GFX 10.3
  - Display rework for better FP code handling
  - Yellow Carp/Cyan Skillfish updates
  - Cyan Skillfish display support
  - convert vega/navi to IP discovery asic enumeration
  - validate IP discovery table
  - RAS improvements
  - Lots of fixes
 
  i915:
  - DG1 PCI IDs + LMEM discovery/placement
  - DG1 GuC submission by default
  - ADL-S PCI IDs updated + enabled by default
  - ADL-P (XE_LPD) fixed and updates
  - DG2 display fixes
  - PXP protected object support for Gen12 integrated
  - expose multi-LRC submission interface for GuC
  - export logical engine instance to user
  - Disable engine bonding on Gen12+
  - PSR cleanup
  - PSR2 selective fetch by default
  - DP 2.0 prep work
  - VESA vendor block + MSO use of it
  - FBC refactor
  - try again to fix fast-narrow vs slow-wide eDP training
  - use THP when IOMMU enabled
  - LMEM backup/restore for suspend/resume
  - locking simplification
  - GuC major reworking
  - async flip VT-D workaround changes
  - DP link training improvements
  - misc display refactorings
 
 bochs:
 - new PCI ID
 
 rcar-du:
 - Non-contiguious buffer import support for rcar-du
 - r8a779a0 support prep
 
 omapdrm:
 - COMPILE_TEST fixes
 
 sti:
 - COMPILE_TEST fixes
 
 msm:
 - fence ordering improvements
 - eDP support in DP sub-driver
 - dpu irq handling cleanup
 - CRC support for making igt happy
 - NO_CONNECTOR bridge support
 - dsi: 14nm phy support for msm8953
 - mdp5: msm8x53, sdm450, sdm632 support
 
 stm:
 - layer alpha + zpo support
 
 v3d:
 - fix Vulkan CTS failure
 - support multiple sync objects
 
 gud:
 - add R8/RGB332/RGB888 pixel formats
 
 vc4:
 - convert to new bridge helpers
 
 vgem:
 - use shmem helpers
 
 virtio:
 - support mapping exported vram
 
 zte:
 - remove obsolete driver
 
 rockchip:
 - use bridge attach no connector for LVDS/RGB
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmGByPYACgkQDHTzWXnE
 hr6fxA//cXUvTHlEtF7UJDBRAYv+9lXH39NbGYU4aLJuBNlZztCuUi5JOSyDFDH1
 N9VI5biVseev2PEnCzJUubWxTqbUO7FBQTw0TyvZ4Eqn+UZMuFeo0dvdKZRAkvjV
 VHSUc0fm0+WSYanKUK7XK0fwG8aE6JVyYngzgKPSjifhszTdiiRsbU21iTinFhkS
 rgh3HEVELp+LqfoG4qzAYqFUjYqUjvCjd/hX/UkzCII8ZXKr38/4127e95443WOk
 +jes0gWGJe9TvSDrqo9TMx4qukcOniINFUvnzoD2RhOS+Jzr/i5rBh51Xy92g3NO
 Q7hy6byZdk/ZO/MXCDQ2giUOkBiqn5fQjlRGQp4iAZYw9pb3HU+/xrTq0BWVWd8o
 /vmzZYEKKU/sCGpxVDMZxsHV3mXIuVBvuZq6bjmSGcybgOBCiDx5F/Rum4nY2yHp
 lr3cuc0HP3m3f4b/HVvACO4tGd1nDDpVcon7CuhBB7HB7t6Zl9u18qc/qFw0tCTh
 3sgAhno6XFXtPFcSX2KAeeg0mhKDKKrsOnq5y3bDRr05Z0jLocJk95aXEKs6em4j
 gbyHwNaX3CHtiCnFn2/5169+n1K7zqHBtVSGmQlmFDv55rcdx7L3Spk7tCahQeSQ
 ur24r+sEggm8d5Wjl+MYq6wW3oP31s04JFaeV6oCkaSp1wS+alg=
 =jdhH
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2021-11-03' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "Summary below. i915 starts to add support for DG2 GPUs, enables DG1
  and ADL-S support by default, lots of work to enable DisplayPort 2.0
  across drivers. Lots of documentation updates and fixes across the
  board.

  core:
   - improve dma_fence, lease and resv documentation
   - shmem-helpers: allocate WC pages on x86, use vmf_insert_pin
   - sched fixes/improvements
   - allow empty drm leases
   - add dma resv iterator
   - add more DP 2.0 headers
   - DP MST helper improvements for DP2.0

  dma-buf:
   - avoid warnings, remove fence trace macros

  bridge:
   - new helper to get rid of panels
   - probe improvements for it66121
   - enable DSI EOTP for anx7625

  fbdev:
   - efifb: release runtime PM on destroy

  ttm:
   - kerneldoc switch
   - helper to clear all DMA mappings
   - pool shrinker optimizaton
   - remove ttm_tt_destroy_common
   - update ttm_move_memcpy for async use

  panel:
   - add new panel-edp driver

  amdgpu:
   - Initial DP 2.0 support
   - Initial USB4 DP tunnelling support
   - Aldebaran MCE support
   - Modifier support for DCC image stores for GFX 10.3
   - Display rework for better FP code handling
   - Yellow Carp/Cyan Skillfish updates
   - Cyan Skillfish display support
   - convert vega/navi to IP discovery asic enumeration
   - validate IP discovery table
   - RAS improvements
   - Lots of fixes

  i915:
   - DG1 PCI IDs + LMEM discovery/placement
   - DG1 GuC submission by default
   - ADL-S PCI IDs updated + enabled by default
   - ADL-P (XE_LPD) fixed and updates
   - DG2 display fixes
   - PXP protected object support for Gen12 integrated
   - expose multi-LRC submission interface for GuC
   - export logical engine instance to user
   - Disable engine bonding on Gen12+
   - PSR cleanup
   - PSR2 selective fetch by default
   - DP 2.0 prep work
   - VESA vendor block + MSO use of it
   - FBC refactor
   - try again to fix fast-narrow vs slow-wide eDP training
   - use THP when IOMMU enabled
   - LMEM backup/restore for suspend/resume
   - locking simplification
   - GuC major reworking
   - async flip VT-D workaround changes
   - DP link training improvements
   - misc display refactorings

  bochs:
   - new PCI ID

  rcar-du:
   - Non-contiguious buffer import support for rcar-du
   - r8a779a0 support prep

  omapdrm:
   - COMPILE_TEST fixes

  sti:
   - COMPILE_TEST fixes

  msm:
   - fence ordering improvements
   - eDP support in DP sub-driver
   - dpu irq handling cleanup
   - CRC support for making igt happy
   - NO_CONNECTOR bridge support
   - dsi: 14nm phy support for msm8953
   - mdp5: msm8x53, sdm450, sdm632 support

  stm:
   - layer alpha + zpo support

  v3d:
   - fix Vulkan CTS failure
   - support multiple sync objects

  gud:
   - add R8/RGB332/RGB888 pixel formats

  vc4:
   - convert to new bridge helpers

  vgem:
   - use shmem helpers

  virtio:
   - support mapping exported vram

  zte:
   - remove obsolete driver

  rockchip:
   - use bridge attach no connector for LVDS/RGB"

* tag 'drm-next-2021-11-03' of git://anongit.freedesktop.org/drm/drm: (1259 commits)
  drm/amdgpu/gmc6: fix DMA mask from 44 to 40 bits
  drm/amd/display: MST support for DPIA
  drm/amdgpu: Fix even more out of bound writes from debugfs
  drm/amdgpu/discovery: add SDMA IP instance info for soc15 parts
  drm/amdgpu/discovery: add UVD/VCN IP instance info for soc15 parts
  drm/amdgpu/UAPI: rearrange header to better align related items
  drm/amd/display: Enable dpia in dmub only for DCN31 B0
  drm/amd/display: Fix USB4 hot plug crash issue
  drm/amd/display: Fix deadlock when falling back to v2 from v3
  drm/amd/display: Fallback to clocks which meet requested voltage on DCN31
  drm/amd/display: move FPU associated DCN301 code to DML folder
  drm/amd/display: fix link training regression for 1 or 2 lane
  drm/amd/display: add two lane settings training options
  drm/amd/display: decouple hw_lane_settings from dpcd_lane_settings
  drm/amd/display: implement decide lane settings
  drm/amd/display: adopt DP2.0 LT SCR revision 8
  drm/amd/display: FEC configuration for dpia links in MST mode
  drm/amd/display: FEC configuration for dpia links
  drm/amd/display: Add workaround flag for EDID read on certain docks
  drm/amd/display: Set phy_mux_sel bit in dmub scratch register
  ...
This commit is contained in:
Linus Torvalds 2021-11-02 16:47:49 -07:00
commit 56d3375448
982 changed files with 81906 additions and 26478 deletions

View File

@ -17,9 +17,16 @@ properties:
compatible:
enum:
- qcom,sc7180-dp
- qcom,sc8180x-dp
- qcom,sc8180x-edp
reg:
maxItems: 1
items:
- description: ahb register block
- description: aux register block
- description: link register block
- description: p0 register block
- description: p1 register block
interrupts:
maxItems: 1
@ -100,7 +107,11 @@ examples:
displayport-controller@ae90000 {
compatible = "qcom,sc7180-dp";
reg = <0xae90000 0x1400>;
reg = <0xae90000 0x200>,
<0xae90200 0x200>,
<0xae90400 0xc00>,
<0xae91000 0x400>,
<0xae91400 0x400>;
interrupt-parent = <&mdss>;
interrupts = <12>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,

View File

@ -0,0 +1,232 @@
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/msm/dpu-sc7280.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Display DPU dt properties for SC7280
maintainers:
- Krishna Manikandan <mkrishn@codeaurora.org>
description: |
Device tree bindings for MSM Mobile Display Subsystem (MDSS) that encapsulates
sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
bindings of MDSS and DPU are mentioned for SC7280.
properties:
compatible:
const: qcom,sc7280-mdss
reg:
maxItems: 1
reg-names:
const: mdss
power-domains:
maxItems: 1
clocks:
items:
- description: Display AHB clock from gcc
- description: Display AHB clock from dispcc
- description: Display core clock
clock-names:
items:
- const: iface
- const: ahb
- const: core
interrupts:
maxItems: 1
interrupt-controller: true
"#address-cells": true
"#size-cells": true
"#interrupt-cells":
const: 1
iommus:
items:
- description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
ranges: true
interconnects:
items:
- description: Interconnect path specifying the port ids for data bus
interconnect-names:
const: mdp0-mem
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
description: Node containing the properties of DPU.
properties:
compatible:
const: qcom,sc7280-dpu
reg:
items:
- description: Address offset and size for mdp register set
- description: Address offset and size for vbif register set
reg-names:
items:
- const: mdp
- const: vbif
clocks:
items:
- description: Display hf axi clock
- description: Display sf axi clock
- description: Display ahb clock
- description: Display lut clock
- description: Display core clock
- description: Display vsync clock
clock-names:
items:
- const: bus
- const: nrt_bus
- const: iface
- const: lut
- const: core
- const: vsync
interrupts:
maxItems: 1
power-domains:
maxItems: 1
operating-points-v2: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
description: |
Contains the list of output ports from DPU device. These ports
connect to interfaces that are external to the DPU hardware,
such as DSI, DP etc. Each output port contains an endpoint that
describes how it is connected to an external interface.
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: DPU_INTF1 (DSI)
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: DPU_INTF5 (EDP)
required:
- port@0
required:
- compatible
- reg
- reg-names
- clocks
- interrupts
- power-domains
- operating-points-v2
- ports
required:
- compatible
- reg
- reg-names
- power-domains
- clocks
- interrupts
- interrupt-controller
- iommus
- ranges
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,dispcc-sc7280.h>
#include <dt-bindings/clock/qcom,gcc-sc7280.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interconnect/qcom,sc7280.h>
#include <dt-bindings/power/qcom-rpmpd.h>
display-subsystem@ae00000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "qcom,sc7280-mdss";
reg = <0xae00000 0x1000>;
reg-names = "mdss";
power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
clocks = <&gcc GCC_DISP_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
clock-names = "iface",
"ahb",
"core";
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>;
interconnect-names = "mdp0-mem";
iommus = <&apps_smmu 0x900 0x402>;
ranges;
display-controller@ae01000 {
compatible = "qcom,sc7280-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp", "vbif";
clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
<&gcc GCC_DISP_SF_AXI_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
clock-names = "bus",
"nrt_bus",
"iface",
"lut",
"core",
"vsync";
interrupt-parent = <&mdss>;
interrupts = <0>;
power-domains = <&rpmhpd SC7280_CX>;
operating-points-v2 = <&mdp_opp_table>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf1_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf5_out: endpoint {
remote-endpoint = <&edp_in>;
};
};
};
};
};
...

View File

@ -17,6 +17,7 @@ properties:
enum:
- qcom,dsi-phy-14nm
- qcom,dsi-phy-14nm-660
- qcom,dsi-phy-14nm-8953
reg:
items:

View File

@ -1,157 +0,0 @@
Qualcomm adreno/snapdragon GPU
Required properties:
- compatible: "qcom,adreno-XYZ.W", "qcom,adreno" or
"amd,imageon-XYZ.W", "amd,imageon"
for example: "qcom,adreno-306.0", "qcom,adreno"
Note that you need to list the less specific "qcom,adreno" (since this
is what the device is matched on), in addition to the more specific
with the chip-id.
If "amd,imageon" is used, there should be no top level msm device.
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt signal from the gpu.
- clocks: device clocks (if applicable)
See ../clocks/clock-bindings.txt for details.
- clock-names: the following clocks are required by a3xx, a4xx and a5xx
cores:
* "core"
* "iface"
* "mem_iface"
For GMU attached devices the GPU clocks are not used and are not required. The
following devices should not list clocks:
- qcom,adreno-630.2
- iommus: optional phandle to an adreno iommu instance
- operating-points-v2: optional phandle to the OPP operating points
- interconnects: optional phandle to an interconnect provider. See
../interconnect/interconnect.txt for details. Some A3xx and all A4xx platforms
will have two paths; all others will have one path.
- interconnect-names: The names of the interconnect paths that correspond to the
interconnects property. Values must be gfx-mem and ocmem.
- qcom,gmu: For GMU attached devices a phandle to the GMU device that will
control the power for the GPU. Applicable targets:
- qcom,adreno-630.2
- zap-shader: For a5xx and a6xx devices this node contains a memory-region that
points to reserved memory to store the zap shader that can be used to help
bring the GPU out of secure mode.
- firmware-name: optional property of the 'zap-shader' node, listing the
relative path of the device specific zap firmware.
- sram: phandle to the On Chip Memory (OCMEM) that's present on some a3xx and
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:
/ {
...
gpu: adreno@fdb00000 {
compatible = "qcom,adreno-330.2",
"qcom,adreno";
reg = <0xfdb00000 0x10000>;
reg-names = "kgsl_3d0_reg_memory";
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "kgsl_3d0_irq";
clock-names = "core",
"iface",
"mem_iface";
clocks = <&mmcc OXILI_GFX3D_CLK>,
<&mmcc OXILICX_AHB_CLK>,
<&mmcc OXILICX_AXI_CLK>;
sram = <&gpu_sram>;
power-domains = <&mmcc OXILICX_GDSC>;
operating-points-v2 = <&gpu_opp_table>;
iommus = <&gpu_iommu 0>;
#cooling-cells = <2>;
};
gpu_sram: ocmem@fdd00000 {
compatible = "qcom,msm8974-ocmem";
reg = <0xfdd00000 0x2000>,
<0xfec00000 0x180000>;
reg-names = "ctrl",
"mem";
clocks = <&rpmcc RPM_SMD_OCMEMGX_CLK>,
<&mmcc OCMEMCX_OCMEMNOC_CLK>;
clock-names = "core",
"iface";
#address-cells = <1>;
#size-cells = <1>;
gpu_sram: gpu-sram@0 {
reg = <0x0 0x100000>;
ranges = <0 0 0xfec00000 0x100000>;
};
};
};
Example a6xx (with GMU):
/ {
...
gpu@5000000 {
compatible = "qcom,adreno-630.2", "qcom,adreno";
#stream-id-cells = <16>;
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
*/
interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
iommus = <&adreno_smmu 0>;
operating-points-v2 = <&gpu_opp_table>;
interconnects = <&rsc_hlos MASTER_GFX3D &rsc_hlos SLAVE_EBI1>;
interconnect-names = "gfx-mem";
gpu_opp_table: opp-table {
compatible = "operating-points-v2";
opp-430000000 {
opp-hz = /bits/ 64 <430000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
opp-peak-kBps = <5412000>;
};
opp-355000000 {
opp-hz = /bits/ 64 <355000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
opp-peak-kBps = <3072000>;
};
opp-267000000 {
opp-hz = /bits/ 64 <267000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
opp-peak-kBps = <3072000>;
};
opp-180000000 {
opp-hz = /bits/ 64 <180000000>;
opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
opp-peak-kBps = <1804000>;
};
};
qcom,gmu = <&gmu>;
zap-shader {
memory-region = <&zap_shader_region>;
firmware-name = "qcom/LENOVO/81JL/qcdxkmsuc850.mbn"
};
};
};

View File

@ -0,0 +1,288 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/display/msm/gpu.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Devicetree bindings for the Adreno or Snapdragon GPUs
maintainers:
- Rob Clark <robdclark@gmail.com>
properties:
compatible:
oneOf:
- description: |
The driver is parsing the compat string for Adreno to
figure out the gpu-id and patch level.
items:
- pattern: '^qcom,adreno-[3-6][0-9][0-9]\.[0-9]$'
- const: qcom,adreno
- description: |
The driver is parsing the compat string for Imageon to
figure out the gpu-id and patch level.
items:
- pattern: '^amd,imageon-200\.[0-1]$'
- const: amd,imageon
clocks: true
clock-names: true
reg:
minItems: 1
maxItems: 3
reg-names:
minItems: 1
items:
- const: kgsl_3d0_reg_memory
- const: cx_mem
- const: cx_dbgc
interrupts:
maxItems: 1
interrupt-names:
maxItems: 1
interconnects:
minItems: 1
maxItems: 2
interconnect-names:
minItems: 1
items:
- const: gfx-mem
- const: ocmem
iommus:
maxItems: 1
sram:
$ref: /schemas/types.yaml#/definitions/phandle-array
minItems: 1
maxItems: 4
description: |
phandles to one or more reserved on-chip SRAM regions.
phandle to the On Chip Memory (OCMEM) that's present on some a3xx and
a4xx Snapdragon SoCs. See
Documentation/devicetree/bindings/sram/qcom,ocmem.yaml
operating-points-v2: true
opp-table:
type: object
power-domains:
maxItems: 1
zap-shader:
type: object
description: |
For a5xx and a6xx devices this node contains a memory-region that
points to reserved memory to store the zap shader that can be used to
help bring the GPU out of secure mode.
properties:
memory-region:
$ref: /schemas/types.yaml#/definitions/phandle
firmware-name:
description: |
Default name of the firmware to load to the remote processor.
"#cooling-cells":
const: 2
nvmem-cell-names:
maxItems: 1
nvmem-cells:
description: efuse registers
maxItems: 1
qcom,gmu:
$ref: /schemas/types.yaml#/definitions/phandle
description: |
For GMU attached devices a phandle to the GMU device that will
control the power for the GPU.
required:
- compatible
- reg
- interrupts
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
pattern: '^qcom,adreno-[3-5][0-9][0-9]\.[0-9]$'
then:
properties:
clocks:
minItems: 2
maxItems: 7
clock-names:
items:
anyOf:
- const: core
description: GPU Core clock
- const: iface
description: GPU Interface clock
- const: mem
description: GPU Memory clock
- const: mem_iface
description: GPU Memory Interface clock
- const: alt_mem_iface
description: GPU Alternative Memory Interface clock
- const: gfx3d
description: GPU 3D engine clock
- const: rbbmtimer
description: GPU RBBM Timer for Adreno 5xx series
minItems: 2
maxItems: 7
required:
- clocks
- clock-names
- if:
properties:
compatible:
contains:
pattern: '^qcom,adreno-6[0-9][0-9]\.[0-9]$'
then: # Since Adreno 6xx series clocks should be defined in GMU
properties:
clocks: false
clock-names: false
examples:
- |
// Example a3xx/4xx:
#include <dt-bindings/clock/qcom,mmcc-msm8974.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
gpu: gpu@fdb00000 {
compatible = "qcom,adreno-330.2", "qcom,adreno";
reg = <0xfdb00000 0x10000>;
reg-names = "kgsl_3d0_reg_memory";
clock-names = "core", "iface", "mem_iface";
clocks = <&mmcc OXILI_GFX3D_CLK>,
<&mmcc OXILICX_AHB_CLK>,
<&mmcc OXILICX_AXI_CLK>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "kgsl_3d0_irq";
sram = <&gpu_sram>;
power-domains = <&mmcc OXILICX_GDSC>;
operating-points-v2 = <&gpu_opp_table>;
iommus = <&gpu_iommu 0>;
#cooling-cells = <2>;
};
ocmem@fdd00000 {
compatible = "qcom,msm8974-ocmem";
reg = <0xfdd00000 0x2000>,
<0xfec00000 0x180000>;
reg-names = "ctrl", "mem";
clocks = <&rpmcc RPM_SMD_OCMEMGX_CLK>,
<&mmcc OCMEMCX_OCMEMNOC_CLK>;
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0xfec00000 0x100000>;
gpu_sram: gpu-sram@0 {
reg = <0x0 0x100000>;
};
};
- |
// Example a6xx (with GMU):
#include <dt-bindings/clock/qcom,gpucc-sdm845.h>
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interconnect/qcom,sdm845.h>
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
zap_shader_region: gpu@8f200000 {
compatible = "shared-dma-pool";
reg = <0x0 0x90b00000 0x0 0xa00000>;
no-map;
};
};
gpu@5000000 {
compatible = "qcom,adreno-630.2", "qcom,adreno";
reg = <0x5000000 0x40000>, <0x509e000 0x10>;
reg-names = "kgsl_3d0_reg_memory", "cx_mem";
#cooling-cells = <2>;
interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
iommus = <&adreno_smmu 0>;
operating-points-v2 = <&gpu_opp_table>;
interconnects = <&rsc_hlos MASTER_GFX3D &rsc_hlos SLAVE_EBI1>;
interconnect-names = "gfx-mem";
qcom,gmu = <&gmu>;
gpu_opp_table: opp-table {
compatible = "operating-points-v2";
opp-430000000 {
opp-hz = /bits/ 64 <430000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
opp-peak-kBps = <5412000>;
};
opp-355000000 {
opp-hz = /bits/ 64 <355000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
opp-peak-kBps = <3072000>;
};
opp-267000000 {
opp-hz = /bits/ 64 <267000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
opp-peak-kBps = <3072000>;
};
opp-180000000 {
opp-hz = /bits/ 64 <180000000>;
opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
opp-peak-kBps = <1804000>;
};
};
zap-shader {
memory-region = <&zap_shader_region>;
firmware-name = "qcom/LENOVO/81JL/qcdxkmsuc850.mbn";
};
};

View File

@ -26,6 +26,10 @@ properties:
- auo,b101uan08.3
# BOE TV105WUM-NW0 10.5" WUXGA TFT LCD panel
- boe,tv105wum-nw0
# BOE TV110C9M-LL3 10.95" WUXGA TFT LCD panel
- boe,tv110c9m-ll3
# INX HJ110IZ-01A 10.95" WUXGA TFT LCD panel
- innolux,hj110iz-01a
reg:
description: the virtual channel number of a DSI peripheral
@ -36,6 +40,9 @@ properties:
pp1800-supply:
description: core voltage supply
pp3300-supply:
description: core voltage supply
avdd-supply:
description: phandle of the regulator that provides positive voltage

View File

@ -0,0 +1,188 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/panel-edp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Probeable (via DP AUX / EDID) eDP Panels with simple poweron sequences
maintainers:
- Douglas Anderson <dianders@chromium.org>
description: |
This binding file can be used to indicate that an eDP panel is connected
to a Embedded DisplayPort AUX bus (see display/dp-aux-bus.yaml) without
actually specifying exactly what panel is connected. This is useful for
the case that more than one different panel could be connected to the
board, either for second-sourcing purposes or to support multiple SKUs
with different LCDs that hook up to a common board.
As per above, a requirement for using this binding is that the panel is
represented under the DP AUX bus. This means that we can use any
information provided by the DP AUX bus (including the EDID) to identify
the panel. We can use this to identify display size, resolution, and
timings among other things.
One piece of information about eDP panels that is typically _not_
provided anywhere on the DP AUX bus is the power sequencing timings.
This is the reason why, historically, we've always had to explicitly
list eDP panels. We solve that here with two tricks. The "worst case"
power on timings for any panels expected to be connected to a board are
specified in these bindings. Once we've powered on, it's expected that
the operating system will lookup the panel in a table (based on EDID
information) to figure out other power sequencing timings.
eDP panels in general can have somewhat arbitrary power sequencing
requirements. However, even though it's arbitrary in general, the
vast majority of panel datasheets have a power sequence diagram that
looks the exactly the same as every other panel. Each panel datasheet
cares about different timings in this diagram but the fact that the
diagram is so similar means we can come up with a single driver to
handle it.
These diagrams all look roughly like this, sometimes labeled with
slightly different numbers / lines but all pretty much the same
sequence. This is because much of this diagram comes straight from
the eDP Standard.
__________________________________________________
Vdd ___/: :\____ /
_/ : : \_____/
:<T1>:<T2>: :<--T10-->:<T11>:<T12>:
: +-----------------------+---------+---------+
eDP -----------+ Black video | Src vid | Blk vid +
Display : +-----------------------+---------+---------+
: _______________________:_________:_________:
HPD :<T3>| : : |
___________| : : |_____________
: : : :
Sink +-----------------------:---------:---------+
AUX CH -----------+ AUX Ch operational : : +-------------
+-----------------------:---------:---------+
: : : :
:<T4>: :<T7>: : :
Src main +------+------+--------------+---------+
lnk data----------------+LnkTrn| Idle |Valid vid data| Idle/off+-------------
+------+------+--------------+---------+
: <T5> :<-T6->:<-T8->: :
:__:<T9>:
LED_EN | |
_____________________________________| |____________________________
: :
__________:__:_
PWM | : : |
__________________________| : : |__________________________
: : : :
_____________:__________:__:_:______
Bklight ____/: : : : : :\____
power _______/ :<---T13---->: : : :<T16>: \______________
(Vbl) :<T17>:<---------T14--------->: :<-T15->:<T18>:
The above looks fairly complex but, as per above, each panel only cares
about a subset of those timings.
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: edp-panel
hpd-reliable-delay-ms:
description:
A fixed amount of time that must be waited after powering on the
panel's power-supply before the HPD signal is a reliable way to know
when the AUX channel is ready. This is useful for panels that glitch
the HPD at the start of power-on. This value is not needed if HPD is
always reliable for all panels that might be connected.
hpd-absent-delay-ms:
description:
The panel specifies that HPD will be asserted this many milliseconds
from power on (timing T3 in the diagram above). If we have no way to
measure HPD then a fixed delay of this many milliseconds can be used.
This can also be used as a timeout when waiting for HPD. Does not
include the hpd-reliable-delay, so if hpd-reliable-delay was 80 ms
and hpd-absent-delay was 200 ms then we'd do a fixed 80 ms delay and
then we know HPD would assert in the next 120 ms. This value is not
needed if HPD hooked up, either through a GPIO in the panel node or
hooked up directly to the eDP controller.
backlight: true
enable-gpios: true
port: true
power-supply: true
no-hpd: true
hpd-gpios: true
additionalProperties: false
required:
- compatible
- power-supply
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
bridge@2d {
compatible = "ti,sn65dsi86";
reg = <0x2d>;
interrupt-parent = <&tlmm>;
interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
enable-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>;
vpll-supply = <&src_pp1800_s4a>;
vccio-supply = <&src_pp1800_s4a>;
vcca-supply = <&src_pp1200_l2a>;
vcc-supply = <&src_pp1200_l2a>;
clocks = <&rpmhcc RPMH_LN_BB_CLK2>;
clock-names = "refclk";
no-hpd;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&dsi0_out>;
};
};
port@1 {
reg = <1>;
sn65dsi86_out: endpoint {
remote-endpoint = <&panel_in_edp>;
};
};
};
aux-bus {
panel {
compatible = "edp-panel";
power-supply = <&pp3300_dx_edp>;
backlight = <&backlight>;
hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>;
hpd-reliable-delay-ms = <15>;
port {
panel_in_edp: endpoint {
remote-endpoint = <&sn65dsi86_out>;
};
};
};
};
};
};

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/panel/samsung,s6d27a1.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S6D27A1 display panel
description: The S6D27A1 is a 480x800 DPI display panel from Samsung Mobile
Displays (SMD). The panel must obey the rules for a SPI slave device
as specified in spi/spi-controller.yaml
maintainers:
- Markuss Broks <markuss.broks@gmail.com>
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: samsung,s6d27a1
reg: true
interrupts:
description: provides an optional ESD (electrostatic discharge)
interrupt that signals abnormalities in the display hardware.
This can also be raised for other reasons like erroneous
configuration.
maxItems: 1
reset-gpios: true
vci-supply:
description: regulator that supplies the VCI analog voltage
usually around 3.0 V
vccio-supply:
description: regulator that supplies the VCCIO voltage usually
around 1.8 V
backlight: true
spi-cpha: true
spi-cpol: true
spi-max-frequency:
maximum: 1200000
port: true
required:
- compatible
- reg
- vci-supply
- vccio-supply
- spi-cpha
- spi-cpol
- port
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi {
compatible = "spi-gpio";
sck-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
miso-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
mosi-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
cs-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
num-chipselects = <1>;
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "samsung,s6d27a1";
spi-max-frequency = <1200000>;
spi-cpha;
spi-cpol;
reg = <0>;
vci-supply = <&lcd_3v0_reg>;
vccio-supply = <&lcd_1v8_reg>;
reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
interrupt-parent = <&gpio>;
interrupts = <5 IRQ_TYPE_EDGE_RISING>;
port {
panel_in: endpoint {
remote-endpoint = <&display_out>;
};
};
};
};
...

View File

@ -39,6 +39,7 @@ properties:
- renesas,du-r8a77980 # for R-Car V3H compatible DU
- renesas,du-r8a77990 # for R-Car E3 compatible DU
- renesas,du-r8a77995 # for R-Car D3 compatible DU
- renesas,du-r8a779a0 # for R-Car V3U compatible DU
reg:
maxItems: 1
@ -773,6 +774,56 @@ allOf:
- reset-names
- renesas,vsps
- if:
properties:
compatible:
contains:
enum:
- renesas,du-r8a779a0
then:
properties:
clocks:
items:
- description: Functional clock
clock-names:
maxItems: 1
items:
- const: du.0
interrupts:
maxItems: 2
resets:
maxItems: 1
reset-names:
items:
- const: du.0
ports:
properties:
port@0:
description: DSI 0
port@1:
description: DSI 1
port@2: false
port@3: false
required:
- port@0
- port@1
renesas,vsps:
minItems: 2
required:
- clock-names
- interrupts
- resets
- reset-names
- renesas,vsps
additionalProperties: false
examples:

View File

@ -176,12 +176,6 @@ DMA Fences Functions Reference
.. kernel-doc:: include/linux/dma-fence.h
:internal:
Seqno Hardware Fences
~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: include/linux/seqno-fence.h
:internal:
DMA Fence Array
~~~~~~~~~~~~~~~

View File

@ -151,6 +151,18 @@ Overview
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: overview
Display Driver Integration
--------------------------
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: display driver integration
Special Care with MIPI-DSI bridges
----------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
:doc: special care dsi
Bridge Operations
-----------------

View File

@ -28,56 +28,53 @@ UMA devices.
The Translation Table Manager (TTM)
===================================
TTM design background and information belongs here.
.. kernel-doc:: drivers/gpu/drm/ttm/ttm_module.c
:doc: TTM
TTM initialization
------------------
.. kernel-doc:: include/drm/ttm/ttm_caching.h
:internal:
**Warning**
This section is outdated.
TTM device object reference
---------------------------
Drivers wishing to support TTM must pass a filled :c:type:`ttm_bo_driver
<ttm_bo_driver>` structure to ttm_device_init, together with an
initialized global reference to the memory manager. The ttm_bo_driver
structure contains several fields with function pointers for
initializing the TTM, allocating and freeing memory, waiting for command
completion and fence synchronization, and memory migration.
.. kernel-doc:: include/drm/ttm/ttm_device.h
:internal:
The :c:type:`struct drm_global_reference <drm_global_reference>` is made
up of several fields:
.. kernel-doc:: drivers/gpu/drm/ttm/ttm_device.c
:export:
.. code-block:: c
TTM resource placement reference
--------------------------------
struct drm_global_reference {
enum ttm_global_types global_type;
size_t size;
void *object;
int (*init) (struct drm_global_reference *);
void (*release) (struct drm_global_reference *);
};
.. kernel-doc:: include/drm/ttm/ttm_placement.h
:internal:
TTM resource object reference
-----------------------------
There should be one global reference structure for your memory manager
as a whole, and there will be others for each object created by the
memory manager at runtime. Your global TTM should have a type of
TTM_GLOBAL_TTM_MEM. The size field for the global object should be
sizeof(struct ttm_mem_global), and the init and release hooks should
point at your driver-specific init and release routines, which probably
eventually call ttm_mem_global_init and ttm_mem_global_release,
respectively.
.. kernel-doc:: include/drm/ttm/ttm_resource.h
:internal:
Once your global TTM accounting structure is set up and initialized by
calling ttm_global_item_ref() on it, you need to create a buffer
object TTM to provide a pool for buffer object allocation by clients and
the kernel itself. The type of this object should be
TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct
ttm_bo_global). Again, driver-specific init and release functions may
be provided, likely eventually calling ttm_bo_global_ref_init() and
ttm_bo_global_ref_release(), respectively. Also, like the previous
object, ttm_global_item_ref() is used to create an initial reference
count for the TTM, which will call your initialization function.
.. kernel-doc:: drivers/gpu/drm/ttm/ttm_resource.c
:export:
See the radeon_ttm.c file for an example of usage.
TTM TT object reference
-----------------------
.. kernel-doc:: include/drm/ttm/ttm_tt.h
:internal:
.. kernel-doc:: drivers/gpu/drm/ttm/ttm_tt.c
:export:
TTM page pool reference
-----------------------
.. kernel-doc:: include/drm/ttm/ttm_pool.h
:internal:
.. kernel-doc:: drivers/gpu/drm/ttm/ttm_pool.c
:export:
The Graphics Execution Manager (GEM)
====================================
@ -504,3 +501,6 @@ Scheduler Function References
.. kernel-doc:: drivers/gpu/drm/scheduler/sched_main.c
:export:
.. kernel-doc:: drivers/gpu/drm/scheduler/sched_entity.c
:export:

View File

@ -183,26 +183,23 @@ Frame Buffer Compression (FBC)
Display Refresh Rate Switching (DRRS)
-------------------------------------
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
:doc: Display Refresh Rate Switching (DRRS)
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
:functions: intel_dp_set_drrs_state
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
:functions: intel_drrs_enable
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
:functions: intel_edp_drrs_enable
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
:functions: intel_drrs_disable
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
:functions: intel_edp_drrs_disable
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
:functions: intel_drrs_invalidate
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
:functions: intel_edp_drrs_invalidate
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
:functions: intel_drrs_flush
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
:functions: intel_edp_drrs_flush
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
:functions: intel_dp_drrs_init
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
:functions: intel_drrs_init
DPIO
----
@ -474,6 +471,14 @@ Object Tiling IOCTLs
.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_tiling.c
:doc: buffer object tiling
Protected Objects
-----------------
.. kernel-doc:: drivers/gpu/drm/i915/pxp/intel_pxp.c
:doc: PXP
.. kernel-doc:: drivers/gpu/drm/i915/pxp/intel_pxp_types.h
Microcontrollers
================
@ -498,6 +503,8 @@ GuC
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc.c
:doc: GuC
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc.h
GuC Firmware Layout
~~~~~~~~~~~~~~~~~~~

View File

@ -1,122 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2021 Intel Corporation
*/
#define I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 2 /* see i915_context_engines_parallel_submit */
/**
* struct drm_i915_context_engines_parallel_submit - Configure engine for
* parallel submission.
*
* Setup a slot in the context engine map to allow multiple BBs to be submitted
* in a single execbuf IOCTL. Those BBs will then be scheduled to run on the GPU
* in parallel. Multiple hardware contexts are created internally in the i915
* run these BBs. Once a slot is configured for N BBs only N BBs can be
* submitted in each execbuf IOCTL and this is implicit behavior e.g. The user
* doesn't tell the execbuf IOCTL there are N BBs, the execbuf IOCTL knows how
* many BBs there are based on the slot's configuration. The N BBs are the last
* N buffer objects or first N if I915_EXEC_BATCH_FIRST is set.
*
* The default placement behavior is to create implicit bonds between each
* context if each context maps to more than 1 physical engine (e.g. context is
* a virtual engine). Also we only allow contexts of same engine class and these
* contexts must be in logically contiguous order. Examples of the placement
* behavior described below. Lastly, the default is to not allow BBs to
* preempted mid BB rather insert coordinated preemption on all hardware
* contexts between each set of BBs. Flags may be added in the future to change
* both of these default behaviors.
*
* Returns -EINVAL if hardware context placement configuration is invalid or if
* the placement configuration isn't supported on the platform / submission
* interface.
* Returns -ENODEV if extension isn't supported on the platform / submission
* interface.
*
* .. code-block:: none
*
* Example 1 pseudo code:
* CS[X] = generic engine of same class, logical instance X
* INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
* set_engines(INVALID)
* set_parallel(engine_index=0, width=2, num_siblings=1,
* engines=CS[0],CS[1])
*
* Results in the following valid placement:
* CS[0], CS[1]
*
* Example 2 pseudo code:
* CS[X] = generic engine of same class, logical instance X
* INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
* set_engines(INVALID)
* set_parallel(engine_index=0, width=2, num_siblings=2,
* engines=CS[0],CS[2],CS[1],CS[3])
*
* Results in the following valid placements:
* CS[0], CS[1]
* CS[2], CS[3]
*
* This can also be thought of as 2 virtual engines described by 2-D array
* in the engines the field with bonds placed between each index of the
* virtual engines. e.g. CS[0] is bonded to CS[1], CS[2] is bonded to
* CS[3].
* VE[0] = CS[0], CS[2]
* VE[1] = CS[1], CS[3]
*
* Example 3 pseudo code:
* CS[X] = generic engine of same class, logical instance X
* INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
* set_engines(INVALID)
* set_parallel(engine_index=0, width=2, num_siblings=2,
* engines=CS[0],CS[1],CS[1],CS[3])
*
* Results in the following valid and invalid placements:
* CS[0], CS[1]
* CS[1], CS[3] - Not logical contiguous, return -EINVAL
*/
struct drm_i915_context_engines_parallel_submit {
/**
* @base: base user extension.
*/
struct i915_user_extension base;
/**
* @engine_index: slot for parallel engine
*/
__u16 engine_index;
/**
* @width: number of contexts per parallel engine
*/
__u16 width;
/**
* @num_siblings: number of siblings per context
*/
__u16 num_siblings;
/**
* @mbz16: reserved for future use; must be zero
*/
__u16 mbz16;
/**
* @flags: all undefined flags must be zero, currently not defined flags
*/
__u64 flags;
/**
* @mbz64: reserved for future use; must be zero
*/
__u64 mbz64[3];
/**
* @engines: 2-d array of engine instances to configure parallel engine
*
* length = width (i) * num_siblings (j)
* index = j + i * num_siblings
*/
struct i915_engine_class_instance engines[0];
} __packed;

View File

@ -135,8 +135,8 @@ Add I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT and
drm_i915_context_engines_parallel_submit to the uAPI to implement this
extension.
.. kernel-doc:: Documentation/gpu/rfc/i915_parallel_execbuf.h
:functions: drm_i915_context_engines_parallel_submit
.. kernel-doc:: include/uapi/drm/i915_drm.h
:functions: i915_context_engines_parallel_submit
Extend execbuf2 IOCTL to support submitting N BBs in a single IOCTL
-------------------------------------------------------------------

View File

@ -353,23 +353,6 @@ converted, except for struct drm_driver.gem_prime_mmap.
Level: Intermediate
Use DRM_MODESET_LOCK_ALL_* helpers instead of boilerplate
---------------------------------------------------------
For cases where drivers are attempting to grab the modeset locks with a local
acquire context. Replace the boilerplate code surrounding
drm_modeset_lock_all_ctx() with DRM_MODESET_LOCK_ALL_BEGIN() and
DRM_MODESET_LOCK_ALL_END() instead.
This should also be done for all places where drm_modeset_lock_all() is still
used.
As a reference, take a look at the conversions already completed in drm core.
Contact: Sean Paul, respective driver maintainers
Level: Starter
Rename CMA helpers to DMA helpers
---------------------------------

View File

@ -60,7 +60,7 @@ Concepts
Compared to normal mutexes two additional concepts/objects show up in the lock
interface for w/w mutexes:
Acquire context: To ensure eventual forward progress it is important the a task
Acquire context: To ensure eventual forward progress it is important that a task
trying to acquire locks doesn't grab a new reservation id, but keeps the one it
acquired when starting the lock acquisition. This ticket is stored in the
acquire context. Furthermore the acquire context keeps track of debugging state

View File

@ -893,6 +893,7 @@ F: include/uapi/linux/psp-sev.h
AMD DISPLAY CORE
M: Harry Wentland <harry.wentland@amd.com>
M: Leo Li <sunpeng.li@amd.com>
M: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
L: amd-gfx@lists.freedesktop.org
S: Supported
T: git https://gitlab.freedesktop.org/agd5f/linux.git
@ -6046,6 +6047,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
F: drivers/gpu/drm/panel/panel-samsung-db7430.c
DRM DRIVER FOR SAMSUNG S6D27A1 PANELS
M: Markuss Broks <markuss.broks@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
F: drivers/gpu/drm/panel/panel-samsung-s6d27a1.c
DRM DRIVER FOR SITRONIX ST7703 PANELS
M: Guido Günther <agx@sigxcpu.org>
R: Purism Kernel Team <kernel@puri.sm>
@ -6452,6 +6459,14 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/ttm/
F: include/drm/ttm/
DRM GPU SCHEDULER
M: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/scheduler/
F: include/drm/gpu_scheduler.h
DSBR100 USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org

View File

@ -144,6 +144,7 @@ CONFIG_VIDEO_MT9V032=m
CONFIG_DRM=y
CONFIG_DRM_ATMEL_HLCDC=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_FB_ATMEL=y
CONFIG_BACKLIGHT_ATMEL_LCDC=y
CONFIG_BACKLIGHT_PWM=y

View File

@ -227,6 +227,7 @@ CONFIG_DRM_EXYNOS_DPI=y
CONFIG_DRM_EXYNOS_DSI=y
CONFIG_DRM_EXYNOS_HDMI=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_PANEL_SAMSUNG_LD9040=y
CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=y
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=y

View File

@ -281,6 +281,7 @@ CONFIG_DRM=y
CONFIG_DRM_MSM=y
CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
CONFIG_DRM_TI_TFP410=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m

View File

@ -108,6 +108,7 @@ CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_DRM=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_PL111=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y

View File

@ -194,6 +194,7 @@ CONFIG_VIDEO_ATMEL_ISI=m
CONFIG_DRM=y
CONFIG_DRM_ATMEL_HLCDC=m
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_ASPEED_GFX=m
CONFIG_FB_IMX=y
CONFIG_FB_ATMEL=y

View File

@ -704,6 +704,7 @@ CONFIG_DRM_TEGRA=y
CONFIG_DRM_STM=m
CONFIG_DRM_STM_DSI=m
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_PANEL_SAMSUNG_LD9040=m
CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
CONFIG_DRM_PANEL_RAYDIUM_RM68200=m

View File

@ -511,6 +511,7 @@ CONFIG_OMAP2_DSS_DSI=y
CONFIG_DRM_TILCDC=m
CONFIG_DRM_PANEL_DSI_CM=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_EDP=m
CONFIG_DRM_PANEL_LG_LB035Q02=m
CONFIG_DRM_PANEL_NEC_NL8048HL11=m
CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m

View File

@ -158,6 +158,7 @@ CONFIG_MEDIA_SUPPORT=y
CONFIG_DRM=y
CONFIG_DRM_MSM=m
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_ANALOGIX_ANX78XX=m
CONFIG_FB=y
CONFIG_FRAMEBUFFER_CONSOLE=y

View File

@ -61,6 +61,7 @@ CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_DRM=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_DISPLAY_CONNECTOR=y
CONFIG_DRM_SIMPLE_BRIDGE=y
CONFIG_DRM_PL111=y

View File

@ -160,6 +160,7 @@ CONFIG_VIDEO_MT9V032=m
CONFIG_DRM=y
CONFIG_DRM_ATMEL_HLCDC=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y

View File

@ -128,6 +128,7 @@ CONFIG_VIDEO_ML86V7667=y
CONFIG_DRM=y
CONFIG_DRM_RCAR_DU=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_DISPLAY_CONNECTOR=y
CONFIG_DRM_LVDS_CODEC=y
CONFIG_DRM_SII902X=y

View File

@ -108,6 +108,7 @@ CONFIG_DRM_SUN4I_HDMI_CEC=y
CONFIG_DRM_SUN8I_DW_HDMI=y
CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_SIMPLE_BRIDGE=y
CONFIG_DRM_LIMA=y
CONFIG_FB_SIMPLE=y

View File

@ -199,6 +199,7 @@ CONFIG_DRM_TEGRA=y
CONFIG_DRM_TEGRA_STAGING=y
CONFIG_DRM_PANEL_LVDS=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_LVDS_CODEC=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y

View File

@ -57,6 +57,7 @@ CONFIG_GPIO_PL061=y
CONFIG_DRM=y
CONFIG_DRM_PANEL_ARM_VERSATILE=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_DISPLAY_CONNECTOR=y
CONFIG_DRM_SIMPLE_BRIDGE=y
CONFIG_DRM_PL111=y

View File

@ -77,6 +77,7 @@ CONFIG_SENSORS_VEXPRESS=y
CONFIG_REGULATOR_VEXPRESS=y
CONFIG_DRM=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_EDP=y
CONFIG_DRM_SII902X=y
CONFIG_DRM_PL111=y
CONFIG_FB=y

View File

@ -696,6 +696,7 @@ CONFIG_DRM_MSM=m
CONFIG_DRM_TEGRA=m
CONFIG_DRM_PANEL_LVDS=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_EDP=m
CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m
CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m
CONFIG_DRM_PANEL_RAYDIUM_RM67191=m

View File

@ -346,7 +346,7 @@ extern int mce_threshold_remove_device(unsigned int cpu);
void mce_amd_feature_init(struct cpuinfo_x86 *c);
int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr);
enum smca_bank_types smca_get_bank_type(unsigned int bank);
#else
static inline int mce_threshold_create_device(unsigned int cpu) { return 0; };

View File

@ -119,7 +119,7 @@ const char *smca_get_long_name(enum smca_bank_types t)
}
EXPORT_SYMBOL_GPL(smca_get_long_name);
static enum smca_bank_types smca_get_bank_type(unsigned int bank)
enum smca_bank_types smca_get_bank_type(unsigned int bank)
{
struct smca_bank *b;
@ -132,6 +132,7 @@ static enum smca_bank_types smca_get_bank_type(unsigned int bank)
return b->hwid->bank_type;
}
EXPORT_SYMBOL_GPL(smca_get_bank_type);
static struct smca_hwid smca_hwid_mcatypes[] = {
/* { bank_type, hwid_mcatype } */

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
dma-resv.o seqno-fence.o
dma-resv.o
obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o
obj-$(CONFIG_DMABUF_HEAPS) += heaps/
obj-$(CONFIG_SYNC_FILE) += sync_file.o

View File

@ -74,7 +74,7 @@ static void dma_buf_release(struct dentry *dentry)
* If you hit this BUG() it means someone dropped their ref to the
* dma-buf while still having pending operation to the buffer.
*/
BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active);
dma_buf_stats_teardown(dmabuf);
dmabuf->ops->release(dmabuf);
@ -82,6 +82,7 @@ static void dma_buf_release(struct dentry *dentry)
if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])
dma_resv_fini(dmabuf->resv);
WARN_ON(!list_empty(&dmabuf->attachments));
module_put(dmabuf->owner);
kfree(dmabuf->name);
kfree(dmabuf);
@ -205,16 +206,55 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
wake_up_locked_poll(dcb->poll, dcb->active);
dcb->active = 0;
spin_unlock_irqrestore(&dcb->poll->lock, flags);
dma_fence_put(fence);
}
static bool dma_buf_poll_shared(struct dma_resv *resv,
struct dma_buf_poll_cb_t *dcb)
{
struct dma_resv_list *fobj = dma_resv_shared_list(resv);
struct dma_fence *fence;
int i, r;
if (!fobj)
return false;
for (i = 0; i < fobj->shared_count; ++i) {
fence = rcu_dereference_protected(fobj->shared[i],
dma_resv_held(resv));
dma_fence_get(fence);
r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb);
if (!r)
return true;
dma_fence_put(fence);
}
return false;
}
static bool dma_buf_poll_excl(struct dma_resv *resv,
struct dma_buf_poll_cb_t *dcb)
{
struct dma_fence *fence = dma_resv_excl_fence(resv);
int r;
if (!fence)
return false;
dma_fence_get(fence);
r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb);
if (!r)
return true;
dma_fence_put(fence);
return false;
}
static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
{
struct dma_buf *dmabuf;
struct dma_resv *resv;
struct dma_resv_list *fobj;
struct dma_fence *fence_excl;
__poll_t events;
unsigned shared_count, seq;
dmabuf = file->private_data;
if (!dmabuf || !dmabuf->resv)
@ -228,61 +268,12 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
if (!events)
return 0;
retry:
seq = read_seqcount_begin(&resv->seq);
rcu_read_lock();
dma_resv_lock(resv, NULL);
fobj = rcu_dereference(resv->fence);
if (fobj)
shared_count = fobj->shared_count;
else
shared_count = 0;
fence_excl = dma_resv_excl_fence(resv);
if (read_seqcount_retry(&resv->seq, seq)) {
rcu_read_unlock();
goto retry;
}
if (events & EPOLLOUT) {
struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_out;
if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) {
struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
__poll_t pevents = EPOLLIN;
if (shared_count == 0)
pevents |= EPOLLOUT;
spin_lock_irq(&dmabuf->poll.lock);
if (dcb->active) {
dcb->active |= pevents;
events &= ~pevents;
} else
dcb->active = pevents;
spin_unlock_irq(&dmabuf->poll.lock);
if (events & pevents) {
if (!dma_fence_get_rcu(fence_excl)) {
/* force a recheck */
events &= ~pevents;
dma_buf_poll_cb(NULL, &dcb->cb);
} else if (!dma_fence_add_callback(fence_excl, &dcb->cb,
dma_buf_poll_cb)) {
events &= ~pevents;
dma_fence_put(fence_excl);
} else {
/*
* No callback queued, wake up any additional
* waiters.
*/
dma_fence_put(fence_excl);
dma_buf_poll_cb(NULL, &dcb->cb);
}
}
}
if ((events & EPOLLOUT) && shared_count > 0) {
struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared;
int i;
/* Only queue a new callback if no event has fired yet */
/* Check that callback isn't busy */
spin_lock_irq(&dmabuf->poll.lock);
if (dcb->active)
events &= ~EPOLLOUT;
@ -290,39 +281,37 @@ retry:
dcb->active = EPOLLOUT;
spin_unlock_irq(&dmabuf->poll.lock);
if (!(events & EPOLLOUT))
goto out;
for (i = 0; i < shared_count; ++i) {
struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
if (!dma_fence_get_rcu(fence)) {
/*
* fence refcount dropped to zero, this means
* that fobj has been freed
*
* call dma_buf_poll_cb and force a recheck!
*/
events &= ~EPOLLOUT;
if (events & EPOLLOUT) {
if (!dma_buf_poll_shared(resv, dcb) &&
!dma_buf_poll_excl(resv, dcb))
/* No callback queued, wake up any other waiters */
dma_buf_poll_cb(NULL, &dcb->cb);
break;
}
if (!dma_fence_add_callback(fence, &dcb->cb,
dma_buf_poll_cb)) {
dma_fence_put(fence);
else
events &= ~EPOLLOUT;
break;
}
dma_fence_put(fence);
}
/* No callback queued, wake up any additional waiters. */
if (i == shared_count)
dma_buf_poll_cb(NULL, &dcb->cb);
}
out:
rcu_read_unlock();
if (events & EPOLLIN) {
struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_in;
/* Check that callback isn't busy */
spin_lock_irq(&dmabuf->poll.lock);
if (dcb->active)
events &= ~EPOLLIN;
else
dcb->active = EPOLLIN;
spin_unlock_irq(&dmabuf->poll.lock);
if (events & EPOLLIN) {
if (!dma_buf_poll_excl(resv, dcb))
/* No callback queued, wake up any other waiters */
dma_buf_poll_cb(NULL, &dcb->cb);
else
events &= ~EPOLLIN;
}
}
dma_resv_unlock(resv);
return events;
}
@ -565,8 +554,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
dmabuf->owner = exp_info->owner;
spin_lock_init(&dmabuf->name_lock);
init_waitqueue_head(&dmabuf->poll);
dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
dmabuf->cb_in.active = dmabuf->cb_out.active = 0;
if (!resv) {
resv = (struct dma_resv *)&dmabuf[1];

View File

@ -616,20 +616,17 @@ EXPORT_SYMBOL(dma_fence_enable_sw_signaling);
* @cb: the callback to register
* @func: the function to call
*
* Add a software callback to the fence. The caller should keep a reference to
* the fence.
*
* @cb will be initialized by dma_fence_add_callback(), no initialization
* by the caller is required. Any number of callbacks can be registered
* to a fence, but a callback can only be registered to one fence at a time.
*
* Note that the callback can be called from an atomic context. If
* fence is already signaled, this function will return -ENOENT (and
* If fence is already signaled, this function will return -ENOENT (and
* *not* call the callback).
*
* Add a software callback to the fence. Same restrictions apply to
* refcount as it does to dma_fence_wait(), however the caller doesn't need to
* keep a refcount to fence afterward dma_fence_add_callback() has returned:
* when software access is enabled, the creator of the fence is required to keep
* the fence alive until after it signals with dma_fence_signal(). The callback
* itself can be called from irq context.
* Note that the callback can be called from an atomic context or irq context.
*
* Returns 0 in case of success, -ENOENT if the fence is already signaled
* and -EINVAL in case of error.

View File

@ -48,6 +48,8 @@
* write operations) or N shared fences (read operations). The RCU
* mechanism is used to protect read access to fences from locked
* write-side updates.
*
* See struct dma_resv for more details.
*/
DEFINE_WD_CLASS(reservation_ww_class);
@ -137,7 +139,11 @@ EXPORT_SYMBOL(dma_resv_fini);
* @num_fences: number of fences we want to add
*
* Should be called before dma_resv_add_shared_fence(). Must
* be called with obj->lock held.
* be called with @obj locked through dma_resv_lock().
*
* Note that the preallocated slots need to be re-reserved if @obj is unlocked
* at any time before calling dma_resv_add_shared_fence(). This is validated
* when CONFIG_DEBUG_MUTEXES is enabled.
*
* RETURNS
* Zero for success, or -errno
@ -234,8 +240,10 @@ EXPORT_SYMBOL(dma_resv_reset_shared_max);
* @obj: the reservation object
* @fence: the shared fence to add
*
* Add a fence to a shared slot, obj->lock must be held, and
* Add a fence to a shared slot, @obj must be locked with dma_resv_lock(), and
* dma_resv_reserve_shared() has been called.
*
* See also &dma_resv.fence for a discussion of the semantics.
*/
void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
{
@ -278,9 +286,11 @@ EXPORT_SYMBOL(dma_resv_add_shared_fence);
/**
* dma_resv_add_excl_fence - Add an exclusive fence.
* @obj: the reservation object
* @fence: the shared fence to add
* @fence: the exclusive fence to add
*
* Add a fence to the exclusive slot. The obj->lock must be held.
* Add a fence to the exclusive slot. @obj must be locked with dma_resv_lock().
* Note that this function replaces all fences attached to @obj, see also
* &dma_resv.fence_excl for a discussion of the semantics.
*/
void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
{
@ -313,6 +323,106 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
}
EXPORT_SYMBOL(dma_resv_add_excl_fence);
/**
* dma_resv_iter_restart_unlocked - restart the unlocked iterator
* @cursor: The dma_resv_iter object to restart
*
* Restart the unlocked iteration by initializing the cursor object.
*/
static void dma_resv_iter_restart_unlocked(struct dma_resv_iter *cursor)
{
cursor->seq = read_seqcount_begin(&cursor->obj->seq);
cursor->index = -1;
if (cursor->all_fences)
cursor->fences = dma_resv_shared_list(cursor->obj);
else
cursor->fences = NULL;
cursor->is_restarted = true;
}
/**
* dma_resv_iter_walk_unlocked - walk over fences in a dma_resv obj
* @cursor: cursor to record the current position
*
* Return all the fences in the dma_resv object which are not yet signaled.
* The returned fence has an extra local reference so will stay alive.
* If a concurrent modify is detected the whole iteration is started over again.
*/
static void dma_resv_iter_walk_unlocked(struct dma_resv_iter *cursor)
{
struct dma_resv *obj = cursor->obj;
do {
/* Drop the reference from the previous round */
dma_fence_put(cursor->fence);
if (cursor->index == -1) {
cursor->fence = dma_resv_excl_fence(obj);
cursor->index++;
if (!cursor->fence)
continue;
} else if (!cursor->fences ||
cursor->index >= cursor->fences->shared_count) {
cursor->fence = NULL;
break;
} else {
struct dma_resv_list *fences = cursor->fences;
unsigned int idx = cursor->index++;
cursor->fence = rcu_dereference(fences->shared[idx]);
}
cursor->fence = dma_fence_get_rcu(cursor->fence);
if (!cursor->fence || !dma_fence_is_signaled(cursor->fence))
break;
} while (true);
}
/**
* dma_resv_iter_first_unlocked - first fence in an unlocked dma_resv obj.
* @cursor: the cursor with the current position
*
* Returns the first fence from an unlocked dma_resv obj.
*/
struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor)
{
rcu_read_lock();
do {
dma_resv_iter_restart_unlocked(cursor);
dma_resv_iter_walk_unlocked(cursor);
} while (read_seqcount_retry(&cursor->obj->seq, cursor->seq));
rcu_read_unlock();
return cursor->fence;
}
EXPORT_SYMBOL(dma_resv_iter_first_unlocked);
/**
* dma_resv_iter_next_unlocked - next fence in an unlocked dma_resv obj.
* @cursor: the cursor with the current position
*
* Returns the next fence from an unlocked dma_resv obj.
*/
struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
{
bool restart;
rcu_read_lock();
cursor->is_restarted = false;
restart = read_seqcount_retry(&cursor->obj->seq, cursor->seq);
do {
if (restart)
dma_resv_iter_restart_unlocked(cursor);
dma_resv_iter_walk_unlocked(cursor);
restart = true;
} while (read_seqcount_retry(&cursor->obj->seq, cursor->seq));
rcu_read_unlock();
return cursor->fence;
}
EXPORT_SYMBOL(dma_resv_iter_next_unlocked);
/**
* dma_resv_copy_fences - Copy all fences from src to dst.
* @dst: the destination reservation object
@ -322,74 +432,54 @@ EXPORT_SYMBOL(dma_resv_add_excl_fence);
*/
int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
{
struct dma_resv_list *src_list, *dst_list;
struct dma_fence *old, *new;
unsigned int i;
struct dma_resv_iter cursor;
struct dma_resv_list *list;
struct dma_fence *f, *excl;
dma_resv_assert_held(dst);
rcu_read_lock();
src_list = dma_resv_shared_list(src);
list = NULL;
excl = NULL;
retry:
if (src_list) {
unsigned int shared_count = src_list->shared_count;
dma_resv_iter_begin(&cursor, src, true);
dma_resv_for_each_fence_unlocked(&cursor, f) {
rcu_read_unlock();
if (dma_resv_iter_is_restarted(&cursor)) {
dma_resv_list_free(list);
dma_fence_put(excl);
dst_list = dma_resv_list_alloc(shared_count);
if (!dst_list)
return -ENOMEM;
if (cursor.fences) {
unsigned int cnt = cursor.fences->shared_count;
rcu_read_lock();
src_list = dma_resv_shared_list(src);
if (!src_list || src_list->shared_count > shared_count) {
kfree(dst_list);
goto retry;
list = dma_resv_list_alloc(cnt);
if (!list) {
dma_resv_iter_end(&cursor);
return -ENOMEM;
}
list->shared_count = 0;
} else {
list = NULL;
}
excl = NULL;
}
dst_list->shared_count = 0;
for (i = 0; i < src_list->shared_count; ++i) {
struct dma_fence __rcu **dst;
struct dma_fence *fence;
fence = rcu_dereference(src_list->shared[i]);
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
&fence->flags))
continue;
if (!dma_fence_get_rcu(fence)) {
dma_resv_list_free(dst_list);
src_list = dma_resv_shared_list(src);
goto retry;
}
if (dma_fence_is_signaled(fence)) {
dma_fence_put(fence);
continue;
}
dst = &dst_list->shared[dst_list->shared_count++];
rcu_assign_pointer(*dst, fence);
}
} else {
dst_list = NULL;
dma_fence_get(f);
if (dma_resv_iter_is_exclusive(&cursor))
excl = f;
else
RCU_INIT_POINTER(list->shared[list->shared_count++], f);
}
new = dma_fence_get_rcu_safe(&src->fence_excl);
rcu_read_unlock();
src_list = dma_resv_shared_list(dst);
old = dma_resv_excl_fence(dst);
dma_resv_iter_end(&cursor);
write_seqcount_begin(&dst->seq);
/* write_seqcount_begin provides the necessary memory barrier */
RCU_INIT_POINTER(dst->fence_excl, new);
RCU_INIT_POINTER(dst->fence, dst_list);
excl = rcu_replace_pointer(dst->fence_excl, excl, dma_resv_held(dst));
list = rcu_replace_pointer(dst->fence, list, dma_resv_held(dst));
write_seqcount_end(&dst->seq);
dma_resv_list_free(src_list);
dma_fence_put(old);
dma_resv_list_free(list);
dma_fence_put(excl);
return 0;
}
@ -399,99 +489,61 @@ EXPORT_SYMBOL(dma_resv_copy_fences);
* dma_resv_get_fences - Get an object's shared and exclusive
* fences without update side lock held
* @obj: the reservation object
* @pfence_excl: the returned exclusive fence (or NULL)
* @pshared_count: the number of shared fences returned
* @pshared: the array of shared fence ptrs returned (array is krealloc'd to
* @fence_excl: the returned exclusive fence (or NULL)
* @shared_count: the number of shared fences returned
* @shared: the array of shared fence ptrs returned (array is krealloc'd to
* the required size, and must be freed by caller)
*
* Retrieve all fences from the reservation object. If the pointer for the
* exclusive fence is not specified the fence is put into the array of the
* shared fences as well. Returns either zero or -ENOMEM.
*/
int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **pfence_excl,
unsigned int *pshared_count,
struct dma_fence ***pshared)
int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl,
unsigned int *shared_count, struct dma_fence ***shared)
{
struct dma_fence **shared = NULL;
struct dma_fence *fence_excl;
unsigned int shared_count;
int ret = 1;
struct dma_resv_iter cursor;
struct dma_fence *fence;
do {
struct dma_resv_list *fobj;
unsigned int i, seq;
size_t sz = 0;
*shared_count = 0;
*shared = NULL;
shared_count = i = 0;
if (fence_excl)
*fence_excl = NULL;
rcu_read_lock();
seq = read_seqcount_begin(&obj->seq);
dma_resv_iter_begin(&cursor, obj, true);
dma_resv_for_each_fence_unlocked(&cursor, fence) {
fence_excl = dma_resv_excl_fence(obj);
if (fence_excl && !dma_fence_get_rcu(fence_excl))
goto unlock;
if (dma_resv_iter_is_restarted(&cursor)) {
unsigned int count;
fobj = dma_resv_shared_list(obj);
if (fobj)
sz += sizeof(*shared) * fobj->shared_max;
while (*shared_count)
dma_fence_put((*shared)[--(*shared_count)]);
if (!pfence_excl && fence_excl)
sz += sizeof(*shared);
if (fence_excl)
dma_fence_put(*fence_excl);
if (sz) {
struct dma_fence **nshared;
count = cursor.fences ? cursor.fences->shared_count : 0;
count += fence_excl ? 0 : 1;
nshared = krealloc(shared, sz,
GFP_NOWAIT | __GFP_NOWARN);
if (!nshared) {
rcu_read_unlock();
dma_fence_put(fence_excl);
fence_excl = NULL;
nshared = krealloc(shared, sz, GFP_KERNEL);
if (nshared) {
shared = nshared;
continue;
}
ret = -ENOMEM;
break;
}
shared = nshared;
shared_count = fobj ? fobj->shared_count : 0;
for (i = 0; i < shared_count; ++i) {
shared[i] = rcu_dereference(fobj->shared[i]);
if (!dma_fence_get_rcu(shared[i]))
break;
/* Eventually re-allocate the array */
*shared = krealloc_array(*shared, count,
sizeof(void *),
GFP_KERNEL);
if (count && !*shared) {
dma_resv_iter_end(&cursor);
return -ENOMEM;
}
}
if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
while (i--)
dma_fence_put(shared[i]);
dma_fence_put(fence_excl);
goto unlock;
}
ret = 0;
unlock:
rcu_read_unlock();
} while (ret);
if (pfence_excl)
*pfence_excl = fence_excl;
else if (fence_excl)
shared[shared_count++] = fence_excl;
if (!shared_count) {
kfree(shared);
shared = NULL;
dma_fence_get(fence);
if (dma_resv_iter_is_exclusive(&cursor) && fence_excl)
*fence_excl = fence;
else
(*shared)[(*shared_count)++] = fence;
}
dma_resv_iter_end(&cursor);
*pshared_count = shared_count;
*pshared = shared;
return ret;
return 0;
}
EXPORT_SYMBOL_GPL(dma_resv_get_fences);
@ -513,94 +565,25 @@ long dma_resv_wait_timeout(struct dma_resv *obj, bool wait_all, bool intr,
unsigned long timeout)
{
long ret = timeout ? timeout : 1;
unsigned int seq, shared_count;
struct dma_resv_iter cursor;
struct dma_fence *fence;
int i;
retry:
shared_count = 0;
seq = read_seqcount_begin(&obj->seq);
rcu_read_lock();
i = -1;
fence = dma_resv_excl_fence(obj);
if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
if (!dma_fence_get_rcu(fence))
goto unlock_retry;
if (dma_fence_is_signaled(fence)) {
dma_fence_put(fence);
fence = NULL;
}
} else {
fence = NULL;
}
if (wait_all) {
struct dma_resv_list *fobj = dma_resv_shared_list(obj);
if (fobj)
shared_count = fobj->shared_count;
for (i = 0; !fence && i < shared_count; ++i) {
struct dma_fence *lfence;
lfence = rcu_dereference(fobj->shared[i]);
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
&lfence->flags))
continue;
if (!dma_fence_get_rcu(lfence))
goto unlock_retry;
if (dma_fence_is_signaled(lfence)) {
dma_fence_put(lfence);
continue;
}
fence = lfence;
break;
}
}
rcu_read_unlock();
if (fence) {
if (read_seqcount_retry(&obj->seq, seq)) {
dma_fence_put(fence);
goto retry;
}
dma_resv_iter_begin(&cursor, obj, wait_all);
dma_resv_for_each_fence_unlocked(&cursor, fence) {
ret = dma_fence_wait_timeout(fence, intr, ret);
dma_fence_put(fence);
if (ret > 0 && wait_all && (i + 1 < shared_count))
goto retry;
if (ret <= 0) {
dma_resv_iter_end(&cursor);
return ret;
}
}
return ret;
dma_resv_iter_end(&cursor);
unlock_retry:
rcu_read_unlock();
goto retry;
return ret;
}
EXPORT_SYMBOL_GPL(dma_resv_wait_timeout);
static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence)
{
struct dma_fence *fence, *lfence = passed_fence;
int ret = 1;
if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
fence = dma_fence_get_rcu(lfence);
if (!fence)
return -1;
ret = !!dma_fence_is_signaled(fence);
dma_fence_put(fence);
}
return ret;
}
/**
* dma_resv_test_signaled - Test if a reservation object's fences have been
* signaled.
@ -609,49 +592,24 @@ static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence)
* fence
*
* Callers are not required to hold specific locks, but maybe hold
* dma_resv_lock() already
* dma_resv_lock() already.
*
* RETURNS
* true if all fences signaled, else false
*
* True if all fences signaled, else false.
*/
bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all)
{
struct dma_resv_iter cursor;
struct dma_fence *fence;
unsigned int seq;
int ret;
rcu_read_lock();
retry:
ret = true;
seq = read_seqcount_begin(&obj->seq);
if (test_all) {
struct dma_resv_list *fobj = dma_resv_shared_list(obj);
unsigned int i, shared_count;
shared_count = fobj ? fobj->shared_count : 0;
for (i = 0; i < shared_count; ++i) {
fence = rcu_dereference(fobj->shared[i]);
ret = dma_resv_test_signaled_single(fence);
if (ret < 0)
goto retry;
else if (!ret)
break;
}
dma_resv_iter_begin(&cursor, obj, test_all);
dma_resv_for_each_fence_unlocked(&cursor, fence) {
dma_resv_iter_end(&cursor);
return false;
}
fence = dma_resv_excl_fence(obj);
if (ret && fence) {
ret = dma_resv_test_signaled_single(fence);
if (ret < 0)
goto retry;
}
if (read_seqcount_retry(&obj->seq, seq))
goto retry;
rcu_read_unlock();
return ret;
dma_resv_iter_end(&cursor);
return true;
}
EXPORT_SYMBOL_GPL(dma_resv_test_signaled);

View File

@ -40,11 +40,12 @@ struct dma_heap_attachment {
bool mapped;
};
#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
#define MID_ORDER_GFP (LOW_ORDER_GFP | __GFP_NOWARN)
#define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
| __GFP_NORETRY) & ~__GFP_RECLAIM) \
| __GFP_COMP)
#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP)
static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP, LOW_ORDER_GFP};
static gfp_t order_flags[] = {HIGH_ORDER_GFP, MID_ORDER_GFP, LOW_ORDER_GFP};
/*
* The selection of the orders used for allocation (1MB, 64K, 4K) is designed
* to match with the sizes often found in IOMMUs. Using order 4 pages instead

View File

@ -1,71 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* seqno-fence, using a dma-buf to synchronize fencing
*
* Copyright (C) 2012 Texas Instruments
* Copyright (C) 2012-2014 Canonical Ltd
* Authors:
* Rob Clark <robdclark@gmail.com>
* Maarten Lankhorst <maarten.lankhorst@canonical.com>
*/
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/seqno-fence.h>
static const char *seqno_fence_get_driver_name(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->get_driver_name(fence);
}
static const char *seqno_fence_get_timeline_name(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->get_timeline_name(fence);
}
static bool seqno_enable_signaling(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->enable_signaling(fence);
}
static bool seqno_signaled(struct dma_fence *fence)
{
struct seqno_fence *seqno_fence = to_seqno_fence(fence);
return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence);
}
static void seqno_release(struct dma_fence *fence)
{
struct seqno_fence *f = to_seqno_fence(fence);
dma_buf_put(f->sync_buf);
if (f->ops->release)
f->ops->release(fence);
else
dma_fence_free(&f->base);
}
static signed long seqno_wait(struct dma_fence *fence, bool intr,
signed long timeout)
{
struct seqno_fence *f = to_seqno_fence(fence);
return f->ops->wait(fence, intr, timeout);
}
const struct dma_fence_ops seqno_fence_ops = {
.get_driver_name = seqno_fence_get_driver_name,
.get_timeline_name = seqno_fence_get_timeline_name,
.enable_signaling = seqno_enable_signaling,
.signaled = seqno_signaled,
.wait = seqno_wait,
.release = seqno_release,
};
EXPORT_SYMBOL(seqno_fence_ops);

View File

@ -103,7 +103,7 @@ config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
config DRM_FBDEV_EMULATION
bool "Enable legacy fbdev support for your modesetting driver"
depends on DRM
depends on FB
depends on FB=y || FB=DRM
select DRM_KMS_HELPER
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
@ -211,7 +211,7 @@ config DRM_KMS_CMA_HELPER
config DRM_GEM_SHMEM_HELPER
bool
depends on DRM
depends on DRM && MMU
help
Choose this if you need the GEM shmem helper functions
@ -271,7 +271,8 @@ source "drivers/gpu/drm/kmb/Kconfig"
config DRM_VGEM
tristate "Virtual GEM provider"
depends on DRM
depends on DRM && MMU
select DRM_GEM_SHMEM_HELPER
help
Choose this option to get a virtual graphics memory manager,
as used by Mesa's software renderer for enhanced performance.
@ -279,7 +280,7 @@ config DRM_VGEM
config DRM_VKMS
tristate "Virtual KMS (EXPERIMENTAL)"
depends on DRM
depends on DRM && MMU
select DRM_KMS_HELPER
select DRM_GEM_SHMEM_HELPER
select CRC32
@ -351,8 +352,6 @@ source "drivers/gpu/drm/hisilicon/Kconfig"
source "drivers/gpu/drm/mediatek/Kconfig"
source "drivers/gpu/drm/zte/Kconfig"
source "drivers/gpu/drm/mxsfb/Kconfig"
source "drivers/gpu/drm/meson/Kconfig"

View File

@ -113,7 +113,6 @@ obj-y += bridge/
obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
obj-y += hisilicon/
obj-$(CONFIG_DRM_ZTE) += zte/
obj-$(CONFIG_DRM_MXSFB) += mxsfb/
obj-y += tiny/
obj-$(CONFIG_DRM_PL111) += pl111/

View File

@ -73,10 +73,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 vangogh_reg_init.o \
nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o \
beige_goby_reg_init.o yellow_carp_reg_init.o cyan_skillfish_reg_init.o
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o
# add DF block
amdgpu-y += \

View File

@ -307,6 +307,8 @@ static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev)
adev->ip_blocks[i].status.late_initialized = true;
}
amdgpu_ras_set_error_query_ready(adev, true);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);

View File

@ -205,6 +205,7 @@ extern struct amdgpu_mgpu_info mgpu_info;
extern int amdgpu_ras_enable;
extern uint amdgpu_ras_mask;
extern int amdgpu_bad_page_threshold;
extern bool amdgpu_ignore_bad_page_threshold;
extern struct amdgpu_watchdog_timer amdgpu_watchdog_timer;
extern int amdgpu_async_gfx_ring;
extern int amdgpu_mcbp;
@ -744,6 +745,7 @@ enum amd_hw_ip_block_type {
UVD_HWIP,
VCN_HWIP = UVD_HWIP,
JPEG_HWIP = VCN_HWIP,
VCN1_HWIP,
VCE_HWIP,
DF_HWIP,
DCE_HWIP,
@ -755,11 +757,16 @@ enum amd_hw_ip_block_type {
CLK_HWIP,
UMC_HWIP,
RSMU_HWIP,
XGMI_HWIP,
DCI_HWIP,
MAX_HWIP
};
#define HWIP_MAX_INSTANCE 10
#define HW_ID_MAX 300
#define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv))
struct amd_powerplay {
void *pp_handle;
const struct amd_pm_funcs *pp_funcs;
@ -830,6 +837,7 @@ struct amdgpu_device {
struct notifier_block acpi_nb;
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
struct debugfs_blob_wrapper debugfs_vbios_blob;
struct debugfs_blob_wrapper debugfs_discovery_blob;
struct mutex srbm_mutex;
/* GRBM index mutex. Protects concurrent access to GRBM index */
struct mutex grbm_idx_mutex;
@ -1078,8 +1086,6 @@ struct amdgpu_device {
char product_name[32];
char serial[20];
struct amdgpu_autodump autodump;
atomic_t throttling_logging_enabled;
struct ratelimit_state throttling_logging_rs;
uint32_t ras_hw_enabled;
@ -1090,6 +1096,7 @@ struct amdgpu_device {
pci_channel_state_t pci_channel_state;
struct amdgpu_reset_control *reset_cntl;
uint32_t ip_versions[HW_ID_MAX][HWIP_MAX_INSTANCE];
};
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)

View File

@ -31,6 +31,8 @@
#include <linux/dma-buf.h>
#include "amdgpu_xgmi.h"
#include <uapi/linux/kfd_ioctl.h>
#include "amdgpu_ras.h"
#include "amdgpu_umc.h"
/* Total memory size in system memory and all GPU VRAM. Used to
* estimate worst case amount of memory to reserve for page tables
@ -70,8 +72,7 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
if (!kfd_initialized)
return;
adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev,
adev->pdev, adev->asic_type, vf);
adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev, vf);
if (adev->kfd.dev)
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
@ -780,3 +781,15 @@ bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd)
return adev->have_atomics_support;
}
void amdgpu_amdkfd_ras_poison_consumption_handler(struct kgd_dev *kgd)
{
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
struct ras_err_data err_data = {0, 0, 0, NULL};
/* CPU MCA will handle page retirement if connected_to_cpu is 1 */
if (!adev->gmc.xgmi.connected_to_cpu)
amdgpu_umc_process_ras_data_cb(adev, &err_data, NULL);
else
amdgpu_amdkfd_gpu_reset(kgd);
}

View File

@ -279,6 +279,8 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr);
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
struct kgd_mem *mem, void **kptr, uint64_t *size);
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem);
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
struct dma_fence **ef);
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
@ -290,6 +292,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
uint64_t *mmap_offset);
int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
struct tile_config *config);
void amdgpu_amdkfd_ras_poison_consumption_handler(struct kgd_dev *kgd);
#if IS_ENABLED(CONFIG_HSA_AMD)
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
@ -321,8 +324,7 @@ int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
#if IS_ENABLED(CONFIG_HSA_AMD)
int kgd2kfd_init(void);
void kgd2kfd_exit(void);
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
unsigned int asic_type, bool vf);
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, bool vf);
bool kgd2kfd_device_init(struct kfd_dev *kfd,
struct drm_device *ddev,
const struct kgd2kfd_shared_resources *gpu_resources);
@ -346,8 +348,7 @@ static inline void kgd2kfd_exit(void)
}
static inline
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
unsigned int asic_type, bool vf)
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, bool vf)
{
return NULL;
}

View File

@ -1503,7 +1503,7 @@ allocate_init_user_pages_failed:
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
err_node_allow:
amdgpu_bo_unref(&bo);
drm_gem_object_put(gobj);
/* Don't unreserve system mem limit twice */
goto err_reserve_limit;
err_bo_create:
@ -1871,6 +1871,16 @@ bo_reserve_failed:
return ret;
}
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem)
{
struct amdgpu_bo *bo = mem->bo;
amdgpu_bo_reserve(bo, true);
amdgpu_bo_kunmap(bo);
amdgpu_bo_unpin(bo);
amdgpu_bo_unreserve(bo);
}
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
struct kfd_vm_fault_info *mem)
{
@ -2041,19 +2051,26 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
/* Get updated user pages */
ret = amdgpu_ttm_tt_get_user_pages(bo, bo->tbo.ttm->pages);
if (ret) {
pr_debug("%s: Failed to get user pages: %d\n",
__func__, ret);
pr_debug("Failed %d to get user pages\n", ret);
/* Return error -EBUSY or -ENOMEM, retry restore */
return ret;
/* Return -EFAULT bad address error as success. It will
* fail later with a VM fault if the GPU tries to access
* it. Better than hanging indefinitely with stalled
* user mode queues.
*
* Return other error -EBUSY or -ENOMEM to retry restore
*/
if (ret != -EFAULT)
return ret;
} else {
/*
* FIXME: Cannot ignore the return code, must hold
* notifier_lock
*/
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
}
/*
* FIXME: Cannot ignore the return code, must hold
* notifier_lock
*/
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
/* Mark the BO as valid unless it was invalidated
* again concurrently.
*/

View File

@ -61,7 +61,7 @@ static void amdgpu_bo_list_free(struct kref *ref)
int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
struct drm_amdgpu_bo_list_entry *info,
unsigned num_entries, struct amdgpu_bo_list **result)
size_t num_entries, struct amdgpu_bo_list **result)
{
unsigned last_entry = 0, first_userptr = num_entries;
struct amdgpu_bo_list_entry *array;

View File

@ -61,7 +61,7 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in,
int amdgpu_bo_list_create(struct amdgpu_device *adev,
struct drm_file *filp,
struct drm_amdgpu_bo_list_entry *info,
unsigned num_entries,
size_t num_entries,
struct amdgpu_bo_list **list);
static inline struct amdgpu_bo_list_entry *

View File

@ -1222,6 +1222,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
if (r)
goto error_unlock;
drm_sched_job_arm(&job->base);
/* No memory allocation is allowed while holding the notifier lock.
* The lock is held until amdgpu_cs_submit is finished and fence is
* added to BOs.
@ -1259,7 +1261,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
trace_amdgpu_cs_ioctl(job);
amdgpu_vm_bo_trace_cs(&fpriv->vm, &p->ticket);
drm_sched_entity_push_job(&job->base, entity);
drm_sched_entity_push_job(&job->base);
amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm);

View File

@ -43,14 +43,61 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = {
[AMDGPU_HW_IP_VCN_JPEG] = 1,
};
static int amdgpu_ctx_priority_permit(struct drm_file *filp,
enum drm_sched_priority priority)
bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio)
{
if (priority < 0 || priority >= DRM_SCHED_PRIORITY_COUNT)
switch (ctx_prio) {
case AMDGPU_CTX_PRIORITY_UNSET:
case AMDGPU_CTX_PRIORITY_VERY_LOW:
case AMDGPU_CTX_PRIORITY_LOW:
case AMDGPU_CTX_PRIORITY_NORMAL:
case AMDGPU_CTX_PRIORITY_HIGH:
case AMDGPU_CTX_PRIORITY_VERY_HIGH:
return true;
default:
return false;
}
}
static enum drm_sched_priority
amdgpu_ctx_to_drm_sched_prio(int32_t ctx_prio)
{
switch (ctx_prio) {
case AMDGPU_CTX_PRIORITY_UNSET:
return DRM_SCHED_PRIORITY_UNSET;
case AMDGPU_CTX_PRIORITY_VERY_LOW:
return DRM_SCHED_PRIORITY_MIN;
case AMDGPU_CTX_PRIORITY_LOW:
return DRM_SCHED_PRIORITY_MIN;
case AMDGPU_CTX_PRIORITY_NORMAL:
return DRM_SCHED_PRIORITY_NORMAL;
case AMDGPU_CTX_PRIORITY_HIGH:
return DRM_SCHED_PRIORITY_HIGH;
case AMDGPU_CTX_PRIORITY_VERY_HIGH:
return DRM_SCHED_PRIORITY_HIGH;
/* This should not happen as we sanitized userspace provided priority
* already, WARN if this happens.
*/
default:
WARN(1, "Invalid context priority %d\n", ctx_prio);
return DRM_SCHED_PRIORITY_NORMAL;
}
}
static int amdgpu_ctx_priority_permit(struct drm_file *filp,
int32_t priority)
{
if (!amdgpu_ctx_priority_is_valid(priority))
return -EINVAL;
/* NORMAL and below are accessible by everyone */
if (priority <= DRM_SCHED_PRIORITY_NORMAL)
if (priority <= AMDGPU_CTX_PRIORITY_NORMAL)
return 0;
if (capable(CAP_SYS_NICE))
@ -62,26 +109,51 @@ static int amdgpu_ctx_priority_permit(struct drm_file *filp,
return -EACCES;
}
static enum gfx_pipe_priority amdgpu_ctx_sched_prio_to_compute_prio(enum drm_sched_priority prio)
static enum amdgpu_gfx_pipe_priority amdgpu_ctx_prio_to_compute_prio(int32_t prio)
{
switch (prio) {
case DRM_SCHED_PRIORITY_HIGH:
case DRM_SCHED_PRIORITY_KERNEL:
case AMDGPU_CTX_PRIORITY_HIGH:
case AMDGPU_CTX_PRIORITY_VERY_HIGH:
return AMDGPU_GFX_PIPE_PRIO_HIGH;
default:
return AMDGPU_GFX_PIPE_PRIO_NORMAL;
}
}
static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev,
enum drm_sched_priority prio,
u32 hw_ip)
static enum amdgpu_ring_priority_level amdgpu_ctx_sched_prio_to_ring_prio(int32_t prio)
{
switch (prio) {
case AMDGPU_CTX_PRIORITY_HIGH:
return AMDGPU_RING_PRIO_1;
case AMDGPU_CTX_PRIORITY_VERY_HIGH:
return AMDGPU_RING_PRIO_2;
default:
return AMDGPU_RING_PRIO_0;
}
}
static unsigned int amdgpu_ctx_get_hw_prio(struct amdgpu_ctx *ctx, u32 hw_ip)
{
struct amdgpu_device *adev = ctx->adev;
int32_t ctx_prio;
unsigned int hw_prio;
hw_prio = (hw_ip == AMDGPU_HW_IP_COMPUTE) ?
amdgpu_ctx_sched_prio_to_compute_prio(prio) :
AMDGPU_RING_PRIO_DEFAULT;
ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ?
ctx->init_priority : ctx->override_priority;
switch (hw_ip) {
case AMDGPU_HW_IP_COMPUTE:
hw_prio = amdgpu_ctx_prio_to_compute_prio(ctx_prio);
break;
case AMDGPU_HW_IP_VCE:
case AMDGPU_HW_IP_VCN_ENC:
hw_prio = amdgpu_ctx_sched_prio_to_ring_prio(ctx_prio);
break;
default:
hw_prio = AMDGPU_RING_PRIO_DEFAULT;
break;
}
hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
if (adev->gpu_sched[hw_ip][hw_prio].num_scheds == 0)
hw_prio = AMDGPU_RING_PRIO_DEFAULT;
@ -89,15 +161,17 @@ static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev,
return hw_prio;
}
static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
const u32 ring)
const u32 ring)
{
struct amdgpu_device *adev = ctx->adev;
struct amdgpu_ctx_entity *entity;
struct drm_gpu_scheduler **scheds = NULL, *sched = NULL;
unsigned num_scheds = 0;
int32_t ctx_prio;
unsigned int hw_prio;
enum drm_sched_priority priority;
enum drm_sched_priority drm_prio;
int r;
entity = kzalloc(struct_size(entity, fences, amdgpu_sched_jobs),
@ -105,10 +179,11 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
if (!entity)
return -ENOMEM;
ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ?
ctx->init_priority : ctx->override_priority;
entity->sequence = 1;
priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
ctx->init_priority : ctx->override_priority;
hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority, hw_ip);
hw_prio = amdgpu_ctx_get_hw_prio(ctx, hw_ip);
drm_prio = amdgpu_ctx_to_drm_sched_prio(ctx_prio);
hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
@ -124,7 +199,7 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
num_scheds = 1;
}
r = drm_sched_entity_init(&entity->entity, priority, scheds, num_scheds,
r = drm_sched_entity_init(&entity->entity, drm_prio, scheds, num_scheds,
&ctx->guilty);
if (r)
goto error_free_entity;
@ -139,7 +214,7 @@ error_free_entity:
}
static int amdgpu_ctx_init(struct amdgpu_device *adev,
enum drm_sched_priority priority,
int32_t priority,
struct drm_file *filp,
struct amdgpu_ctx *ctx)
{
@ -161,7 +236,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev,
ctx->reset_counter_query = ctx->reset_counter;
ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
ctx->init_priority = priority;
ctx->override_priority = DRM_SCHED_PRIORITY_UNSET;
ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;
return 0;
}
@ -234,7 +309,7 @@ int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
struct amdgpu_fpriv *fpriv,
struct drm_file *filp,
enum drm_sched_priority priority,
int32_t priority,
uint32_t *id)
{
struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
@ -397,19 +472,19 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
{
int r;
uint32_t id;
enum drm_sched_priority priority;
int32_t priority;
union drm_amdgpu_ctx *args = data;
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_fpriv *fpriv = filp->driver_priv;
id = args->in.ctx_id;
r = amdgpu_to_sched_priority(args->in.priority, &priority);
priority = args->in.priority;
/* For backwards compatibility reasons, we need to accept
* ioctls with garbage in the priority field */
if (r == -EINVAL)
priority = DRM_SCHED_PRIORITY_NORMAL;
if (!amdgpu_ctx_priority_is_valid(priority))
priority = AMDGPU_CTX_PRIORITY_NORMAL;
switch (args->in.op) {
case AMDGPU_CTX_OP_ALLOC_CTX:
@ -515,9 +590,9 @@ struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
}
static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
struct amdgpu_ctx_entity *aentity,
int hw_ip,
enum drm_sched_priority priority)
struct amdgpu_ctx_entity *aentity,
int hw_ip,
int32_t priority)
{
struct amdgpu_device *adev = ctx->adev;
unsigned int hw_prio;
@ -525,12 +600,12 @@ static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
unsigned num_scheds;
/* set sw priority */
drm_sched_entity_set_priority(&aentity->entity, priority);
drm_sched_entity_set_priority(&aentity->entity,
amdgpu_ctx_to_drm_sched_prio(priority));
/* set hw priority */
if (hw_ip == AMDGPU_HW_IP_COMPUTE) {
hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority,
AMDGPU_HW_IP_COMPUTE);
hw_prio = amdgpu_ctx_get_hw_prio(ctx, hw_ip);
hw_prio = array_index_nospec(hw_prio, AMDGPU_RING_PRIO_MAX);
scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;
@ -540,14 +615,14 @@ static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
}
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
enum drm_sched_priority priority)
int32_t priority)
{
enum drm_sched_priority ctx_prio;
int32_t ctx_prio;
unsigned i, j;
ctx->override_priority = priority;
ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ?
ctx->init_priority : ctx->override_priority;
for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {

View File

@ -47,8 +47,8 @@ struct amdgpu_ctx {
spinlock_t ring_lock;
struct amdgpu_ctx_entity *entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM];
bool preamble_presented;
enum drm_sched_priority init_priority;
enum drm_sched_priority override_priority;
int32_t init_priority;
int32_t override_priority;
struct mutex lock;
atomic_t guilty;
unsigned long ras_counter_ce;
@ -75,8 +75,8 @@ void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
struct drm_sched_entity *entity,
uint64_t seq);
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
enum drm_sched_priority priority);
bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio);
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, int32_t ctx_prio);
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);

View File

@ -27,7 +27,6 @@
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <linux/pm_runtime.h>
#include <linux/poll.h>
#include "amdgpu.h"
#include "amdgpu_pm.h"
@ -36,87 +35,10 @@
#include "amdgpu_rap.h"
#include "amdgpu_securedisplay.h"
#include "amdgpu_fw_attestation.h"
int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev)
{
#if defined(CONFIG_DEBUG_FS)
unsigned long timeout = 600 * HZ;
int ret;
wake_up_interruptible(&adev->autodump.gpu_hang);
ret = wait_for_completion_interruptible_timeout(&adev->autodump.dumping, timeout);
if (ret == 0) {
pr_err("autodump: timeout, move on to gpu recovery\n");
return -ETIMEDOUT;
}
#endif
return 0;
}
#include "amdgpu_umr.h"
#if defined(CONFIG_DEBUG_FS)
static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file)
{
struct amdgpu_device *adev = inode->i_private;
int ret;
file->private_data = adev;
ret = down_read_killable(&adev->reset_sem);
if (ret)
return ret;
if (adev->autodump.dumping.done) {
reinit_completion(&adev->autodump.dumping);
ret = 0;
} else {
ret = -EBUSY;
}
up_read(&adev->reset_sem);
return ret;
}
static int amdgpu_debugfs_autodump_release(struct inode *inode, struct file *file)
{
struct amdgpu_device *adev = file->private_data;
complete_all(&adev->autodump.dumping);
return 0;
}
static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_table_struct *poll_table)
{
struct amdgpu_device *adev = file->private_data;
poll_wait(file, &adev->autodump.gpu_hang, poll_table);
if (amdgpu_in_reset(adev))
return POLLIN | POLLRDNORM | POLLWRNORM;
return 0;
}
static const struct file_operations autodump_debug_fops = {
.owner = THIS_MODULE,
.open = amdgpu_debugfs_autodump_open,
.poll = amdgpu_debugfs_autodump_poll,
.release = amdgpu_debugfs_autodump_release,
};
static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev)
{
init_completion(&adev->autodump.dumping);
complete_all(&adev->autodump.dumping);
init_waitqueue_head(&adev->autodump.gpu_hang);
debugfs_create_file("amdgpu_autodump", 0600,
adev_to_drm(adev)->primary->debugfs_root,
adev, &autodump_debug_fops);
}
/**
* amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes
*
@ -279,6 +201,145 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos);
}
static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file)
{
struct amdgpu_debugfs_regs2_data *rd;
rd = kzalloc(sizeof *rd, GFP_KERNEL);
if (!rd)
return -ENOMEM;
rd->adev = file_inode(file)->i_private;
file->private_data = rd;
mutex_init(&rd->lock);
return 0;
}
static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file)
{
struct amdgpu_debugfs_regs2_data *rd = file->private_data;
mutex_destroy(&rd->lock);
kfree(file->private_data);
return 0;
}
static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en)
{
struct amdgpu_debugfs_regs2_data *rd = f->private_data;
struct amdgpu_device *adev = rd->adev;
ssize_t result = 0;
int r;
uint32_t value;
if (size & 0x3 || offset & 0x3)
return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;
}
r = amdgpu_virt_enable_access_debugfs(adev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;
}
mutex_lock(&rd->lock);
if (rd->id.use_grbm) {
if ((rd->id.grbm.sh != 0xFFFFFFFF && rd->id.grbm.sh >= adev->gfx.config.max_sh_per_se) ||
(rd->id.grbm.se != 0xFFFFFFFF && rd->id.grbm.se >= adev->gfx.config.max_shader_engines)) {
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev);
mutex_unlock(&rd->lock);
return -EINVAL;
}
mutex_lock(&adev->grbm_idx_mutex);
amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se,
rd->id.grbm.sh,
rd->id.grbm.instance);
}
if (rd->id.use_srbm) {
mutex_lock(&adev->srbm_mutex);
amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe,
rd->id.srbm.queue, rd->id.srbm.vmid);
}
if (rd->id.pg_lock)
mutex_lock(&adev->pm.mutex);
while (size) {
if (!write_en) {
value = RREG32(offset >> 2);
r = put_user(value, (uint32_t *)buf);
} else {
r = get_user(value, (uint32_t *)buf);
if (!r)
amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value);
}
if (r) {
result = r;
goto end;
}
offset += 4;
size -= 4;
result += 4;
buf += 4;
}
end:
if (rd->id.use_grbm) {
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
}
if (rd->id.use_srbm) {
amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
}
if (rd->id.pg_lock)
mutex_unlock(&adev->pm.mutex);
mutex_unlock(&rd->lock);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev);
return result;
}
static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data)
{
struct amdgpu_debugfs_regs2_data *rd = f->private_data;
int r;
switch (cmd) {
case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE:
mutex_lock(&rd->lock);
r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata *)data, sizeof rd->id);
mutex_unlock(&rd->lock);
return r ? -EINVAL : 0;
default:
return -EINVAL;
}
return 0;
}
static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos)
{
return amdgpu_debugfs_regs2_op(f, buf, *pos, size, 0);
}
static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos)
{
return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1);
}
/**
* amdgpu_debugfs_regs_pcie_read - Read from a PCIE register
@ -1091,6 +1152,16 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf,
return result;
}
static const struct file_operations amdgpu_debugfs_regs2_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = amdgpu_debugfs_regs2_ioctl,
.read = amdgpu_debugfs_regs2_read,
.write = amdgpu_debugfs_regs2_write,
.open = amdgpu_debugfs_regs2_open,
.release = amdgpu_debugfs_regs2_release,
.llseek = default_llseek
};
static const struct file_operations amdgpu_debugfs_regs_fops = {
.owner = THIS_MODULE,
.read = amdgpu_debugfs_regs_read,
@ -1148,6 +1219,7 @@ static const struct file_operations amdgpu_debugfs_gfxoff_fops = {
static const struct file_operations *debugfs_regs[] = {
&amdgpu_debugfs_regs_fops,
&amdgpu_debugfs_regs2_fops,
&amdgpu_debugfs_regs_didt_fops,
&amdgpu_debugfs_regs_pcie_fops,
&amdgpu_debugfs_regs_smc_fops,
@ -1160,6 +1232,7 @@ static const struct file_operations *debugfs_regs[] = {
static const char *debugfs_regs_names[] = {
"amdgpu_regs",
"amdgpu_regs2",
"amdgpu_regs_didt",
"amdgpu_regs_pcie",
"amdgpu_regs_smc",
@ -1206,7 +1279,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
}
/* Avoid accidently unparking the sched thread during GPU reset */
r = down_read_killable(&adev->reset_sem);
r = down_write_killable(&adev->reset_sem);
if (r)
return r;
@ -1235,7 +1308,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
kthread_unpark(ring->sched.thread);
}
up_read(&adev->reset_sem);
up_write(&adev->reset_sem);
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
@ -1255,7 +1328,7 @@ static int amdgpu_debugfs_evict_vram(void *data, u64 *val)
return r;
}
*val = amdgpu_bo_evict_vram(adev);
*val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
@ -1268,17 +1341,15 @@ static int amdgpu_debugfs_evict_gtt(void *data, u64 *val)
{
struct amdgpu_device *adev = (struct amdgpu_device *)data;
struct drm_device *dev = adev_to_drm(adev);
struct ttm_resource_manager *man;
int r;
r = pm_runtime_get_sync(dev->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(dev->dev);
return r;
}
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
*val = ttm_resource_manager_evict_all(&adev->mman.bdev, man);
*val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT);
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
@ -1544,6 +1615,9 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
struct dentry *ent;
int r, i;
if (!debugfs_initialized())
return 0;
ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev,
&fops_ib_preempt);
if (IS_ERR(ent)) {
@ -1582,13 +1656,10 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
if (!ring)
continue;
if (amdgpu_debugfs_ring_init(adev, ring)) {
DRM_ERROR("Failed to register debugfs file for rings !\n");
}
amdgpu_debugfs_ring_init(adev, ring);
}
amdgpu_ras_debugfs_create_all(adev);
amdgpu_debugfs_autodump_init(adev);
amdgpu_rap_debugfs_init(adev);
amdgpu_securedisplay_debugfs_init(adev);
amdgpu_fw_attestation_debugfs_init(adev);
@ -1607,6 +1678,11 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
debugfs_create_blob("amdgpu_vbios", 0444, root,
&adev->debugfs_vbios_blob);
adev->debugfs_discovery_blob.data = adev->mman.discovery_bin;
adev->debugfs_discovery_blob.size = adev->mman.discovery_tmr_size;
debugfs_create_blob("amdgpu_discovery", 0444, root,
&adev->debugfs_discovery_blob);
return 0;
}

View File

@ -22,14 +22,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*
* Debugfs
*/
struct amdgpu_autodump {
struct completion dumping;
struct wait_queue_head gpu_hang;
};
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
int amdgpu_debugfs_init(struct amdgpu_device *adev);
@ -37,4 +32,3 @@ void amdgpu_debugfs_fini(struct amdgpu_device *adev);
void amdgpu_debugfs_fence_init(struct amdgpu_device *adev);
void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev);
void amdgpu_debugfs_gem_init(struct amdgpu_device *adev);
int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev);

View File

@ -125,6 +125,7 @@ const char *amdgpu_asic_name[] = {
"DIMGREY_CAVEFISH",
"BEIGE_GOBY",
"YELLOW_CARP",
"IP DISCOVERY",
"LAST",
};
@ -305,7 +306,7 @@ void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
uint64_t last;
int idx;
if (!drm_dev_enter(&adev->ddev, &idx))
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return;
BUG_ON(!IS_ALIGNED(pos, 4) || !IS_ALIGNED(size, 4));
@ -2126,46 +2127,11 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
if (r)
return r;
break;
case CHIP_VEGA10:
case CHIP_VEGA12:
case CHIP_VEGA20:
case CHIP_RAVEN:
case CHIP_ARCTURUS:
case CHIP_RENOIR:
case CHIP_ALDEBARAN:
if (adev->flags & AMD_IS_APU)
adev->family = AMDGPU_FAMILY_RV;
else
adev->family = AMDGPU_FAMILY_AI;
r = soc15_set_ip_blocks(adev);
if (r)
return r;
break;
case CHIP_NAVI10:
case CHIP_NAVI14:
case CHIP_NAVI12:
case CHIP_SIENNA_CICHLID:
case CHIP_NAVY_FLOUNDER:
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
case CHIP_VANGOGH:
case CHIP_YELLOW_CARP:
case CHIP_CYAN_SKILLFISH:
if (adev->asic_type == CHIP_VANGOGH)
adev->family = AMDGPU_FAMILY_VGH;
else if (adev->asic_type == CHIP_YELLOW_CARP)
adev->family = AMDGPU_FAMILY_YC;
else
adev->family = AMDGPU_FAMILY_NV;
r = nv_set_ip_blocks(adev);
if (r)
return r;
break;
default:
/* FIXME: not supported yet */
return -EINVAL;
r = amdgpu_discovery_set_ip_blocks(adev);
if (r)
return r;
break;
}
amdgpu_amdkfd_device_probe(adev);
@ -2745,6 +2711,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
adev->ip_blocks[i].status.hw = false;
}
if (amdgpu_sriov_vf(adev)) {
if (amdgpu_virt_release_full_gpu(adev, false))
DRM_ERROR("failed to release exclusive mode on fini\n");
}
return 0;
}
@ -2805,10 +2776,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
amdgpu_ras_fini(adev);
if (amdgpu_sriov_vf(adev))
if (amdgpu_virt_release_full_gpu(adev, false))
DRM_ERROR("failed to release exclusive mode on fini\n");
return 0;
}
@ -3240,6 +3207,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
case CHIP_NAVI14:
case CHIP_NAVI12:
case CHIP_RENOIR:
case CHIP_CYAN_SKILLFISH:
case CHIP_SIENNA_CICHLID:
case CHIP_NAVY_FLOUNDER:
case CHIP_DIMGREY_CAVEFISH:
@ -3247,13 +3215,15 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
case CHIP_VANGOGH:
case CHIP_YELLOW_CARP:
#endif
default:
return amdgpu_dc != 0;
#endif
#else
default:
if (amdgpu_dc > 0)
DRM_INFO_ONCE("Display Core has been requested via kernel parameter "
"but isn't supported by ASIC, ignoring\n");
return false;
#endif
}
}
@ -3354,6 +3324,8 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
continue;
} else if (timeout < 0) {
timeout = MAX_SCHEDULE_TIMEOUT;
dev_warn(adev->dev, "lockup timeout disabled");
add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
} else {
timeout = msecs_to_jiffies(timeout);
}
@ -3538,17 +3510,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base);
DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size);
/* enable PCIE atomic ops */
r = pci_enable_atomic_ops_to_root(adev->pdev,
PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
PCI_EXP_DEVCAP2_ATOMIC_COMP64);
if (r) {
adev->have_atomics_support = false;
DRM_INFO("PCIE atomic ops is not supported\n");
} else {
adev->have_atomics_support = true;
}
amdgpu_device_get_pcie_info(adev);
if (amdgpu_mcbp)
@ -3571,6 +3532,19 @@ int amdgpu_device_init(struct amdgpu_device *adev,
if (r)
return r;
/* enable PCIE atomic ops */
if (amdgpu_sriov_vf(adev))
adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_enabled_flags ==
(PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64);
else
adev->have_atomics_support =
!pci_enable_atomic_ops_to_root(adev->pdev,
PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
PCI_EXP_DEVCAP2_ATOMIC_COMP64);
if (!adev->have_atomics_support)
dev_info(adev->dev, "PCIE atomic ops is not supported\n");
/* doorbell bar mapping and doorbell index init*/
amdgpu_device_doorbell_init(adev);
@ -3865,9 +3839,11 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
amdgpu_fbdev_fini(adev);
amdgpu_device_ip_fini_early(adev);
amdgpu_irq_fini_hw(adev);
amdgpu_device_ip_fini_early(adev);
ttm_device_clear_dma_mappings(&adev->mman.bdev);
amdgpu_gart_dummy_page_fini(adev);
@ -3876,8 +3852,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
{
amdgpu_device_ip_fini(adev);
amdgpu_fence_driver_sw_fini(adev);
amdgpu_device_ip_fini(adev);
release_firmware(adev->firmware.gpu_info_fw);
adev->firmware.gpu_info_fw = NULL;
adev->accel_working = false;
@ -3909,6 +3885,25 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
}
/**
* amdgpu_device_evict_resources - evict device resources
* @adev: amdgpu device object
*
* Evicts all ttm device resources(vram BOs, gart table) from the lru list
* of the vram memory type. Mainly used for evicting device resources
* at suspend time.
*
*/
static void amdgpu_device_evict_resources(struct amdgpu_device *adev)
{
/* No need to evict vram on APUs for suspend to ram */
if (adev->in_s3 && (adev->flags & AMD_IS_APU))
return;
if (amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM))
DRM_WARN("evicting device resources failed\n");
}
/*
* Suspend & resume.
@ -3949,17 +3944,16 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
if (!adev->in_s0ix)
amdgpu_amdkfd_suspend(adev, adev->in_runpm);
/* evict vram memory */
amdgpu_bo_evict_vram(adev);
/* First evict vram memory */
amdgpu_device_evict_resources(adev);
amdgpu_fence_driver_hw_fini(adev);
amdgpu_device_ip_suspend_phase2(adev);
/* evict remaining vram memory
* This second call to evict vram is to evict the gart page table
* using the CPU.
/* This second call to evict device resources is to evict
* the gart page table using the CPU.
*/
amdgpu_bo_evict_vram(adev);
amdgpu_device_evict_resources(adev);
return 0;
}
@ -4466,10 +4460,6 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
if (reset_context->reset_req_dev == adev)
job = reset_context->job;
/* no need to dump if device is not in good state during probe period */
if (!adev->gmc.xgmi.pending_reset)
amdgpu_debugfs_wait_dump(adev);
if (amdgpu_sriov_vf(adev)) {
/* stop the data exchange thread */
amdgpu_virt_fini_data_exchange(adev);

View File

@ -52,6 +52,7 @@ struct amdgpu_df_funcs {
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);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
};
struct amdgpu_df {

View File

@ -21,16 +21,58 @@
*
*/
#include <linux/firmware.h>
#include "amdgpu.h"
#include "amdgpu_discovery.h"
#include "soc15_hw_ip.h"
#include "discovery.h"
#include "soc15.h"
#include "gfx_v9_0.h"
#include "gmc_v9_0.h"
#include "df_v1_7.h"
#include "df_v3_6.h"
#include "nbio_v6_1.h"
#include "nbio_v7_0.h"
#include "nbio_v7_4.h"
#include "hdp_v4_0.h"
#include "vega10_ih.h"
#include "vega20_ih.h"
#include "sdma_v4_0.h"
#include "uvd_v7_0.h"
#include "vce_v4_0.h"
#include "vcn_v1_0.h"
#include "vcn_v2_5.h"
#include "jpeg_v2_5.h"
#include "smuio_v9_0.h"
#include "gmc_v10_0.h"
#include "gfxhub_v2_0.h"
#include "mmhub_v2_0.h"
#include "nbio_v2_3.h"
#include "nbio_v7_2.h"
#include "hdp_v5_0.h"
#include "nv.h"
#include "navi10_ih.h"
#include "gfx_v10_0.h"
#include "sdma_v5_0.h"
#include "sdma_v5_2.h"
#include "vcn_v2_0.h"
#include "jpeg_v2_0.h"
#include "vcn_v3_0.h"
#include "jpeg_v3_0.h"
#include "amdgpu_vkms.h"
#include "mes_v10_1.h"
#include "smuio_v11_0.h"
#include "smuio_v11_0_6.h"
#include "smuio_v13_0.h"
MODULE_FIRMWARE("amdgpu/ip_discovery.bin");
#define mmRCC_CONFIG_MEMSIZE 0xde3
#define mmMM_INDEX 0x0
#define mmMM_INDEX_HI 0x6
#define mmMM_DATA 0x1
#define HW_ID_MAX 300
static const char *hw_id_names[HW_ID_MAX] = {
[MP1_HWID] = "MP1",
@ -66,6 +108,8 @@ static const char *hw_id_names[HW_ID_MAX] = {
[HDP_HWID] = "HDP",
[SDMA0_HWID] = "SDMA0",
[SDMA1_HWID] = "SDMA1",
[SDMA2_HWID] = "SDMA2",
[SDMA3_HWID] = "SDMA3",
[ISP_HWID] = "ISP",
[DBGU_IO_HWID] = "DBGU_IO",
[DF_HWID] = "DF",
@ -129,6 +173,8 @@ static int hw_id_map[MAX_HWIP] = {
[THM_HWIP] = THM_HWID,
[CLK_HWIP] = CLKA_HWID,
[UMC_HWIP] = UMC_HWID,
[XGMI_HWIP] = XGMI_HWID,
[DCI_HWIP] = DCI_HWID,
};
static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
@ -164,6 +210,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
struct binary_header *bhdr;
struct ip_discovery_header *ihdr;
struct gpu_info_header *ghdr;
const struct firmware *fw;
uint16_t offset;
uint16_t size;
uint16_t checksum;
@ -174,10 +221,21 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
if (!adev->mman.discovery_bin)
return -ENOMEM;
r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin);
if (r) {
DRM_ERROR("failed to read ip discovery binary\n");
goto out;
if (amdgpu_discovery == 2) {
r = request_firmware(&fw, "amdgpu/ip_discovery.bin", adev->dev);
if (r)
goto get_from_vram;
dev_info(adev->dev, "Using IP discovery from file\n");
memcpy((u8 *)adev->mman.discovery_bin, (u8 *)fw->data,
adev->mman.discovery_tmr_size);
release_firmware(fw);
} else {
get_from_vram:
r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin);
if (r) {
DRM_ERROR("failed to read ip discovery binary\n");
goto out;
}
}
bhdr = (struct binary_header *)adev->mman.discovery_bin;
@ -245,6 +303,22 @@ void amdgpu_discovery_fini(struct amdgpu_device *adev)
adev->mman.discovery_bin = NULL;
}
static int amdgpu_discovery_validate_ip(const struct ip *ip)
{
if (ip->number_instance >= HWIP_MAX_INSTANCE) {
DRM_ERROR("Unexpected number_instance (%d) from ip discovery blob\n",
ip->number_instance);
return -EINVAL;
}
if (le16_to_cpu(ip->hw_id) >= HW_ID_MAX) {
DRM_ERROR("Unexpected hw_id (%d) from ip discovery blob\n",
le16_to_cpu(ip->hw_id));
return -EINVAL;
}
return 0;
}
int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
{
struct binary_header *bhdr;
@ -290,6 +364,10 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
for (j = 0; j < num_ips; j++) {
ip = (struct ip *)(adev->mman.discovery_bin + ip_offset);
if (amdgpu_discovery_validate_ip(ip))
goto next_ip;
num_base_address = ip->num_base_address;
DRM_DEBUG("%s(%d) #%d v%d.%d.%d:\n",
@ -301,6 +379,11 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
if (le16_to_cpu(ip->hw_id) == VCN_HWID)
adev->vcn.num_vcn_inst++;
if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||
le16_to_cpu(ip->hw_id) == SDMA1_HWID ||
le16_to_cpu(ip->hw_id) == SDMA2_HWID ||
le16_to_cpu(ip->hw_id) == SDMA3_HWID)
adev->sdma.num_instances++;
for (k = 0; k < num_base_address; k++) {
/*
@ -317,10 +400,21 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
hw_id_names[le16_to_cpu(ip->hw_id)]);
adev->reg_offset[hw_ip][ip->number_instance] =
ip->base_address;
/* Instance support is somewhat inconsistent.
* SDMA is a good example. Sienna cichlid has 4 total
* SDMA instances, each enumerated separately (HWIDs
* 42, 43, 68, 69). Arcturus has 8 total SDMA instances,
* but they are enumerated as multiple instances of the
* same HWIDs (4x HWID 42, 4x HWID 43). UMC is another
* example. On most chips there are multiple instances
* with the same HWID.
*/
adev->ip_versions[hw_ip][ip->number_instance] =
IP_VERSION(ip->major, ip->minor, ip->revision);
}
}
next_ip:
ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);
}
}
@ -401,6 +495,10 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
switch (le32_to_cpu(harvest_info->list[i].hw_id)) {
case VCN_HWID:
vcn_harvest_count++;
if (harvest_info->list[i].number_instance == 0)
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN0;
else
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;
break;
case DMU_HWID:
adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
@ -409,10 +507,21 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
break;
}
}
/* some IP discovery tables on Navy Flounder don't have this set correctly */
if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) &&
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2)))
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;
if (vcn_harvest_count == adev->vcn.num_vcn_inst) {
adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
}
if ((adev->pdev->device == 0x731E &&
(adev->pdev->revision == 0xC6 || adev->pdev->revision == 0xC7)) ||
(adev->pdev->device == 0x7340 && adev->pdev->revision == 0xC9) ||
(adev->pdev->device == 0x7360 && adev->pdev->revision == 0xC7)) {
adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
}
}
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
@ -450,3 +559,753 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
return 0;
}
static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
{
/* what IP to use for this? */
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 3, 0):
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
break;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
{
/* use GC or MMHUB IP version */
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 3, 0):
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
break;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->ip_versions[OSSSYS_HWIP][0]) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 1, 0):
case IP_VERSION(4, 1, 1):
case IP_VERSION(4, 3, 0):
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
break;
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 1):
case IP_VERSION(4, 4, 0):
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
break;
case IP_VERSION(5, 0, 0):
case IP_VERSION(5, 0, 1):
case IP_VERSION(5, 0, 2):
case IP_VERSION(5, 0, 3):
case IP_VERSION(5, 2, 0):
case IP_VERSION(5, 2, 1):
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->ip_versions[MP0_HWIP][0]) {
case IP_VERSION(9, 0, 0):
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
break;
case IP_VERSION(10, 0, 0):
case IP_VERSION(10, 0, 1):
amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
break;
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 0, 5):
case IP_VERSION(11, 0, 9):
case IP_VERSION(11, 0, 7):
case IP_VERSION(11, 0, 11):
case IP_VERSION(11, 0, 12):
case IP_VERSION(11, 0, 13):
case IP_VERSION(11, 5, 0):
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
break;
case IP_VERSION(11, 0, 8):
amdgpu_device_ip_block_add(adev, &psp_v11_0_8_ip_block);
break;
case IP_VERSION(11, 0, 3):
case IP_VERSION(12, 0, 1):
amdgpu_device_ip_block_add(adev, &psp_v12_0_ip_block);
break;
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 3):
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(10, 0, 0):
case IP_VERSION(10, 0, 1):
case IP_VERSION(11, 0, 2):
if (adev->asic_type == CHIP_ARCTURUS)
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
else
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
break;
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 5):
case IP_VERSION(11, 0, 9):
case IP_VERSION(11, 0, 7):
case IP_VERSION(11, 0, 8):
case IP_VERSION(11, 0, 11):
case IP_VERSION(11, 0, 12):
case IP_VERSION(11, 0, 13):
case IP_VERSION(11, 5, 0):
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
break;
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
amdgpu_device_ip_block_add(adev, &smu_v12_0_ip_block);
break;
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 3):
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
{
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) {
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
} else if (adev->ip_versions[DCE_HWIP][0]) {
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
case IP_VERSION(2, 0, 2):
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 3):
case IP_VERSION(2, 1, 0):
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 2):
case IP_VERSION(3, 0, 3):
case IP_VERSION(3, 0, 1):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
amdgpu_device_ip_block_add(adev, &dm_ip_block);
break;
default:
return -EINVAL;
}
} else if (adev->ip_versions[DCI_HWIP][0]) {
switch (adev->ip_versions[DCI_HWIP][0]) {
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
case IP_VERSION(12, 1, 0):
amdgpu_device_ip_block_add(adev, &dm_ip_block);
break;
default:
return -EINVAL;
}
#endif
}
return 0;
}
static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 3, 0):
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
break;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
case IP_VERSION(10, 3, 3):
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->ip_versions[SDMA0_HWIP][0]) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 1, 0):
case IP_VERSION(4, 1, 1):
case IP_VERSION(4, 1, 2):
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 2):
case IP_VERSION(4, 4, 0):
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
break;
case IP_VERSION(5, 0, 0):
case IP_VERSION(5, 0, 1):
case IP_VERSION(5, 0, 2):
case IP_VERSION(5, 0, 5):
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
break;
case IP_VERSION(5, 2, 0):
case IP_VERSION(5, 2, 2):
case IP_VERSION(5, 2, 4):
case IP_VERSION(5, 2, 5):
case IP_VERSION(5, 2, 3):
case IP_VERSION(5, 2, 1):
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
{
if (adev->ip_versions[VCE_HWIP][0]) {
switch (adev->ip_versions[UVD_HWIP][0]) {
case IP_VERSION(7, 0, 0):
case IP_VERSION(7, 2, 0):
/* UVD is not supported on vega20 SR-IOV */
if (!(adev->asic_type == CHIP_VEGA20 && amdgpu_sriov_vf(adev)))
amdgpu_device_ip_block_add(adev, &uvd_v7_0_ip_block);
break;
default:
return -EINVAL;
}
switch (adev->ip_versions[VCE_HWIP][0]) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 1, 0):
/* VCE is not supported on vega20 SR-IOV */
if (!(adev->asic_type == CHIP_VEGA20 && amdgpu_sriov_vf(adev)))
amdgpu_device_ip_block_add(adev, &vce_v4_0_ip_block);
break;
default:
return -EINVAL;
}
} else {
switch (adev->ip_versions[UVD_HWIP][0]) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block);
break;
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 2):
case IP_VERSION(2, 2, 0):
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
break;
case IP_VERSION(2, 0, 3):
break;
case IP_VERSION(2, 5, 0):
amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v2_5_ip_block);
break;
case IP_VERSION(2, 6, 0):
amdgpu_device_ip_block_add(adev, &vcn_v2_6_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v2_6_ip_block);
break;
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 16):
case IP_VERSION(3, 1, 1):
case IP_VERSION(3, 0, 2):
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
break;
case IP_VERSION(3, 0, 33):
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
break;
default:
return -EINVAL;
}
}
return 0;
}
static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 1):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
break;
default:
break;;
}
return 0;
}
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
switch (adev->asic_type) {
case CHIP_VEGA10:
vega10_reg_base_init(adev);
adev->sdma.num_instances = 2;
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 0, 0);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 0, 0);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 0, 0);
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 0, 0);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(2, 1, 0);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(6, 1, 0);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 0, 0);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 0, 1);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(7, 0, 0);
adev->ip_versions[VCE_HWIP][0] = IP_VERSION(4, 0, 0);
adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 0, 0);
break;
case CHIP_VEGA12:
vega10_reg_base_init(adev);
adev->sdma.num_instances = 2;
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 3, 0);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 3, 0);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 0, 1);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 0, 1);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 0, 1);
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 0, 1);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(2, 5, 0);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(6, 2, 0);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 1, 0);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(9, 0, 0);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(9, 0, 1);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 2, 1);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(7, 0, 0);
adev->ip_versions[VCE_HWIP][0] = IP_VERSION(4, 0, 0);
adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 0, 1);
break;
case CHIP_RAVEN:
vega10_reg_base_init(adev);
adev->sdma.num_instances = 1;
adev->vcn.num_vcn_inst = 1;
if (adev->apu_flags & AMD_APU_IS_RAVEN2) {
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 2, 0);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 2, 0);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 1, 1);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 1, 1);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 1, 1);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(2, 1, 1);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 0, 1);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(7, 5, 0);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(10, 0, 1);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(10, 0, 1);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(10, 1, 0);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(10, 0, 1);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 2, 2);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(1, 0, 1);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(1, 0, 1);
} else {
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 1, 0);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 1, 0);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 1, 0);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 1, 0);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 1, 0);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(2, 1, 0);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 0, 0);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(7, 0, 0);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(10, 0, 0);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(10, 0, 0);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(10, 0, 0);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(10, 0, 0);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 1, 0);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(1, 0, 0);
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(1, 0, 0);
}
break;
case CHIP_VEGA20:
vega20_reg_base_init(adev);
adev->sdma.num_instances = 2;
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 4, 0);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 4, 0);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 2, 0);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 2, 0);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 2, 0);
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 2, 0);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(3, 6, 0);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 4, 0);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 1, 1);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(11, 0, 2);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(11, 0, 2);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(11, 0, 2);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(11, 0, 2);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 4, 0);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(7, 2, 0);
adev->ip_versions[UVD_HWIP][1] = IP_VERSION(7, 2, 0);
adev->ip_versions[VCE_HWIP][0] = IP_VERSION(4, 1, 0);
adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 1, 0);
break;
case CHIP_ARCTURUS:
arct_reg_base_init(adev);
adev->sdma.num_instances = 8;
adev->vcn.num_vcn_inst = 2;
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 4, 1);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 4, 1);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 2, 1);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 2, 1);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][1] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][2] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][3] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][4] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][5] = IP_VERSION(4, 2, 2);
adev->ip_versions[SDMA1_HWIP][6] = IP_VERSION(4, 2, 2);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(3, 6, 1);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 4, 1);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 1, 2);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(11, 0, 4);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(11, 0, 2);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(11, 0, 3);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(11, 0, 3);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 4, 1);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(2, 5, 0);
adev->ip_versions[UVD_HWIP][1] = IP_VERSION(2, 5, 0);
break;
case CHIP_ALDEBARAN:
aldebaran_reg_base_init(adev);
adev->sdma.num_instances = 5;
adev->vcn.num_vcn_inst = 2;
adev->ip_versions[MMHUB_HWIP][0] = IP_VERSION(9, 4, 2);
adev->ip_versions[ATHUB_HWIP][0] = IP_VERSION(9, 4, 2);
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 4, 0);
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 4, 0);
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 4, 0);
adev->ip_versions[SDMA0_HWIP][1] = IP_VERSION(4, 4, 0);
adev->ip_versions[SDMA0_HWIP][2] = IP_VERSION(4, 4, 0);
adev->ip_versions[SDMA0_HWIP][3] = IP_VERSION(4, 4, 0);
adev->ip_versions[SDMA0_HWIP][4] = IP_VERSION(4, 4, 0);
adev->ip_versions[DF_HWIP][0] = IP_VERSION(3, 6, 2);
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 4, 4);
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 7, 0);
adev->ip_versions[MP0_HWIP][0] = IP_VERSION(13, 0, 2);
adev->ip_versions[MP1_HWIP][0] = IP_VERSION(13, 0, 2);
adev->ip_versions[THM_HWIP][0] = IP_VERSION(13, 0, 2);
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(13, 0, 2);
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 4, 2);
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(2, 6, 0);
adev->ip_versions[UVD_HWIP][1] = IP_VERSION(2, 6, 0);
adev->ip_versions[XGMI_HWIP][0] = IP_VERSION(6, 1, 0);
break;
default:
r = amdgpu_discovery_reg_base_init(adev);
if (r)
return -EINVAL;
amdgpu_discovery_harvest_ip(adev);
if (!adev->mman.discovery_bin) {
DRM_ERROR("ip discovery uninitialized\n");
return -EINVAL;
}
break;
}
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 2, 1):
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
adev->family = AMDGPU_FAMILY_AI;
break;
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
case IP_VERSION(9, 3, 0):
adev->family = AMDGPU_FAMILY_RV;
break;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
adev->family = AMDGPU_FAMILY_NV;
break;
case IP_VERSION(10, 3, 1):
adev->family = AMDGPU_FAMILY_VGH;
break;
case IP_VERSION(10, 3, 3):
adev->family = AMDGPU_FAMILY_YC;
break;
default:
return -EINVAL;
}
if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(4, 8, 0))
adev->gmc.xgmi.supported = true;
/* set NBIO version */
switch (adev->ip_versions[NBIO_HWIP][0]) {
case IP_VERSION(6, 1, 0):
case IP_VERSION(6, 2, 0):
adev->nbio.funcs = &nbio_v6_1_funcs;
adev->nbio.hdp_flush_reg = &nbio_v6_1_hdp_flush_reg;
break;
case IP_VERSION(7, 0, 0):
case IP_VERSION(7, 0, 1):
case IP_VERSION(2, 5, 0):
adev->nbio.funcs = &nbio_v7_0_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_0_hdp_flush_reg;
break;
case IP_VERSION(7, 4, 0):
case IP_VERSION(7, 4, 1):
adev->nbio.funcs = &nbio_v7_4_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg;
break;
case IP_VERSION(7, 4, 4):
adev->nbio.funcs = &nbio_v7_4_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg_ald;
break;
case IP_VERSION(7, 2, 0):
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 5, 0):
adev->nbio.funcs = &nbio_v7_2_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg;
break;
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 3, 0):
case IP_VERSION(2, 3, 1):
case IP_VERSION(2, 3, 2):
adev->nbio.funcs = &nbio_v2_3_funcs;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
break;
case IP_VERSION(3, 3, 0):
case IP_VERSION(3, 3, 1):
case IP_VERSION(3, 3, 2):
case IP_VERSION(3, 3, 3):
adev->nbio.funcs = &nbio_v2_3_funcs;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg_sc;
break;
default:
break;
}
switch (adev->ip_versions[HDP_HWIP][0]) {
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 1):
case IP_VERSION(4, 1, 0):
case IP_VERSION(4, 1, 1):
case IP_VERSION(4, 1, 2):
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 1):
case IP_VERSION(4, 4, 0):
adev->hdp.funcs = &hdp_v4_0_funcs;
break;
case IP_VERSION(5, 0, 0):
case IP_VERSION(5, 0, 1):
case IP_VERSION(5, 0, 2):
case IP_VERSION(5, 0, 3):
case IP_VERSION(5, 0, 4):
case IP_VERSION(5, 2, 0):
adev->hdp.funcs = &hdp_v5_0_funcs;
break;
default:
break;
}
switch (adev->ip_versions[DF_HWIP][0]) {
case IP_VERSION(3, 6, 0):
case IP_VERSION(3, 6, 1):
case IP_VERSION(3, 6, 2):
adev->df.funcs = &df_v3_6_funcs;
break;
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 5, 0):
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 5, 2):
adev->df.funcs = &df_v1_7_funcs;
break;
default:
break;
}
switch (adev->ip_versions[SMUIO_HWIP][0]) {
case IP_VERSION(9, 0, 0):
case IP_VERSION(9, 0, 1):
case IP_VERSION(10, 0, 0):
case IP_VERSION(10, 0, 1):
case IP_VERSION(10, 0, 2):
adev->smuio.funcs = &smuio_v9_0_funcs;
break;
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 0, 7):
case IP_VERSION(11, 0, 8):
adev->smuio.funcs = &smuio_v11_0_funcs;
break;
case IP_VERSION(11, 0, 6):
case IP_VERSION(11, 0, 10):
case IP_VERSION(11, 0, 11):
case IP_VERSION(11, 5, 0):
case IP_VERSION(13, 0, 1):
adev->smuio.funcs = &smuio_v11_0_6_funcs;
break;
case IP_VERSION(13, 0, 2):
adev->smuio.funcs = &smuio_v13_0_funcs;
break;
default:
break;
}
r = amdgpu_discovery_set_common_ip_blocks(adev);
if (r)
return r;
r = amdgpu_discovery_set_gmc_ip_blocks(adev);
if (r)
return r;
/* For SR-IOV, PSP needs to be initialized before IH */
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_discovery_set_psp_ip_blocks(adev);
if (r)
return r;
r = amdgpu_discovery_set_ih_ip_blocks(adev);
if (r)
return r;
} else {
r = amdgpu_discovery_set_ih_ip_blocks(adev);
if (r)
return r;
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
r = amdgpu_discovery_set_psp_ip_blocks(adev);
if (r)
return r;
}
}
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
r = amdgpu_discovery_set_smu_ip_blocks(adev);
if (r)
return r;
}
r = amdgpu_discovery_set_display_ip_blocks(adev);
if (r)
return r;
r = amdgpu_discovery_set_gc_ip_blocks(adev);
if (r)
return r;
r = amdgpu_discovery_set_sdma_ip_blocks(adev);
if (r)
return r;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
!amdgpu_sriov_vf(adev)) {
r = amdgpu_discovery_set_smu_ip_blocks(adev);
if (r)
return r;
}
r = amdgpu_discovery_set_mm_ip_blocks(adev);
if (r)
return r;
if (adev->enable_mes) {
r = amdgpu_discovery_set_mes_ip_blocks(adev);
if (r)
return r;
}
return 0;
}

View File

@ -36,5 +36,6 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int n
int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance,
int *major, int *minor, int *revision);
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev);
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);
#endif /* __AMDGPU_DISCOVERY__ */

View File

@ -97,9 +97,11 @@
* - 3.40.0 - Add AMDGPU_IDS_FLAGS_TMZ
* - 3.41.0 - Add video codec query
* - 3.42.0 - Add 16bpc fixed point display support
* - 3.43.0 - Add device hot plug/unplug support
* - 3.44.0 - DCN3 supports DCC independent block settings: !64B && 128B, 64B && 128B
*/
#define KMS_DRIVER_MAJOR 3
#define KMS_DRIVER_MINOR 42
#define KMS_DRIVER_MINOR 44
#define KMS_DRIVER_PATCHLEVEL 0
int amdgpu_vram_limit;
@ -628,7 +630,7 @@ module_param_named(mcbp, amdgpu_mcbp, int, 0444);
/**
* DOC: discovery (int)
* Allow driver to discover hardware IP information from IP Discovery table at the top of VRAM.
* (-1 = auto (default), 0 = disabled, 1 = enabled)
* (-1 = auto (default), 0 = disabled, 1 = enabled, 2 = use ip_discovery table from file)
*/
MODULE_PARM_DESC(discovery,
"Allow driver to discover hardware IPs from IP Discovery table at the top of VRAM");
@ -876,7 +878,7 @@ module_param_named(reset_method, amdgpu_reset_method, int, 0444);
* result in the GPU entering bad status when the number of total
* faulty pages by ECC exceeds the threshold value.
*/
MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)");
MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement, -2 = ignore bad page threshold)");
module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444);
MODULE_PARM_DESC(num_kcq, "number of kernel compute queue user want to setup (8 if set to greater than 8 or less than 0, only affect gfx 8+)");
@ -891,6 +893,636 @@ MODULE_PARM_DESC(smu_pptable_id,
"specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)");
module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444);
/* These devices are not supported by amdgpu.
* They are supported by the mach64, r128, radeon drivers
*/
static const u16 amdgpu_unsupported_pciidlist[] = {
/* mach64 */
0x4354,
0x4358,
0x4554,
0x4742,
0x4744,
0x4749,
0x474C,
0x474D,
0x474E,
0x474F,
0x4750,
0x4751,
0x4752,
0x4753,
0x4754,
0x4755,
0x4756,
0x4757,
0x4758,
0x4759,
0x475A,
0x4C42,
0x4C44,
0x4C47,
0x4C49,
0x4C4D,
0x4C4E,
0x4C50,
0x4C51,
0x4C52,
0x4C53,
0x5654,
0x5655,
0x5656,
/* r128 */
0x4c45,
0x4c46,
0x4d46,
0x4d4c,
0x5041,
0x5042,
0x5043,
0x5044,
0x5045,
0x5046,
0x5047,
0x5048,
0x5049,
0x504A,
0x504B,
0x504C,
0x504D,
0x504E,
0x504F,
0x5050,
0x5051,
0x5052,
0x5053,
0x5054,
0x5055,
0x5056,
0x5057,
0x5058,
0x5245,
0x5246,
0x5247,
0x524b,
0x524c,
0x534d,
0x5446,
0x544C,
0x5452,
/* radeon */
0x3150,
0x3151,
0x3152,
0x3154,
0x3155,
0x3E50,
0x3E54,
0x4136,
0x4137,
0x4144,
0x4145,
0x4146,
0x4147,
0x4148,
0x4149,
0x414A,
0x414B,
0x4150,
0x4151,
0x4152,
0x4153,
0x4154,
0x4155,
0x4156,
0x4237,
0x4242,
0x4336,
0x4337,
0x4437,
0x4966,
0x4967,
0x4A48,
0x4A49,
0x4A4A,
0x4A4B,
0x4A4C,
0x4A4D,
0x4A4E,
0x4A4F,
0x4A50,
0x4A54,
0x4B48,
0x4B49,
0x4B4A,
0x4B4B,
0x4B4C,
0x4C57,
0x4C58,
0x4C59,
0x4C5A,
0x4C64,
0x4C66,
0x4C67,
0x4E44,
0x4E45,
0x4E46,
0x4E47,
0x4E48,
0x4E49,
0x4E4A,
0x4E4B,
0x4E50,
0x4E51,
0x4E52,
0x4E53,
0x4E54,
0x4E56,
0x5144,
0x5145,
0x5146,
0x5147,
0x5148,
0x514C,
0x514D,
0x5157,
0x5158,
0x5159,
0x515A,
0x515E,
0x5460,
0x5462,
0x5464,
0x5548,
0x5549,
0x554A,
0x554B,
0x554C,
0x554D,
0x554E,
0x554F,
0x5550,
0x5551,
0x5552,
0x5554,
0x564A,
0x564B,
0x564F,
0x5652,
0x5653,
0x5657,
0x5834,
0x5835,
0x5954,
0x5955,
0x5974,
0x5975,
0x5960,
0x5961,
0x5962,
0x5964,
0x5965,
0x5969,
0x5a41,
0x5a42,
0x5a61,
0x5a62,
0x5b60,
0x5b62,
0x5b63,
0x5b64,
0x5b65,
0x5c61,
0x5c63,
0x5d48,
0x5d49,
0x5d4a,
0x5d4c,
0x5d4d,
0x5d4e,
0x5d4f,
0x5d50,
0x5d52,
0x5d57,
0x5e48,
0x5e4a,
0x5e4b,
0x5e4c,
0x5e4d,
0x5e4f,
0x6700,
0x6701,
0x6702,
0x6703,
0x6704,
0x6705,
0x6706,
0x6707,
0x6708,
0x6709,
0x6718,
0x6719,
0x671c,
0x671d,
0x671f,
0x6720,
0x6721,
0x6722,
0x6723,
0x6724,
0x6725,
0x6726,
0x6727,
0x6728,
0x6729,
0x6738,
0x6739,
0x673e,
0x6740,
0x6741,
0x6742,
0x6743,
0x6744,
0x6745,
0x6746,
0x6747,
0x6748,
0x6749,
0x674A,
0x6750,
0x6751,
0x6758,
0x6759,
0x675B,
0x675D,
0x675F,
0x6760,
0x6761,
0x6762,
0x6763,
0x6764,
0x6765,
0x6766,
0x6767,
0x6768,
0x6770,
0x6771,
0x6772,
0x6778,
0x6779,
0x677B,
0x6840,
0x6841,
0x6842,
0x6843,
0x6849,
0x684C,
0x6850,
0x6858,
0x6859,
0x6880,
0x6888,
0x6889,
0x688A,
0x688C,
0x688D,
0x6898,
0x6899,
0x689b,
0x689c,
0x689d,
0x689e,
0x68a0,
0x68a1,
0x68a8,
0x68a9,
0x68b0,
0x68b8,
0x68b9,
0x68ba,
0x68be,
0x68bf,
0x68c0,
0x68c1,
0x68c7,
0x68c8,
0x68c9,
0x68d8,
0x68d9,
0x68da,
0x68de,
0x68e0,
0x68e1,
0x68e4,
0x68e5,
0x68e8,
0x68e9,
0x68f1,
0x68f2,
0x68f8,
0x68f9,
0x68fa,
0x68fe,
0x7100,
0x7101,
0x7102,
0x7103,
0x7104,
0x7105,
0x7106,
0x7108,
0x7109,
0x710A,
0x710B,
0x710C,
0x710E,
0x710F,
0x7140,
0x7141,
0x7142,
0x7143,
0x7144,
0x7145,
0x7146,
0x7147,
0x7149,
0x714A,
0x714B,
0x714C,
0x714D,
0x714E,
0x714F,
0x7151,
0x7152,
0x7153,
0x715E,
0x715F,
0x7180,
0x7181,
0x7183,
0x7186,
0x7187,
0x7188,
0x718A,
0x718B,
0x718C,
0x718D,
0x718F,
0x7193,
0x7196,
0x719B,
0x719F,
0x71C0,
0x71C1,
0x71C2,
0x71C3,
0x71C4,
0x71C5,
0x71C6,
0x71C7,
0x71CD,
0x71CE,
0x71D2,
0x71D4,
0x71D5,
0x71D6,
0x71DA,
0x71DE,
0x7200,
0x7210,
0x7211,
0x7240,
0x7243,
0x7244,
0x7245,
0x7246,
0x7247,
0x7248,
0x7249,
0x724A,
0x724B,
0x724C,
0x724D,
0x724E,
0x724F,
0x7280,
0x7281,
0x7283,
0x7284,
0x7287,
0x7288,
0x7289,
0x728B,
0x728C,
0x7290,
0x7291,
0x7293,
0x7297,
0x7834,
0x7835,
0x791e,
0x791f,
0x793f,
0x7941,
0x7942,
0x796c,
0x796d,
0x796e,
0x796f,
0x9400,
0x9401,
0x9402,
0x9403,
0x9405,
0x940A,
0x940B,
0x940F,
0x94A0,
0x94A1,
0x94A3,
0x94B1,
0x94B3,
0x94B4,
0x94B5,
0x94B9,
0x9440,
0x9441,
0x9442,
0x9443,
0x9444,
0x9446,
0x944A,
0x944B,
0x944C,
0x944E,
0x9450,
0x9452,
0x9456,
0x945A,
0x945B,
0x945E,
0x9460,
0x9462,
0x946A,
0x946B,
0x947A,
0x947B,
0x9480,
0x9487,
0x9488,
0x9489,
0x948A,
0x948F,
0x9490,
0x9491,
0x9495,
0x9498,
0x949C,
0x949E,
0x949F,
0x94C0,
0x94C1,
0x94C3,
0x94C4,
0x94C5,
0x94C6,
0x94C7,
0x94C8,
0x94C9,
0x94CB,
0x94CC,
0x94CD,
0x9500,
0x9501,
0x9504,
0x9505,
0x9506,
0x9507,
0x9508,
0x9509,
0x950F,
0x9511,
0x9515,
0x9517,
0x9519,
0x9540,
0x9541,
0x9542,
0x954E,
0x954F,
0x9552,
0x9553,
0x9555,
0x9557,
0x955f,
0x9580,
0x9581,
0x9583,
0x9586,
0x9587,
0x9588,
0x9589,
0x958A,
0x958B,
0x958C,
0x958D,
0x958E,
0x958F,
0x9590,
0x9591,
0x9593,
0x9595,
0x9596,
0x9597,
0x9598,
0x9599,
0x959B,
0x95C0,
0x95C2,
0x95C4,
0x95C5,
0x95C6,
0x95C7,
0x95C9,
0x95CC,
0x95CD,
0x95CE,
0x95CF,
0x9610,
0x9611,
0x9612,
0x9613,
0x9614,
0x9615,
0x9616,
0x9640,
0x9641,
0x9642,
0x9643,
0x9644,
0x9645,
0x9647,
0x9648,
0x9649,
0x964a,
0x964b,
0x964c,
0x964e,
0x964f,
0x9710,
0x9711,
0x9712,
0x9713,
0x9714,
0x9715,
0x9802,
0x9803,
0x9804,
0x9805,
0x9806,
0x9807,
0x9808,
0x9809,
0x980A,
0x9900,
0x9901,
0x9903,
0x9904,
0x9905,
0x9906,
0x9907,
0x9908,
0x9909,
0x990A,
0x990B,
0x990C,
0x990D,
0x990E,
0x990F,
0x9910,
0x9913,
0x9917,
0x9918,
0x9919,
0x9990,
0x9991,
0x9992,
0x9993,
0x9994,
0x9995,
0x9996,
0x9997,
0x9998,
0x9999,
0x999A,
0x999B,
0x999C,
0x999D,
0x99A0,
0x99A2,
0x99A4,
};
static const struct pci_device_id pciidlist[] = {
#ifdef CONFIG_DRM_AMDGPU_SI
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
@ -1240,6 +1872,16 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{ PCI_DEVICE(0x1002, PCI_ANY_ID),
.class = PCI_CLASS_DISPLAY_VGA << 8,
.class_mask = 0xffffff,
.driver_data = CHIP_IP_DISCOVERY },
{ PCI_DEVICE(0x1002, PCI_ANY_ID),
.class = PCI_CLASS_DISPLAY_OTHER << 8,
.class_mask = 0xffffff,
.driver_data = CHIP_IP_DISCOVERY },
{0, 0, 0}
};
@ -1253,9 +1895,20 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
struct drm_device *ddev;
struct amdgpu_device *adev;
unsigned long flags = ent->driver_data;
int ret, retry = 0;
int ret, retry = 0, i;
bool supports_atomic = false;
/* skip devices which are owned by radeon */
for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) {
if (amdgpu_unsupported_pciidlist[i] == pdev->device)
return -ENODEV;
}
if (flags == 0) {
DRM_INFO("Unsupported asic. Remove me when IP discovery init is in place.\n");
return -ENODEV;
}
if (amdgpu_virtual_display ||
amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
supports_atomic = true;
@ -1510,6 +2163,10 @@ static int amdgpu_pmops_resume(struct device *dev)
struct amdgpu_device *adev = drm_to_adev(drm_dev);
int r;
/* Avoids registers access if device is physically gone */
if (!pci_device_is_present(adev->pdev))
adev->no_hw_access = true;
r = amdgpu_device_resume(drm_dev, true);
if (amdgpu_acpi_is_s0ix_active(adev))
adev->in_s0ix = false;

View File

@ -266,7 +266,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
struct amdgpu_fence_driver *drv = &ring->fence_drv;
struct amdgpu_device *adev = ring->adev;
uint32_t seq, last_seq;
int r;
do {
last_seq = atomic_read(&ring->fence_drv.last_seq);
@ -298,12 +297,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
if (!fence)
continue;
r = dma_fence_signal(fence);
if (!r)
DMA_FENCE_TRACE(fence, "signaled from irq context\n");
else
BUG();
dma_fence_signal(fence);
dma_fence_put(fence);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@ -556,7 +550,7 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
drm_sched_stop(&ring->sched, NULL);
/* You can't wait for HW to signal if it's gone */
if (!drm_dev_is_unplugged(&adev->ddev))
if (!drm_dev_is_unplugged(adev_to_drm(adev)))
r = amdgpu_fence_wait_empty(ring);
else
r = -ENODEV;
@ -684,8 +678,6 @@ static bool amdgpu_fence_enable_signaling(struct dma_fence *f)
if (!timer_pending(&ring->fence_drv.fallback_timer))
amdgpu_fence_schedule_fallback(ring);
DMA_FENCE_TRACE(f, "armed on ring %i!\n", ring->idx);
return true;
}

View File

@ -34,6 +34,7 @@
#include <asm/set_memory.h>
#endif
#include "amdgpu.h"
#include <drm/drm_drv.h>
/*
* GART
@ -230,12 +231,16 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
u64 page_base;
/* Starting from VEGA10, system bit must be 0 to mean invalid. */
uint64_t flags = 0;
int idx;
if (!adev->gart.ready) {
WARN(1, "trying to unbind memory from uninitialized GART !\n");
return -EINVAL;
}
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return 0;
t = offset / AMDGPU_GPU_PAGE_SIZE;
p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE;
for (i = 0; i < pages; i++, p++) {
@ -254,6 +259,7 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
for (i = 0; i < adev->num_vmhubs; i++)
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
drm_dev_exit(idx);
return 0;
}
@ -276,12 +282,16 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
{
uint64_t page_base;
unsigned i, j, t;
int idx;
if (!adev->gart.ready) {
WARN(1, "trying to bind memory to uninitialized GART !\n");
return -EINVAL;
}
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return 0;
t = offset / AMDGPU_GPU_PAGE_SIZE;
for (i = 0; i < pages; i++) {
@ -291,6 +301,7 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
page_base += AMDGPU_GPU_PAGE_SIZE;
}
}
drm_dev_exit(idx);
return 0;
}

View File

@ -60,10 +60,9 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf)
goto unlock;
}
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
drm_dev_exit(idx);
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
TTM_BO_VM_NUM_PREFAULT, 1);
drm_dev_exit(idx);
} else {
ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot);
}

View File

@ -42,10 +42,9 @@
#define AMDGPU_MAX_GFX_QUEUES KGD_MAX_QUEUES
#define AMDGPU_MAX_COMPUTE_QUEUES KGD_MAX_QUEUES
enum gfx_pipe_priority {
AMDGPU_GFX_PIPE_PRIO_NORMAL = 1,
AMDGPU_GFX_PIPE_PRIO_HIGH,
AMDGPU_GFX_PIPE_PRIO_MAX
enum amdgpu_gfx_pipe_priority {
AMDGPU_GFX_PIPE_PRIO_NORMAL = AMDGPU_RING_PRIO_1,
AMDGPU_GFX_PIPE_PRIO_HIGH = AMDGPU_RING_PRIO_2
};
/* Argument for PPSMC_MSG_GpuChangeState */

View File

@ -153,10 +153,6 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
{
void __iomem *ptr = (void *)cpu_pt_addr;
uint64_t value;
int idx;
if (!drm_dev_enter(&adev->ddev, &idx))
return 0;
/*
* The following is for PTE only. GART does not have PDEs.
@ -165,8 +161,6 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
value |= flags;
writeq(value, ptr + (gpu_page_idx * 8));
drm_dev_exit(idx);
return 0;
}
@ -749,6 +743,10 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev)
adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
u64 vram_end = vram_addr + vram_size;
u64 gart_ptb_gpu_pa = amdgpu_gmc_vram_pa(adev, adev->gart.bo);
int idx;
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return;
flags |= AMDGPU_PTE_VALID | AMDGPU_PTE_READABLE;
flags |= AMDGPU_PTE_WRITEABLE;
@ -770,6 +768,7 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev)
flags |= AMDGPU_PDE_BFS(0) | AMDGPU_PTE_SNOOPED;
/* Requires gart_ptb_gpu_pa to be 4K aligned */
amdgpu_gmc_set_pte_pde(adev, adev->gmc.ptr_pdb0, i, gart_ptb_gpu_pa, flags);
drm_dev_exit(idx);
}
/**

View File

@ -300,20 +300,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
*/
int amdgpu_ib_pool_init(struct amdgpu_device *adev)
{
unsigned size;
int r, i;
if (adev->ib_pool_ready)
return 0;
for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) {
if (i == AMDGPU_IB_POOL_DIRECT)
size = PAGE_SIZE * 6;
else
size = AMDGPU_IB_POOL_SIZE;
r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i],
size, AMDGPU_GPU_PAGE_SIZE,
AMDGPU_IB_POOL_SIZE,
AMDGPU_GPU_PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT);
if (r)
goto error;

View File

@ -38,7 +38,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
struct amdgpu_device *adev = ring->adev;
int idx;
if (!drm_dev_enter(&adev->ddev, &idx)) {
if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
DRM_INFO("%s - device unplugged skipping recovery on scheduler:%s",
__func__, s_job->sched->name);
@ -182,9 +182,11 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
if (r)
return r;
drm_sched_job_arm(&job->base);
*f = dma_fence_get(&job->base.s_fence->finished);
amdgpu_job_free_resources(job);
drm_sched_entity_push_job(&job->base, entity);
drm_sched_entity_push_job(&job->base);
return 0;
}

View File

@ -340,28 +340,35 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
case AMDGPU_INFO_FW_TA:
switch (query_fw->index) {
case TA_FW_TYPE_PSP_XGMI:
fw_info->ver = adev->psp.ta_fw_version;
fw_info->feature = adev->psp.xgmi.feature_version;
fw_info->ver = adev->psp.xgmi_context.context.bin_desc.fw_version;
fw_info->feature = adev->psp.xgmi_context.context
.bin_desc.feature_version;
break;
case TA_FW_TYPE_PSP_RAS:
fw_info->ver = adev->psp.ta_fw_version;
fw_info->feature = adev->psp.ras.feature_version;
fw_info->ver = adev->psp.ras_context.context.bin_desc.fw_version;
fw_info->feature = adev->psp.ras_context.context
.bin_desc.feature_version;
break;
case TA_FW_TYPE_PSP_HDCP:
fw_info->ver = adev->psp.ta_fw_version;
fw_info->feature = adev->psp.hdcp.feature_version;
fw_info->ver = adev->psp.hdcp_context.context.bin_desc.fw_version;
fw_info->feature = adev->psp.hdcp_context.context
.bin_desc.feature_version;
break;
case TA_FW_TYPE_PSP_DTM:
fw_info->ver = adev->psp.ta_fw_version;
fw_info->feature = adev->psp.dtm.feature_version;
fw_info->ver = adev->psp.dtm_context.context.bin_desc.fw_version;
fw_info->feature = adev->psp.dtm_context.context
.bin_desc.feature_version;
break;
case TA_FW_TYPE_PSP_RAP:
fw_info->ver = adev->psp.ta_fw_version;
fw_info->feature = adev->psp.rap.feature_version;
fw_info->ver = adev->psp.rap_context.context.bin_desc.fw_version;
fw_info->feature = adev->psp.rap_context.context
.bin_desc.feature_version;
break;
case TA_FW_TYPE_PSP_SECUREDISPLAY:
fw_info->ver = adev->psp.ta_fw_version;
fw_info->feature = adev->psp.securedisplay.feature_version;
fw_info->ver = adev->psp.securedisplay_context.context.bin_desc.fw_version;
fw_info->feature =
adev->psp.securedisplay_context.context.bin_desc
.feature_version;
break;
default:
return -EINVAL;
@ -378,8 +385,8 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
fw_info->feature = adev->psp.sos.feature_version;
break;
case AMDGPU_INFO_FW_ASD:
fw_info->ver = adev->psp.asd.fw_version;
fw_info->feature = adev->psp.asd.feature_version;
fw_info->ver = adev->psp.asd_context.bin_desc.fw_version;
fw_info->feature = adev->psp.asd_context.bin_desc.feature_version;
break;
case AMDGPU_INFO_FW_DMCU:
fw_info->ver = adev->dm.dmcu_fw_version;

View File

@ -31,7 +31,7 @@ void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev,
uint64_t mc_status_addr,
unsigned long *error_count)
{
uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4);
uint64_t mc_status = RREG64_PCIE(mc_status_addr);
if (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
@ -42,7 +42,7 @@ void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev,
uint64_t mc_status_addr,
unsigned long *error_count)
{
uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4);
uint64_t mc_status = RREG64_PCIE(mc_status_addr);
if ((REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
(REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
@ -56,7 +56,7 @@ void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev,
void amdgpu_mca_reset_error_count(struct amdgpu_device *adev,
uint64_t mc_status_addr)
{
WREG64_PCIE(mc_status_addr * 4, 0x0ULL);
WREG64_PCIE(mc_status_addr, 0x0ULL);
}
void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
@ -87,8 +87,8 @@ int amdgpu_mca_ras_late_init(struct amdgpu_device *adev,
if (!mca_dev->ras_if)
return -ENOMEM;
mca_dev->ras_if->block = mca_dev->ras_funcs->ras_block;
mca_dev->ras_if->sub_block_index = mca_dev->ras_funcs->ras_sub_block;
mca_dev->ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
mca_dev->ras_if->sub_block_index = 0;
}
ih_info.head = fs_info.head = *mca_dev->ras_if;
r = amdgpu_ras_late_init(adev, mca_dev->ras_if,

View File

@ -29,6 +29,7 @@ struct amdgpu_mca_ras_funcs {
void (*query_ras_error_address)(struct amdgpu_device *adev,
void *ras_error_status);
uint32_t ras_block;
uint32_t ras_sub_block;
const char* sysfs_name;
};

View File

@ -694,40 +694,6 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev,
return r;
}
/**
* amdgpu_bo_validate - validate an &amdgpu_bo buffer object
* @bo: pointer to the buffer object
*
* Sets placement according to domain; and changes placement and caching
* policy of the buffer object according to the placement.
* This is used for validating shadow bos. It calls ttm_bo_validate() to
* make sure the buffer is resident where it needs to be.
*
* Returns:
* 0 for success or a negative error code on failure.
*/
int amdgpu_bo_validate(struct amdgpu_bo *bo)
{
struct ttm_operation_ctx ctx = { false, false };
uint32_t domain;
int r;
if (bo->tbo.pin_count)
return 0;
domain = bo->preferred_domains;
retry:
amdgpu_bo_placement_from_domain(bo, domain);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
domain = bo->allowed_domains;
goto retry;
}
return r;
}
/**
* amdgpu_bo_add_to_shadow_list - add a BO to the shadow list
*
@ -1038,29 +1004,6 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo)
}
}
/**
* amdgpu_bo_evict_vram - evict VRAM buffers
* @adev: amdgpu device object
*
* Evicts all VRAM buffers on the lru list of the memory type.
* Mainly used for evicting vram at suspend time.
*
* Returns:
* 0 for success or a negative error code on failure.
*/
int amdgpu_bo_evict_vram(struct amdgpu_device *adev)
{
struct ttm_resource_manager *man;
if (adev->in_s3 && (adev->flags & AMD_IS_APU)) {
/* No need to evict vram on APUs for suspend to ram */
return 0;
}
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[] = {
"UNKNOWN",
"GDDR1",

View File

@ -304,7 +304,6 @@ 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);
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);
void amdgpu_bo_fini(struct amdgpu_device *adev);
int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags);
@ -327,7 +326,6 @@ int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv,
int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr);
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo);
u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo);
int amdgpu_bo_validate(struct amdgpu_bo *bo);
void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem,
uint64_t *gtt_mem, uint64_t *cpu_mem);
void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo);

File diff suppressed because it is too large Load Diff

View File

@ -34,17 +34,20 @@
#define PSP_FENCE_BUFFER_SIZE 0x1000
#define PSP_CMD_BUFFER_SIZE 0x1000
#define PSP_XGMI_SHARED_MEM_SIZE 0x4000
#define PSP_RAS_SHARED_MEM_SIZE 0x4000
#define PSP_1_MEG 0x100000
#define PSP_TMR_SIZE(adev) ((adev)->asic_type == CHIP_ALDEBARAN ? 0x800000 : 0x400000)
#define PSP_HDCP_SHARED_MEM_SIZE 0x4000
#define PSP_DTM_SHARED_MEM_SIZE 0x4000
#define PSP_RAP_SHARED_MEM_SIZE 0x4000
#define PSP_SECUREDISPLAY_SHARED_MEM_SIZE 0x4000
#define PSP_SHARED_MEM_SIZE 0x4000
#define PSP_FW_NAME_LEN 0x24
enum psp_shared_mem_size {
PSP_ASD_SHARED_MEM_SIZE = 0x0,
PSP_XGMI_SHARED_MEM_SIZE = 0x4000,
PSP_RAS_SHARED_MEM_SIZE = 0x4000,
PSP_HDCP_SHARED_MEM_SIZE = 0x4000,
PSP_DTM_SHARED_MEM_SIZE = 0x4000,
PSP_RAP_SHARED_MEM_SIZE = 0x4000,
PSP_SECUREDISPLAY_SHARED_MEM_SIZE = 0x4000,
};
struct psp_context;
struct psp_xgmi_node_info;
struct psp_xgmi_topology_info;
@ -131,21 +134,26 @@ struct psp_xgmi_topology_info {
struct psp_xgmi_node_info nodes[AMDGPU_XGMI_MAX_CONNECTED_NODES];
};
struct psp_asd_context {
bool asd_initialized;
uint32_t session_id;
struct psp_bin_desc {
uint32_t fw_version;
uint32_t feature_version;
uint32_t size_bytes;
uint8_t *start_addr;
};
struct ta_mem_context {
struct amdgpu_bo *shared_bo;
uint64_t shared_mc_addr;
void *shared_buf;
enum psp_shared_mem_size shared_mem_size;
};
struct ta_context {
bool initialized;
uint32_t session_id;
struct ta_mem_context mem_context;
struct psp_bin_desc bin_desc;
enum psp_gfx_cmd_id ta_load_type;
};
struct ta_cp_context {
@ -263,13 +271,6 @@ struct psp_runtime_boot_cfg_entry {
uint32_t reserved;
};
struct psp_bin_desc {
uint32_t fw_version;
uint32_t feature_version;
uint32_t size_bytes;
uint8_t *start_addr;
};
struct psp_context
{
struct amdgpu_device *adev;
@ -301,7 +302,6 @@ struct psp_context
/* asd firmware */
const struct firmware *asd_fw;
struct psp_bin_desc asd;
/* toc firmware */
const struct firmware *toc_fw;
@ -326,14 +326,8 @@ struct psp_context
/* xgmi ta firmware and buffer */
const struct firmware *ta_fw;
uint32_t ta_fw_version;
struct psp_bin_desc xgmi;
struct psp_bin_desc ras;
struct psp_bin_desc hdcp;
struct psp_bin_desc dtm;
struct psp_bin_desc rap;
struct psp_bin_desc securedisplay;
struct psp_asd_context asd_context;
struct ta_context asd_context;
struct psp_xgmi_context xgmi_context;
struct psp_ras_context ras_context;
struct ta_cp_context hdcp_context;

View File

@ -35,7 +35,11 @@
#include "amdgpu_xgmi.h"
#include "ivsrcid/nbio/irqsrcs_nbif_7_4.h"
#include "atom.h"
#ifdef CONFIG_X86_MCE_AMD
#include <asm/mce.h>
static bool notifier_registered;
#endif
static const char *RAS_FS_NAME = "ras";
const char *ras_error_string[] = {
@ -61,8 +65,30 @@ const char *ras_block_string[] = {
"mp0",
"mp1",
"fuse",
"mca",
};
const char *ras_mca_block_string[] = {
"mca_mp0",
"mca_mp1",
"mca_mpio",
"mca_iohc",
};
const char *get_ras_block_str(struct ras_common_if *ras_block)
{
if (!ras_block)
return "NULL";
if (ras_block->block >= AMDGPU_RAS_BLOCK_COUNT)
return "OUT OF RANGE";
if (ras_block->block == AMDGPU_RAS_BLOCK__MCA)
return ras_mca_block_string[ras_block->sub_block_index];
return ras_block_string[ras_block->block];
}
#define ras_err_str(i) (ras_error_string[ffs(i)])
#define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS)
@ -85,6 +111,14 @@ 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);
#ifdef CONFIG_X86_MCE_AMD
static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev);
struct mce_notifier_adev_list {
struct amdgpu_device *devs[MAX_GPU_INSTANCE];
int num_gpu;
};
static struct mce_notifier_adev_list mce_adev_list;
#endif
void amdgpu_ras_set_error_query_ready(struct amdgpu_device *adev, bool ready)
{
@ -187,7 +221,7 @@ static int amdgpu_ras_find_block_id_by_name(const char *name, int *block_id)
for (i = 0; i < ARRAY_SIZE(ras_block_string); i++) {
*block_id = i;
if (strcmp(name, ras_block_str(i)) == 0)
if (strcmp(name, ras_block_string[i]) == 0)
return 0;
}
return -EINVAL;
@ -509,7 +543,6 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev,
if (amdgpu_ras_query_error_status(obj->adev, &info))
return -EINVAL;
if (obj->adev->asic_type == CHIP_ALDEBARAN) {
if (amdgpu_ras_reset_error_status(obj->adev, info.head.block))
DRM_WARN("Failed to reset error counter and error status");
@ -529,7 +562,7 @@ static inline void put_obj(struct ras_manager *obj)
if (obj && (--obj->use == 0))
list_del(&obj->node);
if (obj && (obj->use < 0))
DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", ras_block_str(obj->head.block));
DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", get_ras_block_str(&obj->head));
}
/* make one obj and return it. */
@ -545,7 +578,14 @@ static struct ras_manager *amdgpu_ras_create_obj(struct amdgpu_device *adev,
if (head->block >= AMDGPU_RAS_BLOCK_COUNT)
return NULL;
obj = &con->objs[head->block];
if (head->block == AMDGPU_RAS_BLOCK__MCA) {
if (head->sub_block_index >= AMDGPU_RAS_MCA_BLOCK__LAST)
return NULL;
obj = &con->objs[AMDGPU_RAS_BLOCK__LAST + head->sub_block_index];
} else
obj = &con->objs[head->block];
/* already exist. return obj? */
if (alive_obj(obj))
return NULL;
@ -573,19 +613,21 @@ struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
if (head->block >= AMDGPU_RAS_BLOCK_COUNT)
return NULL;
obj = &con->objs[head->block];
if (head->block == AMDGPU_RAS_BLOCK__MCA) {
if (head->sub_block_index >= AMDGPU_RAS_MCA_BLOCK__LAST)
return NULL;
if (alive_obj(obj)) {
WARN_ON(head->block != obj->head.block);
obj = &con->objs[AMDGPU_RAS_BLOCK__LAST + head->sub_block_index];
} else
obj = &con->objs[head->block];
if (alive_obj(obj))
return obj;
}
} else {
for (i = 0; i < AMDGPU_RAS_BLOCK_COUNT; i++) {
for (i = 0; i < AMDGPU_RAS_BLOCK_COUNT + AMDGPU_RAS_MCA_BLOCK_COUNT; i++) {
obj = &con->objs[i];
if (alive_obj(obj)) {
WARN_ON(i != obj->head.block);
if (alive_obj(obj))
return obj;
}
}
}
@ -626,8 +668,6 @@ static int __amdgpu_ras_feature_enable(struct amdgpu_device *adev,
*/
if (!amdgpu_ras_is_feature_allowed(adev, head))
return 0;
if (!(!!enable ^ !!amdgpu_ras_is_feature_enabled(adev, head)))
return 0;
if (enable) {
if (!obj) {
@ -678,19 +718,14 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
/* Do not enable if it is not allowed. */
WARN_ON(enable && !amdgpu_ras_is_feature_allowed(adev, head));
/* Are we alerady in that state we are going to set? */
if (!(!!enable ^ !!amdgpu_ras_is_feature_enabled(adev, head))) {
ret = 0;
goto out;
}
if (!amdgpu_ras_intr_triggered()) {
ret = psp_ras_enable_features(&adev->psp, info, enable);
if (ret) {
dev_err(adev->dev, "ras %s %s failed %d\n",
dev_err(adev->dev, "ras %s %s failed poison:%d ret:%d\n",
enable ? "enable":"disable",
ras_block_str(head->block),
ret);
get_ras_block_str(head),
amdgpu_ras_is_poison_mode_supported(adev), ret);
goto out;
}
}
@ -731,7 +766,7 @@ int amdgpu_ras_feature_enable_on_boot(struct amdgpu_device *adev,
if (!ret)
dev_info(adev->dev,
"RAS INFO: %s setup object\n",
ras_block_str(head->block));
get_ras_block_str(head));
}
} else {
/* setup the object then issue a ras TA disable cmd.*/
@ -781,17 +816,39 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev,
bool bypass)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
int ras_block_count = AMDGPU_RAS_BLOCK_COUNT;
int i;
const enum amdgpu_ras_error_type default_ras_type =
AMDGPU_RAS_ERROR__NONE;
const enum amdgpu_ras_error_type default_ras_type = AMDGPU_RAS_ERROR__NONE;
for (i = 0; i < ras_block_count; i++) {
for (i = 0; i < AMDGPU_RAS_BLOCK_COUNT; i++) {
struct ras_common_if head = {
.block = i,
.type = default_ras_type,
.sub_block_index = 0,
};
if (i == AMDGPU_RAS_BLOCK__MCA)
continue;
if (bypass) {
/*
* bypass psp. vbios enable ras for us.
* so just create the obj
*/
if (__amdgpu_ras_feature_enable(adev, &head, 1))
break;
} else {
if (amdgpu_ras_feature_enable(adev, &head, 1))
break;
}
}
for (i = 0; i < AMDGPU_RAS_MCA_BLOCK_COUNT; i++) {
struct ras_common_if head = {
.block = AMDGPU_RAS_BLOCK__MCA,
.type = default_ras_type,
.sub_block_index = i,
};
if (bypass) {
/*
* bypass psp. vbios enable ras for us.
@ -809,6 +866,32 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev,
}
/* feature ctl end */
void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
struct ras_common_if *ras_block,
struct ras_err_data *err_data)
{
switch (ras_block->sub_block_index) {
case AMDGPU_RAS_MCA_BLOCK__MP0:
if (adev->mca.mp0.ras_funcs &&
adev->mca.mp0.ras_funcs->query_ras_error_count)
adev->mca.mp0.ras_funcs->query_ras_error_count(adev, &err_data);
break;
case AMDGPU_RAS_MCA_BLOCK__MP1:
if (adev->mca.mp1.ras_funcs &&
adev->mca.mp1.ras_funcs->query_ras_error_count)
adev->mca.mp1.ras_funcs->query_ras_error_count(adev, &err_data);
break;
case AMDGPU_RAS_MCA_BLOCK__MPIO:
if (adev->mca.mpio.ras_funcs &&
adev->mca.mpio.ras_funcs->query_ras_error_count)
adev->mca.mpio.ras_funcs->query_ras_error_count(adev, &err_data);
break;
default:
break;
}
}
/* query/inject/cure begin */
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
struct ras_query_if *info)
@ -872,6 +955,9 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
adev->hdp.ras_funcs->query_ras_error_count)
adev->hdp.ras_funcs->query_ras_error_count(adev, &err_data);
break;
case AMDGPU_RAS_BLOCK__MCA:
amdgpu_ras_mca_query_error_status(adev, &info->head, &err_data);
break;
default:
break;
}
@ -893,13 +979,13 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
adev->smuio.funcs->get_socket_id(adev),
adev->smuio.funcs->get_die_id(adev),
obj->err_data.ce_count,
ras_block_str(info->head.block));
get_ras_block_str(&info->head));
} else {
dev_info(adev->dev, "%ld correctable hardware errors "
"detected in %s block, no user "
"action is needed.\n",
obj->err_data.ce_count,
ras_block_str(info->head.block));
get_ras_block_str(&info->head));
}
}
if (err_data.ue_count) {
@ -912,15 +998,18 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
adev->smuio.funcs->get_socket_id(adev),
adev->smuio.funcs->get_die_id(adev),
obj->err_data.ue_count,
ras_block_str(info->head.block));
get_ras_block_str(&info->head));
} else {
dev_info(adev->dev, "%ld uncorrectable hardware errors "
"detected in %s block\n",
obj->err_data.ue_count,
ras_block_str(info->head.block));
get_ras_block_str(&info->head));
}
}
if (!amdgpu_persistent_edc_harvesting_supported(adev))
amdgpu_ras_reset_error_status(adev, info->head.block);
return 0;
}
@ -1027,6 +1116,7 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
case AMDGPU_RAS_BLOCK__SDMA:
case AMDGPU_RAS_BLOCK__MMHUB:
case AMDGPU_RAS_BLOCK__PCIE_BIF:
case AMDGPU_RAS_BLOCK__MCA:
ret = psp_ras_trigger_error(&adev->psp, &block_info);
break;
case AMDGPU_RAS_BLOCK__XGMI_WAFL:
@ -1034,13 +1124,13 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
break;
default:
dev_info(adev->dev, "%s error injection is not supported yet\n",
ras_block_str(info->head.block));
get_ras_block_str(&info->head));
ret = -EINVAL;
}
if (ret)
dev_err(adev->dev, "ras inject %s failed %d\n",
ras_block_str(info->head.block), ret);
get_ras_block_str(&info->head), ret);
return ret;
}
@ -1383,7 +1473,7 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
if (amdgpu_ras_is_supported(adev, obj->head.block) &&
(obj->attr_inuse == 1)) {
sprintf(fs_info.debugfs_name, "%s_err_inject",
ras_block_str(obj->head.block));
get_ras_block_str(&obj->head));
fs_info.head = obj->head;
amdgpu_ras_debugfs_create(adev, &fs_info, dir);
}
@ -1469,22 +1559,28 @@ static void amdgpu_ras_interrupt_handler(struct ras_manager *obj)
data->rptr = (data->aligned_element_size +
data->rptr) % data->ring_size;
/* Let IP handle its data, maybe we need get the output
* from the callback to udpate the error type/count, etc
*/
if (data->cb) {
ret = data->cb(obj->adev, &err_data, &entry);
/* ue will trigger an interrupt, and in that case
* we need do a reset to recovery the whole system.
* But leave IP do that recovery, here we just dispatch
* the error.
*/
if (ret == AMDGPU_RAS_SUCCESS) {
/* these counts could be left as 0 if
* some blocks do not count error number
if (amdgpu_ras_is_poison_mode_supported(obj->adev) &&
obj->head.block == AMDGPU_RAS_BLOCK__UMC)
dev_info(obj->adev->dev,
"Poison is created, no user action is needed.\n");
else {
/* Let IP handle its data, maybe we need get the output
* from the callback to udpate the error type/count, etc
*/
obj->err_data.ue_count += err_data.ue_count;
obj->err_data.ce_count += err_data.ce_count;
ret = data->cb(obj->adev, &err_data, &entry);
/* ue will trigger an interrupt, and in that case
* we need do a reset to recovery the whole system.
* But leave IP do that recovery, here we just dispatch
* the error.
*/
if (ret == AMDGPU_RAS_SUCCESS) {
/* these counts could be left as 0 if
* some blocks do not count error number
*/
obj->err_data.ue_count += err_data.ue_count;
obj->err_data.ce_count += err_data.ce_count;
}
}
}
}
@ -2014,6 +2110,11 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs);
}
#ifdef CONFIG_X86_MCE_AMD
if ((adev->asic_type == CHIP_ALDEBARAN) &&
(adev->gmc.xgmi.connected_to_cpu))
amdgpu_register_bad_pages_mca_notifier(adev);
#endif
return 0;
free:
@ -2056,19 +2157,6 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
}
/* recovery end */
/* return 0 if ras will reset gpu and repost.*/
int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev,
unsigned int block)
{
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
if (!ras)
return -EINVAL;
ras->flags |= AMDGPU_RAS_FLAG_INIT_NEED_RESET;
return 0;
}
static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev)
{
return adev->asic_type == CHIP_VEGA10 ||
@ -2176,12 +2264,14 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
int r;
bool df_poison, umc_poison;
if (con)
return 0;
con = kmalloc(sizeof(struct amdgpu_ras) +
sizeof(struct ras_manager) * AMDGPU_RAS_BLOCK_COUNT,
sizeof(struct ras_manager) * AMDGPU_RAS_BLOCK_COUNT +
sizeof(struct ras_manager) * AMDGPU_RAS_MCA_BLOCK_COUNT,
GFP_KERNEL|__GFP_ZERO);
if (!con)
return -ENOMEM;
@ -2245,6 +2335,23 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
goto release_con;
}
/* Init poison supported flag, the default value is false */
if (adev->df.funcs &&
adev->df.funcs->query_ras_poison_mode &&
adev->umc.ras_funcs &&
adev->umc.ras_funcs->query_ras_poison_mode) {
df_poison =
adev->df.funcs->query_ras_poison_mode(adev);
umc_poison =
adev->umc.ras_funcs->query_ras_poison_mode(adev);
/* Only poison is set in both DF and UMC, we can support it */
if (df_poison && umc_poison)
con->poison_supported = true;
else if (df_poison != umc_poison)
dev_warn(adev->dev, "Poison setting is inconsistent in DF/UMC(%d:%d)!\n",
df_poison, umc_poison);
}
if (amdgpu_ras_fs_init(adev)) {
r = -EINVAL;
goto release_con;
@ -2288,6 +2395,16 @@ static int amdgpu_persistent_edc_harvesting(struct amdgpu_device *adev,
return 0;
}
bool amdgpu_ras_is_poison_mode_supported(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
if (!con)
return false;
return con->poison_supported;
}
/* helper function to handle common stuff in ip late init phase */
int amdgpu_ras_late_init(struct amdgpu_device *adev,
struct ras_common_if *ras_block,
@ -2306,12 +2423,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev,
r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1);
if (r) {
if (r == -EAGAIN) {
/* request gpu reset. will run again */
amdgpu_ras_request_reset_on_boot(adev,
ras_block->block);
return 0;
} else if (adev->in_suspend || amdgpu_in_reset(adev)) {
if (adev->in_suspend || amdgpu_in_reset(adev)) {
/* in resume phase, if fail to enable ras,
* clean up all ras fs nodes, and disable ras */
goto cleanup;
@ -2403,19 +2515,6 @@ void amdgpu_ras_resume(struct amdgpu_device *adev)
}
}
}
if (con->flags & AMDGPU_RAS_FLAG_INIT_NEED_RESET) {
con->flags &= ~AMDGPU_RAS_FLAG_INIT_NEED_RESET;
/* setup ras obj state as disabled.
* for init_by_vbios case.
* if we want to enable ras, just enable it in a normal way.
* If we want do disable it, need setup ras obj as enabled,
* then issue another TA disable cmd.
* See feature_enable_on_boot
*/
amdgpu_ras_disable_all_features(adev, 1);
amdgpu_ras_reset_gpu(adev);
}
}
void amdgpu_ras_suspend(struct amdgpu_device *adev)
@ -2507,3 +2606,136 @@ void amdgpu_release_ras_context(struct amdgpu_device *adev)
kfree(con);
}
}
#ifdef CONFIG_X86_MCE_AMD
static struct amdgpu_device *find_adev(uint32_t node_id)
{
int i;
struct amdgpu_device *adev = NULL;
for (i = 0; i < mce_adev_list.num_gpu; i++) {
adev = mce_adev_list.devs[i];
if (adev && adev->gmc.xgmi.connected_to_cpu &&
adev->gmc.xgmi.physical_node_id == node_id)
break;
adev = NULL;
}
return adev;
}
#define GET_MCA_IPID_GPUID(m) (((m) >> 44) & 0xF)
#define GET_UMC_INST(m) (((m) >> 21) & 0x7)
#define GET_CHAN_INDEX(m) ((((m) >> 12) & 0x3) | (((m) >> 18) & 0x4))
#define GPU_ID_OFFSET 8
static int amdgpu_bad_page_notifier(struct notifier_block *nb,
unsigned long val, void *data)
{
struct mce *m = (struct mce *)data;
struct amdgpu_device *adev = NULL;
uint32_t gpu_id = 0;
uint32_t umc_inst = 0;
uint32_t ch_inst, channel_index = 0;
struct ras_err_data err_data = {0, 0, 0, NULL};
struct eeprom_table_record err_rec;
uint64_t retired_page;
/*
* If the error was generated in UMC_V2, which belongs to GPU UMCs,
* and error occurred in DramECC (Extended error code = 0) then only
* process the error, else bail out.
*/
if (!m || !((smca_get_bank_type(m->bank) == SMCA_UMC_V2) &&
(XEC(m->status, 0x3f) == 0x0)))
return NOTIFY_DONE;
/*
* If it is correctable error, return.
*/
if (mce_is_correctable(m))
return NOTIFY_OK;
/*
* GPU Id is offset by GPU_ID_OFFSET in MCA_IPID_UMC register.
*/
gpu_id = GET_MCA_IPID_GPUID(m->ipid) - GPU_ID_OFFSET;
adev = find_adev(gpu_id);
if (!adev) {
DRM_WARN("%s: Unable to find adev for gpu_id: %d\n", __func__,
gpu_id);
return NOTIFY_DONE;
}
/*
* If it is uncorrectable error, then find out UMC instance and
* channel index.
*/
umc_inst = GET_UMC_INST(m->ipid);
ch_inst = GET_CHAN_INDEX(m->ipid);
dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d",
umc_inst, ch_inst);
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
/*
* Translate UMC channel address to Physical address
*/
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num
+ ch_inst];
retired_page = ADDR_OF_8KB_BLOCK(m->addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(m->addr);
err_rec.address = m->addr;
err_rec.retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
err_rec.ts = (uint64_t)ktime_get_real_seconds();
err_rec.err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
err_rec.cu = 0;
err_rec.mem_channel = channel_index;
err_rec.mcumc_id = umc_inst;
err_data.err_addr = &err_rec;
err_data.err_addr_cnt = 1;
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
err_data.err_addr_cnt);
amdgpu_ras_save_bad_pages(adev);
}
return NOTIFY_OK;
}
static struct notifier_block amdgpu_bad_page_nb = {
.notifier_call = amdgpu_bad_page_notifier,
.priority = MCE_PRIO_UC,
};
static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev)
{
/*
* Add the adev to the mce_adev_list.
* During mode2 reset, amdgpu device is temporarily
* removed from the mgpu_info list which can cause
* page retirement to fail.
* Use this list instead of mgpu_info to find the amdgpu
* device on which the UMC error was reported.
*/
mce_adev_list.devs[mce_adev_list.num_gpu++] = adev;
/*
* Register the x86 notifier only once
* with MCE subsystem.
*/
if (notifier_registered == false) {
mce_register_decode_chain(&amdgpu_bad_page_nb);
notifier_registered = true;
}
}
#endif

View File

@ -32,7 +32,6 @@
#include "amdgpu_ras_eeprom.h"
#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0)
#define AMDGPU_RAS_FLAG_INIT_NEED_RESET (0x1 << 1)
enum amdgpu_ras_block {
AMDGPU_RAS_BLOCK__UMC = 0,
@ -49,15 +48,22 @@ enum amdgpu_ras_block {
AMDGPU_RAS_BLOCK__MP0,
AMDGPU_RAS_BLOCK__MP1,
AMDGPU_RAS_BLOCK__FUSE,
AMDGPU_RAS_BLOCK__MPIO,
AMDGPU_RAS_BLOCK__MCA,
AMDGPU_RAS_BLOCK__LAST
};
extern const char *ras_block_string[];
enum amdgpu_ras_mca_block {
AMDGPU_RAS_MCA_BLOCK__MP0 = 0,
AMDGPU_RAS_MCA_BLOCK__MP1,
AMDGPU_RAS_MCA_BLOCK__MPIO,
AMDGPU_RAS_MCA_BLOCK__IOHC,
AMDGPU_RAS_MCA_BLOCK__LAST
};
#define ras_block_str(i) (ras_block_string[i])
#define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST
#define AMDGPU_RAS_MCA_BLOCK_COUNT AMDGPU_RAS_MCA_BLOCK__LAST
#define AMDGPU_RAS_BLOCK_MASK ((1ULL << AMDGPU_RAS_BLOCK_COUNT) - 1)
enum amdgpu_ras_gfx_subblock {
@ -345,6 +351,9 @@ struct amdgpu_ras {
/* disable ras error count harvest in recovery */
bool disable_ras_err_cnt_harvest;
/* is poison mode supported */
bool poison_supported;
/* RAS count errors delayed work */
struct delayed_work ras_counte_delay_work;
atomic_t ras_ue_count;
@ -488,8 +497,6 @@ static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev,
}
int amdgpu_ras_recovery_init(struct amdgpu_device *adev);
int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev,
unsigned int block);
void amdgpu_ras_resume(struct amdgpu_device *adev);
void amdgpu_ras_suspend(struct amdgpu_device *adev);
@ -544,6 +551,8 @@ amdgpu_ras_block_to_ta(enum amdgpu_ras_block block) {
return TA_RAS_BLOCK__MP1;
case AMDGPU_RAS_BLOCK__FUSE:
return TA_RAS_BLOCK__FUSE;
case AMDGPU_RAS_BLOCK__MCA:
return TA_RAS_BLOCK__MCA;
default:
WARN_ONCE(1, "RAS ERROR: unexpected block id %d\n", block);
return TA_RAS_BLOCK__UMC;
@ -638,4 +647,8 @@ void amdgpu_release_ras_context(struct amdgpu_device *adev);
int amdgpu_persistent_edc_harvesting_supported(struct amdgpu_device *adev);
const char *get_ras_block_str(struct ras_common_if *ras_block);
bool amdgpu_ras_is_poison_mode_supported(struct amdgpu_device *adev);
#endif

View File

@ -1077,6 +1077,13 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
if (res)
DRM_ERROR("RAS table incorrect checksum or error:%d\n",
res);
/* Warn if we are at 90% of the threshold or above
*/
if (10 * control->ras_num_recs >= 9 * ras->bad_page_cnt_threshold)
dev_warn(adev->dev, "RAS records:%u exceeds 90%% of threshold:%d",
control->ras_num_recs,
ras->bad_page_cnt_threshold);
} else if (hdr->header == RAS_TABLE_HDR_BAD &&
amdgpu_bad_page_threshold != 0) {
res = __verify_ras_table_checksum(control);
@ -1098,11 +1105,18 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
res = amdgpu_ras_eeprom_correct_header_tag(control,
RAS_TABLE_HDR_VAL);
} else {
*exceed_err_limit = true;
dev_err(adev->dev,
"RAS records:%d exceed threshold:%d, "
"maybe retire this GPU?",
dev_err(adev->dev, "RAS records:%d exceed threshold:%d",
control->ras_num_recs, ras->bad_page_cnt_threshold);
if (amdgpu_bad_page_threshold == -2) {
dev_warn(adev->dev, "GPU will be initialized due to bad_page_threshold = -2.");
res = 0;
} else {
*exceed_err_limit = true;
dev_err(adev->dev,
"RAS records:%d exceed threshold:%d, "
"GPU will not be initialized. Replace this GPU or increase the threshold",
control->ras_num_recs, ras->bad_page_cnt_threshold);
}
}
} else {
DRM_INFO("Creating a new EEPROM table");

View File

@ -415,26 +415,20 @@ static const struct file_operations amdgpu_debugfs_ring_fops = {
#endif
int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
#if defined(CONFIG_DEBUG_FS)
struct drm_minor *minor = adev_to_drm(adev)->primary;
struct dentry *ent, *root = minor->debugfs_root;
struct dentry *root = minor->debugfs_root;
char name[32];
sprintf(name, "amdgpu_ring_%s", ring->name);
debugfs_create_file_size(name, S_IFREG | S_IRUGO, root, ring,
&amdgpu_debugfs_ring_fops,
ring->ring_size + 12);
ent = debugfs_create_file(name,
S_IFREG | S_IRUGO, root,
ring, &amdgpu_debugfs_ring_fops);
if (IS_ERR(ent))
return PTR_ERR(ent);
i_size_write(ent->d_inode, ring->ring_size + 12);
ring->ent = ent;
#endif
return 0;
}
/**

View File

@ -36,8 +36,13 @@
#define AMDGPU_MAX_VCE_RINGS 3
#define AMDGPU_MAX_UVD_ENC_RINGS 2
#define AMDGPU_RING_PRIO_DEFAULT 1
#define AMDGPU_RING_PRIO_MAX AMDGPU_GFX_PIPE_PRIO_MAX
enum amdgpu_ring_priority_level {
AMDGPU_RING_PRIO_0,
AMDGPU_RING_PRIO_1,
AMDGPU_RING_PRIO_DEFAULT = 1,
AMDGPU_RING_PRIO_2,
AMDGPU_RING_PRIO_MAX
};
/* some special values for the owner field */
#define AMDGPU_FENCE_OWNER_UNDEFINED ((void *)0ul)
@ -248,10 +253,6 @@ struct amdgpu_ring {
bool has_compute_vm_bug;
bool no_scheduler;
int hw_prio;
#if defined(CONFIG_DEBUG_FS)
struct dentry *ent;
#endif
};
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
@ -351,8 +352,6 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring,
int amdgpu_ring_test_helper(struct amdgpu_ring *ring);
int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring);
void amdgpu_debugfs_ring_fini(struct amdgpu_ring *ring);
void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring);
#endif

View File

@ -32,37 +32,9 @@
#include "amdgpu_sched.h"
#include "amdgpu_vm.h"
int amdgpu_to_sched_priority(int amdgpu_priority,
enum drm_sched_priority *prio)
{
switch (amdgpu_priority) {
case AMDGPU_CTX_PRIORITY_VERY_HIGH:
*prio = DRM_SCHED_PRIORITY_HIGH;
break;
case AMDGPU_CTX_PRIORITY_HIGH:
*prio = DRM_SCHED_PRIORITY_HIGH;
break;
case AMDGPU_CTX_PRIORITY_NORMAL:
*prio = DRM_SCHED_PRIORITY_NORMAL;
break;
case AMDGPU_CTX_PRIORITY_LOW:
case AMDGPU_CTX_PRIORITY_VERY_LOW:
*prio = DRM_SCHED_PRIORITY_MIN;
break;
case AMDGPU_CTX_PRIORITY_UNSET:
*prio = DRM_SCHED_PRIORITY_UNSET;
break;
default:
WARN(1, "Invalid context priority %d\n", amdgpu_priority);
return -EINVAL;
}
return 0;
}
static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
int fd,
enum drm_sched_priority priority)
int32_t priority)
{
struct fd f = fdget(fd);
struct amdgpu_fpriv *fpriv;
@ -89,7 +61,7 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev,
int fd,
unsigned ctx_id,
enum drm_sched_priority priority)
int32_t priority)
{
struct fd f = fdget(fd);
struct amdgpu_fpriv *fpriv;
@ -124,7 +96,6 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data,
{
union drm_amdgpu_sched *args = data;
struct amdgpu_device *adev = drm_to_adev(dev);
enum drm_sched_priority priority;
int r;
/* First check the op, then the op's argument.
@ -138,21 +109,22 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
r = amdgpu_to_sched_priority(args->in.priority, &priority);
if (r)
return r;
if (!amdgpu_ctx_priority_is_valid(args->in.priority)) {
WARN(1, "Invalid context priority %d\n", args->in.priority);
return -EINVAL;
}
switch (args->in.op) {
case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE:
r = amdgpu_sched_process_priority_override(adev,
args->in.fd,
priority);
args->in.priority);
break;
case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE:
r = amdgpu_sched_context_priority_override(adev,
args->in.fd,
args->in.ctx_id,
priority);
args->in.priority);
break;
default:
/* Impossible.

View File

@ -696,6 +696,9 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
true, NULL);
out_unlock:
mmap_read_unlock(mm);
if (r)
pr_debug("failed %d to get user pages 0x%lx\n", r, start);
mmput(mm);
return r;
@ -894,7 +897,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev,
DRM_ERROR("failed to pin userptr\n");
return r;
}
} else if (ttm->page_flags & TTM_PAGE_FLAG_SG) {
} else if (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) {
if (!ttm->sg) {
struct dma_buf_attachment *attach;
struct sg_table *sgt;
@ -1066,8 +1069,6 @@ static void amdgpu_ttm_backend_destroy(struct ttm_device *bdev,
{
struct amdgpu_ttm_tt *gtt = (void *)ttm;
amdgpu_ttm_backend_unbind(bdev, ttm);
ttm_tt_destroy_common(bdev, ttm);
if (gtt->usertask)
put_task_struct(gtt->usertask);
@ -1121,6 +1122,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev,
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
pgoff_t i;
int ret;
/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
if (gtt->userptr) {
@ -1130,10 +1133,17 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev,
return 0;
}
if (ttm->page_flags & TTM_PAGE_FLAG_SG)
if (ttm->page_flags & TTM_TT_FLAG_EXTERNAL)
return 0;
return ttm_pool_alloc(&adev->mman.bdev.pool, ttm, ctx);
ret = ttm_pool_alloc(&adev->mman.bdev.pool, ttm, ctx);
if (ret)
return ret;
for (i = 0; i < ttm->num_pages; ++i)
ttm->pages[i]->mapping = bdev->dev_mapping;
return 0;
}
/*
@ -1147,6 +1157,9 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
{
struct amdgpu_ttm_tt *gtt = (void *)ttm;
struct amdgpu_device *adev;
pgoff_t i;
amdgpu_ttm_backend_unbind(bdev, ttm);
if (gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
@ -1155,9 +1168,12 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
return;
}
if (ttm->page_flags & TTM_PAGE_FLAG_SG)
if (ttm->page_flags & TTM_TT_FLAG_EXTERNAL)
return;
for (i = 0; i < ttm->num_pages; ++i)
ttm->pages[i]->mapping = NULL;
adev = amdgpu_ttm_adev(bdev);
return ttm_pool_free(&adev->mman.bdev.pool, ttm);
}
@ -1185,8 +1201,8 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
return -ENOMEM;
}
/* Set TTM_PAGE_FLAG_SG before populate but after create. */
bo->ttm->page_flags |= TTM_PAGE_FLAG_SG;
/* Set TTM_TT_FLAG_EXTERNAL before populate but after create. */
bo->ttm->page_flags |= TTM_TT_FLAG_EXTERNAL;
gtt = (void *)bo->ttm;
gtt->userptr = addr;
@ -1222,7 +1238,7 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm)
*
*/
bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
unsigned long end)
unsigned long end, unsigned long *userptr)
{
struct amdgpu_ttm_tt *gtt = (void *)ttm;
unsigned long size;
@ -1237,6 +1253,8 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
if (gtt->userptr > end || gtt->userptr + size <= start)
return false;
if (userptr)
*userptr = gtt->userptr;
return true;
}
@ -2036,6 +2054,36 @@ error_free:
return r;
}
/**
* amdgpu_ttm_evict_resources - evict memory buffers
* @adev: amdgpu device object
* @mem_type: evicted BO's memory type
*
* Evicts all @mem_type buffers on the lru list of the memory type.
*
* Returns:
* 0 for success or a negative error code on failure.
*/
int amdgpu_ttm_evict_resources(struct amdgpu_device *adev, int mem_type)
{
struct ttm_resource_manager *man;
switch (mem_type) {
case TTM_PL_VRAM:
case TTM_PL_TT:
case AMDGPU_PL_GWS:
case AMDGPU_PL_GDS:
case AMDGPU_PL_OA:
man = ttm_manager_type(&adev->mman.bdev, mem_type);
break;
default:
DRM_ERROR("Trying to evict invalid memory type\n");
return -EINVAL;
}
return ttm_resource_manager_evict_all(&adev->mman.bdev, man);
}
#if defined(CONFIG_DEBUG_FS)
static int amdgpu_mm_vram_table_show(struct seq_file *m, void *unused)

View File

@ -182,7 +182,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm);
struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm);
bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
unsigned long end);
unsigned long end, unsigned long *userptr);
bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm,
int *last_invalidated);
bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm);
@ -190,6 +190,7 @@ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm);
uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem);
uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
struct ttm_resource *mem);
int amdgpu_ttm_evict_resources(struct amdgpu_device *adev, int mem_type);
void amdgpu_ttm_debugfs_init(struct amdgpu_device *adev);

View File

@ -416,10 +416,11 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
else
return AMDGPU_FW_LOAD_PSP;
default:
DRM_ERROR("Unknown firmware load type\n");
if (!load_type)
return AMDGPU_FW_LOAD_DIRECT;
else
return AMDGPU_FW_LOAD_PSP;
}
return AMDGPU_FW_LOAD_DIRECT;
}
const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
@ -508,7 +509,7 @@ static ssize_t show_##name(struct device *dev, \
struct drm_device *ddev = dev_get_drvdata(dev); \
struct amdgpu_device *adev = drm_to_adev(ddev); \
\
return snprintf(buf, PAGE_SIZE, "0x%08x\n", adev->field); \
return sysfs_emit(buf, "0x%08x\n", adev->field); \
} \
static DEVICE_ATTR(name, mode, show_##name, NULL)
@ -525,9 +526,9 @@ FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version);
FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version);
FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version);
FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version);
FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd.fw_version);
FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras.feature_version);
FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi.feature_version);
FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version);
FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.fw_version);
FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi_context.context.bin_desc.fw_version);
FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version);
FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version);
FW_VERSION_ATTR(sdma2_fw_version, 0444, sdma.instance[1].fw_version);
@ -572,6 +573,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;
const struct dmcub_firmware_header_v1_0 *dmcub_hdr = NULL;
const struct mes_firmware_header_v1_0 *mes_hdr = NULL;
u8 *ucode_addr;
if (NULL == ucode->fw)
return 0;
@ -588,94 +590,83 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
dmcub_hdr = (const struct dmcub_firmware_header_v1_0 *)ucode->fw->data;
mes_hdr = (const struct mes_firmware_header_v1_0 *)ucode->fw->data;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
(ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2 &&
ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1_JT &&
ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2_JT &&
ucode->ucode_id != AMDGPU_UCODE_ID_CP_MES &&
ucode->ucode_id != AMDGPU_UCODE_ID_CP_MES_DATA &&
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL &&
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_IRAM &&
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_DRAM &&
ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV &&
ucode->ucode_id != AMDGPU_UCODE_ID_DMCUB)) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes)),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1 ||
ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4;
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes)),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT ||
ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT) {
ucode->ucode_size = le32_to_cpu(cp_hdr->jt_size) * 4;
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes) +
le32_to_cpu(cp_hdr->jt_offset) * 4),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_ERAM) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
switch (ucode->ucode_id) {
case AMDGPU_UCODE_ID_CP_MEC1:
case AMDGPU_UCODE_ID_CP_MEC2:
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4;
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes);
break;
case AMDGPU_UCODE_ID_CP_MEC1_JT:
case AMDGPU_UCODE_ID_CP_MEC2_JT:
ucode->ucode_size = le32_to_cpu(cp_hdr->jt_size) * 4;
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes) +
le32_to_cpu(cp_hdr->jt_offset) * 4;
break;
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
ucode->ucode_size = adev->gfx.rlc.save_restore_list_cntl_size_bytes;
ucode_addr = adev->gfx.rlc.save_restore_list_cntl;
break;
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
ucode->ucode_size = adev->gfx.rlc.save_restore_list_gpm_size_bytes;
ucode_addr = adev->gfx.rlc.save_restore_list_gpm;
break;
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
ucode->ucode_size = adev->gfx.rlc.save_restore_list_srm_size_bytes;
ucode_addr = adev->gfx.rlc.save_restore_list_srm;
break;
case AMDGPU_UCODE_ID_RLC_IRAM:
ucode->ucode_size = adev->gfx.rlc.rlc_iram_ucode_size_bytes;
ucode_addr = adev->gfx.rlc.rlc_iram_ucode;
break;
case AMDGPU_UCODE_ID_RLC_DRAM:
ucode->ucode_size = adev->gfx.rlc.rlc_dram_ucode_size_bytes;
ucode_addr = adev->gfx.rlc.rlc_dram_ucode;
break;
case AMDGPU_UCODE_ID_CP_MES:
ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(mes_hdr->mes_ucode_offset_bytes);
break;
case AMDGPU_UCODE_ID_CP_MES_DATA:
ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes);
break;
case AMDGPU_UCODE_ID_DMCU_ERAM:
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
le32_to_cpu(dmcu_hdr->intv_size_bytes);
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes)),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_INTV) {
ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size_bytes);
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes) +
le32_to_cpu(dmcu_hdr->intv_offset_bytes)),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCUB) {
ucode->ucode_size = le32_to_cpu(dmcub_hdr->inst_const_bytes);
memcpy(ucode->kaddr,
(void *)((uint8_t *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes)),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
ucode->ucode_size = adev->gfx.rlc.save_restore_list_cntl_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM) {
ucode->ucode_size = adev->gfx.rlc.save_restore_list_gpm_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_gpm,
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM) {
ucode->ucode_size = adev->gfx.rlc.save_restore_list_srm_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_srm,
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_IRAM) {
ucode->ucode_size = adev->gfx.rlc.rlc_iram_ucode_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.rlc_iram_ucode,
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_DRAM) {
ucode->ucode_size = adev->gfx.rlc.rlc_dram_ucode_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.rlc_dram_ucode,
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MES) {
ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes);
memcpy(ucode->kaddr, (void *)((uint8_t *)adev->mes.fw->data +
le32_to_cpu(mes_hdr->mes_ucode_offset_bytes)),
ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MES_DATA) {
ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes);
memcpy(ucode->kaddr, (void *)((uint8_t *)adev->mes.fw->data +
le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes)),
ucode->ucode_size);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes);
break;
case AMDGPU_UCODE_ID_DMCU_INTV:
ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes) +
le32_to_cpu(dmcu_hdr->intv_offset_bytes);
break;
case AMDGPU_UCODE_ID_DMCUB:
ucode->ucode_size = le32_to_cpu(dmcub_hdr->inst_const_bytes);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes);
break;
default:
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes);
break;
}
} else {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
ucode_addr = (u8 *)ucode->fw->data +
le32_to_cpu(header->ucode_array_offset_bytes);
}
memcpy(ucode->kaddr, ucode_addr, ucode->ucode_size);
return 0;
}

View File

@ -48,6 +48,7 @@ struct amdgpu_umc_ras_funcs {
void *ras_error_status);
void (*query_ras_error_address)(struct amdgpu_device *adev,
void *ras_error_status);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
};
struct amdgpu_umc_funcs {

View File

@ -0,0 +1,51 @@
/*
* Copyright 2021 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/ioctl.h>
/*
* MMIO debugfs IOCTL structure
*/
struct amdgpu_debugfs_regs2_iocdata {
__u32 use_srbm, use_grbm, pg_lock;
struct {
__u32 se, sh, instance;
} grbm;
struct {
__u32 me, pipe, queue, vmid;
} srbm;
};
/*
* MMIO debugfs state data (per file* handle)
*/
struct amdgpu_debugfs_regs2_data {
struct amdgpu_device *adev;
struct mutex lock;
struct amdgpu_debugfs_regs2_iocdata id;
};
enum AMDGPU_DEBUGFS_REGS2_CMDS {
AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE=0,
};
#define AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE _IOWR(0x20, AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE, struct amdgpu_debugfs_regs2_iocdata)

View File

@ -134,6 +134,51 @@ MODULE_FIRMWARE(FIRMWARE_VEGA12);
MODULE_FIRMWARE(FIRMWARE_VEGA20);
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo);
static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
uint32_t size,
struct amdgpu_bo **bo_ptr)
{
struct ttm_operation_ctx ctx = { true, false };
struct amdgpu_bo *bo = NULL;
void *addr;
int r;
r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&bo, NULL, &addr);
if (r)
return r;
if (adev->uvd.address_64_bit)
goto succ;
amdgpu_bo_kunmap(bo);
amdgpu_bo_unpin(bo);
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
amdgpu_uvd_force_into_uvd_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
if (r)
goto err;
r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_VRAM);
if (r)
goto err_pin;
r = amdgpu_bo_kmap(bo, &addr);
if (r)
goto err_kmap;
succ:
amdgpu_bo_unreserve(bo);
*bo_ptr = bo;
return 0;
err_kmap:
amdgpu_bo_unpin(bo);
err_pin:
err:
amdgpu_bo_unreserve(bo);
amdgpu_bo_unref(&bo);
return r;
}
int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
{
@ -302,6 +347,10 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))
adev->uvd.address_64_bit = true;
r = amdgpu_uvd_create_msg_bo_helper(adev, 128 << 10, &adev->uvd.ib_bo);
if (r)
return r;
switch (adev->asic_type) {
case CHIP_TONGA:
adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_65_10;
@ -324,6 +373,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
{
void *addr = amdgpu_bo_kptr(adev->uvd.ib_bo);
int i, j;
drm_sched_entity_destroy(&adev->uvd.entity);
@ -342,6 +392,7 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
for (i = 0; i < AMDGPU_MAX_UVD_ENC_RINGS; ++i)
amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]);
}
amdgpu_bo_free_kernel(&adev->uvd.ib_bo, NULL, &addr);
release_firmware(adev->uvd.fw);
return 0;
@ -403,7 +454,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
if (!adev->uvd.inst[j].saved_bo)
return -ENOMEM;
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
/* re-write 0 since err_event_athub will corrupt VCPU buffer */
if (in_ras_intr)
memset(adev->uvd.inst[j].saved_bo, 0, size);
@ -436,7 +487,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
ptr = adev->uvd.inst[i].cpu_addr;
if (adev->uvd.inst[i].saved_bo != NULL) {
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memcpy_toio(ptr, adev->uvd.inst[i].saved_bo, size);
drm_dev_exit(idx);
}
@ -449,7 +500,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memcpy_toio(adev->uvd.inst[i].cpu_addr, adev->uvd.fw->data + offset,
le32_to_cpu(hdr->ucode_size_bytes));
drm_dev_exit(idx);
@ -1080,23 +1131,10 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
unsigned offset_idx = 0;
unsigned offset[3] = { UVD_BASE_SI, 0, 0 };
amdgpu_bo_kunmap(bo);
amdgpu_bo_unpin(bo);
if (!ring->adev->uvd.address_64_bit) {
struct ttm_operation_ctx ctx = { true, false };
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
amdgpu_uvd_force_into_uvd_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
if (r)
goto err;
}
r = amdgpu_job_alloc_with_ib(adev, 64, direct ? AMDGPU_IB_POOL_DIRECT :
AMDGPU_IB_POOL_DELAYED, &job);
if (r)
goto err;
return r;
if (adev->asic_type >= CHIP_VEGA10) {
offset_idx = 1 + ring->me;
@ -1147,9 +1185,9 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
goto err_free;
}
amdgpu_bo_reserve(bo, true);
amdgpu_bo_fence(bo, f, false);
amdgpu_bo_unreserve(bo);
amdgpu_bo_unref(&bo);
if (fence)
*fence = dma_fence_get(f);
@ -1159,10 +1197,6 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
err_free:
amdgpu_job_free(job);
err:
amdgpu_bo_unreserve(bo);
amdgpu_bo_unref(&bo);
return r;
}
@ -1173,16 +1207,11 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_bo *bo = NULL;
struct amdgpu_bo *bo = adev->uvd.ib_bo;
uint32_t *msg;
int r, i;
r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&bo, NULL, (void **)&msg);
if (r)
return r;
int i;
msg = amdgpu_bo_kptr(bo);
/* stitch together an UVD create msg */
msg[0] = cpu_to_le32(0x00000de4);
msg[1] = cpu_to_le32(0x00000000);
@ -1199,6 +1228,7 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
msg[i] = cpu_to_le32(0x0);
return amdgpu_uvd_send_msg(ring, bo, true, fence);
}
int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
@ -1209,12 +1239,15 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
uint32_t *msg;
int r, i;
r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&bo, NULL, (void **)&msg);
if (r)
return r;
if (direct) {
bo = adev->uvd.ib_bo;
} else {
r = amdgpu_uvd_create_msg_bo_helper(adev, 4096, &bo);
if (r)
return r;
}
msg = amdgpu_bo_kptr(bo);
/* stitch together an UVD destroy msg */
msg[0] = cpu_to_le32(0x00000de4);
msg[1] = cpu_to_le32(0x00000002);
@ -1223,7 +1256,12 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
for (i = 4; i < 1024; ++i)
msg[i] = cpu_to_le32(0x0);
return amdgpu_uvd_send_msg(ring, bo, direct, fence);
r = amdgpu_uvd_send_msg(ring, bo, direct, fence);
if (!direct)
amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg);
return r;
}
static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
@ -1298,10 +1336,17 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout)
struct dma_fence *fence;
long r;
r = amdgpu_uvd_get_create_msg(ring, 1, NULL);
r = amdgpu_uvd_get_create_msg(ring, 1, &fence);
if (r)
goto error;
r = dma_fence_wait_timeout(fence, false, timeout);
dma_fence_put(fence);
if (r == 0)
r = -ETIMEDOUT;
if (r < 0)
goto error;
r = amdgpu_uvd_get_destroy_msg(ring, 1, true, &fence);
if (r)
goto error;

View File

@ -68,6 +68,7 @@ struct amdgpu_uvd {
/* store image width to adjust nb memory state */
unsigned decode_image_width;
uint32_t keyselect;
struct amdgpu_bo *ib_bo;
};
int amdgpu_uvd_sw_init(struct amdgpu_device *adev);

View File

@ -82,7 +82,6 @@ MODULE_FIRMWARE(FIRMWARE_VEGA20);
static void amdgpu_vce_idle_work_handler(struct work_struct *work);
static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct amdgpu_bo *bo,
struct dma_fence **fence);
static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
bool direct, struct dma_fence **fence);
@ -314,7 +313,7 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->vce.fw->data;
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memcpy_toio(cpu_addr, adev->vce.fw->data + offset,
adev->vce.fw->size - offset);
drm_dev_exit(idx);
@ -441,12 +440,12 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
* Open up a stream for HW test
*/
static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct amdgpu_bo *bo,
struct dma_fence **fence)
{
const unsigned ib_size_dw = 1024;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
struct amdgpu_ib ib_msg;
struct dma_fence *f = NULL;
uint64_t addr;
int i, r;
@ -456,9 +455,17 @@ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
if (r)
return r;
ib = &job->ibs[0];
memset(&ib_msg, 0, sizeof(ib_msg));
/* only one gpu page is needed, alloc +1 page to make addr aligned. */
r = amdgpu_ib_get(ring->adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2,
AMDGPU_IB_POOL_DIRECT,
&ib_msg);
if (r)
goto err;
addr = amdgpu_bo_gpu_offset(bo);
ib = &job->ibs[0];
/* let addr point to page boundary */
addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg.gpu_addr);
/* stitch together an VCE create msg */
ib->length_dw = 0;
@ -498,6 +505,7 @@ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
ib->ptr[i] = 0x0;
r = amdgpu_job_submit_direct(job, ring, &f);
amdgpu_ib_free(ring->adev, &ib_msg, f);
if (r)
goto err;
@ -1134,20 +1142,13 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct dma_fence *fence = NULL;
struct amdgpu_bo *bo = NULL;
long r;
/* skip vce ring1/2 ib test for now, since it's not reliable */
if (ring != &ring->adev->vce.ring[0])
return 0;
r = amdgpu_bo_create_reserved(ring->adev, 512, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM,
&bo, NULL, NULL);
if (r)
return r;
r = amdgpu_vce_get_create_msg(ring, 1, bo, NULL);
r = amdgpu_vce_get_create_msg(ring, 1, NULL);
if (r)
goto error;
@ -1163,7 +1164,19 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
error:
dma_fence_put(fence);
amdgpu_bo_unreserve(bo);
amdgpu_bo_free_kernel(&bo, NULL, NULL);
return r;
}
enum amdgpu_ring_priority_level amdgpu_vce_get_ring_prio(int ring)
{
switch(ring) {
case 0:
return AMDGPU_RING_PRIO_0;
case 1:
return AMDGPU_RING_PRIO_1;
case 2:
return AMDGPU_RING_PRIO_2;
default:
return AMDGPU_RING_PRIO_0;
}
}

View File

@ -71,5 +71,6 @@ void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring);
void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring);
unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring);
unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring);
enum amdgpu_ring_priority_level amdgpu_vce_get_ring_prio(int ring);
#endif

View File

@ -86,8 +86,9 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
for (i = 0; i < adev->vcn.num_vcn_inst; i++)
atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
switch (adev->asic_type) {
case CHIP_RAVEN:
switch (adev->ip_versions[UVD_HWIP][0]) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
fw_name = FIRMWARE_RAVEN2;
else if (adev->apu_flags & AMD_APU_IS_PICASSO)
@ -95,13 +96,13 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
else
fw_name = FIRMWARE_RAVEN;
break;
case CHIP_ARCTURUS:
case IP_VERSION(2, 5, 0):
fw_name = FIRMWARE_ARCTURUS;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_RENOIR:
case IP_VERSION(2, 2, 0):
if (adev->apu_flags & AMD_APU_IS_RENOIR)
fw_name = FIRMWARE_RENOIR;
else
@ -111,58 +112,52 @@ 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_ALDEBARAN:
case IP_VERSION(2, 6, 0):
fw_name = FIRMWARE_ALDEBARAN;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_NAVI10:
case IP_VERSION(2, 0, 0):
fw_name = FIRMWARE_NAVI10;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_NAVI14:
fw_name = FIRMWARE_NAVI14;
case IP_VERSION(2, 0, 2):
if (adev->asic_type == CHIP_NAVI12)
fw_name = FIRMWARE_NAVI12;
else
fw_name = FIRMWARE_NAVI14;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_NAVI12:
fw_name = FIRMWARE_NAVI12;
case IP_VERSION(3, 0, 0):
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
fw_name = FIRMWARE_SIENNA_CICHLID;
else
fw_name = FIRMWARE_NAVY_FLOUNDER;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_SIENNA_CICHLID:
fw_name = FIRMWARE_SIENNA_CICHLID;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_NAVY_FLOUNDER:
fw_name = FIRMWARE_NAVY_FLOUNDER;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_VANGOGH:
case IP_VERSION(3, 0, 2):
fw_name = FIRMWARE_VANGOGH;
break;
case CHIP_DIMGREY_CAVEFISH:
case IP_VERSION(3, 0, 16):
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;
case CHIP_BEIGE_GOBY:
case IP_VERSION(3, 0, 33):
fw_name = FIRMWARE_BEIGE_GOBY;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case CHIP_YELLOW_CARP:
case IP_VERSION(3, 1, 1):
fw_name = FIRMWARE_YELLOW_CARP;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
@ -330,7 +325,7 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
if (!adev->vcn.inst[i].saved_bo)
return -ENOMEM;
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
drm_dev_exit(idx);
}
@ -354,7 +349,7 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
ptr = adev->vcn.inst[i].cpu_addr;
if (adev->vcn.inst[i].saved_bo != NULL) {
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
drm_dev_exit(idx);
}
@ -367,7 +362,7 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
if (drm_dev_enter(&adev->ddev, &idx)) {
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
memcpy_toio(adev->vcn.inst[i].cpu_addr, adev->vcn.fw->data + offset,
le32_to_cpu(hdr->ucode_size_bytes));
drm_dev_exit(idx);
@ -541,15 +536,14 @@ int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring)
}
static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct amdgpu_ib *ib_msg,
struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
struct dma_fence *f = NULL;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
uint64_t addr;
void *msg = NULL;
uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
int i, r;
r = amdgpu_job_alloc_with_ib(adev, 64,
@ -558,8 +552,6 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
goto err;
ib = &job->ibs[0];
addr = amdgpu_bo_gpu_offset(bo);
msg = amdgpu_bo_kptr(bo);
ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
ib->ptr[1] = addr;
ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
@ -576,9 +568,7 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
if (r)
goto err_free;
amdgpu_bo_fence(bo, f, false);
amdgpu_bo_unreserve(bo);
amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg);
amdgpu_ib_free(adev, ib_msg, f);
if (fence)
*fence = dma_fence_get(f);
@ -588,27 +578,26 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
err_free:
amdgpu_job_free(job);
err:
amdgpu_bo_unreserve(bo);
amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg);
amdgpu_ib_free(adev, ib_msg, f);
return r;
}
static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct amdgpu_bo **bo)
struct amdgpu_ib *ib)
{
struct amdgpu_device *adev = ring->adev;
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);
memset(ib, 0, sizeof(*ib));
r = amdgpu_ib_get(adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2,
AMDGPU_IB_POOL_DIRECT,
ib);
if (r)
return r;
msg = (uint32_t *)AMDGPU_GPU_PAGE_ALIGN((unsigned long)ib->ptr);
msg[0] = cpu_to_le32(0x00000028);
msg[1] = cpu_to_le32(0x00000038);
msg[2] = cpu_to_le32(0x00000001);
@ -630,19 +619,20 @@ static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
}
static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
struct amdgpu_bo **bo)
struct amdgpu_ib *ib)
{
struct amdgpu_device *adev = ring->adev;
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);
memset(ib, 0, sizeof(*ib));
r = amdgpu_ib_get(adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2,
AMDGPU_IB_POOL_DIRECT,
ib);
if (r)
return r;
msg = (uint32_t *)AMDGPU_GPU_PAGE_ALIGN((unsigned long)ib->ptr);
msg[0] = cpu_to_le32(0x00000028);
msg[1] = cpu_to_le32(0x00000018);
msg[2] = cpu_to_le32(0x00000000);
@ -658,21 +648,21 @@ static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct dma_fence *fence = NULL;
struct amdgpu_bo *bo;
struct amdgpu_ib ib;
long r;
r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo);
r = amdgpu_vcn_dec_get_create_msg(ring, 1, &ib);
if (r)
goto error;
r = amdgpu_vcn_dec_send_msg(ring, bo, NULL);
r = amdgpu_vcn_dec_send_msg(ring, &ib, NULL);
if (r)
goto error;
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo);
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &ib);
if (r)
goto error;
r = amdgpu_vcn_dec_send_msg(ring, bo, &fence);
r = amdgpu_vcn_dec_send_msg(ring, &ib, &fence);
if (r)
goto error;
@ -688,8 +678,8 @@ error:
}
static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct dma_fence **fence)
struct amdgpu_ib *ib_msg,
struct dma_fence **fence)
{
struct amdgpu_vcn_decode_buffer *decode_buffer = NULL;
const unsigned int ib_size_dw = 64;
@ -697,7 +687,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
struct dma_fence *f = NULL;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
uint64_t addr;
uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
int i, r;
r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4,
@ -706,7 +696,6 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
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;
@ -726,9 +715,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
if (r)
goto err_free;
amdgpu_bo_fence(bo, f, false);
amdgpu_bo_unreserve(bo);
amdgpu_bo_unref(&bo);
amdgpu_ib_free(adev, ib_msg, f);
if (fence)
*fence = dma_fence_get(f);
@ -738,31 +725,29 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
err_free:
amdgpu_job_free(job);
err:
amdgpu_bo_unreserve(bo);
amdgpu_bo_unref(&bo);
amdgpu_ib_free(adev, ib_msg, f);
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;
struct amdgpu_ib ib;
long r;
r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo);
r = amdgpu_vcn_dec_get_create_msg(ring, 1, &ib);
if (r)
goto error;
r = amdgpu_vcn_dec_sw_send_msg(ring, bo, NULL);
r = amdgpu_vcn_dec_sw_send_msg(ring, &ib, NULL);
if (r)
goto error;
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo);
r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &ib);
if (r)
goto error;
r = amdgpu_vcn_dec_sw_send_msg(ring, bo, &fence);
r = amdgpu_vcn_dec_sw_send_msg(ring, &ib, &fence);
if (r)
goto error;
@ -809,7 +794,7 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
}
static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
struct amdgpu_bo *bo,
struct amdgpu_ib *ib_msg,
struct dma_fence **fence)
{
const unsigned ib_size_dw = 16;
@ -825,7 +810,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
return r;
ib = &job->ibs[0];
addr = amdgpu_bo_gpu_offset(bo);
addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
ib->length_dw = 0;
ib->ptr[ib->length_dw++] = 0x00000018;
@ -863,7 +848,7 @@ err:
}
static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
struct amdgpu_bo *bo,
struct amdgpu_ib *ib_msg,
struct dma_fence **fence)
{
const unsigned ib_size_dw = 16;
@ -879,7 +864,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
return r;
ib = &job->ibs[0];
addr = amdgpu_bo_gpu_offset(bo);
addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
ib->length_dw = 0;
ib->ptr[ib->length_dw++] = 0x00000018;
@ -918,21 +903,23 @@ err:
int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
{
struct amdgpu_device *adev = ring->adev;
struct dma_fence *fence = NULL;
struct amdgpu_bo *bo = NULL;
struct amdgpu_ib ib;
long r;
r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM,
&bo, NULL, NULL);
memset(&ib, 0, sizeof(ib));
r = amdgpu_ib_get(adev, NULL, (128 << 10) + AMDGPU_GPU_PAGE_SIZE,
AMDGPU_IB_POOL_DIRECT,
&ib);
if (r)
return r;
r = amdgpu_vcn_enc_get_create_msg(ring, 1, bo, NULL);
r = amdgpu_vcn_enc_get_create_msg(ring, 1, &ib, NULL);
if (r)
goto error;
r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, bo, &fence);
r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, &ib, &fence);
if (r)
goto error;
@ -943,9 +930,49 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
r = 0;
error:
amdgpu_ib_free(adev, &ib, fence);
dma_fence_put(fence);
amdgpu_bo_unreserve(bo);
amdgpu_bo_free_kernel(&bo, NULL, NULL);
return r;
}
enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
{
switch(ring) {
case 0:
return AMDGPU_RING_PRIO_0;
case 1:
return AMDGPU_RING_PRIO_1;
case 2:
return AMDGPU_RING_PRIO_2;
default:
return AMDGPU_RING_PRIO_0;
}
}
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
{
int i;
unsigned int idx;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
/* currently only support 2 FW instances */
if (i >= 2) {
dev_info(adev->dev, "More then 2 VCN FW instances!\n");
break;
}
idx = AMDGPU_UCODE_ID_VCN + i;
adev->firmware.ucode[idx].ucode_id = idx;
adev->firmware.ucode[idx].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
}
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
}

View File

@ -308,4 +308,8 @@ 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);
enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring);
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev);
#endif

View File

@ -532,9 +532,12 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ras.feature_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.xgmi.feature_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD,
adev->psp.asd_context.bin_desc.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS,
adev->psp.ras_context.context.bin_desc.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI,
adev->psp.xgmi_context.context.bin_desc.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version);
@ -581,6 +584,7 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
vf2pf_info->encode_usage = 0;
vf2pf_info->decode_usage = 0;
vf2pf_info->dummy_page_addr = (uint64_t)adev->dummy_page_addr;
vf2pf_info->checksum =
amd_sriov_msg_checksum(
vf2pf_info, vf2pf_info->header.size, 0, 0);

View File

@ -800,7 +800,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
struct amdgpu_bo *bo = &vmbo->bo;
unsigned entries, ats_entries;
uint64_t addr;
int r;
int r, idx;
/* Figure out our place in the hierarchy */
if (ancestor->parent) {
@ -845,9 +845,12 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
return r;
}
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return -ENODEV;
r = vm->update_funcs->map_table(vmbo);
if (r)
return r;
goto exit;
memset(&params, 0, sizeof(params));
params.adev = adev;
@ -856,7 +859,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
r = vm->update_funcs->prepare(&params, NULL, AMDGPU_SYNC_EXPLICIT);
if (r)
return r;
goto exit;
addr = 0;
if (ats_entries) {
@ -872,7 +875,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
r = vm->update_funcs->update(&params, vmbo, addr, 0, ats_entries,
value, flags);
if (r)
return r;
goto exit;
addr += ats_entries * 8;
}
@ -895,10 +898,13 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
r = vm->update_funcs->update(&params, vmbo, addr, 0, entries,
value, flags);
if (r)
return r;
goto exit;
}
return vm->update_funcs->commit(&params, NULL);
r = vm->update_funcs->commit(&params, NULL);
exit:
drm_dev_exit(idx);
return r;
}
/**
@ -1384,11 +1390,14 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
struct amdgpu_vm *vm, bool immediate)
{
struct amdgpu_vm_update_params params;
int r;
int r, idx;
if (list_empty(&vm->relocated))
return 0;
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return -ENODEV;
memset(&params, 0, sizeof(params));
params.adev = adev;
params.vm = vm;
@ -1396,7 +1405,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
r = vm->update_funcs->prepare(&params, NULL, AMDGPU_SYNC_EXPLICIT);
if (r)
return r;
goto exit;
while (!list_empty(&vm->relocated)) {
struct amdgpu_vm_bo_base *entry;
@ -1414,10 +1423,13 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
r = vm->update_funcs->commit(&params, &vm->last_update);
if (r)
goto error;
drm_dev_exit(idx);
return 0;
error:
amdgpu_vm_invalidate_pds(adev, vm);
exit:
drm_dev_exit(idx);
return r;
}
@ -1706,7 +1718,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
enum amdgpu_sync_mode sync_mode;
int r, idx;
if (!drm_dev_enter(&adev->ddev, &idx))
if (!drm_dev_enter(adev_to_drm(adev), &idx))
return -ENODEV;
memset(&params, 0, sizeof(params));

View File

@ -204,8 +204,10 @@ struct amd_sriov_msg_pf2vf_info {
} mm_bw_management[AMD_SRIOV_MSG_RESERVE_VCN_INST];
/* UUID info */
struct amd_sriov_msg_uuid_info uuid_info;
/* pcie atomic Ops info */
uint32_t pcie_atomic_ops_enabled_flags;
/* reserved */
uint32_t reserved[256 - 47];
uint32_t reserved[256 - 48];
};
struct amd_sriov_msg_vf2pf_info_header {
@ -259,9 +261,10 @@ struct amd_sriov_msg_vf2pf_info {
uint8_t id;
uint32_t version;
} ucode_info[AMD_SRIOV_MSG_RESERVE_UCODE];
uint64_t dummy_page_addr;
/* reserved */
uint32_t reserved[256-68];
uint32_t reserved[256-70];
};
/* mailbox message send from guest to host */

View File

@ -77,10 +77,9 @@ int athub_v2_0_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
switch (adev->asic_type) {
case CHIP_NAVI10:
case CHIP_NAVI14:
case CHIP_NAVI12:
switch (adev->ip_versions[ATHUB_HWIP][0]) {
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 2):
athub_v2_0_update_medium_grain_clock_gating(adev,
state == AMD_CG_STATE_GATE);
athub_v2_0_update_medium_grain_light_sleep(adev,

View File

@ -70,11 +70,10 @@ int athub_v2_1_set_clockgating(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
return 0;
switch (adev->asic_type) {
case CHIP_SIENNA_CICHLID:
case CHIP_NAVY_FLOUNDER:
case CHIP_DIMGREY_CAVEFISH:
case CHIP_BEIGE_GOBY:
switch (adev->ip_versions[ATHUB_HWIP][0]) {
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
case IP_VERSION(2, 1, 2):
athub_v2_1_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE);
athub_v2_1_update_medium_grain_light_sleep(adev, state == AMD_CG_STATE_GATE);
break;

View File

@ -1,54 +0,0 @@
/*
* 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 "amdgpu.h"
#include "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "beige_goby_ip_offset.h"
int beige_goby_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialize the block needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN0_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA2_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA3_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
}
return 0;
}

View File

@ -1,51 +0,0 @@
/*
* Copyright 2018 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 "amdgpu.h"
#include "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "cyan_skillfish_ip_offset.h"
int cyan_skillfish_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialized the blocke needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
}
return 0;
}

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