Merge 56d3375448 ("Merge tag 'drm-next-2021-11-03' of git://anongit.freedesktop.org/drm/drm") into android-mainline
Resolves conflicts in: drivers/gpu/drm/amd/display/include/dal_asic_id.h drivers/gpu/drm/i915/gem/i915_gem_context.c drivers/gpu/drm/i915/gt/intel_context.c Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I5412a9d724fed352e2cc6448be33366ffd914dcc
This commit is contained in:
@@ -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>,
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -17,6 +17,7 @@ properties:
|
||||
enum:
|
||||
- qcom,dsi-phy-14nm
|
||||
- qcom,dsi-phy-14nm-660
|
||||
- qcom,dsi-phy-14nm-8953
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
||||
@@ -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"
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
@@ -471,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
|
||||
================
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
-------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
---------------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+75
-87
@@ -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);
|
||||
@@ -206,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)
|
||||
@@ -229,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;
|
||||
@@ -291,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;
|
||||
}
|
||||
|
||||
@@ -566,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];
|
||||
|
||||
+185
-239
@@ -323,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
|
||||
@@ -332,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;
|
||||
}
|
||||
@@ -409,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);
|
||||
|
||||
@@ -523,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.
|
||||
@@ -627,43 +600,16 @@ static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence)
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 += \
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -3839,10 +3839,10 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_fbdev_fini(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
||||
amdgpu_device_ip_fini_early(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
||||
ttm_device_clear_dma_mappings(&adev->mman.bdev);
|
||||
|
||||
amdgpu_gart_dummy_page_fini(adev);
|
||||
@@ -3852,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;
|
||||
|
||||
@@ -108,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",
|
||||
@@ -505,6 +507,10 @@ 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;
|
||||
@@ -736,6 +742,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
|
||||
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):
|
||||
@@ -745,8 +752,6 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(3, 1, 3):
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
break;
|
||||
case IP_VERSION(2, 0, 3):
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -926,6 +931,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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);
|
||||
@@ -946,6 +952,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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);
|
||||
@@ -1004,6 +1011,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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);
|
||||
@@ -1013,6 +1021,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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;
|
||||
@@ -1025,6 +1034,13 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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);
|
||||
@@ -1034,6 +1050,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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);
|
||||
@@ -1044,6 +1061,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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);
|
||||
@@ -1053,6 +1074,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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:
|
||||
@@ -1120,10 +1142,13 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
break;
|
||||
case IP_VERSION(7, 4, 0):
|
||||
case IP_VERSION(7, 4, 1):
|
||||
case IP_VERSION(7, 4, 4):
|
||||
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):
|
||||
@@ -1134,12 +1159,15 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
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;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg_sc;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -878,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+)");
|
||||
|
||||
@@ -340,32 +340,32 @@ 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->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->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->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->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->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->ver = adev->psp.securedisplay_context.context.bin_desc.fw_version;
|
||||
fw_info->feature =
|
||||
adev->psp.securedisplay_context.context.bin_desc
|
||||
.feature_version;
|
||||
|
||||
@@ -65,7 +65,6 @@ static int psp_securedisplay_terminate(struct psp_context *psp);
|
||||
*
|
||||
* This new sequence is required for
|
||||
* - Arcturus and onwards
|
||||
* - Navi12 and onwards
|
||||
*/
|
||||
static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp)
|
||||
{
|
||||
@@ -77,7 +76,9 @@ static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp
|
||||
}
|
||||
|
||||
switch (adev->ip_versions[MP0_HWIP][0]) {
|
||||
case IP_VERSION(11, 0, 0):
|
||||
case IP_VERSION(11, 0, 4):
|
||||
case IP_VERSION(11, 0, 5):
|
||||
case IP_VERSION(11, 0, 7):
|
||||
case IP_VERSION(11, 0, 9):
|
||||
case IP_VERSION(11, 0, 11):
|
||||
@@ -1114,7 +1115,7 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
|
||||
static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
|
||||
{
|
||||
return psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
|
||||
psp->xgmi_context.context.bin_desc.feature_version >= 0x2000000b;
|
||||
psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1291,6 +1292,29 @@ static int psp_ras_unload(struct psp_context *psp)
|
||||
return psp_ta_unload(psp, &psp->ras_context.context);
|
||||
}
|
||||
|
||||
static void psp_ras_ta_check_status(struct psp_context *psp)
|
||||
{
|
||||
struct ta_ras_shared_memory *ras_cmd =
|
||||
(struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
|
||||
|
||||
switch (ras_cmd->ras_status) {
|
||||
case TA_RAS_STATUS__ERROR_UNSUPPORTED_IP:
|
||||
dev_warn(psp->adev->dev,
|
||||
"RAS WARNING: cmd failed due to unsupported ip\n");
|
||||
break;
|
||||
case TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ:
|
||||
dev_warn(psp->adev->dev,
|
||||
"RAS WARNING: cmd failed due to unsupported error injection\n");
|
||||
break;
|
||||
case TA_RAS_STATUS__SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_warn(psp->adev->dev,
|
||||
"RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
|
||||
{
|
||||
struct ta_ras_shared_memory *ras_cmd;
|
||||
@@ -1325,10 +1349,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
|
||||
dev_warn(psp->adev->dev,
|
||||
"RAS internal register access blocked\n");
|
||||
|
||||
if (ras_cmd->ras_status == TA_RAS_STATUS__ERROR_UNSUPPORTED_IP)
|
||||
dev_warn(psp->adev->dev, "RAS WARNING: cmd failed due to unsupported ip\n");
|
||||
else if (ras_cmd->ras_status)
|
||||
dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status);
|
||||
psp_ras_ta_check_status(psp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2622,6 +2643,12 @@ static int psp_resume(void *handle)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = psp_rl_load(adev);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "PSP load RL failed!\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
ret = psp_xgmi_initialize(psp, false, true);
|
||||
/* Warning the XGMI seesion initialize failure
|
||||
@@ -3081,32 +3108,32 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
|
||||
psp->asd_context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_XGMI:
|
||||
psp->xgmi_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->xgmi_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->xgmi_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->xgmi_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_RAS:
|
||||
psp->ras_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->ras_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->ras_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->ras_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_HDCP:
|
||||
psp->hdcp_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->hdcp_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->hdcp_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->hdcp_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_DTM:
|
||||
psp->dtm_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->dtm_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->dtm_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->dtm_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_RAP:
|
||||
psp->rap_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->rap_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->rap_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->rap_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_SECUREDISPLAY:
|
||||
psp->securedisplay_context.context.bin_desc.feature_version =
|
||||
psp->securedisplay_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(desc->fw_version);
|
||||
psp->securedisplay_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(desc->size_bytes);
|
||||
|
||||
@@ -112,7 +112,12 @@ static bool amdgpu_ras_check_bad_page_unlock(struct amdgpu_ras *con,
|
||||
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(void);
|
||||
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)
|
||||
@@ -2108,7 +2113,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
||||
#ifdef CONFIG_X86_MCE_AMD
|
||||
if ((adev->asic_type == CHIP_ALDEBARAN) &&
|
||||
(adev->gmc.xgmi.connected_to_cpu))
|
||||
amdgpu_register_bad_pages_mca_notifier();
|
||||
amdgpu_register_bad_pages_mca_notifier(adev);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -2605,24 +2610,18 @@ void amdgpu_release_ras_context(struct amdgpu_device *adev)
|
||||
#ifdef CONFIG_X86_MCE_AMD
|
||||
static struct amdgpu_device *find_adev(uint32_t node_id)
|
||||
{
|
||||
struct amdgpu_gpu_instance *gpu_instance;
|
||||
int i;
|
||||
struct amdgpu_device *adev = NULL;
|
||||
|
||||
mutex_lock(&mgpu_info.mutex);
|
||||
for (i = 0; i < mce_adev_list.num_gpu; i++) {
|
||||
adev = mce_adev_list.devs[i];
|
||||
|
||||
for (i = 0; i < mgpu_info.num_gpu; i++) {
|
||||
gpu_instance = &(mgpu_info.gpu_ins[i]);
|
||||
adev = gpu_instance->adev;
|
||||
|
||||
if (adev->gmc.xgmi.connected_to_cpu &&
|
||||
if (adev && adev->gmc.xgmi.connected_to_cpu &&
|
||||
adev->gmc.xgmi.physical_node_id == node_id)
|
||||
break;
|
||||
adev = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&mgpu_info.mutex);
|
||||
|
||||
return adev;
|
||||
}
|
||||
|
||||
@@ -2718,8 +2717,18 @@ static struct notifier_block amdgpu_bad_page_nb = {
|
||||
.priority = MCE_PRIO_UC,
|
||||
};
|
||||
|
||||
static void amdgpu_register_bad_pages_mca_notifier(void)
|
||||
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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
@@ -1119,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) {
|
||||
@@ -1128,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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1145,6 +1157,7 @@ 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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -509,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)
|
||||
|
||||
@@ -527,8 +527,8 @@ 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_context.bin_desc.fw_version);
|
||||
FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.feature_version);
|
||||
FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi_context.context.bin_desc.feature_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);
|
||||
|
||||
@@ -949,3 +949,30 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,4 +310,6 @@ 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
|
||||
|
||||
@@ -535,9 +535,9 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
|
||||
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.feature_version);
|
||||
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.feature_version);
|
||||
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);
|
||||
@@ -584,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);
|
||||
|
||||
@@ -261,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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -270,25 +270,6 @@ MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/cyan_skillfish2_rlc.bin");
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_0[] =
|
||||
{
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_INDEX, 0xffffffff, 0x00000000),
|
||||
/* TA_GRAD_ADJ_UCONFIG -> TA_GRAD_ADJ */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2544c382),
|
||||
/* VGT_TF_RING_SIZE_UMD -> VGT_TF_RING_SIZE */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2262c24e),
|
||||
/* VGT_HS_OFFCHIP_PARAM_UMD -> VGT_HS_OFFCHIP_PARAM */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226cc24f),
|
||||
/* VGT_TF_MEMORY_BASE_UMD -> VGT_TF_MEMORY_BASE */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226ec250),
|
||||
/* VGT_TF_MEMORY_BASE_HI_UMD -> VGT_TF_MEMORY_BASE_HI */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2278c261),
|
||||
/* VGT_ESGS_RING_SIZE_UMD -> VGT_ESGS_RING_SIZE */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2232c240),
|
||||
/* VGT_GSVS_RING_SIZE_UMD -> VGT_GSVS_RING_SIZE */
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2233c241),
|
||||
};
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_1[] =
|
||||
{
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014),
|
||||
@@ -3809,9 +3790,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_3_5));
|
||||
break;
|
||||
case IP_VERSION(10, 1, 3):
|
||||
soc15_program_register_sequence(adev,
|
||||
golden_settings_gc_10_0,
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_0));
|
||||
soc15_program_register_sequence(adev,
|
||||
golden_settings_gc_10_0_cyan_skillfish,
|
||||
(const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish));
|
||||
@@ -8238,8 +8216,9 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
|
||||
/* === CGCG + CGLS === */
|
||||
gfx_v10_0_update_coarse_grain_clock_gating(adev, enable);
|
||||
|
||||
if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 1, 10)) &&
|
||||
(adev->ip_versions[GC_HWIP][0] <= IP_VERSION(10, 1, 2)))
|
||||
if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 10)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 1)) ||
|
||||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2)))
|
||||
gfx_v10_0_apply_medium_grain_clock_gating_workaround(adev);
|
||||
} else {
|
||||
/* CGCG/CGLS should be disabled before MGCG/MGLS
|
||||
|
||||
@@ -706,6 +706,11 @@ int gfx_v9_4_2_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
return 0;
|
||||
|
||||
/* Workaround for ALDEBARAN, skip GPRs init in GPU reset.
|
||||
Will remove it once GPRs init algorithm works for all CU settings. */
|
||||
if (amdgpu_in_reset(adev))
|
||||
return 0;
|
||||
|
||||
gfx_v9_4_2_do_sgprs_init(adev);
|
||||
|
||||
gfx_v9_4_2_do_vgprs_init(adev);
|
||||
|
||||
@@ -841,12 +841,12 @@ static int gmc_v6_0_sw_init(void *handle)
|
||||
|
||||
adev->gmc.mc_mask = 0xffffffffffULL;
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
|
||||
if (r) {
|
||||
dev_warn(adev->dev, "No suitable DMA available.\n");
|
||||
return r;
|
||||
}
|
||||
adev->need_swiotlb = drm_need_swiotlb(44);
|
||||
adev->need_swiotlb = drm_need_swiotlb(40);
|
||||
|
||||
r = gmc_v6_0_init_microcode(adev);
|
||||
if (r) {
|
||||
|
||||
@@ -1,55 +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 "navi10_ip_offset.h"
|
||||
|
||||
int navi10_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int 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 *)(&(VCN_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[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
|
||||
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
|
||||
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +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 "navi12_ip_offset.h"
|
||||
|
||||
int navi12_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
/* HW has more IP blocks, only initialized the blocks 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 *)(&(NBIF0_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]));
|
||||
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
|
||||
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,53 +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 "navi14_ip_offset.h"
|
||||
|
||||
int navi14_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int 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 *)(&(NBIF0_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]));
|
||||
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
|
||||
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -53,6 +53,16 @@
|
||||
|
||||
#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
|
||||
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK 0x00001000L /* Don't use. Firmware uses this bit internally */
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK 0x00002000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK 0x00004000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK 0x00008000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK 0x00010000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK 0x00020000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK 0x00040000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK 0x00080000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK 0x00100000L
|
||||
|
||||
static void nbio_v2_3_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL,
|
||||
@@ -318,6 +328,27 @@ const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg = {
|
||||
.ref_and_mask_sdma1 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__SDMA1_MASK,
|
||||
};
|
||||
|
||||
const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg_sc = {
|
||||
.ref_and_mask_cp0 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP0_MASK,
|
||||
.ref_and_mask_cp1 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP1_MASK,
|
||||
.ref_and_mask_cp2 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP2_MASK,
|
||||
.ref_and_mask_cp3 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP3_MASK,
|
||||
.ref_and_mask_cp4 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP4_MASK,
|
||||
.ref_and_mask_cp5 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP5_MASK,
|
||||
.ref_and_mask_cp6 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP6_MASK,
|
||||
.ref_and_mask_cp7 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP7_MASK,
|
||||
.ref_and_mask_cp8 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP8_MASK,
|
||||
.ref_and_mask_cp9 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP9_MASK,
|
||||
.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK,
|
||||
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK,
|
||||
.ref_and_mask_sdma2 = GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK,
|
||||
.ref_and_mask_sdma3 = GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK,
|
||||
.ref_and_mask_sdma4 = GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK,
|
||||
.ref_and_mask_sdma5 = GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK,
|
||||
.ref_and_mask_sdma6 = GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK,
|
||||
.ref_and_mask_sdma7 = GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK,
|
||||
};
|
||||
|
||||
static void nbio_v2_3_init_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t def, data;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "soc15_common.h"
|
||||
|
||||
extern const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg;
|
||||
extern const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg_sc;
|
||||
extern const struct amdgpu_nbio_funcs nbio_v2_3_funcs;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,12 +56,15 @@
|
||||
* These are nbio v7_4_1 registers mask. Temporarily define these here since
|
||||
* nbio v7_4_1 header is incomplete.
|
||||
*/
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK 0x00001000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK 0x00001000L /* Don't use. Firmware uses this bit internally */
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK 0x00002000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK 0x00004000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK 0x00008000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK 0x00010000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK 0x00020000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK 0x00040000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK 0x00080000L
|
||||
#define GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK 0x00100000L
|
||||
|
||||
#define mmBIF_MMSCH1_DOORBELL_RANGE 0x01dc
|
||||
#define mmBIF_MMSCH1_DOORBELL_RANGE_BASE_IDX 2
|
||||
@@ -334,12 +337,27 @@ const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg = {
|
||||
.ref_and_mask_cp9 = GPU_HDP_FLUSH_DONE__CP9_MASK,
|
||||
.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__SDMA0_MASK,
|
||||
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__SDMA1_MASK,
|
||||
.ref_and_mask_sdma2 = GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK,
|
||||
.ref_and_mask_sdma3 = GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK,
|
||||
.ref_and_mask_sdma4 = GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK,
|
||||
.ref_and_mask_sdma5 = GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK,
|
||||
.ref_and_mask_sdma6 = GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK,
|
||||
.ref_and_mask_sdma7 = GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK,
|
||||
};
|
||||
|
||||
const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald = {
|
||||
.ref_and_mask_cp0 = GPU_HDP_FLUSH_DONE__CP0_MASK,
|
||||
.ref_and_mask_cp1 = GPU_HDP_FLUSH_DONE__CP1_MASK,
|
||||
.ref_and_mask_cp2 = GPU_HDP_FLUSH_DONE__CP2_MASK,
|
||||
.ref_and_mask_cp3 = GPU_HDP_FLUSH_DONE__CP3_MASK,
|
||||
.ref_and_mask_cp4 = GPU_HDP_FLUSH_DONE__CP4_MASK,
|
||||
.ref_and_mask_cp5 = GPU_HDP_FLUSH_DONE__CP5_MASK,
|
||||
.ref_and_mask_cp6 = GPU_HDP_FLUSH_DONE__CP6_MASK,
|
||||
.ref_and_mask_cp7 = GPU_HDP_FLUSH_DONE__CP7_MASK,
|
||||
.ref_and_mask_cp8 = GPU_HDP_FLUSH_DONE__CP8_MASK,
|
||||
.ref_and_mask_cp9 = GPU_HDP_FLUSH_DONE__CP9_MASK,
|
||||
.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK,
|
||||
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK,
|
||||
.ref_and_mask_sdma2 = GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK,
|
||||
.ref_and_mask_sdma3 = GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK,
|
||||
.ref_and_mask_sdma4 = GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK,
|
||||
.ref_and_mask_sdma5 = GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK,
|
||||
.ref_and_mask_sdma6 = GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK,
|
||||
.ref_and_mask_sdma7 = GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK,
|
||||
};
|
||||
|
||||
static void nbio_v7_4_init_registers(struct amdgpu_device *adev)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "soc15_common.h"
|
||||
|
||||
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg;
|
||||
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald;
|
||||
extern const struct amdgpu_nbio_funcs nbio_v7_4_funcs;
|
||||
extern const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs;
|
||||
|
||||
|
||||
@@ -607,304 +607,11 @@ const struct amdgpu_ip_block_version nv_common_ip_block =
|
||||
.funcs = &nv_common_ip_funcs,
|
||||
};
|
||||
|
||||
static int nv_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (amdgpu_discovery) {
|
||||
r = amdgpu_discovery_reg_base_init(adev);
|
||||
if (r) {
|
||||
DRM_WARN("failed to init reg base from ip discovery table, "
|
||||
"fallback to legacy init method\n");
|
||||
goto legacy_init;
|
||||
}
|
||||
|
||||
amdgpu_discovery_harvest_ip(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
legacy_init:
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
navi10_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_NAVI14:
|
||||
navi14_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_NAVI12:
|
||||
navi12_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
sienna_cichlid_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_VANGOGH:
|
||||
vangogh_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
dimgrey_cavefish_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_BEIGE_GOBY:
|
||||
beige_goby_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_YELLOW_CARP:
|
||||
yellow_carp_reg_base_init(adev);
|
||||
break;
|
||||
case CHIP_CYAN_SKILLFISH:
|
||||
cyan_skillfish_reg_base_init(adev);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv_set_virt_ops(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->virt.ops = &xgpu_nv_virt_ops;
|
||||
}
|
||||
|
||||
int nv_set_ip_blocks(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->asic_type == CHIP_CYAN_SKILLFISH) {
|
||||
adev->nbio.funcs = &nbio_v2_3_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
|
||||
} else if (adev->flags & AMD_IS_APU) {
|
||||
adev->nbio.funcs = &nbio_v7_2_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg;
|
||||
} else {
|
||||
adev->nbio.funcs = &nbio_v2_3_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
|
||||
}
|
||||
adev->hdp.funcs = &hdp_v5_0_funcs;
|
||||
|
||||
if (adev->asic_type >= CHIP_SIENNA_CICHLID)
|
||||
adev->smuio.funcs = &smuio_v11_0_6_funcs;
|
||||
else
|
||||
adev->smuio.funcs = &smuio_v11_0_funcs;
|
||||
|
||||
if (adev->asic_type == CHIP_SIENNA_CICHLID)
|
||||
adev->gmc.xgmi.supported = true;
|
||||
|
||||
/* Set IP register base before any HW register access */
|
||||
r = nv_reg_base_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
|
||||
!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
|
||||
!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
|
||||
if (adev->enable_mes)
|
||||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||
break;
|
||||
case CHIP_NAVI12:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
} else {
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
}
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
|
||||
!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
|
||||
break;
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
} else {
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
}
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
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);
|
||||
if (adev->enable_mes)
|
||||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||
break;
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
break;
|
||||
case CHIP_VANGOGH:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
|
||||
break;
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
|
||||
break;
|
||||
case CHIP_BEIGE_GOBY:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
|
||||
is_support_sw_smu(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
|
||||
break;
|
||||
case CHIP_YELLOW_CARP:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
|
||||
break;
|
||||
case CHIP_CYAN_SKILLFISH:
|
||||
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
|
||||
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_8_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
}
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t nv_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
return adev->nbio.funcs->get_rev_id(adev);
|
||||
|
||||
@@ -31,15 +31,5 @@ extern const struct amdgpu_ip_block_version nv_common_ip_block;
|
||||
void nv_grbm_select(struct amdgpu_device *adev,
|
||||
u32 me, u32 pipe, u32 queue, u32 vmid);
|
||||
void nv_set_virt_ops(struct amdgpu_device *adev);
|
||||
int nv_set_ip_blocks(struct amdgpu_device *adev);
|
||||
int navi10_reg_base_init(struct amdgpu_device *adev);
|
||||
int navi14_reg_base_init(struct amdgpu_device *adev);
|
||||
int navi12_reg_base_init(struct amdgpu_device *adev);
|
||||
int sienna_cichlid_reg_base_init(struct amdgpu_device *adev);
|
||||
void vangogh_reg_base_init(struct amdgpu_device *adev);
|
||||
int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev);
|
||||
int beige_goby_reg_base_init(struct amdgpu_device *adev);
|
||||
int yellow_carp_reg_base_init(struct amdgpu_device *adev);
|
||||
int cyan_skillfish_reg_base_init(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -84,7 +84,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)
|
||||
adev->psp.ta_fw->data;
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version =
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
@@ -92,7 +92,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
(uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version =
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
@@ -100,7 +100,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
(uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
|
||||
le32_to_cpu(ta_hdr->dtm.offset_bytes);
|
||||
|
||||
adev->psp.securedisplay_context.context.bin_desc.feature_version =
|
||||
adev->psp.securedisplay_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->securedisplay.fw_version);
|
||||
adev->psp.securedisplay_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->securedisplay.size_bytes);
|
||||
|
||||
@@ -151,7 +151,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
goto out2;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.xgmi_context.context.bin_desc.feature_version =
|
||||
adev->psp.xgmi_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->xgmi.fw_version);
|
||||
adev->psp.xgmi_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->xgmi.size_bytes);
|
||||
@@ -159,7 +159,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
(uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
adev->psp.ras_context.context.bin_desc.feature_version =
|
||||
adev->psp.ras_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->ras.fw_version);
|
||||
adev->psp.ras_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->ras.size_bytes);
|
||||
@@ -192,7 +192,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
goto out2;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version =
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
@@ -203,7 +203,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version =
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
|
||||
@@ -84,7 +84,7 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)
|
||||
adev->psp.ta_fw->data;
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version =
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
@@ -94,7 +94,7 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version =
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "nv.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
#include "soc15_hw_ip.h"
|
||||
#include "sienna_cichlid_ip_offset.h"
|
||||
|
||||
int sienna_cichlid_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 *)(&(VCN_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;
|
||||
}
|
||||
@@ -780,185 +780,6 @@ void soc15_set_virt_ops(struct amdgpu_device *adev)
|
||||
soc15_reg_base_init(adev);
|
||||
}
|
||||
|
||||
int soc15_set_ip_blocks(struct amdgpu_device *adev)
|
||||
{
|
||||
/* for bare metal case */
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
soc15_reg_base_init(adev);
|
||||
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
adev->nbio.funcs = &nbio_v7_0_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v7_0_hdp_flush_reg;
|
||||
} else if (adev->asic_type == CHIP_VEGA20 ||
|
||||
adev->asic_type == CHIP_ARCTURUS ||
|
||||
adev->asic_type == CHIP_ALDEBARAN) {
|
||||
adev->nbio.funcs = &nbio_v7_4_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg;
|
||||
} else {
|
||||
adev->nbio.funcs = &nbio_v6_1_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbio_v6_1_hdp_flush_reg;
|
||||
}
|
||||
adev->hdp.funcs = &hdp_v4_0_funcs;
|
||||
|
||||
if (adev->asic_type == CHIP_VEGA20 ||
|
||||
adev->asic_type == CHIP_ARCTURUS ||
|
||||
adev->asic_type == CHIP_ALDEBARAN)
|
||||
adev->df.funcs = &df_v3_6_funcs;
|
||||
else
|
||||
adev->df.funcs = &df_v1_7_funcs;
|
||||
|
||||
if (adev->asic_type == CHIP_VEGA20 ||
|
||||
adev->asic_type == CHIP_ARCTURUS)
|
||||
adev->smuio.funcs = &smuio_v11_0_funcs;
|
||||
else if (adev->asic_type == CHIP_ALDEBARAN)
|
||||
adev->smuio.funcs = &smuio_v13_0_funcs;
|
||||
else
|
||||
adev->smuio.funcs = &smuio_v9_0_funcs;
|
||||
|
||||
adev->rev_id = soc15_get_rev_id(adev);
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
|
||||
/* For Vega10 SR-IOV, PSP need to be initialized before IH */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
|
||||
if (adev->asic_type == CHIP_VEGA20)
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
|
||||
}
|
||||
if (adev->asic_type == CHIP_VEGA20)
|
||||
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
|
||||
} else {
|
||||
if (adev->asic_type == CHIP_VEGA20)
|
||||
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
|
||||
if (adev->asic_type == CHIP_VEGA20)
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
|
||||
}
|
||||
}
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
if (is_support_sw_smu(adev)) {
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
} else {
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
}
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
if (!(adev->asic_type == CHIP_VEGA20 && amdgpu_sriov_vf(adev))) {
|
||||
amdgpu_device_ip_block_add(adev, &uvd_v7_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vce_v4_0_ip_block);
|
||||
}
|
||||
break;
|
||||
case CHIP_RAVEN:
|
||||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block);
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
|
||||
} else {
|
||||
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
}
|
||||
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
|
||||
} else {
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
|
||||
}
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_5_ip_block);
|
||||
break;
|
||||
case CHIP_RENOIR:
|
||||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v12_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &smu_v12_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
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 (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
|
||||
break;
|
||||
case CHIP_ALDEBARAN:
|
||||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
|
||||
} else {
|
||||
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
|
||||
}
|
||||
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
|
||||
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_6_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_6_ip_block);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool soc15_need_full_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
/* change this when we implement soft reset */
|
||||
|
||||
@@ -102,7 +102,6 @@ struct soc15_ras_field_entry {
|
||||
void soc15_grbm_select(struct amdgpu_device *adev,
|
||||
u32 me, u32 pipe, u32 queue, u32 vmid);
|
||||
void soc15_set_virt_ops(struct amdgpu_device *adev);
|
||||
int soc15_set_ip_blocks(struct amdgpu_device *adev);
|
||||
|
||||
void soc15_program_register_sequence(struct amdgpu_device *adev,
|
||||
const struct soc15_reg_golden *registers,
|
||||
|
||||
@@ -59,7 +59,12 @@ enum ta_ras_status {
|
||||
TA_RAS_STATUS__ERROR_SYS_DRV_REG_ACCESS = 0xA011,
|
||||
TA_RAS_STATUS__ERROR_RAS_READ_WRITE = 0xA012,
|
||||
TA_RAS_STATUS__ERROR_NULL_PTR = 0xA013,
|
||||
TA_RAS_STATUS__ERROR_UNSUPPORTED_IP = 0xA014
|
||||
TA_RAS_STATUS__ERROR_UNSUPPORTED_IP = 0xA014,
|
||||
TA_RAS_STATUS__ERROR_PCS_STATE_QUIET = 0xA015,
|
||||
TA_RAS_STATUS__ERROR_PCS_STATE_ERROR = 0xA016,
|
||||
TA_RAS_STATUS__ERROR_PCS_STATE_HANG = 0xA017,
|
||||
TA_RAS_STATUS__ERROR_PCS_STATE_UNKNOWN = 0xA018,
|
||||
TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ = 0xA019
|
||||
};
|
||||
|
||||
enum ta_ras_block {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "nv.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
#include "soc15_hw_ip.h"
|
||||
#include "vangogh_ip_offset.h"
|
||||
|
||||
void vangogh_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 *)(&(VCN_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[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
|
||||
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
|
||||
}
|
||||
}
|
||||
@@ -111,15 +111,7 @@ static int vcn_v1_0_sw_init(void *handle)
|
||||
/* Override the work func */
|
||||
adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler;
|
||||
|
||||
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;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].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");
|
||||
}
|
||||
amdgpu_vcn_setup_ucode(adev);
|
||||
|
||||
r = amdgpu_vcn_resume(adev);
|
||||
if (r)
|
||||
|
||||
@@ -115,15 +115,7 @@ static int vcn_v2_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
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;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].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");
|
||||
}
|
||||
amdgpu_vcn_setup_ucode(adev);
|
||||
|
||||
r = amdgpu_vcn_resume(adev);
|
||||
if (r)
|
||||
@@ -1884,15 +1876,14 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev)
|
||||
|
||||
/* mc resume*/
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
tmp = AMDGPU_UCODE_ID_VCN;
|
||||
MMSCH_V2_0_INSERT_DIRECT_WT(
|
||||
SOC15_REG_OFFSET(UVD, i,
|
||||
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
|
||||
adev->firmware.ucode[tmp].tmr_mc_addr_lo);
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo);
|
||||
MMSCH_V2_0_INSERT_DIRECT_WT(
|
||||
SOC15_REG_OFFSET(UVD, i,
|
||||
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
|
||||
adev->firmware.ucode[tmp].tmr_mc_addr_hi);
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi);
|
||||
offset = 0;
|
||||
} else {
|
||||
MMSCH_V2_0_INSERT_DIRECT_WT(
|
||||
|
||||
@@ -139,22 +139,7 @@ static int vcn_v2_5_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
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;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
|
||||
|
||||
if (adev->vcn.num_vcn_inst == VCN25_MAX_HW_INSTANCES_ARCTURUS) {
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].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");
|
||||
}
|
||||
amdgpu_vcn_setup_ucode(adev);
|
||||
|
||||
r = amdgpu_vcn_resume(adev);
|
||||
if (r)
|
||||
|
||||
@@ -60,11 +60,6 @@ static int amdgpu_ih_clientid_vcns[] = {
|
||||
SOC15_IH_CLIENTID_VCN1
|
||||
};
|
||||
|
||||
static int amdgpu_ucode_id_vcns[] = {
|
||||
AMDGPU_UCODE_ID_VCN,
|
||||
AMDGPU_UCODE_ID_VCN1
|
||||
};
|
||||
|
||||
static int vcn_v3_0_start_sriov(struct amdgpu_device *adev);
|
||||
static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev);
|
||||
@@ -130,22 +125,7 @@ static int vcn_v3_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
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;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
|
||||
|
||||
if (adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) {
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].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");
|
||||
}
|
||||
amdgpu_vcn_setup_ucode(adev);
|
||||
|
||||
r = amdgpu_vcn_resume(adev);
|
||||
if (r)
|
||||
@@ -1293,7 +1273,6 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
|
||||
uint32_t param, resp, expected;
|
||||
uint32_t offset, cache_size;
|
||||
uint32_t tmp, timeout;
|
||||
uint32_t id;
|
||||
|
||||
struct amdgpu_mm_table *table = &adev->virt.mm_table;
|
||||
uint32_t *table_loc;
|
||||
@@ -1337,13 +1316,12 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
|
||||
cache_size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4);
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
id = amdgpu_ucode_id_vcns[i];
|
||||
MMSCH_V3_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
|
||||
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
|
||||
adev->firmware.ucode[id].tmr_mc_addr_lo);
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo);
|
||||
MMSCH_V3_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
|
||||
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
|
||||
adev->firmware.ucode[id].tmr_mc_addr_hi);
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi);
|
||||
offset = 0;
|
||||
MMSCH_V3_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
|
||||
mmUVD_VCPU_CACHE_OFFSET0),
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "nv.h"
|
||||
|
||||
#include "soc15_common.h"
|
||||
#include "soc15_hw_ip.h"
|
||||
#include "yellow_carp_offset.h"
|
||||
|
||||
int yellow_carp_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
/* HW has more IP blocks, only initialized 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 *)(&(VCN_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 *)(&(SDMA0_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;
|
||||
}
|
||||
@@ -405,7 +405,7 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
retval = pqm_update_queue(&p->pqm, args->queue_id, &properties);
|
||||
retval = pqm_update_queue_properties(&p->pqm, args->queue_id, &properties);
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
@@ -418,7 +418,7 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
|
||||
int retval;
|
||||
const int max_num_cus = 1024;
|
||||
struct kfd_ioctl_set_cu_mask_args *args = data;
|
||||
struct queue_properties properties;
|
||||
struct mqd_update_info minfo = {0};
|
||||
uint32_t __user *cu_mask_ptr = (uint32_t __user *)args->cu_mask_ptr;
|
||||
size_t cu_mask_size = sizeof(uint32_t) * (args->num_cu_mask / 32);
|
||||
|
||||
@@ -428,8 +428,8 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
properties.cu_mask_count = args->num_cu_mask;
|
||||
if (properties.cu_mask_count == 0) {
|
||||
minfo.cu_mask.count = args->num_cu_mask;
|
||||
if (minfo.cu_mask.count == 0) {
|
||||
pr_debug("CU mask cannot be 0");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -438,32 +438,33 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
|
||||
* limit of max_num_cus bits. We can then just drop any CU mask bits
|
||||
* past max_num_cus bits and just use the first max_num_cus bits.
|
||||
*/
|
||||
if (properties.cu_mask_count > max_num_cus) {
|
||||
if (minfo.cu_mask.count > max_num_cus) {
|
||||
pr_debug("CU mask cannot be greater than 1024 bits");
|
||||
properties.cu_mask_count = max_num_cus;
|
||||
minfo.cu_mask.count = max_num_cus;
|
||||
cu_mask_size = sizeof(uint32_t) * (max_num_cus/32);
|
||||
}
|
||||
|
||||
properties.cu_mask = kzalloc(cu_mask_size, GFP_KERNEL);
|
||||
if (!properties.cu_mask)
|
||||
minfo.cu_mask.ptr = kzalloc(cu_mask_size, GFP_KERNEL);
|
||||
if (!minfo.cu_mask.ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
retval = copy_from_user(properties.cu_mask, cu_mask_ptr, cu_mask_size);
|
||||
retval = copy_from_user(minfo.cu_mask.ptr, cu_mask_ptr, cu_mask_size);
|
||||
if (retval) {
|
||||
pr_debug("Could not copy CU mask from userspace");
|
||||
kfree(properties.cu_mask);
|
||||
return -EFAULT;
|
||||
retval = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
minfo.update_flag = UPDATE_FLAG_CU_MASK;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
retval = pqm_set_cu_mask(&p->pqm, args->queue_id, &properties);
|
||||
retval = pqm_update_mqd(&p->pqm, args->queue_id, &minfo);
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
if (retval)
|
||||
kfree(properties.cu_mask);
|
||||
|
||||
out:
|
||||
kfree(minfo.cu_mask.ptr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1011,11 +1012,6 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
|
||||
void *mem, *kern_addr;
|
||||
uint64_t size;
|
||||
|
||||
if (p->signal_page) {
|
||||
pr_err("Event page is already set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfd = kfd_device_by_id(GET_GPU_ID(args->event_page_offset));
|
||||
if (!kfd) {
|
||||
pr_err("Getting device by id failed in %s\n", __func__);
|
||||
@@ -1023,6 +1019,13 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
|
||||
}
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
if (p->signal_page) {
|
||||
pr_err("Event page is already set\n");
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
pdd = kfd_bind_process_to_device(kfd, p);
|
||||
if (IS_ERR(pdd)) {
|
||||
err = PTR_ERR(pdd);
|
||||
@@ -1037,20 +1040,24 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(kfd->kgd,
|
||||
mem, &kern_addr, &size);
|
||||
if (err) {
|
||||
pr_err("Failed to map event page to kernel\n");
|
||||
return err;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
err = kfd_event_page_set(p, kern_addr, size);
|
||||
if (err) {
|
||||
pr_err("Failed to set event page\n");
|
||||
return err;
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(kfd->kgd, mem);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
p->signal_handle = args->event_page_offset;
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
}
|
||||
|
||||
err = kfd_event_create(filp, p, args->event_type,
|
||||
@@ -1259,6 +1266,23 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
|
||||
if (args->size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
|
||||
/* Flush pending deferred work to avoid racing with deferred actions
|
||||
* from previous memory map changes (e.g. munmap).
|
||||
*/
|
||||
svm_range_list_lock_and_flush_work(&p->svms, current->mm);
|
||||
mutex_lock(&p->svms.lock);
|
||||
mmap_write_unlock(current->mm);
|
||||
if (interval_tree_iter_first(&p->svms.objects,
|
||||
args->va_addr >> PAGE_SHIFT,
|
||||
(args->va_addr + args->size - 1) >> PAGE_SHIFT)) {
|
||||
pr_err("Address: 0x%llx already allocated by SVM\n",
|
||||
args->va_addr);
|
||||
mutex_unlock(&p->svms.lock);
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
mutex_unlock(&p->svms.lock);
|
||||
#endif
|
||||
dev = kfd_device_by_id(args->gpu_id);
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
@@ -1351,6 +1375,15 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
/*
|
||||
* Safeguard to prevent user space from freeing signal BO.
|
||||
* It will be freed at process termination.
|
||||
*/
|
||||
if (p->signal_handle && (p->signal_handle == args->handle)) {
|
||||
pr_err("Free signal BO is not allowed\n");
|
||||
ret = -EPERM;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
pdd = kfd_get_process_device_data(dev, p);
|
||||
if (!pdd) {
|
||||
|
||||
@@ -93,7 +93,6 @@ static const struct kfd_device_info carrizo_device_info = {
|
||||
.num_xgmi_sdma_engines = 0,
|
||||
.num_sdma_queues_per_engine = 2,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct kfd_device_info raven_device_info = {
|
||||
.asic_family = CHIP_RAVEN,
|
||||
@@ -113,7 +112,9 @@ static const struct kfd_device_info raven_device_info = {
|
||||
.num_xgmi_sdma_engines = 0,
|
||||
.num_sdma_queues_per_engine = 2,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||
static const struct kfd_device_info hawaii_device_info = {
|
||||
.asic_family = CHIP_HAWAII,
|
||||
.asic_name = "hawaii",
|
||||
@@ -133,6 +134,7 @@ static const struct kfd_device_info hawaii_device_info = {
|
||||
.num_xgmi_sdma_engines = 0,
|
||||
.num_sdma_queues_per_engine = 2,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct kfd_device_info tonga_device_info = {
|
||||
.asic_family = CHIP_TONGA,
|
||||
@@ -1021,6 +1023,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
kfd_double_confirm_iommu_support(kfd);
|
||||
|
||||
if (kfd_iommu_device_init(kfd)) {
|
||||
kfd->use_iommu_v2 = false;
|
||||
dev_err(kfd_device, "Error initializing iommuv2\n");
|
||||
goto device_iommu_error;
|
||||
}
|
||||
@@ -1029,6 +1032,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
|
||||
svm_migrate_init((struct amdgpu_device *)kfd->kgd);
|
||||
|
||||
if(kgd2kfd_resume_iommu(kfd))
|
||||
goto device_iommu_error;
|
||||
|
||||
if (kfd_resume(kfd))
|
||||
goto kfd_resume_error;
|
||||
|
||||
|
||||
@@ -557,7 +557,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int update_queue(struct device_queue_manager *dqm, struct queue *q)
|
||||
static int update_queue(struct device_queue_manager *dqm, struct queue *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
int retval = 0;
|
||||
struct mqd_manager *mqd_mgr;
|
||||
@@ -605,7 +606,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
|
||||
}
|
||||
}
|
||||
|
||||
mqd_mgr->update_mqd(mqd_mgr, q->mqd, &q->properties);
|
||||
mqd_mgr->update_mqd(mqd_mgr, q->mqd, &q->properties, minfo);
|
||||
|
||||
/*
|
||||
* check active state vs. the previous state and modify
|
||||
|
||||
@@ -93,7 +93,7 @@ struct device_queue_manager_ops {
|
||||
struct queue *q);
|
||||
|
||||
int (*update_queue)(struct device_queue_manager *dqm,
|
||||
struct queue *q);
|
||||
struct queue *q, struct mqd_update_info *minfo);
|
||||
|
||||
int (*register_process)(struct device_queue_manager *dqm,
|
||||
struct qcm_process_device *qpd);
|
||||
|
||||
@@ -136,7 +136,6 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
prop.write_ptr = (uint32_t *) kq->wptr_gpu_addr;
|
||||
prop.eop_ring_buffer_address = kq->eop_gpu_addr;
|
||||
prop.eop_ring_buffer_size = PAGE_SIZE;
|
||||
prop.cu_mask = NULL;
|
||||
|
||||
if (init_queue(&kq->queue, &prop) != 0)
|
||||
goto err_init_queue;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/hmm.h>
|
||||
#include <linux/dma-direction.h>
|
||||
@@ -34,6 +33,11 @@
|
||||
#include "kfd_svm.h"
|
||||
#include "kfd_migrate.h"
|
||||
|
||||
#ifdef dev_fmt
|
||||
#undef dev_fmt
|
||||
#endif
|
||||
#define dev_fmt(fmt) "kfd_migrate: %s: " fmt, __func__
|
||||
|
||||
static uint64_t
|
||||
svm_migrate_direct_mapping_addr(struct amdgpu_device *adev, uint64_t addr)
|
||||
{
|
||||
@@ -151,14 +155,14 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys,
|
||||
gart_d = svm_migrate_direct_mapping_addr(adev, *vram);
|
||||
}
|
||||
if (r) {
|
||||
pr_debug("failed %d to create gart mapping\n", r);
|
||||
dev_err(adev->dev, "fail %d create gart mapping\n", r);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
r = amdgpu_copy_buffer(ring, gart_s, gart_d, size * PAGE_SIZE,
|
||||
NULL, &next, false, true, false);
|
||||
if (r) {
|
||||
pr_debug("failed %d to copy memory\n", r);
|
||||
dev_err(adev->dev, "fail %d to copy memory\n", r);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
@@ -264,6 +268,19 @@ static void svm_migrate_put_sys_page(unsigned long addr)
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
static unsigned long svm_migrate_successful_pages(struct migrate_vma *migrate)
|
||||
{
|
||||
unsigned long cpages = 0;
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < migrate->npages; i++) {
|
||||
if (migrate->src[i] & MIGRATE_PFN_VALID &&
|
||||
migrate->src[i] & MIGRATE_PFN_MIGRATE)
|
||||
cpages++;
|
||||
}
|
||||
return cpages;
|
||||
}
|
||||
|
||||
static int
|
||||
svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
struct migrate_vma *migrate, struct dma_fence **mfence,
|
||||
@@ -285,7 +302,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
|
||||
r = svm_range_vram_node_new(adev, prange, true);
|
||||
if (r) {
|
||||
pr_debug("failed %d get 0x%llx pages from vram\n", r, npages);
|
||||
dev_err(adev->dev, "fail %d to alloc vram\n", r);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -305,7 +322,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
DMA_TO_DEVICE);
|
||||
r = dma_mapping_error(dev, src[i]);
|
||||
if (r) {
|
||||
pr_debug("failed %d dma_map_page\n", r);
|
||||
dev_err(adev->dev, "fail %d dma_map_page\n", r);
|
||||
goto out_free_vram_pages;
|
||||
}
|
||||
} else {
|
||||
@@ -325,8 +342,8 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
continue;
|
||||
}
|
||||
|
||||
pr_debug("dma mapping src to 0x%llx, page_to_pfn 0x%lx\n",
|
||||
src[i] >> PAGE_SHIFT, page_to_pfn(spage));
|
||||
pr_debug_ratelimited("dma mapping src to 0x%llx, pfn 0x%lx\n",
|
||||
src[i] >> PAGE_SHIFT, page_to_pfn(spage));
|
||||
|
||||
if (j >= (cursor.size >> PAGE_SHIFT) - 1 && i < npages - 1) {
|
||||
r = svm_migrate_copy_memory_gart(adev, src + i - j,
|
||||
@@ -372,7 +389,7 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
static long
|
||||
svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
struct vm_area_struct *vma, uint64_t start,
|
||||
uint64_t end)
|
||||
@@ -381,6 +398,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
struct kfd_process_device *pdd;
|
||||
struct dma_fence *mfence = NULL;
|
||||
struct migrate_vma migrate;
|
||||
unsigned long cpages = 0;
|
||||
dma_addr_t *scratch;
|
||||
size_t size;
|
||||
void *buf;
|
||||
@@ -405,23 +423,31 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
|
||||
r = migrate_vma_setup(&migrate);
|
||||
if (r) {
|
||||
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
|
||||
r, prange->svms, prange->start, prange->last);
|
||||
dev_err(adev->dev, "vma setup fail %d range [0x%lx 0x%lx]\n", r,
|
||||
prange->start, prange->last);
|
||||
goto out_free;
|
||||
}
|
||||
if (migrate.cpages != npages) {
|
||||
pr_debug("Partial migration. 0x%lx/0x%llx pages can be migrated\n",
|
||||
migrate.cpages,
|
||||
npages);
|
||||
}
|
||||
|
||||
if (migrate.cpages) {
|
||||
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence,
|
||||
scratch);
|
||||
migrate_vma_pages(&migrate);
|
||||
svm_migrate_copy_done(adev, mfence);
|
||||
migrate_vma_finalize(&migrate);
|
||||
cpages = migrate.cpages;
|
||||
if (!cpages) {
|
||||
pr_debug("failed collect migrate sys pages [0x%lx 0x%lx]\n",
|
||||
prange->start, prange->last);
|
||||
goto out_free;
|
||||
}
|
||||
if (cpages != npages)
|
||||
pr_debug("partial migration, 0x%lx/0x%llx pages migrated\n",
|
||||
cpages, npages);
|
||||
else
|
||||
pr_debug("0x%lx pages migrated\n", cpages);
|
||||
|
||||
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch);
|
||||
migrate_vma_pages(&migrate);
|
||||
|
||||
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
|
||||
svm_migrate_successful_pages(&migrate), cpages, migrate.npages);
|
||||
|
||||
svm_migrate_copy_done(adev, mfence);
|
||||
migrate_vma_finalize(&migrate);
|
||||
|
||||
svm_range_dma_unmap(adev->dev, scratch, 0, npages);
|
||||
svm_range_free_dma_mappings(prange);
|
||||
@@ -429,12 +455,13 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
out_free:
|
||||
kvfree(buf);
|
||||
out:
|
||||
if (!r) {
|
||||
if (!r && cpages) {
|
||||
pdd = svm_range_get_pdd_by_adev(prange, adev);
|
||||
if (pdd)
|
||||
WRITE_ONCE(pdd->page_in, pdd->page_in + migrate.cpages);
|
||||
}
|
||||
WRITE_ONCE(pdd->page_in, pdd->page_in + cpages);
|
||||
|
||||
return cpages;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -456,7 +483,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
||||
unsigned long addr, start, end;
|
||||
struct vm_area_struct *vma;
|
||||
struct amdgpu_device *adev;
|
||||
int r = 0;
|
||||
unsigned long cpages = 0;
|
||||
long r = 0;
|
||||
|
||||
if (prange->actual_loc == best_loc) {
|
||||
pr_debug("svms 0x%p [0x%lx 0x%lx] already on best_loc 0x%x\n",
|
||||
@@ -488,17 +516,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
||||
|
||||
next = min(vma->vm_end, end);
|
||||
r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next);
|
||||
if (r) {
|
||||
pr_debug("failed to migrate\n");
|
||||
if (r < 0) {
|
||||
pr_debug("failed %ld to migrate\n", r);
|
||||
break;
|
||||
} else {
|
||||
cpages += r;
|
||||
}
|
||||
addr = next;
|
||||
}
|
||||
|
||||
if (!r)
|
||||
if (cpages)
|
||||
prange->actual_loc = best_loc;
|
||||
|
||||
return r;
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
||||
static void svm_migrate_page_free(struct page *page)
|
||||
@@ -506,7 +536,7 @@ static void svm_migrate_page_free(struct page *page)
|
||||
struct svm_range_bo *svm_bo = page->zone_device_data;
|
||||
|
||||
if (svm_bo) {
|
||||
pr_debug("svm_bo ref left: %d\n", kref_read(&svm_bo->kref));
|
||||
pr_debug_ratelimited("ref: %d\n", kref_read(&svm_bo->kref));
|
||||
svm_range_bo_unref(svm_bo);
|
||||
}
|
||||
}
|
||||
@@ -572,12 +602,12 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
r = dma_mapping_error(dev, dst[i]);
|
||||
if (r) {
|
||||
pr_debug("failed %d dma_map_page\n", r);
|
||||
dev_err(adev->dev, "fail %d dma_map_page\n", r);
|
||||
goto out_oom;
|
||||
}
|
||||
|
||||
pr_debug("dma mapping dst to 0x%llx, page_to_pfn 0x%lx\n",
|
||||
dst[i] >> PAGE_SHIFT, page_to_pfn(dpage));
|
||||
pr_debug_ratelimited("dma mapping dst to 0x%llx, pfn 0x%lx\n",
|
||||
dst[i] >> PAGE_SHIFT, page_to_pfn(dpage));
|
||||
|
||||
migrate->dst[i] = migrate_pfn(page_to_pfn(dpage));
|
||||
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
|
||||
@@ -599,7 +629,7 @@ out_oom:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
static long
|
||||
svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
struct vm_area_struct *vma, uint64_t start, uint64_t end)
|
||||
{
|
||||
@@ -607,6 +637,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
struct kfd_process_device *pdd;
|
||||
struct dma_fence *mfence = NULL;
|
||||
struct migrate_vma migrate;
|
||||
unsigned long cpages = 0;
|
||||
dma_addr_t *scratch;
|
||||
size_t size;
|
||||
void *buf;
|
||||
@@ -631,34 +662,43 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
|
||||
r = migrate_vma_setup(&migrate);
|
||||
if (r) {
|
||||
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
|
||||
r, prange->svms, prange->start, prange->last);
|
||||
dev_err(adev->dev, "vma setup fail %d range [0x%lx 0x%lx]\n", r,
|
||||
prange->start, prange->last);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
pr_debug("cpages %ld\n", migrate.cpages);
|
||||
|
||||
if (migrate.cpages) {
|
||||
r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence,
|
||||
scratch, npages);
|
||||
migrate_vma_pages(&migrate);
|
||||
svm_migrate_copy_done(adev, mfence);
|
||||
migrate_vma_finalize(&migrate);
|
||||
} else {
|
||||
cpages = migrate.cpages;
|
||||
if (!cpages) {
|
||||
pr_debug("failed collect migrate device pages [0x%lx 0x%lx]\n",
|
||||
prange->start, prange->last);
|
||||
goto out_free;
|
||||
}
|
||||
if (cpages != npages)
|
||||
pr_debug("partial migration, 0x%lx/0x%llx pages migrated\n",
|
||||
cpages, npages);
|
||||
else
|
||||
pr_debug("0x%lx pages migrated\n", cpages);
|
||||
|
||||
r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence,
|
||||
scratch, npages);
|
||||
migrate_vma_pages(&migrate);
|
||||
|
||||
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
|
||||
svm_migrate_successful_pages(&migrate), cpages, migrate.npages);
|
||||
|
||||
svm_migrate_copy_done(adev, mfence);
|
||||
migrate_vma_finalize(&migrate);
|
||||
svm_range_dma_unmap(adev->dev, scratch, 0, npages);
|
||||
|
||||
out_free:
|
||||
kvfree(buf);
|
||||
out:
|
||||
if (!r) {
|
||||
if (!r && cpages) {
|
||||
pdd = svm_range_get_pdd_by_adev(prange, adev);
|
||||
if (pdd)
|
||||
WRITE_ONCE(pdd->page_out,
|
||||
pdd->page_out + migrate.cpages);
|
||||
WRITE_ONCE(pdd->page_out, pdd->page_out + cpages);
|
||||
|
||||
return cpages;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -680,7 +720,8 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm)
|
||||
unsigned long addr;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
int r = 0;
|
||||
unsigned long cpages = 0;
|
||||
long r = 0;
|
||||
|
||||
if (!prange->actual_loc) {
|
||||
pr_debug("[0x%lx 0x%lx] already migrated to ram\n",
|
||||
@@ -711,18 +752,21 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm)
|
||||
|
||||
next = min(vma->vm_end, end);
|
||||
r = svm_migrate_vma_to_ram(adev, prange, vma, addr, next);
|
||||
if (r) {
|
||||
pr_debug("failed %d to migrate\n", r);
|
||||
if (r < 0) {
|
||||
pr_debug("failed %ld to migrate\n", r);
|
||||
break;
|
||||
} else {
|
||||
cpages += r;
|
||||
}
|
||||
addr = next;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
if (cpages) {
|
||||
svm_range_vram_node_free(prange);
|
||||
prange->actual_loc = 0;
|
||||
}
|
||||
return r;
|
||||
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,7 +80,8 @@ struct mqd_manager {
|
||||
struct mm_struct *mms);
|
||||
|
||||
void (*update_mqd)(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q);
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo);
|
||||
|
||||
int (*destroy_mqd)(struct mqd_manager *mm, void *mqd,
|
||||
enum kfd_preempt_type type,
|
||||
|
||||
@@ -42,16 +42,17 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@@ -135,7 +136,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
@@ -152,7 +153,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static void free_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@@ -185,7 +186,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q, unsigned int atc_bit)
|
||||
struct queue_properties *q, struct mqd_update_info *minfo,
|
||||
unsigned int atc_bit)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
|
||||
@@ -214,16 +216,17 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
if (q->format == KFD_QUEUE_FORMAT_AQL)
|
||||
m->cp_hqd_pq_control |= NO_UPDATE_RPTR;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
}
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, 1);
|
||||
__update_mqd(mm, mqd, q, minfo, 1);
|
||||
}
|
||||
|
||||
static uint32_t read_doorbell_id(void *mqd)
|
||||
@@ -234,13 +237,15 @@ static uint32_t read_doorbell_id(void *mqd)
|
||||
}
|
||||
|
||||
static void update_mqd_hawaii(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, 0);
|
||||
__update_mqd(mm, mqd, q, minfo, 0);
|
||||
}
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct cik_sdma_rlc_registers *m;
|
||||
|
||||
@@ -318,7 +323,8 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
}
|
||||
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
|
||||
|
||||
@@ -42,16 +42,17 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@@ -136,7 +137,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@@ -162,7 +163,8 @@ static int hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
|
||||
@@ -218,7 +220,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
if (mm->dev->cwsr_enabled)
|
||||
m->cp_hqd_ctx_save_control = 0;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
@@ -311,7 +313,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
@@ -326,7 +328,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
#define SDMA_RLC_DUMMY_DEFAULT 0xf
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v10_sdma_mqd *m;
|
||||
|
||||
|
||||
@@ -43,16 +43,17 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
uint32_t se_mask[KFD_MAX_NUM_SE] = {0};
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@@ -188,7 +189,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@@ -212,7 +213,8 @@ static int hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
|
||||
@@ -269,7 +271,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
if (mm->dev->cwsr_enabled && q->ctx_save_restore_area_address)
|
||||
m->cp_hqd_ctx_save_control = 0;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
@@ -366,7 +368,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
@@ -381,7 +383,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
#define SDMA_RLC_DUMMY_DEFAULT 0xf
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v9_sdma_mqd *m;
|
||||
|
||||
|
||||
@@ -45,16 +45,17 @@ static inline struct vi_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct vi_mqd *m;
|
||||
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@@ -150,7 +151,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@@ -167,8 +168,8 @@ static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q, unsigned int mtype,
|
||||
unsigned int atc_bit)
|
||||
struct queue_properties *q, struct mqd_update_info *minfo,
|
||||
unsigned int mtype, unsigned int atc_bit)
|
||||
{
|
||||
struct vi_mqd *m;
|
||||
|
||||
@@ -230,7 +231,7 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
atc_bit << CP_HQD_CTX_SAVE_CONTROL__ATC__SHIFT |
|
||||
mtype << CP_HQD_CTX_SAVE_CONTROL__MTYPE__SHIFT;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
@@ -238,9 +239,10 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, MTYPE_CC, 1);
|
||||
__update_mqd(mm, mqd, q, minfo, MTYPE_CC, 1);
|
||||
}
|
||||
|
||||
static uint32_t read_doorbell_id(void *mqd)
|
||||
@@ -251,9 +253,10 @@ static uint32_t read_doorbell_id(void *mqd)
|
||||
}
|
||||
|
||||
static void update_mqd_tonga(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, MTYPE_UC, 0);
|
||||
__update_mqd(mm, mqd, q, minfo, MTYPE_UC, 0);
|
||||
}
|
||||
|
||||
static int destroy_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@@ -317,9 +320,10 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
}
|
||||
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, MTYPE_UC, 0);
|
||||
__update_mqd(mm, mqd, q, minfo, MTYPE_UC, 0);
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
@@ -336,7 +340,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
@@ -349,7 +353,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct vi_sdma_mqd *m;
|
||||
|
||||
|
||||
@@ -472,9 +472,6 @@ struct queue_properties {
|
||||
uint32_t ctl_stack_size;
|
||||
uint64_t tba_addr;
|
||||
uint64_t tma_addr;
|
||||
/* Relevant for CU */
|
||||
uint32_t cu_mask_count; /* Must be a multiple of 32 */
|
||||
uint32_t *cu_mask;
|
||||
};
|
||||
|
||||
#define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 && \
|
||||
@@ -482,6 +479,20 @@ struct queue_properties {
|
||||
(q).queue_percent > 0 && \
|
||||
!(q).is_evicted)
|
||||
|
||||
enum mqd_update_flag {
|
||||
UPDATE_FLAG_CU_MASK = 0,
|
||||
};
|
||||
|
||||
struct mqd_update_info {
|
||||
union {
|
||||
struct {
|
||||
uint32_t count; /* Must be a multiple of 32 */
|
||||
uint32_t *ptr;
|
||||
} cu_mask;
|
||||
};
|
||||
enum mqd_update_flag update_flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct queue
|
||||
*
|
||||
@@ -608,12 +619,14 @@ struct qcm_process_device {
|
||||
uint32_t sh_hidden_private_base;
|
||||
|
||||
/* CWSR memory */
|
||||
struct kgd_mem *cwsr_mem;
|
||||
void *cwsr_kaddr;
|
||||
uint64_t cwsr_base;
|
||||
uint64_t tba_addr;
|
||||
uint64_t tma_addr;
|
||||
|
||||
/* IB memory */
|
||||
struct kgd_mem *ib_mem;
|
||||
uint64_t ib_base;
|
||||
void *ib_kaddr;
|
||||
|
||||
@@ -808,6 +821,7 @@ struct kfd_process {
|
||||
/* Event ID allocator and lookup */
|
||||
struct idr event_idr;
|
||||
/* Event page */
|
||||
u64 signal_handle;
|
||||
struct kfd_signal_page *signal_page;
|
||||
size_t signal_mapped_size;
|
||||
size_t signal_event_count;
|
||||
@@ -1031,10 +1045,10 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
unsigned int *qid,
|
||||
uint32_t *p_doorbell_offset_in_process);
|
||||
int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid);
|
||||
int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p);
|
||||
int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid,
|
||||
int pqm_update_queue_properties(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p);
|
||||
int pqm_update_mqd(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct mqd_update_info *minfo);
|
||||
int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
|
||||
void *gws);
|
||||
struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm,
|
||||
|
||||
@@ -72,6 +72,8 @@ static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep);
|
||||
static void evict_process_worker(struct work_struct *work);
|
||||
static void restore_process_worker(struct work_struct *work);
|
||||
|
||||
static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd);
|
||||
|
||||
struct kfd_procfs_tree {
|
||||
struct kobject *kobj;
|
||||
};
|
||||
@@ -685,10 +687,15 @@ void kfd_process_destroy_wq(void)
|
||||
}
|
||||
|
||||
static void kfd_process_free_gpuvm(struct kgd_mem *mem,
|
||||
struct kfd_process_device *pdd)
|
||||
struct kfd_process_device *pdd, void *kptr)
|
||||
{
|
||||
struct kfd_dev *dev = pdd->dev;
|
||||
|
||||
if (kptr) {
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(dev->kgd, mem);
|
||||
kptr = NULL;
|
||||
}
|
||||
|
||||
amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(dev->kgd, mem, pdd->drm_priv);
|
||||
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->kgd, mem, pdd->drm_priv,
|
||||
NULL);
|
||||
@@ -702,63 +709,46 @@ static void kfd_process_free_gpuvm(struct kgd_mem *mem,
|
||||
*/
|
||||
static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
|
||||
uint64_t gpu_va, uint32_t size,
|
||||
uint32_t flags, void **kptr)
|
||||
uint32_t flags, struct kgd_mem **mem, void **kptr)
|
||||
{
|
||||
struct kfd_dev *kdev = pdd->dev;
|
||||
struct kgd_mem *mem = NULL;
|
||||
int handle;
|
||||
int err;
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(kdev->kgd, gpu_va, size,
|
||||
pdd->drm_priv, &mem, NULL, flags);
|
||||
pdd->drm_priv, mem, NULL, flags);
|
||||
if (err)
|
||||
goto err_alloc_mem;
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem,
|
||||
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, *mem,
|
||||
pdd->drm_priv, NULL);
|
||||
if (err)
|
||||
goto err_map_mem;
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_sync_memory(kdev->kgd, mem, true);
|
||||
err = amdgpu_amdkfd_gpuvm_sync_memory(kdev->kgd, *mem, true);
|
||||
if (err) {
|
||||
pr_debug("Sync memory failed, wait interrupted by user signal\n");
|
||||
goto sync_memory_failed;
|
||||
}
|
||||
|
||||
/* Create an obj handle so kfd_process_device_remove_obj_handle
|
||||
* will take care of the bo removal when the process finishes.
|
||||
* We do not need to take p->mutex, because the process is just
|
||||
* created and the ioctls have not had the chance to run.
|
||||
*/
|
||||
handle = kfd_process_device_create_obj_handle(pdd, mem);
|
||||
|
||||
if (handle < 0) {
|
||||
err = handle;
|
||||
goto free_gpuvm;
|
||||
}
|
||||
|
||||
if (kptr) {
|
||||
err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(kdev->kgd,
|
||||
(struct kgd_mem *)mem, kptr, NULL);
|
||||
(struct kgd_mem *)*mem, kptr, NULL);
|
||||
if (err) {
|
||||
pr_debug("Map GTT BO to kernel failed\n");
|
||||
goto free_obj_handle;
|
||||
goto sync_memory_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
free_obj_handle:
|
||||
kfd_process_device_remove_obj_handle(pdd, handle);
|
||||
free_gpuvm:
|
||||
sync_memory_failed:
|
||||
kfd_process_free_gpuvm(mem, pdd);
|
||||
return err;
|
||||
amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(kdev->kgd, *mem, pdd->drm_priv);
|
||||
|
||||
err_map_mem:
|
||||
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(kdev->kgd, mem, pdd->drm_priv,
|
||||
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(kdev->kgd, *mem, pdd->drm_priv,
|
||||
NULL);
|
||||
err_alloc_mem:
|
||||
*mem = NULL;
|
||||
*kptr = NULL;
|
||||
return err;
|
||||
}
|
||||
@@ -776,6 +766,7 @@ static int kfd_process_device_reserve_ib_mem(struct kfd_process_device *pdd)
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
|
||||
struct kgd_mem *mem;
|
||||
void *kaddr;
|
||||
int ret;
|
||||
|
||||
@@ -784,15 +775,26 @@ static int kfd_process_device_reserve_ib_mem(struct kfd_process_device *pdd)
|
||||
|
||||
/* ib_base is only set for dGPU */
|
||||
ret = kfd_process_alloc_gpuvm(pdd, qpd->ib_base, PAGE_SIZE, flags,
|
||||
&kaddr);
|
||||
&mem, &kaddr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
qpd->ib_mem = mem;
|
||||
qpd->ib_kaddr = kaddr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kfd_process_device_destroy_ib_mem(struct kfd_process_device *pdd)
|
||||
{
|
||||
struct qcm_process_device *qpd = &pdd->qpd;
|
||||
|
||||
if (!qpd->ib_kaddr || !qpd->ib_base)
|
||||
return;
|
||||
|
||||
kfd_process_free_gpuvm(qpd->ib_mem, pdd, qpd->ib_kaddr);
|
||||
}
|
||||
|
||||
struct kfd_process *kfd_create_process(struct file *filep)
|
||||
{
|
||||
struct kfd_process *process;
|
||||
@@ -947,6 +949,37 @@ static void kfd_process_device_free_bos(struct kfd_process_device *pdd)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Just kunmap and unpin signal BO here. It will be freed in
|
||||
* kfd_process_free_outstanding_kfd_bos()
|
||||
*/
|
||||
static void kfd_process_kunmap_signal_bo(struct kfd_process *p)
|
||||
{
|
||||
struct kfd_process_device *pdd;
|
||||
struct kfd_dev *kdev;
|
||||
void *mem;
|
||||
|
||||
kdev = kfd_device_by_id(GET_GPU_ID(p->signal_handle));
|
||||
if (!kdev)
|
||||
return;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
pdd = kfd_get_process_device_data(kdev, p);
|
||||
if (!pdd)
|
||||
goto out;
|
||||
|
||||
mem = kfd_process_device_translate_handle(
|
||||
pdd, GET_IDR_HANDLE(p->signal_handle));
|
||||
if (!mem)
|
||||
goto out;
|
||||
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(kdev->kgd, mem);
|
||||
|
||||
out:
|
||||
mutex_unlock(&p->mutex);
|
||||
}
|
||||
|
||||
static void kfd_process_free_outstanding_kfd_bos(struct kfd_process *p)
|
||||
{
|
||||
int i;
|
||||
@@ -965,6 +998,9 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
|
||||
pr_debug("Releasing pdd (topology id %d) for process (pasid 0x%x)\n",
|
||||
pdd->dev->id, p->pasid);
|
||||
|
||||
kfd_process_device_destroy_cwsr_dgpu(pdd);
|
||||
kfd_process_device_destroy_ib_mem(pdd);
|
||||
|
||||
if (pdd->drm_file) {
|
||||
amdgpu_amdkfd_gpuvm_release_process_vm(
|
||||
pdd->dev->kgd, pdd->drm_priv);
|
||||
@@ -1049,9 +1085,11 @@ static void kfd_process_wq_release(struct work_struct *work)
|
||||
{
|
||||
struct kfd_process *p = container_of(work, struct kfd_process,
|
||||
release_work);
|
||||
|
||||
kfd_process_remove_sysfs(p);
|
||||
kfd_iommu_unbind_process(p);
|
||||
|
||||
kfd_process_kunmap_signal_bo(p);
|
||||
kfd_process_free_outstanding_kfd_bos(p);
|
||||
svm_range_list_fini(p);
|
||||
|
||||
@@ -1198,6 +1236,7 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
uint32_t flags = KFD_IOC_ALLOC_MEM_FLAGS_GTT
|
||||
| KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE
|
||||
| KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
|
||||
struct kgd_mem *mem;
|
||||
void *kaddr;
|
||||
int ret;
|
||||
|
||||
@@ -1206,10 +1245,11 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
|
||||
/* cwsr_base is only set for dGPU */
|
||||
ret = kfd_process_alloc_gpuvm(pdd, qpd->cwsr_base,
|
||||
KFD_CWSR_TBA_TMA_SIZE, flags, &kaddr);
|
||||
KFD_CWSR_TBA_TMA_SIZE, flags, &mem, &kaddr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
qpd->cwsr_mem = mem;
|
||||
qpd->cwsr_kaddr = kaddr;
|
||||
qpd->tba_addr = qpd->cwsr_base;
|
||||
|
||||
@@ -1222,6 +1262,17 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
{
|
||||
struct kfd_dev *dev = pdd->dev;
|
||||
struct qcm_process_device *qpd = &pdd->qpd;
|
||||
|
||||
if (!dev->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base)
|
||||
return;
|
||||
|
||||
kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, qpd->cwsr_kaddr);
|
||||
}
|
||||
|
||||
void kfd_process_set_trap_handler(struct qcm_process_device *qpd,
|
||||
uint64_t tba_addr,
|
||||
uint64_t tma_addr)
|
||||
|
||||
@@ -121,7 +121,7 @@ int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
|
||||
pdd->qpd.num_gws = gws ? amdgpu_amdkfd_get_num_gws(dev->kgd) : 0;
|
||||
|
||||
return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
|
||||
pqn->q);
|
||||
pqn->q, NULL);
|
||||
}
|
||||
|
||||
void kfd_process_dequeue_from_all_devices(struct kfd_process *p)
|
||||
@@ -394,8 +394,6 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
|
||||
pdd->qpd.num_gws = 0;
|
||||
}
|
||||
|
||||
kfree(pqn->q->properties.cu_mask);
|
||||
pqn->q->properties.cu_mask = NULL;
|
||||
uninit_queue(pqn->q);
|
||||
}
|
||||
|
||||
@@ -411,8 +409,8 @@ err_destroy_queue:
|
||||
return retval;
|
||||
}
|
||||
|
||||
int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p)
|
||||
int pqm_update_queue_properties(struct process_queue_manager *pqm,
|
||||
unsigned int qid, struct queue_properties *p)
|
||||
{
|
||||
int retval;
|
||||
struct process_queue_node *pqn;
|
||||
@@ -429,15 +427,15 @@ int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
pqn->q->properties.priority = p->priority;
|
||||
|
||||
retval = pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
|
||||
pqn->q);
|
||||
pqn->q, NULL);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p)
|
||||
int pqm_update_mqd(struct process_queue_manager *pqm,
|
||||
unsigned int qid, struct mqd_update_info *minfo)
|
||||
{
|
||||
int retval;
|
||||
struct process_queue_node *pqn;
|
||||
@@ -448,16 +446,8 @@ int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Free the old CU mask memory if it is already allocated, then
|
||||
* allocate memory for the new CU mask.
|
||||
*/
|
||||
kfree(pqn->q->properties.cu_mask);
|
||||
|
||||
pqn->q->properties.cu_mask_count = p->cu_mask_count;
|
||||
pqn->q->properties.cu_mask = p->cu_mask;
|
||||
|
||||
retval = pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
|
||||
pqn->q);
|
||||
pqn->q, minfo);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@
|
||||
#include "kfd_svm.h"
|
||||
#include "kfd_migrate.h"
|
||||
|
||||
#ifdef dev_fmt
|
||||
#undef dev_fmt
|
||||
#endif
|
||||
#define dev_fmt(fmt) "kfd_svm: %s: " fmt, __func__
|
||||
|
||||
#define AMDGPU_SVM_RANGE_RESTORE_DELAY_MS 1
|
||||
|
||||
/* Long enough to ensure no retry fault comes after svm range is restored and
|
||||
@@ -45,7 +50,9 @@ static bool
|
||||
svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni,
|
||||
const struct mmu_notifier_range *range,
|
||||
unsigned long cur_seq);
|
||||
|
||||
static int
|
||||
svm_range_check_vm(struct kfd_process *p, uint64_t start, uint64_t last,
|
||||
uint64_t *bo_s, uint64_t *bo_l);
|
||||
static const struct mmu_interval_notifier_ops svm_range_mn_ops = {
|
||||
.invalidate = svm_range_cpu_invalidate_pagetables,
|
||||
};
|
||||
@@ -158,17 +165,17 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
bo_adev->vm_manager.vram_base_offset -
|
||||
bo_adev->kfd.dev->pgmap.range.start;
|
||||
addr[i] |= SVM_RANGE_VRAM_DOMAIN;
|
||||
pr_debug("vram address detected: 0x%llx\n", addr[i]);
|
||||
pr_debug_ratelimited("vram address: 0x%llx\n", addr[i]);
|
||||
continue;
|
||||
}
|
||||
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
|
||||
r = dma_mapping_error(dev, addr[i]);
|
||||
if (r) {
|
||||
pr_debug("failed %d dma_map_page\n", r);
|
||||
dev_err(dev, "failed %d dma_map_page\n", r);
|
||||
return r;
|
||||
}
|
||||
pr_debug("dma mapping 0x%llx for page addr 0x%lx\n",
|
||||
addr[i] >> PAGE_SHIFT, page_to_pfn(page));
|
||||
pr_debug_ratelimited("dma mapping 0x%llx for page addr 0x%lx\n",
|
||||
addr[i] >> PAGE_SHIFT, page_to_pfn(page));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -217,7 +224,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
|
||||
for (i = offset; i < offset + npages; i++) {
|
||||
if (!svm_is_valid_dma_mapping_addr(dev, dma_addr[i]))
|
||||
continue;
|
||||
pr_debug("dma unmapping 0x%llx\n", dma_addr[i] >> PAGE_SHIFT);
|
||||
pr_debug_ratelimited("unmap 0x%llx\n", dma_addr[i] >> PAGE_SHIFT);
|
||||
dma_unmap_page(dev, dma_addr[i], PAGE_SIZE, dir);
|
||||
dma_addr[i] = 0;
|
||||
}
|
||||
@@ -1454,7 +1461,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
||||
/* This should never happen. actual_loc gets set by
|
||||
* svm_migrate_ram_to_vram after allocating a BO.
|
||||
*/
|
||||
WARN(1, "VRAM BO missing during validation\n");
|
||||
WARN_ONCE(1, "VRAM BO missing during validation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1547,7 +1554,7 @@ unreserve_out:
|
||||
* Context: Returns with mmap write lock held, pending deferred work flushed
|
||||
*
|
||||
*/
|
||||
static void
|
||||
void
|
||||
svm_range_list_lock_and_flush_work(struct svm_range_list *svms,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
@@ -2303,6 +2310,7 @@ svm_range_best_restore_location(struct svm_range *prange,
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
|
||||
unsigned long *start, unsigned long *last)
|
||||
@@ -2350,8 +2358,59 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
|
||||
vma->vm_end >> PAGE_SHIFT, *last);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
svm_range_check_vm_userptr(struct kfd_process *p, uint64_t start, uint64_t last,
|
||||
uint64_t *bo_s, uint64_t *bo_l)
|
||||
{
|
||||
struct amdgpu_bo_va_mapping *mapping;
|
||||
struct interval_tree_node *node;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
unsigned long userptr;
|
||||
uint32_t i;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < p->n_pdds; i++) {
|
||||
struct amdgpu_vm *vm;
|
||||
|
||||
if (!p->pdds[i]->drm_priv)
|
||||
continue;
|
||||
|
||||
vm = drm_priv_to_vm(p->pdds[i]->drm_priv);
|
||||
r = amdgpu_bo_reserve(vm->root.bo, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Check userptr by searching entire vm->va interval tree */
|
||||
node = interval_tree_iter_first(&vm->va, 0, ~0ULL);
|
||||
while (node) {
|
||||
mapping = container_of((struct rb_node *)node,
|
||||
struct amdgpu_bo_va_mapping, rb);
|
||||
bo = mapping->bo_va->base.bo;
|
||||
|
||||
if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
|
||||
start << PAGE_SHIFT,
|
||||
last << PAGE_SHIFT,
|
||||
&userptr)) {
|
||||
node = interval_tree_iter_next(node, 0, ~0ULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
pr_debug("[0x%llx 0x%llx] already userptr mapped\n",
|
||||
start, last);
|
||||
if (bo_s && bo_l) {
|
||||
*bo_s = userptr >> PAGE_SHIFT;
|
||||
*bo_l = *bo_s + bo->tbo.ttm->num_pages - 1;
|
||||
}
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct
|
||||
svm_range *svm_range_create_unregistered_range(struct amdgpu_device *adev,
|
||||
struct kfd_process *p,
|
||||
@@ -2361,10 +2420,26 @@ svm_range *svm_range_create_unregistered_range(struct amdgpu_device *adev,
|
||||
struct svm_range *prange = NULL;
|
||||
unsigned long start, last;
|
||||
uint32_t gpuid, gpuidx;
|
||||
uint64_t bo_s = 0;
|
||||
uint64_t bo_l = 0;
|
||||
int r;
|
||||
|
||||
if (svm_range_get_range_boundaries(p, addr, &start, &last))
|
||||
return NULL;
|
||||
|
||||
r = svm_range_check_vm(p, start, last, &bo_s, &bo_l);
|
||||
if (r != -EADDRINUSE)
|
||||
r = svm_range_check_vm_userptr(p, start, last, &bo_s, &bo_l);
|
||||
|
||||
if (r == -EADDRINUSE) {
|
||||
if (addr >= bo_s && addr <= bo_l)
|
||||
return NULL;
|
||||
|
||||
/* Create one page svm range if 2MB range overlapping */
|
||||
start = addr;
|
||||
last = addr;
|
||||
}
|
||||
|
||||
prange = svm_range_new(&p->svms, start, last);
|
||||
if (!prange) {
|
||||
pr_debug("Failed to create prange in address [0x%llx]\n", addr);
|
||||
@@ -2662,9 +2737,68 @@ int svm_range_list_init(struct kfd_process *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* svm_range_check_vm - check if virtual address range mapped already
|
||||
* @p: current kfd_process
|
||||
* @start: range start address, in pages
|
||||
* @last: range last address, in pages
|
||||
* @bo_s: mapping start address in pages if address range already mapped
|
||||
* @bo_l: mapping last address in pages if address range already mapped
|
||||
*
|
||||
* The purpose is to avoid virtual address ranges already allocated by
|
||||
* kfd_ioctl_alloc_memory_of_gpu ioctl.
|
||||
* It looks for each pdd in the kfd_process.
|
||||
*
|
||||
* Context: Process context
|
||||
*
|
||||
* Return 0 - OK, if the range is not mapped.
|
||||
* Otherwise error code:
|
||||
* -EADDRINUSE - if address is mapped already by kfd_ioctl_alloc_memory_of_gpu
|
||||
* -ERESTARTSYS - A wait for the buffer to become unreserved was interrupted by
|
||||
* a signal. Release all buffer reservations and return to user-space.
|
||||
*/
|
||||
static int
|
||||
svm_range_check_vm(struct kfd_process *p, uint64_t start, uint64_t last,
|
||||
uint64_t *bo_s, uint64_t *bo_l)
|
||||
{
|
||||
struct amdgpu_bo_va_mapping *mapping;
|
||||
struct interval_tree_node *node;
|
||||
uint32_t i;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < p->n_pdds; i++) {
|
||||
struct amdgpu_vm *vm;
|
||||
|
||||
if (!p->pdds[i]->drm_priv)
|
||||
continue;
|
||||
|
||||
vm = drm_priv_to_vm(p->pdds[i]->drm_priv);
|
||||
r = amdgpu_bo_reserve(vm->root.bo, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
node = interval_tree_iter_first(&vm->va, start, last);
|
||||
if (node) {
|
||||
pr_debug("range [0x%llx 0x%llx] already TTM mapped\n",
|
||||
start, last);
|
||||
mapping = container_of((struct rb_node *)node,
|
||||
struct amdgpu_bo_va_mapping, rb);
|
||||
if (bo_s && bo_l) {
|
||||
*bo_s = mapping->start;
|
||||
*bo_l = mapping->last;
|
||||
}
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* svm_range_is_valid - check if virtual address range is valid
|
||||
* @mm: current process mm_struct
|
||||
* @p: current kfd_process
|
||||
* @start: range start address, in pages
|
||||
* @size: range size, in pages
|
||||
*
|
||||
@@ -2673,28 +2807,28 @@ int svm_range_list_init(struct kfd_process *p)
|
||||
* Context: Process context
|
||||
*
|
||||
* Return:
|
||||
* true - valid svm range
|
||||
* false - invalid svm range
|
||||
* 0 - OK, otherwise error code
|
||||
*/
|
||||
static bool
|
||||
svm_range_is_valid(struct mm_struct *mm, uint64_t start, uint64_t size)
|
||||
static int
|
||||
svm_range_is_valid(struct kfd_process *p, uint64_t start, uint64_t size)
|
||||
{
|
||||
const unsigned long device_vma = VM_IO | VM_PFNMAP | VM_MIXEDMAP;
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long end;
|
||||
unsigned long start_unchg = start;
|
||||
|
||||
start <<= PAGE_SHIFT;
|
||||
end = start + (size << PAGE_SHIFT);
|
||||
|
||||
do {
|
||||
vma = find_vma(mm, start);
|
||||
vma = find_vma(p->mm, start);
|
||||
if (!vma || start < vma->vm_start ||
|
||||
(vma->vm_flags & device_vma))
|
||||
return false;
|
||||
return -EFAULT;
|
||||
start = min(end, vma->vm_end);
|
||||
} while (start < end);
|
||||
|
||||
return true;
|
||||
return svm_range_check_vm(p, start_unchg, (end - 1) >> PAGE_SHIFT, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2997,9 +3131,9 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size,
|
||||
|
||||
svm_range_list_lock_and_flush_work(svms, mm);
|
||||
|
||||
if (!svm_range_is_valid(mm, start, size)) {
|
||||
pr_debug("invalid range\n");
|
||||
r = -EFAULT;
|
||||
r = svm_range_is_valid(p, start, size);
|
||||
if (r) {
|
||||
pr_debug("invalid range r=%d\n", r);
|
||||
mmap_write_unlock(mm);
|
||||
goto out;
|
||||
}
|
||||
@@ -3101,6 +3235,7 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
|
||||
uint32_t flags_or = 0;
|
||||
int gpuidx;
|
||||
uint32_t i;
|
||||
int r = 0;
|
||||
|
||||
pr_debug("svms 0x%p [0x%llx 0x%llx] nattr 0x%x\n", &p->svms, start,
|
||||
start + size - 1, nattr);
|
||||
@@ -3114,12 +3249,12 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
|
||||
flush_work(&p->svms.deferred_list_work);
|
||||
|
||||
mmap_read_lock(mm);
|
||||
if (!svm_range_is_valid(mm, start, size)) {
|
||||
pr_debug("invalid range\n");
|
||||
mmap_read_unlock(mm);
|
||||
return -EINVAL;
|
||||
}
|
||||
r = svm_range_is_valid(p, start, size);
|
||||
mmap_read_unlock(mm);
|
||||
if (r) {
|
||||
pr_debug("invalid range r=%d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < nattr; i++) {
|
||||
switch (attrs[i].type) {
|
||||
|
||||
@@ -188,6 +188,7 @@ void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
|
||||
void *owner);
|
||||
struct kfd_process_device *
|
||||
svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev);
|
||||
void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm);
|
||||
|
||||
/* SVM API and HMM page migration work together, device memory type
|
||||
* is initialized to not 0 when page migration register device memory.
|
||||
|
||||
@@ -1296,6 +1296,24 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
|
||||
|
||||
proximity_domain = atomic_inc_return(&topology_crat_proximity_domain);
|
||||
|
||||
adev = (struct amdgpu_device *)(gpu->kgd);
|
||||
|
||||
/* Include the CPU in xGMI hive if xGMI connected by assigning it the hive ID. */
|
||||
if (gpu->hive_id && adev->gmc.xgmi.connected_to_cpu) {
|
||||
struct kfd_topology_device *top_dev;
|
||||
|
||||
down_read(&topology_lock);
|
||||
|
||||
list_for_each_entry(top_dev, &topology_device_list, list) {
|
||||
if (top_dev->gpu)
|
||||
break;
|
||||
|
||||
top_dev->node_props.hive_id = gpu->hive_id;
|
||||
}
|
||||
|
||||
up_read(&topology_lock);
|
||||
}
|
||||
|
||||
/* Check to see if this gpu device exists in the topology_device_list.
|
||||
* If so, assign the gpu to that device,
|
||||
* else create a Virtual CRAT for this gpu device and then parse that
|
||||
@@ -1457,7 +1475,6 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
|
||||
dev->node_props.max_waves_per_simd = 10;
|
||||
}
|
||||
|
||||
adev = (struct amdgpu_device *)(dev->gpu->kgd);
|
||||
/* kfd only concerns sram ecc on GFX and HBM ecc on UMC */
|
||||
dev->node_props.capability |=
|
||||
((adev->ras_enabled & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0) ?
|
||||
|
||||
@@ -730,6 +730,8 @@ static void dm_handle_hpd_work(struct work_struct *work)
|
||||
dmub_hpd_wrk->adev->dm.dmub_callback[dmub_hpd_wrk->dmub_notify->type](dmub_hpd_wrk->adev,
|
||||
dmub_hpd_wrk->dmub_notify);
|
||||
}
|
||||
|
||||
kfree(dmub_hpd_wrk->dmub_notify);
|
||||
kfree(dmub_hpd_wrk);
|
||||
|
||||
}
|
||||
@@ -755,12 +757,6 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
||||
|
||||
if (dc_enable_dmub_notifications(adev->dm.dc) &&
|
||||
irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
|
||||
dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk) {
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk");
|
||||
return;
|
||||
}
|
||||
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
|
||||
|
||||
do {
|
||||
dc_stat_get_dmub_notification(adev->dm.dc, ¬ify);
|
||||
@@ -769,7 +765,20 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
||||
continue;
|
||||
}
|
||||
if (dm->dmub_thread_offload[notify.type] == true) {
|
||||
dmub_hpd_wrk->dmub_notify = ¬ify;
|
||||
dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk) {
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk");
|
||||
return;
|
||||
}
|
||||
dmub_hpd_wrk->dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk->dmub_notify) {
|
||||
kfree(dmub_hpd_wrk);
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk->dmub_notify");
|
||||
return;
|
||||
}
|
||||
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
|
||||
if (dmub_hpd_wrk->dmub_notify)
|
||||
memcpy(dmub_hpd_wrk->dmub_notify, ¬ify, sizeof(struct dmub_notification));
|
||||
dmub_hpd_wrk->adev = adev;
|
||||
if (notify.type == DMUB_NOTIFICATION_HPD) {
|
||||
plink = adev->dm.dc->links[notify.link_index];
|
||||
@@ -1008,6 +1017,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
||||
const unsigned char *fw_inst_const, *fw_bss_data;
|
||||
uint32_t i, fw_inst_const_size, fw_bss_data_size;
|
||||
bool has_hw_support;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
|
||||
if (!dmub_srv)
|
||||
/* DMUB isn't supported on the ASIC. */
|
||||
@@ -1094,6 +1104,19 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
||||
for (i = 0; i < fb_info->num_fb; ++i)
|
||||
hw_params.fb[i] = &fb_info->fb[i];
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_YELLOW_CARP:
|
||||
if (dc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_A0) {
|
||||
hw_params.dpia_supported = true;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
status = dmub_srv_hw_init(dmub_srv, &hw_params);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error initializing DMUB HW: %d\n", status);
|
||||
@@ -1295,6 +1318,37 @@ static struct hpd_rx_irq_offload_work_queue *hpd_rx_irq_create_workqueue(struct
|
||||
return hpd_rx_offload_wq;
|
||||
}
|
||||
|
||||
struct amdgpu_stutter_quirk {
|
||||
u16 chip_vendor;
|
||||
u16 chip_device;
|
||||
u16 subsys_vendor;
|
||||
u16 subsys_device;
|
||||
u8 revision;
|
||||
};
|
||||
|
||||
static const struct amdgpu_stutter_quirk amdgpu_stutter_quirk_list[] = {
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=214417 */
|
||||
{ 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc8 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static bool dm_should_disable_stutter(struct pci_dev *pdev)
|
||||
{
|
||||
const struct amdgpu_stutter_quirk *p = amdgpu_stutter_quirk_list;
|
||||
|
||||
while (p && p->chip_device != 0) {
|
||||
if (pdev->vendor == p->chip_vendor &&
|
||||
pdev->device == p->chip_device &&
|
||||
pdev->subsystem_vendor == p->subsys_vendor &&
|
||||
pdev->subsystem_device == p->subsys_device &&
|
||||
pdev->revision == p->revision) {
|
||||
return true;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dc_init_data init_data;
|
||||
@@ -1356,8 +1410,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
switch (adev->ip_versions[DCE_HWIP][0]) {
|
||||
case IP_VERSION(2, 1, 0):
|
||||
init_data.flags.gpu_vm_support = true;
|
||||
if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
|
||||
init_data.flags.disable_dmcu = true;
|
||||
init_data.flags.disable_dmcu = true;
|
||||
break;
|
||||
case IP_VERSION(1, 0, 0):
|
||||
case IP_VERSION(1, 0, 1):
|
||||
@@ -1407,6 +1460,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
|
||||
if (adev->asic_type != CHIP_CARRIZO && adev->asic_type != CHIP_STONEY)
|
||||
adev->dm.dc->debug.disable_stutter = amdgpu_pp_feature_mask & PP_STUTTER_MODE ? false : true;
|
||||
if (dm_should_disable_stutter(adev->pdev))
|
||||
adev->dm.dc->debug.disable_stutter = true;
|
||||
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
|
||||
adev->dm.dc->debug.disable_stutter = true;
|
||||
@@ -1793,7 +1848,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
||||
break;
|
||||
case IP_VERSION(3, 1, 2):
|
||||
case IP_VERSION(3, 1, 3):
|
||||
dmub_asic = DMUB_ASIC_DCN31;
|
||||
dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31;
|
||||
fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB;
|
||||
break;
|
||||
|
||||
@@ -4031,6 +4086,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
int32_t primary_planes;
|
||||
enum dc_connection_type new_connection_type = dc_connection_none;
|
||||
const struct dc_plane_cap *plane;
|
||||
bool psr_feature_enabled = false;
|
||||
|
||||
dm->display_indexes_num = dm->dc->caps.max_streams;
|
||||
/* Update the actual used number of crtc */
|
||||
@@ -4113,6 +4169,19 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
DRM_DEBUG_KMS("Unsupported DCN IP version for outbox: 0x%X\n",
|
||||
adev->ip_versions[DCE_HWIP][0]);
|
||||
}
|
||||
|
||||
/* Determine whether to enable PSR support by default. */
|
||||
if (!(amdgpu_dc_debug_mask & DC_DISABLE_PSR)) {
|
||||
switch (adev->ip_versions[DCE_HWIP][0]) {
|
||||
case IP_VERSION(3, 1, 2):
|
||||
case IP_VERSION(3, 1, 3):
|
||||
psr_feature_enabled = true;
|
||||
break;
|
||||
default:
|
||||
psr_feature_enabled = amdgpu_dc_feature_mask & DC_PSR_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* loops over all connectors on the board */
|
||||
@@ -4156,7 +4225,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
} else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
|
||||
amdgpu_dm_update_connector_after_detect(aconnector);
|
||||
register_backlight_device(dm, link);
|
||||
if (amdgpu_dc_feature_mask & DC_PSR_MASK)
|
||||
|
||||
if (psr_feature_enabled)
|
||||
amdgpu_dm_set_psr_caps(link);
|
||||
}
|
||||
|
||||
@@ -10535,18 +10605,18 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *new_crtc_state)
|
||||
{
|
||||
struct drm_plane_state *new_cursor_state, *new_primary_state;
|
||||
int cursor_scale_w, cursor_scale_h, primary_scale_w, primary_scale_h;
|
||||
struct drm_plane *cursor = crtc->cursor, *underlying;
|
||||
struct drm_plane_state *new_cursor_state, *new_underlying_state;
|
||||
int i;
|
||||
int cursor_scale_w, cursor_scale_h, underlying_scale_w, underlying_scale_h;
|
||||
|
||||
/* On DCE and DCN there is no dedicated hardware cursor plane. We get a
|
||||
* cursor per pipe but it's going to inherit the scaling and
|
||||
* positioning from the underlying pipe. Check the cursor plane's
|
||||
* blending properties match the primary plane's. */
|
||||
* blending properties match the underlying planes'. */
|
||||
|
||||
new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor);
|
||||
new_primary_state = drm_atomic_get_new_plane_state(state, crtc->primary);
|
||||
if (!new_cursor_state || !new_primary_state ||
|
||||
!new_cursor_state->fb || !new_primary_state->fb) {
|
||||
new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
|
||||
if (!new_cursor_state || !new_cursor_state->fb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -10555,15 +10625,34 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
|
||||
cursor_scale_h = new_cursor_state->crtc_h * 1000 /
|
||||
(new_cursor_state->src_h >> 16);
|
||||
|
||||
primary_scale_w = new_primary_state->crtc_w * 1000 /
|
||||
(new_primary_state->src_w >> 16);
|
||||
primary_scale_h = new_primary_state->crtc_h * 1000 /
|
||||
(new_primary_state->src_h >> 16);
|
||||
for_each_new_plane_in_state_reverse(state, underlying, new_underlying_state, i) {
|
||||
/* Narrow down to non-cursor planes on the same CRTC as the cursor */
|
||||
if (new_underlying_state->crtc != crtc || underlying == crtc->cursor)
|
||||
continue;
|
||||
|
||||
if (cursor_scale_w != primary_scale_w ||
|
||||
cursor_scale_h != primary_scale_h) {
|
||||
drm_dbg_atomic(crtc->dev, "Cursor plane scaling doesn't match primary plane\n");
|
||||
return -EINVAL;
|
||||
/* Ignore disabled planes */
|
||||
if (!new_underlying_state->fb)
|
||||
continue;
|
||||
|
||||
underlying_scale_w = new_underlying_state->crtc_w * 1000 /
|
||||
(new_underlying_state->src_w >> 16);
|
||||
underlying_scale_h = new_underlying_state->crtc_h * 1000 /
|
||||
(new_underlying_state->src_h >> 16);
|
||||
|
||||
if (cursor_scale_w != underlying_scale_w ||
|
||||
cursor_scale_h != underlying_scale_h) {
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"Cursor [PLANE:%d:%s] scaling doesn't match underlying [PLANE:%d:%s]\n",
|
||||
cursor->base.id, cursor->name, underlying->base.id, underlying->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If this plane covers the whole CRTC, no need to check planes underneath */
|
||||
if (new_underlying_state->crtc_x <= 0 &&
|
||||
new_underlying_state->crtc_y <= 0 &&
|
||||
new_underlying_state->crtc_x + new_underlying_state->crtc_w >= new_crtc_state->mode.hdisplay &&
|
||||
new_underlying_state->crtc_y + new_underlying_state->crtc_h >= new_crtc_state->mode.vdisplay)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -10594,53 +10683,6 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
|
||||
}
|
||||
#endif
|
||||
|
||||
static int validate_overlay(struct drm_atomic_state *state)
|
||||
{
|
||||
int i;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *new_plane_state;
|
||||
struct drm_plane_state *primary_state, *overlay_state = NULL;
|
||||
|
||||
/* Check if primary plane is contained inside overlay */
|
||||
for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) {
|
||||
if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
|
||||
if (drm_atomic_plane_disabling(plane->state, new_plane_state))
|
||||
return 0;
|
||||
|
||||
overlay_state = new_plane_state;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we're making changes to the overlay plane */
|
||||
if (!overlay_state)
|
||||
return 0;
|
||||
|
||||
/* check if overlay plane is enabled */
|
||||
if (!overlay_state->crtc)
|
||||
return 0;
|
||||
|
||||
/* find the primary plane for the CRTC that the overlay is enabled on */
|
||||
primary_state = drm_atomic_get_plane_state(state, overlay_state->crtc->primary);
|
||||
if (IS_ERR(primary_state))
|
||||
return PTR_ERR(primary_state);
|
||||
|
||||
/* check if primary plane is enabled */
|
||||
if (!primary_state->crtc)
|
||||
return 0;
|
||||
|
||||
/* Perform the bounds check to ensure the overlay plane covers the primary */
|
||||
if (primary_state->crtc_x < overlay_state->crtc_x ||
|
||||
primary_state->crtc_y < overlay_state->crtc_y ||
|
||||
primary_state->crtc_x + primary_state->crtc_w > overlay_state->crtc_x + overlay_state->crtc_w ||
|
||||
primary_state->crtc_y + primary_state->crtc_h > overlay_state->crtc_y + overlay_state->crtc_h) {
|
||||
DRM_DEBUG_ATOMIC("Overlay plane is enabled with hardware cursor but does not fully cover primary plane\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
|
||||
* @dev: The DRM device
|
||||
@@ -10683,6 +10725,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
struct dm_crtc_state *dm_old_crtc_state;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct dsc_mst_fairness_vars vars[MAX_PIPES];
|
||||
struct drm_dp_mst_topology_state *mst_state;
|
||||
struct drm_dp_mst_topology_mgr *mgr;
|
||||
#endif
|
||||
|
||||
trace_amdgpu_dm_atomic_check_begin(state);
|
||||
@@ -10822,10 +10866,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = validate_overlay(state);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/* Add new/modified planes */
|
||||
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
|
||||
ret = dm_update_plane_state(dc, state, plane,
|
||||
@@ -10891,6 +10931,33 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
lock_and_validation_needed = true;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
/* set the slot info for each mst_state based on the link encoding format */
|
||||
for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
|
||||
struct amdgpu_dm_connector *aconnector;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
u8 link_coding_cap;
|
||||
|
||||
if (!mgr->mst_state )
|
||||
continue;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
int id = connector->index;
|
||||
|
||||
if (id == mst_state->mgr->conn_base_id) {
|
||||
aconnector = to_amdgpu_dm_connector(connector);
|
||||
link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
|
||||
drm_dp_mst_update_slots(mst_state, link_coding_cap);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Streams and planes are reset when there are changes that affect
|
||||
* bandwidth. Anything that affects bandwidth needs to go through
|
||||
|
||||
@@ -294,6 +294,9 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
|
||||
case LINK_RATE_RBR2:
|
||||
case LINK_RATE_HIGH2:
|
||||
case LINK_RATE_HIGH3:
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
case LINK_RATE_UHBR10:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
valid_input = false;
|
||||
|
||||
@@ -219,6 +219,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||
struct drm_dp_mst_port *mst_port;
|
||||
bool ret;
|
||||
u8 link_coding_cap = DP_8b_10b_ENCODING;
|
||||
|
||||
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
|
||||
/* Accessing the connector state is required for vcpi_slots allocation
|
||||
@@ -238,6 +239,10 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
||||
|
||||
mst_port = aconnector->port;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
|
||||
#endif
|
||||
|
||||
if (enable) {
|
||||
|
||||
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port,
|
||||
@@ -251,7 +256,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
||||
}
|
||||
|
||||
/* It's OK for this to fail */
|
||||
drm_dp_update_payload_part1(mst_mgr);
|
||||
drm_dp_update_payload_part1(mst_mgr, (link_coding_cap == DP_CAP_ANSI_128B132B) ? 0:1);
|
||||
|
||||
/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
|
||||
* AUX message. The sequence is slot 1-63 allocated sequence for each
|
||||
|
||||
@@ -64,6 +64,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
payload.i2c_over_aux = (msg->request & DP_AUX_NATIVE_WRITE) == 0;
|
||||
payload.write = (msg->request & DP_AUX_I2C_READ) == 0;
|
||||
payload.mot = (msg->request & DP_AUX_I2C_MOT) != 0;
|
||||
payload.write_status_update =
|
||||
(msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0;
|
||||
payload.defer_delay = 0;
|
||||
|
||||
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
|
||||
|
||||
@@ -107,6 +107,8 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
|
||||
*/
|
||||
// Init fail safe of 2 frames static
|
||||
unsigned int num_frames_static = 2;
|
||||
unsigned int power_opt = 0;
|
||||
bool psr_enable = true;
|
||||
|
||||
DRM_DEBUG_DRIVER("Enabling psr...\n");
|
||||
|
||||
@@ -133,7 +135,9 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
|
||||
&stream, 1,
|
||||
¶ms);
|
||||
|
||||
return dc_link_set_psr_allow_active(link, true, false, false);
|
||||
power_opt |= psr_power_opt_z10_static_screen;
|
||||
|
||||
return dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -144,10 +148,12 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
|
||||
*/
|
||||
bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
|
||||
{
|
||||
unsigned int power_opt = 0;
|
||||
bool psr_enable = false;
|
||||
|
||||
DRM_DEBUG_DRIVER("Disabling psr...\n");
|
||||
|
||||
return dc_link_set_psr_allow_active(stream->link, false, true, false);
|
||||
return dc_link_set_psr_allow_active(stream->link, &psr_enable, true, false, &power_opt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -99,6 +99,10 @@ static enum bp_result get_firmware_info_v3_2(
|
||||
struct bios_parser *bp,
|
||||
struct dc_firmware_info *info);
|
||||
|
||||
static enum bp_result get_firmware_info_v3_4(
|
||||
struct bios_parser *bp,
|
||||
struct dc_firmware_info *info);
|
||||
|
||||
static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
|
||||
struct atom_display_object_path_v2 *object);
|
||||
|
||||
@@ -1426,8 +1430,10 @@ static enum bp_result bios_parser_get_firmware_info(
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
result = get_firmware_info_v3_2(bp, info);
|
||||
break;
|
||||
case 4:
|
||||
result = get_firmware_info_v3_4(bp, info);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1575,6 +1581,88 @@ static enum bp_result get_firmware_info_v3_2(
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
static enum bp_result get_firmware_info_v3_4(
|
||||
struct bios_parser *bp,
|
||||
struct dc_firmware_info *info)
|
||||
{
|
||||
struct atom_firmware_info_v3_4 *firmware_info;
|
||||
struct atom_common_table_header *header;
|
||||
struct atom_data_revision revision;
|
||||
struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
|
||||
struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
|
||||
if (!info)
|
||||
return BP_RESULT_BADINPUT;
|
||||
|
||||
firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
|
||||
DATA_TABLES(firmwareinfo));
|
||||
|
||||
if (!firmware_info)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
header = GET_IMAGE(struct atom_common_table_header,
|
||||
DATA_TABLES(dce_info));
|
||||
|
||||
get_atom_data_table_revision(header, &revision);
|
||||
|
||||
switch (revision.major) {
|
||||
case 4:
|
||||
switch (revision.minor) {
|
||||
case 4:
|
||||
dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
|
||||
DATA_TABLES(dce_info));
|
||||
|
||||
if (!dce_info_v4_4)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
/* 100MHz expected */
|
||||
info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
|
||||
info->dp_phy_ref_clk = dce_info_v4_4->dpphy_refclk_10khz * 10;
|
||||
/* 50MHz expected */
|
||||
info->i2c_engine_ref_clk = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
|
||||
|
||||
/* Get SMU Display PLL VCO Frequency in KHz*/
|
||||
info->smu_gpu_pll_output_freq = dce_info_v4_4->dispclk_pll_vco_freq * 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* should not come here, keep as backup, as was before */
|
||||
dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
|
||||
DATA_TABLES(dce_info));
|
||||
|
||||
if (!dce_info_v4_1)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
|
||||
info->dp_phy_ref_clk = dce_info_v4_1->dpphy_refclk_10khz * 10;
|
||||
info->i2c_engine_ref_clk = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
header = GET_IMAGE(struct atom_common_table_header,
|
||||
DATA_TABLES(smu_info));
|
||||
get_atom_data_table_revision(header, &revision);
|
||||
|
||||
// We need to convert from 10KHz units into KHz units.
|
||||
info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
|
||||
|
||||
if (firmware_info->board_i2c_feature_id == 0x2) {
|
||||
info->oem_i2c_present = true;
|
||||
info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
|
||||
} else {
|
||||
info->oem_i2c_present = false;
|
||||
}
|
||||
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
static enum bp_result bios_parser_get_encoder_cap_info(
|
||||
struct dc_bios *dcb,
|
||||
struct graphics_object_id object_id,
|
||||
@@ -2233,6 +2321,8 @@ static enum bp_result get_integrated_info_v2_2(
|
||||
|
||||
info->ext_disp_conn_info.checksum =
|
||||
info_v2_2->extdispconninfo.checksum;
|
||||
info->ext_disp_conn_info.fixdpvoltageswing =
|
||||
info_v2_2->extdispconninfo.fixdpvoltageswing;
|
||||
|
||||
info->edp1_info.edp_backlight_pwm_hz =
|
||||
le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
|
||||
|
||||
@@ -100,11 +100,13 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
|
||||
|
||||
if (edp_num) {
|
||||
for (panel_inst = 0; panel_inst < edp_num; panel_inst++) {
|
||||
bool allow_active = false;
|
||||
|
||||
edp_link = edp_links[panel_inst];
|
||||
if (!edp_link->psr_settings.psr_feature_enabled)
|
||||
continue;
|
||||
clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
|
||||
dc_link_set_psr_allow_active(edp_link, false, false, false);
|
||||
dc_link_set_psr_allow_active(edp_link, &allow_active, false, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +126,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
|
||||
if (!edp_link->psr_settings.psr_feature_enabled)
|
||||
continue;
|
||||
dc_link_set_psr_allow_active(edp_link,
|
||||
clk_mgr->psr_allow_active_cache, false, false);
|
||||
&clk_mgr->psr_allow_active_cache, false, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,13 +285,8 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
|
||||
BREAK_TO_DEBUGGER();
|
||||
return NULL;
|
||||
}
|
||||
if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev)) {
|
||||
/* TODO: to add DCN31 clk_mgr support, once CLK IP header files are available,
|
||||
* for now use DCN3.0 clk mgr.
|
||||
*/
|
||||
dcn31_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
|
||||
return &clk_mgr->base.base;
|
||||
}
|
||||
|
||||
dcn31_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
|
||||
return &clk_mgr->base.base;
|
||||
}
|
||||
#endif
|
||||
@@ -326,7 +323,6 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
|
||||
break;
|
||||
|
||||
case FAMILY_YELLOW_CARP:
|
||||
if (ASICREV_IS_YELLOW_CARP(clk_mgr_base->ctx->asic_id.hw_internal_rev))
|
||||
dcn31_clk_mgr_destroy(clk_mgr);
|
||||
break;
|
||||
|
||||
|
||||
@@ -219,14 +219,17 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
update_dispclk = true;
|
||||
}
|
||||
|
||||
/* TODO: add back DTO programming when DPPCLK restore is fixed in FSDL*/
|
||||
if (dpp_clock_lowered) {
|
||||
// increase per DPP DTO before lowering global dppclk
|
||||
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
|
||||
dcn31_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
|
||||
} else {
|
||||
// increase global DPPCLK before lowering per DPP DTO
|
||||
if (update_dppclk || update_dispclk)
|
||||
dcn31_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
|
||||
// always update dtos unless clock is lowered and not safe to lower
|
||||
if (new_clocks->dppclk_khz >= dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz)
|
||||
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
|
||||
}
|
||||
|
||||
// notify DMCUB of latest clocks
|
||||
|
||||
@@ -71,8 +71,6 @@
|
||||
|
||||
#include "dmub/dmub_srv.h"
|
||||
|
||||
#include "dcn30/dcn30_vpg.h"
|
||||
|
||||
#include "i2caux_interface.h"
|
||||
#include "dce/dmub_hw_lock_mgr.h"
|
||||
|
||||
@@ -1899,12 +1897,14 @@ static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
|
||||
static void process_deferred_updates(struct dc *dc)
|
||||
{
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN
|
||||
int i;
|
||||
int i = 0;
|
||||
|
||||
if (dc->debug.enable_mem_low_power.bits.cm)
|
||||
if (dc->debug.enable_mem_low_power.bits.cm) {
|
||||
ASSERT(dc->dcn_ip->max_num_dpp);
|
||||
for (i = 0; i < dc->dcn_ip->max_num_dpp; i++)
|
||||
if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update)
|
||||
dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2285,6 +2285,9 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
||||
update_flags->bits.gamma_change = 1;
|
||||
}
|
||||
|
||||
if (u->lut3d_func || u->func_shaper)
|
||||
update_flags->bits.lut_3d = 1;
|
||||
|
||||
if (u->hdr_mult.value)
|
||||
if (u->hdr_mult.value != u->surface->hdr_mult.value) {
|
||||
update_flags->bits.hdr_mult = 1;
|
||||
@@ -2298,6 +2301,7 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
||||
|
||||
if (update_flags->bits.input_csc_change
|
||||
|| update_flags->bits.coeff_reduction_change
|
||||
|| update_flags->bits.lut_3d
|
||||
|| update_flags->bits.gamma_change
|
||||
|| update_flags->bits.gamut_remap_change) {
|
||||
type = UPDATE_TYPE_FULL;
|
||||
@@ -2356,6 +2360,11 @@ static enum surface_update_type check_update_surfaces_for_stream(
|
||||
if (stream_update->dsc_config)
|
||||
su_flags->bits.dsc_changed = 1;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (stream_update->mst_bw_update)
|
||||
su_flags->bits.mst_bw = 1;
|
||||
#endif
|
||||
|
||||
if (su_flags->raw != 0)
|
||||
overall_type = UPDATE_TYPE_FULL;
|
||||
|
||||
@@ -2674,9 +2683,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
enum surface_update_type update_type,
|
||||
struct dc_state *context)
|
||||
{
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct vpg *vpg;
|
||||
#endif
|
||||
int j;
|
||||
|
||||
// Stream updates
|
||||
@@ -2697,11 +2703,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
stream_update->vrr_infopacket ||
|
||||
stream_update->vsc_infopacket ||
|
||||
stream_update->vsp_infopacket) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
vpg = pipe_ctx->stream_res.stream_enc->vpg;
|
||||
if (vpg && vpg->funcs->vpg_poweron)
|
||||
vpg->funcs->vpg_poweron(vpg);
|
||||
#endif
|
||||
resource_build_info_frame(pipe_ctx);
|
||||
dc->hwss.update_info_frame(pipe_ctx);
|
||||
}
|
||||
@@ -2741,6 +2742,15 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
if (stream_update->dsc_config)
|
||||
dp_update_dsc_config(pipe_ctx);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (stream_update->mst_bw_update) {
|
||||
if (stream_update->mst_bw_update->is_increase)
|
||||
dc_link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw);
|
||||
else
|
||||
dc_link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (stream_update->pending_test_pattern) {
|
||||
dc_link_dp_set_test_pattern(stream->link,
|
||||
stream->test_pattern.type,
|
||||
@@ -3118,8 +3128,13 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
||||
if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state)
|
||||
new_pipe->plane_state->force_full_update = true;
|
||||
}
|
||||
} else if (update_type == UPDATE_TYPE_FAST) {
|
||||
/* Previous frame finished and HW is ready for optimization. */
|
||||
} else if (update_type == UPDATE_TYPE_FAST && dc_ctx->dce_version >= DCE_VERSION_MAX) {
|
||||
/*
|
||||
* Previous frame finished and HW is ready for optimization.
|
||||
*
|
||||
* Only relevant for DCN behavior where we can guarantee the optimization
|
||||
* is safe to apply - retain the legacy behavior for DCE.
|
||||
*/
|
||||
dc_post_update_surfaces_to_stream(dc);
|
||||
}
|
||||
|
||||
@@ -3178,6 +3193,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
||||
}
|
||||
}
|
||||
|
||||
/* Legacy optimization path for DCE. */
|
||||
if (update_type >= UPDATE_TYPE_FULL && dc_ctx->dce_version < DCE_VERSION_MAX) {
|
||||
dc_post_update_surfaces_to_stream(dc);
|
||||
TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -3478,6 +3499,7 @@ void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_
|
||||
bool dc_set_psr_allow_active(struct dc *dc, bool enable)
|
||||
{
|
||||
int i;
|
||||
bool allow_active;
|
||||
|
||||
for (i = 0; i < dc->current_state->stream_count ; i++) {
|
||||
struct dc_link *link;
|
||||
@@ -3489,10 +3511,12 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
|
||||
|
||||
if (link->psr_settings.psr_feature_enabled) {
|
||||
if (enable && !link->psr_settings.psr_allow_active) {
|
||||
if (!dc_link_set_psr_allow_active(link, true, false, false))
|
||||
allow_active = true;
|
||||
if (!dc_link_set_psr_allow_active(link, &allow_active, false, false, NULL))
|
||||
return false;
|
||||
} else if (!enable && link->psr_settings.psr_allow_active) {
|
||||
if (!dc_link_set_psr_allow_active(link, false, true, false))
|
||||
allow_active = false;
|
||||
if (!dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3726,6 +3750,60 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
|
||||
return is_cmd_complete;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* Function: dc_process_dmub_set_mst_slots
|
||||
*
|
||||
* @brief
|
||||
* Submits mst slot allocation command to dmub via inbox message
|
||||
*
|
||||
* @param
|
||||
* [in] dc: dc structure
|
||||
* [in] link_index: link index
|
||||
* [in] mst_alloc_slots: mst slots to be allotted
|
||||
* [out] mst_slots_in_use: mst slots in use returned in failure case
|
||||
*
|
||||
* @return
|
||||
* DC_OK if successful, DC_ERROR if failure
|
||||
*****************************************************************************
|
||||
*/
|
||||
enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
|
||||
uint32_t link_index,
|
||||
uint8_t mst_alloc_slots,
|
||||
uint8_t *mst_slots_in_use)
|
||||
{
|
||||
union dmub_rb_cmd cmd = {0};
|
||||
struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
/* prepare MST_ALLOC_SLOTS command */
|
||||
cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA;
|
||||
cmd.set_mst_alloc_slots.header.sub_type = DMUB_CMD__DPIA_MST_ALLOC_SLOTS;
|
||||
|
||||
cmd.set_mst_alloc_slots.mst_slots_control.instance = dc->links[link_index]->ddc_hw_inst;
|
||||
cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots;
|
||||
|
||||
if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd))
|
||||
/* command is not processed by dmub */
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
/* command processed by dmub, if ret_status is 1 */
|
||||
if (cmd.set_config_access.header.ret_status != 1)
|
||||
/* command processing error */
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
/* command processed and we have a status of 2, mst not enabled in dpia */
|
||||
if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 2)
|
||||
return DC_FAIL_UNSUPPORTED_1;
|
||||
|
||||
/* previously configured mst alloc and used slots did not match */
|
||||
if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 3) {
|
||||
*mst_slots_in_use = cmd.set_mst_alloc_slots.mst_slots_control.mst_slots_in_use;
|
||||
return DC_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_disable_accelerated_mode - disable accelerated mode
|
||||
* @dc: dc structure
|
||||
|
||||
@@ -674,13 +674,13 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link)
|
||||
|
||||
static void read_current_link_settings_on_detect(struct dc_link *link)
|
||||
{
|
||||
union lane_count_set lane_count_set = { {0} };
|
||||
union lane_count_set lane_count_set = {0};
|
||||
uint8_t link_bw_set;
|
||||
uint8_t link_rate_set;
|
||||
uint32_t read_dpcd_retry_cnt = 10;
|
||||
enum dc_status status = DC_ERROR_UNEXPECTED;
|
||||
int i;
|
||||
union max_down_spread max_down_spread = { {0} };
|
||||
union max_down_spread max_down_spread = {0};
|
||||
|
||||
// Read DPCD 00101h to find out the number of lanes currently set
|
||||
for (i = 0; i < read_dpcd_retry_cnt; i++) {
|
||||
@@ -1660,6 +1660,14 @@ static bool dc_link_construct_legacy(struct dc_link *link,
|
||||
DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
|
||||
DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
|
||||
}
|
||||
|
||||
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
|
||||
link->bios_forced_drive_settings.VOLTAGE_SWING =
|
||||
(info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
|
||||
link->bios_forced_drive_settings.PRE_EMPHASIS =
|
||||
((info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1757,6 +1765,9 @@ static bool dc_link_construct_dpia(struct dc_link *link,
|
||||
|
||||
link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
|
||||
|
||||
/* Some docks seem to NAK I2C writes to segment pointer with mot=0. */
|
||||
link->wa_flags.dp_mot_reset_segment = true;
|
||||
|
||||
return true;
|
||||
|
||||
ddc_create_fail:
|
||||
@@ -1869,8 +1880,13 @@ static enum dc_status enable_link_dp(struct dc_state *state,
|
||||
do_fallback = true;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
/*
|
||||
* Temporary w/a to get DP2.0 link rates to work with SST.
|
||||
* TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.
|
||||
*/
|
||||
if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING &&
|
||||
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
|
||||
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
|
||||
link->dc->debug.set_mst_en_for_sst) {
|
||||
dp_enable_mst_on_sink(link, true);
|
||||
}
|
||||
#endif
|
||||
@@ -1983,51 +1999,6 @@ static enum dc_status enable_link_dp_mst(
|
||||
return enable_link_dp(state, pipe_ctx);
|
||||
}
|
||||
|
||||
void blank_all_dp_displays(struct dc *dc, bool hw_init)
|
||||
{
|
||||
unsigned int i, j, fe;
|
||||
uint8_t dpcd_power_state = '\0';
|
||||
enum dc_status status = DC_ERROR_UNEXPECTED;
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
enum signal_type signal = dc->links[i]->connector_signal;
|
||||
|
||||
if ((signal == SIGNAL_TYPE_EDP) ||
|
||||
(signal == SIGNAL_TYPE_DISPLAY_PORT)) {
|
||||
if (hw_init && signal != SIGNAL_TYPE_EDP && dc->links[i]->priv != NULL) {
|
||||
/* DP 2.0 spec requires that we read LTTPR caps first */
|
||||
dp_retrieve_lttpr_cap(dc->links[i]);
|
||||
/* if any of the displays are lit up turn them off */
|
||||
status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
|
||||
&dpcd_power_state, sizeof(dpcd_power_state));
|
||||
}
|
||||
|
||||
if ((signal != SIGNAL_TYPE_EDP && status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) ||
|
||||
(!hw_init && dc->links[i]->link_enc &&
|
||||
dc->links[i]->link_enc->funcs->is_dig_enabled(dc->links[i]->link_enc))) {
|
||||
if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
|
||||
fe = dc->links[i]->link_enc->funcs->get_dig_frontend(dc->links[i]->link_enc);
|
||||
if (fe == ENGINE_ID_UNKNOWN)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
|
||||
if (fe == dc->res_pool->stream_enc[j]->id) {
|
||||
dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
|
||||
dc->res_pool->stream_enc[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dc->links[i]->wa_flags.dp_keep_receiver_powered ||
|
||||
(hw_init && signal != SIGNAL_TYPE_EDP && dc->links[i]->priv != NULL))
|
||||
dp_receiver_power_ctrl(dc->links[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
|
||||
enum engine_id eng_id,
|
||||
struct ext_hdmi_settings *settings)
|
||||
@@ -2956,8 +2927,8 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
|
||||
bool wait, bool force_static)
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
|
||||
bool wait, bool force_static, const unsigned int *power_opts)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
@@ -2970,20 +2941,33 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
link->psr_settings.psr_allow_active = allow_active;
|
||||
/* Set power optimization flag */
|
||||
if (power_opts && link->psr_settings.psr_power_opt != *power_opts) {
|
||||
link->psr_settings.psr_power_opt = *power_opts;
|
||||
|
||||
if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt)
|
||||
psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt);
|
||||
}
|
||||
|
||||
/* Enable or Disable PSR */
|
||||
if (allow_active && link->psr_settings.psr_allow_active != *allow_active) {
|
||||
link->psr_settings.psr_allow_active = *allow_active;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (!allow_active)
|
||||
dc_z10_restore(dc);
|
||||
if (!link->psr_settings.psr_allow_active)
|
||||
dc_z10_restore(dc);
|
||||
#endif
|
||||
|
||||
if (psr != NULL && link->psr_settings.psr_feature_enabled) {
|
||||
if (force_static && psr->funcs->psr_force_static)
|
||||
psr->funcs->psr_force_static(psr, panel_inst);
|
||||
psr->funcs->psr_enable(psr, allow_active, wait, panel_inst);
|
||||
} else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
|
||||
dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
|
||||
else
|
||||
return false;
|
||||
if (psr != NULL && link->psr_settings.psr_feature_enabled) {
|
||||
if (force_static && psr->funcs->psr_force_static)
|
||||
psr->funcs->psr_force_static(psr, panel_inst);
|
||||
psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst);
|
||||
} else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) &&
|
||||
link->psr_settings.psr_feature_enabled)
|
||||
dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3272,10 +3256,12 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
|
||||
static void update_mst_stream_alloc_table(
|
||||
struct dc_link *link,
|
||||
struct stream_encoder *stream_enc,
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc?
|
||||
#endif
|
||||
const struct dp_mst_stream_allocation_table *proposed_table)
|
||||
{
|
||||
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
|
||||
{ 0 } };
|
||||
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };
|
||||
struct link_mst_stream_allocation *dc_alloc;
|
||||
|
||||
int i;
|
||||
@@ -3308,6 +3294,9 @@ static void update_mst_stream_alloc_table(
|
||||
work_table[i].slot_count =
|
||||
proposed_table->stream_allocations[i].slot_count;
|
||||
work_table[i].stream_enc = stream_enc;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
work_table[i].hpo_dp_stream_enc = hpo_dp_stream_enc;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3430,11 +3419,15 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
struct dc_link *link = stream->link;
|
||||
struct link_encoder *link_encoder = NULL;
|
||||
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc;
|
||||
struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;
|
||||
#endif
|
||||
struct dp_mst_stream_allocation_table proposed_table = {0};
|
||||
struct fixed31_32 avg_time_slots_per_mtp;
|
||||
struct fixed31_32 pbn;
|
||||
struct fixed31_32 pbn_per_slot;
|
||||
uint8_t i;
|
||||
int i;
|
||||
enum act_return_status ret;
|
||||
DC_LOGGER_INIT(link->ctx->logger);
|
||||
|
||||
@@ -3457,7 +3450,14 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
&proposed_table,
|
||||
true)) {
|
||||
update_mst_stream_alloc_table(
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
link,
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
pipe_ctx->stream_res.hpo_dp_stream_enc,
|
||||
&proposed_table);
|
||||
#else
|
||||
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
DC_LOG_WARNING("Failed to update"
|
||||
@@ -3471,6 +3471,20 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
link->mst_stream_alloc_table.stream_count);
|
||||
|
||||
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
DC_LOG_MST("stream_enc[%d]: %p "
|
||||
"stream[%d].hpo_dp_stream_enc: %p "
|
||||
"stream[%d].vcp_id: %d "
|
||||
"stream[%d].slot_count: %d\n",
|
||||
i,
|
||||
(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
|
||||
i,
|
||||
(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
||||
#else
|
||||
DC_LOG_MST("stream_enc[%d]: %p "
|
||||
"stream[%d].vcp_id: %d "
|
||||
"stream[%d].slot_count: %d\n",
|
||||
@@ -3480,14 +3494,47 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT(proposed_table.stream_count > 0);
|
||||
|
||||
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
static enum dc_status status;
|
||||
uint8_t mst_alloc_slots = 0, prev_mst_slots_in_use = 0xFF;
|
||||
|
||||
for (i = 0; i < link->mst_stream_alloc_table.stream_count; i++)
|
||||
mst_alloc_slots += link->mst_stream_alloc_table.stream_allocations[i].slot_count;
|
||||
|
||||
status = dc_process_dmub_set_mst_slots(link->dc, link->link_index,
|
||||
mst_alloc_slots, &prev_mst_slots_in_use);
|
||||
ASSERT(status == DC_OK);
|
||||
DC_LOG_MST("dpia : status[%d]: alloc_slots[%d]: used_slots[%d]\n",
|
||||
status, mst_alloc_slots, prev_mst_slots_in_use);
|
||||
}
|
||||
|
||||
/* program DP source TX for payload */
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
|
||||
case DP_8b_10b_ENCODING:
|
||||
link_encoder->funcs->update_mst_stream_allocation_table(
|
||||
link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
break;
|
||||
case DP_128b_132b_ENCODING:
|
||||
hpo_dp_link_encoder->funcs->update_stream_allocation_table(
|
||||
hpo_dp_link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
break;
|
||||
case DP_UNKNOWN_ENCODING:
|
||||
DC_LOG_ERROR("Failure: unknown encoding format\n");
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
#else
|
||||
link_encoder->funcs->update_mst_stream_allocation_table(
|
||||
link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
#endif
|
||||
|
||||
/* send down message */
|
||||
ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
||||
@@ -3510,23 +3557,205 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
pbn = get_pbn_from_timing(pipe_ctx);
|
||||
avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
|
||||
case DP_8b_10b_ENCODING:
|
||||
stream_encoder->funcs->set_throttled_vcp_size(
|
||||
stream_encoder,
|
||||
avg_time_slots_per_mtp);
|
||||
break;
|
||||
case DP_128b_132b_ENCODING:
|
||||
hpo_dp_link_encoder->funcs->set_throttled_vcp_size(
|
||||
hpo_dp_link_encoder,
|
||||
hpo_dp_stream_encoder->inst,
|
||||
avg_time_slots_per_mtp);
|
||||
break;
|
||||
case DP_UNKNOWN_ENCODING:
|
||||
DC_LOG_ERROR("Failure: unknown encoding format\n");
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
#else
|
||||
stream_encoder->funcs->set_throttled_vcp_size(
|
||||
stream_encoder,
|
||||
avg_time_slots_per_mtp);
|
||||
#endif
|
||||
|
||||
return DC_OK;
|
||||
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->link;
|
||||
struct fixed31_32 avg_time_slots_per_mtp;
|
||||
struct fixed31_32 pbn;
|
||||
struct fixed31_32 pbn_per_slot;
|
||||
struct link_encoder *link_encoder = link->link_enc;
|
||||
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
||||
struct dp_mst_stream_allocation_table proposed_table = {0};
|
||||
uint8_t i;
|
||||
enum act_return_status ret;
|
||||
DC_LOGGER_INIT(link->ctx->logger);
|
||||
|
||||
/* decrease throttled vcp size */
|
||||
pbn_per_slot = get_pbn_per_slot(stream);
|
||||
pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);
|
||||
avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
|
||||
|
||||
stream_encoder->funcs->set_throttled_vcp_size(
|
||||
stream_encoder,
|
||||
avg_time_slots_per_mtp);
|
||||
|
||||
/* send ALLOCATE_PAYLOAD sideband message with updated pbn */
|
||||
dm_helpers_dp_mst_send_payload_allocation(
|
||||
stream->ctx,
|
||||
stream,
|
||||
true);
|
||||
|
||||
/* notify immediate branch device table update */
|
||||
if (dm_helpers_dp_mst_write_payload_allocation_table(
|
||||
stream->ctx,
|
||||
stream,
|
||||
&proposed_table,
|
||||
true)) {
|
||||
/* update mst stream allocation table software state */
|
||||
update_mst_stream_alloc_table(
|
||||
link,
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
pipe_ctx->stream_res.hpo_dp_stream_enc,
|
||||
&proposed_table);
|
||||
} else {
|
||||
DC_LOG_WARNING("Failed to update"
|
||||
"MST allocation table for"
|
||||
"pipe idx:%d\n",
|
||||
pipe_ctx->pipe_idx);
|
||||
}
|
||||
|
||||
DC_LOG_MST("%s "
|
||||
"stream_count: %d: \n ",
|
||||
__func__,
|
||||
link->mst_stream_alloc_table.stream_count);
|
||||
|
||||
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
|
||||
DC_LOG_MST("stream_enc[%d]: %p "
|
||||
"stream[%d].vcp_id: %d "
|
||||
"stream[%d].slot_count: %d\n",
|
||||
i,
|
||||
(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
||||
}
|
||||
|
||||
ASSERT(proposed_table.stream_count > 0);
|
||||
|
||||
/* update mst stream allocation table hardware state */
|
||||
link_encoder->funcs->update_mst_stream_allocation_table(
|
||||
link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
|
||||
/* poll for immediate branch device ACT handled */
|
||||
ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
||||
stream->ctx,
|
||||
stream);
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->link;
|
||||
struct fixed31_32 avg_time_slots_per_mtp;
|
||||
struct fixed31_32 pbn;
|
||||
struct fixed31_32 pbn_per_slot;
|
||||
struct link_encoder *link_encoder = link->link_enc;
|
||||
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
||||
struct dp_mst_stream_allocation_table proposed_table = {0};
|
||||
uint8_t i;
|
||||
enum act_return_status ret;
|
||||
DC_LOGGER_INIT(link->ctx->logger);
|
||||
|
||||
/* notify immediate branch device table update */
|
||||
if (dm_helpers_dp_mst_write_payload_allocation_table(
|
||||
stream->ctx,
|
||||
stream,
|
||||
&proposed_table,
|
||||
true)) {
|
||||
/* update mst stream allocation table software state */
|
||||
update_mst_stream_alloc_table(
|
||||
link,
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
pipe_ctx->stream_res.hpo_dp_stream_enc,
|
||||
&proposed_table);
|
||||
}
|
||||
|
||||
DC_LOG_MST("%s "
|
||||
"stream_count: %d: \n ",
|
||||
__func__,
|
||||
link->mst_stream_alloc_table.stream_count);
|
||||
|
||||
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
|
||||
DC_LOG_MST("stream_enc[%d]: %p "
|
||||
"stream[%d].vcp_id: %d "
|
||||
"stream[%d].slot_count: %d\n",
|
||||
i,
|
||||
(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
||||
}
|
||||
|
||||
ASSERT(proposed_table.stream_count > 0);
|
||||
|
||||
/* update mst stream allocation table hardware state */
|
||||
link_encoder->funcs->update_mst_stream_allocation_table(
|
||||
link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
|
||||
/* poll for immediate branch device ACT handled */
|
||||
ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
||||
stream->ctx,
|
||||
stream);
|
||||
|
||||
if (ret != ACT_LINK_LOST) {
|
||||
/* send ALLOCATE_PAYLOAD sideband message with updated pbn */
|
||||
dm_helpers_dp_mst_send_payload_allocation(
|
||||
stream->ctx,
|
||||
stream,
|
||||
true);
|
||||
}
|
||||
|
||||
/* increase throttled vcp size */
|
||||
pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);
|
||||
pbn_per_slot = get_pbn_per_slot(stream);
|
||||
avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
|
||||
|
||||
stream_encoder->funcs->set_throttled_vcp_size(
|
||||
stream_encoder,
|
||||
avg_time_slots_per_mtp);
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->link;
|
||||
struct link_encoder *link_encoder = NULL;
|
||||
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc;
|
||||
struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;
|
||||
#endif
|
||||
struct dp_mst_stream_allocation_table proposed_table = {0};
|
||||
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
|
||||
uint8_t i;
|
||||
int i;
|
||||
bool mst_mode = (link->type == dc_connection_mst_branch);
|
||||
DC_LOGGER_INIT(link->ctx->logger);
|
||||
|
||||
@@ -3545,9 +3774,28 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
*/
|
||||
|
||||
/* slot X.Y */
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
|
||||
case DP_8b_10b_ENCODING:
|
||||
stream_encoder->funcs->set_throttled_vcp_size(
|
||||
stream_encoder,
|
||||
avg_time_slots_per_mtp);
|
||||
break;
|
||||
case DP_128b_132b_ENCODING:
|
||||
hpo_dp_link_encoder->funcs->set_throttled_vcp_size(
|
||||
hpo_dp_link_encoder,
|
||||
hpo_dp_stream_encoder->inst,
|
||||
avg_time_slots_per_mtp);
|
||||
break;
|
||||
case DP_UNKNOWN_ENCODING:
|
||||
DC_LOG_ERROR("Failure: unknown encoding format\n");
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
#else
|
||||
stream_encoder->funcs->set_throttled_vcp_size(
|
||||
stream_encoder,
|
||||
avg_time_slots_per_mtp);
|
||||
#endif
|
||||
|
||||
/* TODO: which component is responsible for remove payload table? */
|
||||
if (mst_mode) {
|
||||
@@ -3557,8 +3805,16 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
&proposed_table,
|
||||
false)) {
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
update_mst_stream_alloc_table(
|
||||
link,
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
pipe_ctx->stream_res.hpo_dp_stream_enc,
|
||||
&proposed_table);
|
||||
#else
|
||||
update_mst_stream_alloc_table(
|
||||
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
DC_LOG_WARNING("Failed to update"
|
||||
@@ -3574,6 +3830,20 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
link->mst_stream_alloc_table.stream_count);
|
||||
|
||||
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
DC_LOG_MST("stream_enc[%d]: %p "
|
||||
"stream[%d].hpo_dp_stream_enc: %p "
|
||||
"stream[%d].vcp_id: %d "
|
||||
"stream[%d].slot_count: %d\n",
|
||||
i,
|
||||
(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
|
||||
i,
|
||||
(void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
||||
#else
|
||||
DC_LOG_MST("stream_enc[%d]: %p "
|
||||
"stream[%d].vcp_id: %d "
|
||||
"stream[%d].slot_count: %d\n",
|
||||
@@ -3583,11 +3853,44 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
||||
i,
|
||||
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
enum dc_status status;
|
||||
uint8_t mst_alloc_slots = 0, prev_mst_slots_in_use = 0xFF;
|
||||
|
||||
for (i = 0; i < link->mst_stream_alloc_table.stream_count; i++)
|
||||
mst_alloc_slots += link->mst_stream_alloc_table.stream_allocations[i].slot_count;
|
||||
|
||||
status = dc_process_dmub_set_mst_slots(link->dc, link->link_index,
|
||||
mst_alloc_slots, &prev_mst_slots_in_use);
|
||||
ASSERT(status != DC_NOT_SUPPORTED);
|
||||
DC_LOG_MST("dpia : status[%d]: alloc_slots[%d]: used_slots[%d]\n",
|
||||
status, mst_alloc_slots, prev_mst_slots_in_use);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
|
||||
case DP_8b_10b_ENCODING:
|
||||
link_encoder->funcs->update_mst_stream_allocation_table(
|
||||
link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
break;
|
||||
case DP_128b_132b_ENCODING:
|
||||
hpo_dp_link_encoder->funcs->update_stream_allocation_table(
|
||||
hpo_dp_link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
break;
|
||||
case DP_UNKNOWN_ENCODING:
|
||||
DC_LOG_ERROR("Failure: unknown encoding format\n");
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
#else
|
||||
link_encoder->funcs->update_mst_stream_allocation_table(
|
||||
link_encoder,
|
||||
&link->mst_stream_alloc_table);
|
||||
#endif
|
||||
|
||||
if (mst_mode) {
|
||||
dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
||||
@@ -3610,6 +3913,9 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
|
||||
struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct link_encoder *link_enc = NULL;
|
||||
struct dc_state *state = pipe_ctx->stream->ctx->dc->current_state;
|
||||
struct link_enc_assignment link_enc_assign;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (cp_psp && cp_psp->funcs.update_stream_config) {
|
||||
@@ -3623,9 +3929,72 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
|
||||
config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY) {
|
||||
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY ||
|
||||
pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
link_enc = pipe_ctx->stream->link->link_enc;
|
||||
config.dio_output_type = pipe_ctx->stream->link->ep_type;
|
||||
config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY)
|
||||
link_enc = pipe_ctx->stream->link->link_enc;
|
||||
else if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
|
||||
if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) {
|
||||
link_enc = link_enc_cfg_get_link_enc_used_by_stream(
|
||||
pipe_ctx->stream->ctx->dc,
|
||||
pipe_ctx->stream);
|
||||
}
|
||||
// Initialize PHY ID with ABCDE - 01234 mapping except when it is B0
|
||||
config.phy_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
|
||||
|
||||
//look up the link_enc_assignment for the current pipe_ctx
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (pipe_ctx->stream == state->streams[i]) {
|
||||
link_enc_assign = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
|
||||
}
|
||||
}
|
||||
// Add flag to guard new A0 DIG mapping
|
||||
if (pipe_ctx->stream->ctx->dc->enable_c20_dtm_b0 == true) {
|
||||
config.dig_be = link_enc_assign.eng_id;
|
||||
config.dio_output_type = pipe_ctx->stream->link->ep_type;
|
||||
config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
|
||||
} else {
|
||||
config.dio_output_type = 0;
|
||||
config.dio_output_idx = 0;
|
||||
}
|
||||
|
||||
// Add flag to guard B0 implementation
|
||||
if (pipe_ctx->stream->ctx->dc->enable_c20_dtm_b0 == true &&
|
||||
link_enc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
link_enc = link_enc_assign.stream->link_enc;
|
||||
|
||||
// enum ID 1-4 maps to DPIA PHY ID 0-3
|
||||
config.phy_idx = link_enc_assign.ep_id.link_id.enum_id - ENUM_ID_1;
|
||||
} else { // for non DPIA mode over B0, ABCDE maps to 01564
|
||||
|
||||
switch (link_enc->transmitter) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
config.phy_idx = 0;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
config.phy_idx = 1;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
config.phy_idx = 5;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
config.phy_idx = 6;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
config.phy_idx = 4;
|
||||
break;
|
||||
default:
|
||||
config.phy_idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) {
|
||||
link_enc = link_enc_cfg_get_link_enc_used_by_stream(
|
||||
pipe_ctx->stream->ctx->dc,
|
||||
|
||||
@@ -554,6 +554,7 @@ bool dal_ddc_service_query_ddc_data(
|
||||
payload.address = address;
|
||||
payload.reply = NULL;
|
||||
payload.defer_delay = get_defer_delay(ddc);
|
||||
payload.write_status_update = false;
|
||||
|
||||
if (write_size != 0) {
|
||||
payload.write = true;
|
||||
@@ -625,24 +626,24 @@ bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
|
||||
do {
|
||||
struct aux_payload current_payload;
|
||||
bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >=
|
||||
payload->length;
|
||||
payload->length ? true : false;
|
||||
uint32_t payload_length = is_end_of_payload ?
|
||||
payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
|
||||
|
||||
current_payload.address = payload->address;
|
||||
current_payload.data = &payload->data[retrieved];
|
||||
current_payload.defer_delay = payload->defer_delay;
|
||||
current_payload.i2c_over_aux = payload->i2c_over_aux;
|
||||
current_payload.length = is_end_of_payload ?
|
||||
payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
|
||||
/* set mot (middle of transaction) to false
|
||||
* if it is the last payload
|
||||
*/
|
||||
current_payload.length = payload_length;
|
||||
/* set mot (middle of transaction) to false if it is the last payload */
|
||||
current_payload.mot = is_end_of_payload ? payload->mot:true;
|
||||
current_payload.write_status_update = false;
|
||||
current_payload.reply = payload->reply;
|
||||
current_payload.write = payload->write;
|
||||
|
||||
ret = dc_link_aux_transfer_with_retries(ddc, ¤t_payload);
|
||||
|
||||
retrieved += current_payload.length;
|
||||
retrieved += payload_length;
|
||||
} while (retrieved < payload->length && ret == true);
|
||||
|
||||
return ret;
|
||||
@@ -763,7 +764,7 @@ void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
|
||||
dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
|
||||
sizeof(offset), &tmds_config, sizeof(tmds_config));
|
||||
if (tmds_config & 0x1) {
|
||||
union hdmi_scdc_status_flags_data status_data = { {0} };
|
||||
union hdmi_scdc_status_flags_data status_data = {0};
|
||||
uint8_t scramble_status = 0;
|
||||
|
||||
offset = HDMI_SCDC_SCRAMBLER_STATUS;
|
||||
|
||||
@@ -106,6 +106,10 @@ static bool decide_fallback_link_setting(
|
||||
static struct dc_link_settings get_common_supported_link_settings(
|
||||
struct dc_link_settings link_setting_a,
|
||||
struct dc_link_settings link_setting_b);
|
||||
static void maximize_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
|
||||
static void override_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
|
||||
|
||||
static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
|
||||
const struct dc_link_settings *link_settings)
|
||||
@@ -259,7 +263,7 @@ static void dpcd_set_training_pattern(
|
||||
struct dc_link *link,
|
||||
enum dc_dp_training_pattern training_pattern)
|
||||
{
|
||||
union dpcd_training_pattern dpcd_pattern = { {0} };
|
||||
union dpcd_training_pattern dpcd_pattern = {0};
|
||||
|
||||
dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
|
||||
dc_dp_training_pattern_to_dpcd_training_pattern(
|
||||
@@ -401,8 +405,8 @@ enum dc_status dpcd_set_link_settings(
|
||||
uint8_t rate;
|
||||
enum dc_status status;
|
||||
|
||||
union down_spread_ctrl downspread = { {0} };
|
||||
union lane_count_set lane_count_set = { {0} };
|
||||
union down_spread_ctrl downspread = {0};
|
||||
union lane_count_set lane_count_set = {0};
|
||||
|
||||
downspread.raw = (uint8_t)
|
||||
(lt_settings->link_settings.link_spread);
|
||||
@@ -515,12 +519,10 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
enum dc_dp_training_pattern pattern,
|
||||
uint32_t offset)
|
||||
{
|
||||
union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
uint32_t dpcd_base_lt_offset;
|
||||
|
||||
uint8_t dpcd_lt_buffer[5] = {0};
|
||||
union dpcd_training_pattern dpcd_pattern = { {0} };
|
||||
union dpcd_training_pattern dpcd_pattern = { 0 };
|
||||
uint32_t size_in_bytes;
|
||||
bool edp_workaround = false; /* TODO link_prop.INTERNAL */
|
||||
dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
|
||||
@@ -554,16 +556,14 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
|
||||
}
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->lane_settings, dpcd_lane);
|
||||
|
||||
/* concatenate everything into one buffer*/
|
||||
|
||||
size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
|
||||
size_in_bytes = lt_settings->link_settings.lane_count *
|
||||
sizeof(lt_settings->dpcd_lane_settings[0]);
|
||||
|
||||
// 0x00103 - 0x00102
|
||||
memmove(
|
||||
&dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
|
||||
dpcd_lane,
|
||||
lt_settings->dpcd_lane_settings,
|
||||
size_in_bytes);
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
@@ -575,7 +575,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
@@ -584,10 +584,10 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
} else {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
@@ -595,17 +595,17 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
|
||||
__func__,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
|
||||
__func__,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
}
|
||||
if (edp_workaround) {
|
||||
/* for eDP write in 2 parts because the 5-byte burst is
|
||||
@@ -620,7 +620,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
core_link_write_dpcd(
|
||||
link,
|
||||
DP_TRAINING_LANE0_SET,
|
||||
(uint8_t *)(dpcd_lane),
|
||||
(uint8_t *)(lt_settings->dpcd_lane_settings),
|
||||
size_in_bytes);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@@ -711,34 +711,44 @@ void dp_hw_to_dpcd_lane_settings(
|
||||
}
|
||||
}
|
||||
|
||||
void dp_update_drive_settings(
|
||||
struct link_training_settings *dest,
|
||||
struct link_training_settings src)
|
||||
void dp_decide_lane_settings(
|
||||
const struct link_training_settings *lt_settings,
|
||||
const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
|
||||
struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
|
||||
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
|
||||
{
|
||||
uint32_t lane;
|
||||
for (lane = 0; lane < src.link_settings.lane_count; lane++) {
|
||||
if (dest->voltage_swing == NULL)
|
||||
dest->lane_settings[lane].VOLTAGE_SWING = src.lane_settings[lane].VOLTAGE_SWING;
|
||||
else
|
||||
dest->lane_settings[lane].VOLTAGE_SWING = *dest->voltage_swing;
|
||||
|
||||
if (dest->pre_emphasis == NULL)
|
||||
dest->lane_settings[lane].PRE_EMPHASIS = src.lane_settings[lane].PRE_EMPHASIS;
|
||||
else
|
||||
dest->lane_settings[lane].PRE_EMPHASIS = *dest->pre_emphasis;
|
||||
|
||||
if (dest->post_cursor2 == NULL)
|
||||
dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2;
|
||||
else
|
||||
dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2;
|
||||
|
||||
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_8b_10b_ENCODING) {
|
||||
hw_lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)(ln_adjust[lane].bits.
|
||||
VOLTAGE_SWING_LANE);
|
||||
hw_lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)(ln_adjust[lane].bits.
|
||||
PRE_EMPHASIS_LANE);
|
||||
}
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dest->ffe_preset == NULL)
|
||||
dest->lane_settings[lane].FFE_PRESET = src.lane_settings[lane].FFE_PRESET;
|
||||
else
|
||||
dest->lane_settings[lane].FFE_PRESET = *dest->ffe_preset;
|
||||
else if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
hw_lane_settings[lane].FFE_PRESET.raw =
|
||||
ln_adjust[lane].tx_ffe.PRESET_VALUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
|
||||
|
||||
if (lt_settings->disallow_per_lane_settings) {
|
||||
/* we find the maximum of the requested settings across all lanes*/
|
||||
/* and set this maximum for all lanes*/
|
||||
maximize_lane_settings(lt_settings, hw_lane_settings);
|
||||
override_lane_settings(lt_settings, hw_lane_settings);
|
||||
|
||||
if (lt_settings->always_match_dpcd_with_hw_lane_settings)
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static uint8_t get_nibble_at_index(const uint8_t *buf,
|
||||
@@ -768,55 +778,29 @@ static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
|
||||
|
||||
}
|
||||
|
||||
static void find_max_drive_settings(
|
||||
const struct link_training_settings *link_training_setting,
|
||||
struct link_training_settings *max_lt_setting)
|
||||
static void maximize_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
|
||||
{
|
||||
uint32_t lane;
|
||||
struct dc_lane_settings max_requested;
|
||||
|
||||
max_requested.VOLTAGE_SWING =
|
||||
link_training_setting->
|
||||
lane_settings[0].VOLTAGE_SWING;
|
||||
max_requested.PRE_EMPHASIS =
|
||||
link_training_setting->
|
||||
lane_settings[0].PRE_EMPHASIS;
|
||||
/*max_requested.postCursor2 =
|
||||
* link_training_setting->laneSettings[0].postCursor2;*/
|
||||
max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
|
||||
max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
max_requested.FFE_PRESET =
|
||||
link_training_setting->lane_settings[0].FFE_PRESET;
|
||||
max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
|
||||
#endif
|
||||
|
||||
/* Determine what the maximum of the requested settings are*/
|
||||
for (lane = 1; lane < link_training_setting->link_settings.lane_count;
|
||||
lane++) {
|
||||
if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
|
||||
max_requested.VOLTAGE_SWING)
|
||||
for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
|
||||
if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
|
||||
max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
|
||||
|
||||
max_requested.VOLTAGE_SWING =
|
||||
link_training_setting->
|
||||
lane_settings[lane].VOLTAGE_SWING;
|
||||
|
||||
if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
|
||||
max_requested.PRE_EMPHASIS)
|
||||
max_requested.PRE_EMPHASIS =
|
||||
link_training_setting->
|
||||
lane_settings[lane].PRE_EMPHASIS;
|
||||
|
||||
/*
|
||||
if (link_training_setting->laneSettings[lane].postCursor2 >
|
||||
max_requested.postCursor2)
|
||||
{
|
||||
max_requested.postCursor2 =
|
||||
link_training_setting->laneSettings[lane].postCursor2;
|
||||
}
|
||||
*/
|
||||
if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
|
||||
max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (link_training_setting->lane_settings[lane].FFE_PRESET.settings.level >
|
||||
if (lane_settings[lane].FFE_PRESET.settings.level >
|
||||
max_requested.FFE_PRESET.settings.level)
|
||||
max_requested.FFE_PRESET.settings.level =
|
||||
link_training_setting->
|
||||
lane_settings[lane].FFE_PRESET.settings.level;
|
||||
#endif
|
||||
}
|
||||
@@ -828,10 +812,6 @@ static void find_max_drive_settings(
|
||||
|
||||
if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
|
||||
max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
|
||||
/*
|
||||
if (max_requested.postCursor2 > PostCursor2_MaxLevel)
|
||||
max_requested.postCursor2 = PostCursor2_MaxLevel;
|
||||
*/
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
|
||||
max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
|
||||
@@ -845,61 +825,58 @@ static void find_max_drive_settings(
|
||||
get_max_pre_emphasis_for_voltage_swing(
|
||||
max_requested.VOLTAGE_SWING);
|
||||
|
||||
/*
|
||||
* Post Cursor2 levels are completely independent from
|
||||
* pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
|
||||
* can only be applied to each allowable combination of voltage
|
||||
* swing and pre-emphasis levels */
|
||||
/* if ( max_requested.postCursor2 >
|
||||
* getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
|
||||
* max_requested.postCursor2 =
|
||||
* getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
|
||||
*/
|
||||
|
||||
max_lt_setting->link_settings.link_rate =
|
||||
link_training_setting->link_settings.link_rate;
|
||||
max_lt_setting->link_settings.lane_count =
|
||||
link_training_setting->link_settings.lane_count;
|
||||
max_lt_setting->link_settings.link_spread =
|
||||
link_training_setting->link_settings.link_spread;
|
||||
|
||||
for (lane = 0; lane <
|
||||
link_training_setting->link_settings.lane_count;
|
||||
lane++) {
|
||||
max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
|
||||
max_requested.VOLTAGE_SWING;
|
||||
max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
|
||||
max_requested.PRE_EMPHASIS;
|
||||
/*max_lt_setting->laneSettings[lane].postCursor2 =
|
||||
* max_requested.postCursor2;
|
||||
*/
|
||||
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
|
||||
lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
max_lt_setting->lane_settings[lane].FFE_PRESET =
|
||||
max_requested.FFE_PRESET;
|
||||
lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
static void override_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
|
||||
{
|
||||
uint32_t lane;
|
||||
|
||||
if (lt_settings->voltage_swing == NULL &&
|
||||
lt_settings->pre_emphasis == NULL &&
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
lt_settings->ffe_preset == NULL &&
|
||||
#endif
|
||||
lt_settings->post_cursor2 == NULL)
|
||||
|
||||
return;
|
||||
|
||||
for (lane = 1; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
if (lt_settings->voltage_swing)
|
||||
lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
|
||||
if (lt_settings->pre_emphasis)
|
||||
lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
|
||||
if (lt_settings->post_cursor2)
|
||||
lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (lt_settings->ffe_preset)
|
||||
lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
enum dc_status dp_get_lane_status_and_lane_adjust(
|
||||
struct dc_link *link,
|
||||
const struct link_training_settings *link_training_setting,
|
||||
union lane_status *ln_status,
|
||||
union lane_align_status_updated *ln_status_updated,
|
||||
struct link_training_settings *req_settings,
|
||||
union lane_status ln_status[LANE_COUNT_DP_MAX],
|
||||
union lane_align_status_updated *ln_align,
|
||||
union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
|
||||
uint32_t offset)
|
||||
{
|
||||
unsigned int lane01_status_address = DP_LANE0_1_STATUS;
|
||||
uint8_t lane_adjust_offset = 4;
|
||||
unsigned int lane01_adjust_address;
|
||||
uint8_t dpcd_buf[6] = {0};
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
struct link_training_settings request_settings = { {0} };
|
||||
uint32_t lane;
|
||||
enum dc_status status;
|
||||
|
||||
memset(req_settings, '\0', sizeof(struct link_training_settings));
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
lane01_status_address =
|
||||
DP_LANE0_1_STATUS_PHY_REPEATER1 +
|
||||
@@ -919,11 +896,11 @@ enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
|
||||
ln_status[lane].raw =
|
||||
get_nibble_at_index(&dpcd_buf[0], lane);
|
||||
dpcd_lane_adjust[lane].raw =
|
||||
ln_adjust[lane].raw =
|
||||
get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
|
||||
}
|
||||
|
||||
ln_status_updated->raw = dpcd_buf[2];
|
||||
ln_align->raw = dpcd_buf[2];
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
|
||||
@@ -962,55 +939,6 @@ enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
dpcd_buf[lane_adjust_offset + 1]);
|
||||
}
|
||||
|
||||
/*copy to req_settings*/
|
||||
request_settings.link_settings.lane_count =
|
||||
link_training_setting->link_settings.lane_count;
|
||||
request_settings.link_settings.link_rate =
|
||||
link_training_setting->link_settings.link_rate;
|
||||
request_settings.link_settings.link_spread =
|
||||
link_training_setting->link_settings.link_spread;
|
||||
|
||||
for (lane = 0; lane <
|
||||
(uint32_t)(link_training_setting->link_settings.lane_count);
|
||||
lane++) {
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
request_settings.lane_settings[lane].FFE_PRESET.raw =
|
||||
dpcd_lane_adjust[lane].tx_ffe.PRESET_VALUE;
|
||||
} else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_8b_10b_ENCODING) {
|
||||
request_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
|
||||
VOLTAGE_SWING_LANE);
|
||||
request_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
|
||||
PRE_EMPHASIS_LANE);
|
||||
}
|
||||
#else
|
||||
request_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
|
||||
VOLTAGE_SWING_LANE);
|
||||
request_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
|
||||
PRE_EMPHASIS_LANE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Note: for postcursor2, read adjusted
|
||||
* postcursor2 settings from*/
|
||||
/*DpcdAddress_AdjustRequestPostCursor2 =
|
||||
*0x020C (not implemented yet)*/
|
||||
|
||||
/* we find the maximum of the requested settings across all lanes*/
|
||||
/* and set this maximum for all lanes*/
|
||||
find_max_drive_settings(&request_settings, req_settings);
|
||||
|
||||
/* if post cursor 2 is needed in the future,
|
||||
* read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
|
||||
*/
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1019,7 +947,6 @@ enum dc_status dpcd_set_lane_settings(
|
||||
const struct link_training_settings *link_training_setting,
|
||||
uint32_t offset)
|
||||
{
|
||||
union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
|
||||
unsigned int lane0_set_address;
|
||||
enum dc_status status;
|
||||
|
||||
@@ -1029,34 +956,11 @@ enum dc_status dpcd_set_lane_settings(
|
||||
lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
|
||||
((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(link_training_setting,
|
||||
link_training_setting->lane_settings,
|
||||
dpcd_lane);
|
||||
|
||||
status = core_link_write_dpcd(link,
|
||||
lane0_set_address,
|
||||
(uint8_t *)(dpcd_lane),
|
||||
(uint8_t *)(link_training_setting->dpcd_lane_settings),
|
||||
link_training_setting->link_settings.lane_count);
|
||||
|
||||
/*
|
||||
if (LTSettings.link.rate == LinkRate_High2)
|
||||
{
|
||||
DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
|
||||
for ( uint32_t lane = 0;
|
||||
lane < lane_count_DPMax; lane++)
|
||||
{
|
||||
dpcd_lane2[lane].bits.post_cursor2_set =
|
||||
static_cast<unsigned char>(
|
||||
LTSettings.laneSettings[lane].postCursor2);
|
||||
dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
|
||||
}
|
||||
m_pDpcdAccessSrv->WriteDpcdData(
|
||||
DpcdAddress_Lane0Set2,
|
||||
reinterpret_cast<unsigned char*>(dpcd_lane2),
|
||||
LTSettings.link.lanes);
|
||||
}
|
||||
*/
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
@@ -1066,7 +970,7 @@ enum dc_status dpcd_set_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
@@ -1075,10 +979,10 @@ enum dc_status dpcd_set_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
|
||||
} else {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@@ -1087,17 +991,17 @@ enum dc_status dpcd_set_lane_settings(
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
|
||||
__func__,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
|
||||
__func__,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -1110,7 +1014,7 @@ bool dp_is_max_vs_reached(
|
||||
for (lane = 0; lane <
|
||||
(uint32_t)(lt_settings->link_settings.lane_count);
|
||||
lane++) {
|
||||
if (lt_settings->lane_settings[lane].VOLTAGE_SWING
|
||||
if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
|
||||
== VOLTAGE_SWING_MAX_LEVEL)
|
||||
return true;
|
||||
}
|
||||
@@ -1140,17 +1044,17 @@ static bool perform_post_lt_adj_req_sequence(
|
||||
adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
|
||||
adj_req_timer++) {
|
||||
|
||||
struct link_training_settings req_settings;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
|
||||
union lane_align_status_updated
|
||||
dpcd_lane_status_updated;
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
dp_get_lane_status_and_drive_settings(
|
||||
dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
DPRX);
|
||||
|
||||
if (dpcd_lane_status_updated.bits.
|
||||
@@ -1168,11 +1072,10 @@ static bool perform_post_lt_adj_req_sequence(
|
||||
for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
|
||||
|
||||
if (lt_settings->
|
||||
lane_settings[lane].VOLTAGE_SWING !=
|
||||
req_settings.lane_settings[lane].
|
||||
VOLTAGE_SWING ||
|
||||
lt_settings->lane_settings[lane].PRE_EMPHASIS !=
|
||||
req_settings.lane_settings[lane].PRE_EMPHASIS) {
|
||||
dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
|
||||
dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
|
||||
lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
|
||||
dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
|
||||
|
||||
req_drv_setting_changed = true;
|
||||
break;
|
||||
@@ -1180,8 +1083,8 @@ static bool perform_post_lt_adj_req_sequence(
|
||||
}
|
||||
|
||||
if (req_drv_setting_changed) {
|
||||
dp_update_drive_settings(
|
||||
lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
|
||||
dc_link_dp_set_drive_settings(link,
|
||||
lt_settings);
|
||||
@@ -1261,16 +1164,15 @@ static enum link_training_result perform_channel_equalization_sequence(
|
||||
struct link_training_settings *lt_settings,
|
||||
uint32_t offset)
|
||||
{
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_dp_training_pattern tr_pattern;
|
||||
uint32_t retries_ch_eq;
|
||||
uint32_t wait_time_microsec;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = {0};
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
|
||||
|
||||
/* Note: also check that TPS4 is a supported feature*/
|
||||
|
||||
tr_pattern = lt_settings->pattern_for_eq;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@@ -1316,12 +1218,12 @@ static enum link_training_result perform_channel_equalization_sequence(
|
||||
/* 4. Read lane status and requested
|
||||
* drive settings as set by the sink*/
|
||||
|
||||
dp_get_lane_status_and_drive_settings(
|
||||
dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
offset);
|
||||
|
||||
/* 5. check CR done*/
|
||||
@@ -1335,7 +1237,8 @@ static enum link_training_result perform_channel_equalization_sequence(
|
||||
return LINK_TRAINING_SUCCESS;
|
||||
|
||||
/* 7. update VS/PE/PC2 in lt_settings*/
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
return LINK_TRAINING_EQ_FAIL_EQ;
|
||||
@@ -1361,10 +1264,10 @@ static enum link_training_result perform_clock_recovery_sequence(
|
||||
uint32_t retries_cr;
|
||||
uint32_t retry_count;
|
||||
uint32_t wait_time_microsec;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
|
||||
union lane_align_status_updated dpcd_lane_status_updated;
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
retries_cr = 0;
|
||||
retry_count = 0;
|
||||
@@ -1418,12 +1321,12 @@ static enum link_training_result perform_clock_recovery_sequence(
|
||||
/* 4. Read lane status and requested drive
|
||||
* settings as set by the sink
|
||||
*/
|
||||
dp_get_lane_status_and_drive_settings(
|
||||
dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
offset);
|
||||
|
||||
/* 5. check CR done*/
|
||||
@@ -1441,33 +1344,25 @@ static enum link_training_result perform_clock_recovery_sequence(
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) &&
|
||||
lt_settings->lane_settings[0].FFE_PRESET.settings.level ==
|
||||
req_settings.lane_settings[0].FFE_PRESET.settings.level)
|
||||
retries_cr++;
|
||||
else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) &&
|
||||
lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING)
|
||||
retries_cr++;
|
||||
else
|
||||
retries_cr = 0;
|
||||
#else
|
||||
/* 7. same lane settings*/
|
||||
/* Note: settings are the same for all lanes,
|
||||
* so comparing first lane is sufficient*/
|
||||
if ((lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING)
|
||||
&& (lt_settings->lane_settings[0].PRE_EMPHASIS ==
|
||||
req_settings.lane_settings[0].PRE_EMPHASIS))
|
||||
if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) &&
|
||||
lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
|
||||
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
|
||||
retries_cr++;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) &&
|
||||
lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
|
||||
dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
|
||||
retries_cr++;
|
||||
#endif
|
||||
else
|
||||
retries_cr = 0;
|
||||
#endif
|
||||
|
||||
/* 8. update VS/PE/PC2 in lt_settings*/
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
@@ -1487,7 +1382,7 @@ static inline enum link_training_result dp_transition_to_video_idle(
|
||||
struct link_training_settings *lt_settings,
|
||||
enum link_training_result status)
|
||||
{
|
||||
union lane_count_set lane_count_set = { {0} };
|
||||
union lane_count_set lane_count_set = {0};
|
||||
|
||||
/* 4. mainlink output idle pattern*/
|
||||
dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
|
||||
@@ -1596,6 +1491,9 @@ static inline void decide_8b_10b_training_settings(
|
||||
lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
|
||||
lt_settings->enhanced_framing = 1;
|
||||
lt_settings->should_set_fec_ready = true;
|
||||
lt_settings->disallow_per_lane_settings = true;
|
||||
lt_settings->always_match_dpcd_with_hw_lane_settings = true;
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@@ -1621,6 +1519,9 @@ static inline void decide_128b_132b_training_settings(struct dc_link *link,
|
||||
link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
|
||||
lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
|
||||
LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
|
||||
lt_settings->disallow_per_lane_settings = true;
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1661,7 +1562,13 @@ static void override_training_settings(
|
||||
if (overrides->ffe_preset != NULL)
|
||||
lt_settings->ffe_preset = overrides->ffe_preset;
|
||||
#endif
|
||||
|
||||
/* Override HW lane settings with BIOS forced values if present */
|
||||
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
|
||||
link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
|
||||
lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
|
||||
lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
|
||||
lt_settings->always_match_dpcd_with_hw_lane_settings = false;
|
||||
}
|
||||
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
lt_settings->lane_settings[lane].VOLTAGE_SWING =
|
||||
lt_settings->voltage_swing != NULL ?
|
||||
@@ -1677,6 +1584,9 @@ static void override_training_settings(
|
||||
: POST_CURSOR2_DISABLED;
|
||||
}
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
|
||||
/* Initialize training timings */
|
||||
if (overrides->cr_pattern_time != NULL)
|
||||
lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
|
||||
@@ -1800,7 +1710,7 @@ static enum dc_status configure_lttpr_mode_non_transparent(
|
||||
|
||||
static void repeater_training_done(struct dc_link *link, uint32_t offset)
|
||||
{
|
||||
union dpcd_training_pattern dpcd_pattern = { {0} };
|
||||
union dpcd_training_pattern dpcd_pattern = {0};
|
||||
|
||||
const uint32_t dpcd_base_lt_offset =
|
||||
DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
|
||||
@@ -1947,6 +1857,9 @@ void dc_link_dp_set_drive_settings(
|
||||
/* program ASIC PHY settings*/
|
||||
dp_set_hw_lane_settings(link, lt_settings, DPRX);
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
|
||||
/* Notify DP sink the PHY settings from source */
|
||||
dpcd_set_lane_settings(link, lt_settings, DPRX);
|
||||
}
|
||||
@@ -2074,38 +1987,43 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
|
||||
struct dc_link *link,
|
||||
struct link_training_settings *lt_settings)
|
||||
{
|
||||
uint8_t loop_count = 0;
|
||||
uint8_t loop_count;
|
||||
uint32_t aux_rd_interval = 0;
|
||||
uint32_t wait_time = 0;
|
||||
struct link_training_settings req_settings;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = {0};
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
|
||||
enum link_training_result status = LINK_TRAINING_SUCCESS;
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
|
||||
|
||||
/* Transmit 128b/132b_TPS1 over Main-Link and Set TRAINING_PATTERN_SET to 01h */
|
||||
/* Transmit 128b/132b_TPS1 over Main-Link */
|
||||
dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, DPRX);
|
||||
/* Set TRAINING_PATTERN_SET to 01h */
|
||||
dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
|
||||
|
||||
/* Adjust TX_FFE_PRESET_VALUE as requested */
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
/* Adjust TX_FFE_PRESET_VALUE and Transmit 128b/132b_TPS2 over Main-Link */
|
||||
dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
dp_set_hw_lane_settings(link, lt_settings, DPRX);
|
||||
dpcd_set_lane_settings(link, lt_settings, DPRX);
|
||||
|
||||
/* Transmit 128b/132b_TPS2 over Main-Link and Set TRAINING_PATTERN_SET to 02h */
|
||||
dp_set_hw_training_pattern(link, lt_settings->pattern_for_eq, DPRX);
|
||||
dpcd_set_training_pattern(link, lt_settings->pattern_for_eq);
|
||||
|
||||
/* Set loop counter to start from 1 */
|
||||
loop_count = 1;
|
||||
|
||||
/* Set TRAINING_PATTERN_SET to 02h and TX_FFE_PRESET_VALUE in one AUX transaction */
|
||||
dpcd_set_lt_pattern_and_lane_settings(link, lt_settings,
|
||||
lt_settings->pattern_for_eq, DPRX);
|
||||
|
||||
/* poll for channel EQ done */
|
||||
while (status == LINK_TRAINING_SUCCESS) {
|
||||
loop_count++;
|
||||
dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
|
||||
wait_time += aux_rd_interval;
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
|
||||
if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
|
||||
dpcd_lane_status)) {
|
||||
@@ -2119,6 +2037,7 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
|
||||
dp_set_hw_lane_settings(link, lt_settings, DPRX);
|
||||
dpcd_set_lane_settings(link, lt_settings, DPRX);
|
||||
}
|
||||
loop_count++;
|
||||
}
|
||||
|
||||
/* poll for EQ interlane align done */
|
||||
@@ -2134,8 +2053,8 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
|
||||
dp_wait_for_training_aux_rd_interval(link,
|
||||
lt_settings->eq_pattern_time);
|
||||
wait_time += lt_settings->eq_pattern_time;
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2148,9 +2067,9 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
|
||||
{
|
||||
/* Assumption: assume hardware has transmitted eq pattern */
|
||||
enum link_training_result status = LINK_TRAINING_SUCCESS;
|
||||
struct link_training_settings req_settings;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = {0};
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
uint32_t wait_time = 0;
|
||||
|
||||
/* initiate CDS done sequence */
|
||||
@@ -2161,8 +2080,8 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
|
||||
dp_wait_for_training_aux_rd_interval(link,
|
||||
lt_settings->cds_pattern_time);
|
||||
wait_time += lt_settings->cds_pattern_time;
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
|
||||
dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
|
||||
/* pass */
|
||||
@@ -2219,7 +2138,7 @@ static enum link_training_result dp_perform_8b_10b_link_training(
|
||||
}
|
||||
|
||||
for (lane = 0; lane < (uint8_t)lt_settings->link_settings.lane_count; lane++)
|
||||
lt_settings->lane_settings[lane].VOLTAGE_SWING = VOLTAGE_SWING_LEVEL0;
|
||||
lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET = VOLTAGE_SWING_LEVEL0;
|
||||
}
|
||||
|
||||
if (status == LINK_TRAINING_SUCCESS) {
|
||||
@@ -2863,7 +2782,7 @@ bool dp_verify_link_cap(
|
||||
link->verified_link_cap = *known_limit_link_setting;
|
||||
return true;
|
||||
} else if (link->link_enc && link->dc->res_pool->funcs->link_encs_assign &&
|
||||
!link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine)) {
|
||||
!link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine, link)) {
|
||||
link->verified_link_cap = initial_link_settings;
|
||||
return true;
|
||||
}
|
||||
@@ -3523,6 +3442,8 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
|
||||
if (psr_error_status.bits.LINK_CRC_ERROR ||
|
||||
psr_error_status.bits.RFB_STORAGE_ERROR ||
|
||||
psr_error_status.bits.VSC_SDP_ERROR) {
|
||||
bool allow_active;
|
||||
|
||||
/* Acknowledge and clear error bits */
|
||||
dm_helpers_dp_write_dpcd(
|
||||
link->ctx,
|
||||
@@ -3532,8 +3453,10 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
|
||||
sizeof(psr_error_status.raw));
|
||||
|
||||
/* PSR error, disable and re-enable PSR */
|
||||
dc_link_set_psr_allow_active(link, false, true, false);
|
||||
dc_link_set_psr_allow_active(link, true, true, false);
|
||||
allow_active = false;
|
||||
dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
|
||||
allow_active = true;
|
||||
dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
|
||||
|
||||
return true;
|
||||
} else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
|
||||
@@ -3591,15 +3514,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
||||
#endif
|
||||
unsigned int test_pattern_size = 0;
|
||||
enum dp_test_pattern test_pattern;
|
||||
struct dc_link_training_settings link_settings;
|
||||
union lane_adjust dpcd_lane_adjust;
|
||||
unsigned int lane;
|
||||
struct link_training_settings link_training_settings;
|
||||
int i = 0;
|
||||
|
||||
dpcd_test_pattern.raw = 0;
|
||||
memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
|
||||
memset(&link_settings, 0, sizeof(link_settings));
|
||||
memset(&link_training_settings, 0, sizeof(link_training_settings));
|
||||
|
||||
/* get phy test pattern and pattern parameters from DP receiver */
|
||||
core_link_read_dpcd(
|
||||
@@ -3720,48 +3641,37 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
||||
#endif
|
||||
|
||||
/* prepare link training settings */
|
||||
link_settings.link = link->cur_link_settings;
|
||||
link_training_settings.link_settings = link->cur_link_settings;
|
||||
|
||||
for (lane = 0; lane <
|
||||
(unsigned int)(link->cur_link_settings.lane_count);
|
||||
lane++) {
|
||||
dpcd_lane_adjust.raw =
|
||||
get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(&link->cur_link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
link_settings.lane_settings[lane].FFE_PRESET.raw =
|
||||
dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
|
||||
} else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
|
||||
DP_8b_10b_ENCODING) {
|
||||
link_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)
|
||||
(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
|
||||
link_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)
|
||||
(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
|
||||
link_settings.lane_settings[lane].POST_CURSOR2 =
|
||||
link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
|
||||
(enum dc_post_cursor2)
|
||||
((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
|
||||
}
|
||||
#else
|
||||
link_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)
|
||||
(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
|
||||
link_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)
|
||||
(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
|
||||
link_settings.lane_settings[lane].POST_CURSOR2 =
|
||||
(enum dc_post_cursor2)
|
||||
((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
|
||||
dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
link_training_settings.lane_settings[i] =
|
||||
link_settings.lane_settings[i];
|
||||
link_training_settings.link_settings = link_settings.link;
|
||||
link_training_settings.allow_invalid_msa_timing_param = false;
|
||||
dp_hw_to_dpcd_lane_settings(&link_training_settings,
|
||||
link_training_settings.hw_lane_settings,
|
||||
link_training_settings.dpcd_lane_settings);
|
||||
/*Usage: Measure DP physical lane signal
|
||||
* by DP SI test equipment automatically.
|
||||
* PHY test pattern request is generated by equipment via HPD interrupt.
|
||||
@@ -4065,8 +3975,8 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
|
||||
bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
|
||||
bool defer_handling, bool *has_left_work)
|
||||
{
|
||||
union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
|
||||
union device_service_irq device_service_clear = { { 0 } };
|
||||
union hpd_irq_data hpd_irq_dpcd_data = {0};
|
||||
union device_service_irq device_service_clear = {0};
|
||||
enum dc_status result;
|
||||
bool status = false;
|
||||
|
||||
@@ -5939,7 +5849,7 @@ bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timin
|
||||
uint8_t link_bw_set;
|
||||
uint8_t link_rate_set;
|
||||
uint32_t req_bw;
|
||||
union lane_count_set lane_count_set = { {0} };
|
||||
union lane_count_set lane_count_set = {0};
|
||||
|
||||
ASSERT(link || crtc_timing); // invalid input
|
||||
|
||||
@@ -5993,6 +5903,25 @@ enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link)
|
||||
{
|
||||
struct dc_link_settings link_settings = {0};
|
||||
|
||||
if (!dc_is_dp_signal(link->connector_signal))
|
||||
return DP_UNKNOWN_ENCODING;
|
||||
|
||||
if (link->preferred_link_setting.lane_count !=
|
||||
LANE_COUNT_UNKNOWN &&
|
||||
link->preferred_link_setting.link_rate !=
|
||||
LINK_RATE_UNKNOWN) {
|
||||
link_settings = link->preferred_link_setting;
|
||||
} else {
|
||||
decide_mst_link_settings(link, &link_settings);
|
||||
}
|
||||
|
||||
return dp_get_link_encoding_format(&link_settings);
|
||||
}
|
||||
|
||||
// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
|
||||
static void get_lane_status(
|
||||
struct dc_link *link,
|
||||
|
||||
@@ -263,10 +263,10 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
|
||||
uint32_t retry_count = 0;
|
||||
/* From DP spec, CR read interval is always 100us. */
|
||||
uint32_t wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
uint8_t set_cfg_data;
|
||||
enum dpia_set_config_ts ts;
|
||||
|
||||
@@ -345,11 +345,12 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
hop);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@@ -371,16 +372,18 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
|
||||
* Note: settings are the same for all lanes,
|
||||
* so comparing first lane is sufficient.
|
||||
*/
|
||||
if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING &&
|
||||
lt_settings->lane_settings[0].PRE_EMPHASIS ==
|
||||
req_settings.lane_settings[0].PRE_EMPHASIS)
|
||||
if ((lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
|
||||
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
|
||||
&& (lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET ==
|
||||
dpcd_lane_adjust[0].bits.PRE_EMPHASIS_LANE))
|
||||
retries_cr++;
|
||||
else
|
||||
retries_cr = 0;
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->lane_settings,
|
||||
lt_settings->dpcd_lane_settings);
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
@@ -416,10 +419,10 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
|
||||
uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */
|
||||
uint32_t retry_count = 0;
|
||||
uint32_t wait_time_microsec = lt_settings->cr_pattern_time;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
/* Cap of LINK_TRAINING_MAX_CR_RETRY attempts at clock recovery.
|
||||
* Fix inherited from perform_clock_recovery_sequence() -
|
||||
@@ -445,11 +448,12 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
DPRX);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@@ -471,16 +475,17 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
|
||||
* Note: settings are the same for all lanes,
|
||||
* so comparing first lane is sufficient.
|
||||
*/
|
||||
if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING &&
|
||||
lt_settings->lane_settings[0].PRE_EMPHASIS ==
|
||||
req_settings.lane_settings[0].PRE_EMPHASIS)
|
||||
if ((lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
|
||||
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
|
||||
&& (lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET ==
|
||||
dpcd_lane_adjust[0].bits.PRE_EMPHASIS_LANE))
|
||||
retries_cr++;
|
||||
else
|
||||
retries_cr = 0;
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
@@ -566,10 +571,10 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
|
||||
enum dc_status status;
|
||||
enum dc_dp_training_pattern tr_pattern;
|
||||
uint32_t wait_time_microsec;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
uint8_t set_cfg_data;
|
||||
enum dpia_set_config_ts ts;
|
||||
|
||||
@@ -639,11 +644,12 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
hop);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@@ -664,7 +670,8 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
|
||||
}
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
/* Abort link training if equalization failed due to HPD unplug. */
|
||||
@@ -701,10 +708,10 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
|
||||
enum dc_status status;
|
||||
enum dc_dp_training_pattern tr_pattern = lt_settings->pattern_for_eq;
|
||||
uint32_t wait_time_microsec;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
wait_time_microsec = dpia_get_eq_aux_rd_interval(link, lt_settings, DPRX);
|
||||
|
||||
@@ -720,11 +727,12 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
DPRX);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@@ -745,7 +753,8 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
|
||||
}
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
/* Abort link training if equalization failed due to HPD unplug. */
|
||||
|
||||
@@ -488,16 +488,19 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream(
|
||||
return link_enc;
|
||||
}
|
||||
|
||||
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id)
|
||||
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link)
|
||||
{
|
||||
bool is_avail = true;
|
||||
int i;
|
||||
|
||||
/* Add assigned encoders to list. */
|
||||
/* An encoder is not available if it has already been assigned to a different endpoint. */
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct link_enc_assignment assignment = get_assignment(dc, i);
|
||||
struct display_endpoint_id ep_id = (struct display_endpoint_id) {
|
||||
.link_id = link->link_id,
|
||||
.ep_type = link->ep_type};
|
||||
|
||||
if (assignment.valid && assignment.eng_id == eng_id) {
|
||||
if (assignment.valid && assignment.eng_id == eng_id && !are_ep_ids_equal(&ep_id, &assignment.ep_id)) {
|
||||
is_avail = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1155,9 +1155,17 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
|
||||
pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
|
||||
}
|
||||
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
|
||||
pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
|
||||
res = false;
|
||||
if (!pipe_ctx->stream->ctx->dc->config.enable_windowed_mpo_odm) {
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
|
||||
pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
|
||||
res = false;
|
||||
} else {
|
||||
/* Clamp minimum viewport size */
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE)
|
||||
pipe_ctx->plane_res.scl_data.viewport.height = MIN_VIEWPORT_SIZE;
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
|
||||
pipe_ctx->plane_res.scl_data.viewport.width = MIN_VIEWPORT_SIZE;
|
||||
}
|
||||
|
||||
DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n"
|
||||
"src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n",
|
||||
@@ -3009,6 +3017,11 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla
|
||||
{
|
||||
enum dc_status res = DC_OK;
|
||||
|
||||
/* check if surface has invalid dimensions */
|
||||
if (plane_state->src_rect.width == 0 || plane_state->src_rect.height == 0 ||
|
||||
plane_state->dst_rect.width == 0 || plane_state->dst_rect.height == 0)
|
||||
return DC_FAIL_SURFACE_VALIDATE;
|
||||
|
||||
/* TODO For now validates pixel format only */
|
||||
if (dc->res_pool->funcs->validate_plane)
|
||||
return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);
|
||||
|
||||
@@ -202,6 +202,10 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
|
||||
new_stream->stream_id = new_stream->ctx->dc_stream_id_count;
|
||||
new_stream->ctx->dc_stream_id_count++;
|
||||
|
||||
/* If using dynamic encoder assignment, wait till stream committed to assign encoder. */
|
||||
if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign)
|
||||
new_stream->link_enc = NULL;
|
||||
|
||||
kref_init(&new_stream->refcount);
|
||||
|
||||
return new_stream;
|
||||
|
||||
@@ -47,7 +47,7 @@ struct aux_payload;
|
||||
struct set_config_cmd_payload;
|
||||
struct dmub_notification;
|
||||
|
||||
#define DC_VER "3.2.156"
|
||||
#define DC_VER "3.2.159"
|
||||
|
||||
#define MAX_SURFACES 3
|
||||
#define MAX_PLANES 6
|
||||
@@ -211,12 +211,12 @@ struct dc_dcc_setting {
|
||||
unsigned int max_uncompressed_blk_size;
|
||||
bool independent_64b_blks;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
//These bitfields to be used starting with DCN 3.0
|
||||
//These bitfields to be used starting with DCN
|
||||
struct {
|
||||
uint32_t dcc_256_64_64 : 1;//available in ASICs before DCN 3.0 (the worst compression case)
|
||||
uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN 3.0
|
||||
uint32_t dcc_256_128_128 : 1; //available starting with DCN 3.0
|
||||
uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN 3.0 (the best compression case)
|
||||
uint32_t dcc_256_64_64 : 1;//available in ASICs before DCN (the worst compression case)
|
||||
uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN
|
||||
uint32_t dcc_256_128_128 : 1; //available starting with DCN
|
||||
uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN (the best compression case)
|
||||
} dcc_controls;
|
||||
#endif
|
||||
};
|
||||
@@ -323,6 +323,7 @@ struct dc_config {
|
||||
bool multi_mon_pp_mclk_switch;
|
||||
bool disable_dmcu;
|
||||
bool enable_4to1MPC;
|
||||
bool enable_windowed_mpo_odm;
|
||||
bool allow_edp_hotplug_detection;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool clamp_min_dcfclk;
|
||||
@@ -342,6 +343,12 @@ enum visual_confirm {
|
||||
VISUAL_CONFIRM_SWIZZLE = 9,
|
||||
};
|
||||
|
||||
enum dc_psr_power_opts {
|
||||
psr_power_opt_invalid = 0x0,
|
||||
psr_power_opt_smu_opt_static_screen = 0x1,
|
||||
psr_power_opt_z10_static_screen = 0x10,
|
||||
};
|
||||
|
||||
enum dcc_option {
|
||||
DCC_ENABLE = 0,
|
||||
DCC_DISABLE = 1,
|
||||
@@ -664,6 +671,7 @@ struct dc_debug_options {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
/* TODO - remove once tested */
|
||||
bool legacy_dp2_lt;
|
||||
bool set_mst_en_for_sst;
|
||||
#endif
|
||||
union mem_low_power_enable_options enable_mem_low_power;
|
||||
union root_clock_optimization_options root_clock_optimization;
|
||||
@@ -724,6 +732,9 @@ struct dc {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool idle_optimizations_allowed;
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool enable_c20_dtm_b0;
|
||||
#endif
|
||||
|
||||
/* Require to maintain clocks and bandwidth for UEFI enabled HW */
|
||||
|
||||
@@ -930,6 +941,7 @@ union surface_update_flags {
|
||||
uint32_t bandwidth_change:1;
|
||||
uint32_t clock_change:1;
|
||||
uint32_t stereo_format_change:1;
|
||||
uint32_t lut_3d:1;
|
||||
uint32_t full_update:1;
|
||||
} bits;
|
||||
|
||||
@@ -1416,6 +1428,12 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
|
||||
uint32_t link_index,
|
||||
struct set_config_cmd_payload *payload,
|
||||
struct dmub_notification *notify);
|
||||
|
||||
enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
|
||||
uint32_t link_index,
|
||||
uint8_t mst_alloc_slots,
|
||||
uint8_t *mst_slots_in_use);
|
||||
|
||||
/*******************************************************************************
|
||||
* DSC Interfaces
|
||||
******************************************************************************/
|
||||
|
||||
@@ -174,11 +174,6 @@ struct dc_lane_settings {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dc_link_training_settings {
|
||||
struct dc_link_settings link;
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX];
|
||||
};
|
||||
|
||||
struct dc_link_training_overrides {
|
||||
enum dc_voltage_swing *voltage_swing;
|
||||
enum dc_pre_emphasis *pre_emphasis;
|
||||
|
||||
@@ -85,6 +85,7 @@ struct psr_settings {
|
||||
*/
|
||||
bool psr_frame_capture_indication_req;
|
||||
unsigned int psr_sdp_transmit_line_num_deadline;
|
||||
unsigned int psr_power_opt;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -123,6 +124,10 @@ struct dc_link {
|
||||
struct dc_link_settings cur_link_settings;
|
||||
struct dc_lane_settings cur_lane_setting[LANE_COUNT_DP_MAX];
|
||||
struct dc_link_settings preferred_link_setting;
|
||||
/* preferred_training_settings are override values that
|
||||
* come from DM. DM is responsible for the memory
|
||||
* management of the override pointers.
|
||||
*/
|
||||
struct dc_link_training_overrides preferred_training_settings;
|
||||
struct dp_audio_test_data audio_test_data;
|
||||
|
||||
@@ -177,11 +182,15 @@ struct dc_link {
|
||||
|
||||
struct psr_settings psr_settings;
|
||||
|
||||
/* Drive settings read from integrated info table */
|
||||
struct dc_lane_settings bios_forced_drive_settings;
|
||||
|
||||
/* MST record stream using this link */
|
||||
struct link_flags {
|
||||
bool dp_keep_receiver_powered;
|
||||
bool dp_skip_DID2;
|
||||
bool dp_skip_reset_segment;
|
||||
bool dp_mot_reset_segment;
|
||||
} wa_flags;
|
||||
struct link_mst_stream_allocation_table mst_stream_alloc_table;
|
||||
|
||||
@@ -267,8 +276,8 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link);
|
||||
|
||||
int dc_link_get_target_backlight_pwm(const struct dc_link *link);
|
||||
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable,
|
||||
bool wait, bool force_static);
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *dc_link, const bool *enable,
|
||||
bool wait, bool force_static, const unsigned int *power_opts);
|
||||
|
||||
bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state);
|
||||
|
||||
@@ -277,7 +286,6 @@ bool dc_link_setup_psr(struct dc_link *dc_link,
|
||||
struct psr_context *psr_context);
|
||||
|
||||
void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency);
|
||||
void blank_all_dp_displays(struct dc *dc, bool hw_init);
|
||||
|
||||
/* Request DC to detect if there is a Panel connected.
|
||||
* boot - If this call is during initial boot.
|
||||
@@ -296,6 +304,10 @@ enum dc_detect_reason {
|
||||
bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason);
|
||||
bool dc_link_get_hpd_state(struct dc_link *dc_link);
|
||||
enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn);
|
||||
enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn);
|
||||
#endif
|
||||
|
||||
/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
|
||||
* Return:
|
||||
@@ -425,4 +437,7 @@ uint32_t dc_bandwidth_in_kbps_from_timing(
|
||||
bool dc_link_is_fec_supported(const struct dc_link *link);
|
||||
bool dc_link_should_enable_fec(const struct dc_link *link);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link);
|
||||
#endif
|
||||
#endif /* DC_LINK_H_ */
|
||||
|
||||
@@ -115,6 +115,13 @@ struct periodic_interrupt_config {
|
||||
int lines_offset;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct dc_mst_stream_bw_update {
|
||||
bool is_increase; // is bandwidth reduced or increased
|
||||
uint32_t mst_stream_bw; // new mst bandwidth in kbps
|
||||
};
|
||||
#endif
|
||||
|
||||
union stream_update_flags {
|
||||
struct {
|
||||
uint32_t scaling:1;
|
||||
@@ -125,6 +132,9 @@ union stream_update_flags {
|
||||
uint32_t gamut_remap:1;
|
||||
uint32_t wb_update:1;
|
||||
uint32_t dsc_changed : 1;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
uint32_t mst_bw : 1;
|
||||
#endif
|
||||
} bits;
|
||||
|
||||
uint32_t raw;
|
||||
@@ -278,6 +288,9 @@ struct dc_stream_update {
|
||||
|
||||
struct dc_writeback_update *wb_update;
|
||||
struct dc_dsc_config *dsc_config;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct dc_mst_stream_bw_update *mst_bw_update;
|
||||
#endif
|
||||
struct dc_transfer_func *func_shaper;
|
||||
struct dc_3dlut *lut3d_func;
|
||||
|
||||
|
||||
@@ -653,6 +653,7 @@ enum dc_psr_state {
|
||||
PSR_STATE1a,
|
||||
PSR_STATE2,
|
||||
PSR_STATE2a,
|
||||
PSR_STATE2b,
|
||||
PSR_STATE3,
|
||||
PSR_STATE3Init,
|
||||
PSR_STATE4,
|
||||
|
||||
@@ -514,13 +514,15 @@ void dce_aud_az_configure(
|
||||
union audio_sample_rates sample_rates =
|
||||
audio_mode->sample_rates;
|
||||
uint8_t byte2 = audio_mode->max_bit_rate;
|
||||
uint8_t channel_count = audio_mode->channel_count;
|
||||
|
||||
/* adjust specific properties */
|
||||
switch (audio_format_code) {
|
||||
case AUDIO_FORMAT_CODE_LINEARPCM: {
|
||||
|
||||
check_audio_bandwidth(
|
||||
crtc_info,
|
||||
audio_mode->channel_count,
|
||||
channel_count,
|
||||
signal,
|
||||
&sample_rates);
|
||||
|
||||
@@ -548,7 +550,7 @@ void dce_aud_az_configure(
|
||||
|
||||
/* fill audio format data */
|
||||
set_reg_field_value(value,
|
||||
audio_mode->channel_count - 1,
|
||||
channel_count - 1,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
|
||||
MAX_CHANNELS);
|
||||
|
||||
|
||||
@@ -534,17 +534,26 @@ struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine
|
||||
static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
|
||||
{
|
||||
if (payload->i2c_over_aux) {
|
||||
if (payload->write_status_update) {
|
||||
if (payload->mot)
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT;
|
||||
else
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
|
||||
}
|
||||
if (payload->write) {
|
||||
if (payload->mot)
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
|
||||
else
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
|
||||
}
|
||||
if (payload->mot)
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
|
||||
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_READ;
|
||||
}
|
||||
if (payload->write)
|
||||
return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
|
||||
|
||||
return I2CAUX_TRANSACTION_ACTION_DP_READ;
|
||||
}
|
||||
|
||||
@@ -698,7 +707,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
||||
aux_defer_retries = 0,
|
||||
aux_i2c_defer_retries = 0,
|
||||
aux_timeout_retries = 0,
|
||||
aux_invalid_reply_retries = 0;
|
||||
aux_invalid_reply_retries = 0,
|
||||
aux_ack_m_retries = 0;
|
||||
|
||||
if (ddc_pin) {
|
||||
aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
|
||||
@@ -758,9 +768,27 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
||||
aux_defer_retries,
|
||||
AUX_MAX_RETRIES);
|
||||
goto fail;
|
||||
} else {
|
||||
} else
|
||||
udelay(300);
|
||||
} else if (payload->write && ret > 0) {
|
||||
/* sink requested more time to complete the write via AUX_ACKM */
|
||||
if (++aux_ack_m_retries >= AUX_MAX_RETRIES) {
|
||||
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
|
||||
LOG_FLAG_Error_I2cAux,
|
||||
"dce_aux_transfer_with_retries: FAILURE: aux_ack_m_retries=%d >= AUX_MAX_RETRIES=%d",
|
||||
aux_ack_m_retries,
|
||||
AUX_MAX_RETRIES);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* retry reading the write status until complete
|
||||
* NOTE: payload is modified here
|
||||
*/
|
||||
payload->write = false;
|
||||
payload->write_status_update = true;
|
||||
payload->length = 0;
|
||||
udelay(300);
|
||||
|
||||
} else
|
||||
return true;
|
||||
break;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user