drm for 5.17-rc1
core: - add privacy screen support - move nomodeset option into drm subsystem - clean up nomodeset handling in drivers - make drm_irq.c legacy - fix stack_depot name conflicts - remove DMA_BUF_SET_NAME ioctl restrictions - sysfs: send hotplug event - replace several DRM_* logging macros with drm_* - move hashtable to legacy code - add error return from gem_create_object - cma-helper: improve interfaces, drop CONFIG_DRM_KMS_CMA_HELPER - kernel.h related include cleanups - support XRGB2101010 source buffers ttm: - don't include drm hashtable - stop pruning fences after wait - documentation updates dma-buf: - add dma_resv selftest - add debugfs helpers - remove dma_resv_get_excl_unlocked - documentation - make fences mandatory in dma_resv_add_excl_fence dp: - add link training delay helpers gem: - link shmem/cma helpers into separate modules - use dma_resv iteratior - import dma-buf namespace into gem helper modules scheduler: - fence grab fix - lockdep fixes bridge: - switch to managed MIPI DSI helpers - register and attach during probe fixes - convert to YAML in several places. panel: - add bunch of new panesl simpledrm: - support FB_DAMAGE_CLIPS - support virtual screen sizes - add Apple M1 support amdgpu: - enable seamless boot for DCN 3.01 - runtime PM fixes - use drm_kms_helper_connector_hotplug_event - get all fences at once - use generic drm fb helpers - PSR/DPCD/LTTPR/DSC/PM/RAS/OLED/SRIOV fixes - add smart trace buffer (STB) for supported GPUs - display debugfs entries - new SMU debug option - Documentation update amdkfd: - IP discovery enumeration refactor - interface between driver fixes - SVM fixes - kfd uapi header to define some sysfs bitfields. i915: - support VESA panel backlights - enable ADL-P by default - add eDP privacy screen support - add Raptor Lake S (RPL-S) support - DG2 page table support - lots of GuC/HuC fw refactoring - refactored i915->gt interfaces - CD clock squashing support - enable 10-bit gamma support - update ADL-P DMC fw to v2.14 - enable runtime PM autosuspend by default - ADL-P DSI support - per-lane DP drive settings for ICL+ - add support for pipe C/D DMC firmware - Atomic gamma LUT updates - remove CCS FB stride restrictions on ADL-P - VRR platform support for display 11 - add support for display audio codec keepalive - lots of display refactoring - fix runtime PM handling during PXP suspend - improved eviction performance with async TTM moves - async VMA unbinding improvements - VMA locking refactoring - improved error capture robustness - use per device iommu checks - drop bits stealing from i915_sw_fence function ptr - remove dma_resv_prune - add IC cache invalidation on DG2 nouveau: - crc fixes - validate LUTs in atomic check - set HDMI AVI RGB quant to full tegra: - buffer objects reworks for dma-buf compat - NVDEC driver uAPI support - power management improvements etnaviv: - IOMMU enabled system support - fix > 4GB command buffer mapping - close a DoS vector - fix spurious GPU resets ast: - fix i2c initialization rcar-du: - DSI output support exynos: - replace legacy gpio interface - implement generic GEM object mmap msm: - dpu plane state cleanup in prep for multirect - dpu debugfs cleanups - dp support for sc7280 - a506 support - removal of struct_mutex - remove old eDP sub-driver anx7625: - support MIPI DSI input - support HDMI audio - fix reading EDID lvds: - fix bridge DT bindings megachips: - probe both bridges before registering dw-hdmi: - allow interlace on bridge ps8640: - enable runtime PM - support aux-bus tx358768: - enable reference clock - add pulse mode support ti-sn65dsi86: - use regmap bulk write - add PWM support etnaviv: - get all fences at once gma500: - gem object cleanups kmb: - enable fb console radeon: - use dma_resv_wait_timeout rockchip: - add DSP hold timeout - suspend/resume fixes - PLL clock fixes - implement mmap in GEM object functions - use generic fbdev emulation sun4i: - use CMA helpers without vmap support vc4: - fix HDMI-CEC hang with display is off - power on HDMI controller while disabling - support 4K@60Hz modes - support 10-bit YUV 4:2:0 output vmwgfx: - fix leak on probe errors - fail probing on broken hosts - new placement for MOB page tables - hide internal BOs from userspace - implement GEM support - implement GL 4.3 support virtio: - overflow fixes xen: - implement mmap as GEM object function omapdrm: - fix scatterlist export - support virtual planes mediatek: - MT8192 support - CMDQ refinement -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmHX1vMACgkQDHTzWXnE hr6rAw/9ES5RO5N3Ku9foFk1CI9bqy1Kh663KLkkEc+rDdhKpiZbBnAsrKkZ9sGu fNuHmWNN5nWXtDSOqHWuslt3F7Gh+qEBQtlkqC9mZsBm3bWB0aJK6E4QaJxfeSaK ta6AmyGx8DaV+C69i86dnemQurYSDVjROd7LDPKnCU0Fye/JxiXSXQmXksKMFVxd x5vmO9yfeDSg3EF+u1yB6nJNUYZBV0vhrAfjPqxPCRBXuQc7akuaglE/SFwlGnEk vn0GjVHEQcRTqYKrHr64xvQxIoKXcJP0pkDUyT7KYCsyj8GJkvxkb7/ls5pp5DvL SwyNg3J3vwUVP6w6GEvzf3ffG720qqUZvCbvLmE+A/t2DhGILiAm+HXSo43PTOW8 uagT7Gxma8dy8EovjSxioS9HPX8Gcu+S+XYavgOsevOZ7oeEt4f4TLW7LXsw9d6y 75FrMhiUpreab5hAh8Le0swuLYZHjdnJRdjSTqZJ/T6VdTdVftLT6IfwvSDx5CHy cWuufgcAjd7xVTXFquHWYXWLTQkiSMGf1M02jx9IWolTd4Cm41LNBhqMEDHZLHJD 7ngGgoaREVDQ+MqjG90yfIwJFIpJPI3YOaHLi/Kznga+iDzFY6cyOQWW2vX7ZdY5 7+LJWsgGT8Feb7/bzD5hX1mYqJLxh1pWUIaqIKMl+7LJL7gTVU8= =MByd -----END PGP SIGNATURE----- Merge tag 'drm-next-2022-01-07' of git://anongit.freedesktop.org/drm/drm Pull drm updates from Dave Airlie: "Highlights are support for privacy screens found in new laptops, a bunch of nomodeset refactoring, and i915 enables ADL-P systems by default, while starting to add RPL-S support. vmwgfx adds GEM and support for OpenGL 4.3 features in userspace. Lots of internal refactorings around dma reservations, and lots of driver refactoring as well. Summary: core: - add privacy screen support - move nomodeset option into drm subsystem - clean up nomodeset handling in drivers - make drm_irq.c legacy - fix stack_depot name conflicts - remove DMA_BUF_SET_NAME ioctl restrictions - sysfs: send hotplug event - replace several DRM_* logging macros with drm_* - move hashtable to legacy code - add error return from gem_create_object - cma-helper: improve interfaces, drop CONFIG_DRM_KMS_CMA_HELPER - kernel.h related include cleanups - support XRGB2101010 source buffers ttm: - don't include drm hashtable - stop pruning fences after wait - documentation updates dma-buf: - add dma_resv selftest - add debugfs helpers - remove dma_resv_get_excl_unlocked - documentation - make fences mandatory in dma_resv_add_excl_fence dp: - add link training delay helpers gem: - link shmem/cma helpers into separate modules - use dma_resv iteratior - import dma-buf namespace into gem helper modules scheduler: - fence grab fix - lockdep fixes bridge: - switch to managed MIPI DSI helpers - register and attach during probe fixes - convert to YAML in several places. panel: - add bunch of new panesl simpledrm: - support FB_DAMAGE_CLIPS - support virtual screen sizes - add Apple M1 support amdgpu: - enable seamless boot for DCN 3.01 - runtime PM fixes - use drm_kms_helper_connector_hotplug_event - get all fences at once - use generic drm fb helpers - PSR/DPCD/LTTPR/DSC/PM/RAS/OLED/SRIOV fixes - add smart trace buffer (STB) for supported GPUs - display debugfs entries - new SMU debug option - Documentation update amdkfd: - IP discovery enumeration refactor - interface between driver fixes - SVM fixes - kfd uapi header to define some sysfs bitfields. i915: - support VESA panel backlights - enable ADL-P by default - add eDP privacy screen support - add Raptor Lake S (RPL-S) support - DG2 page table support - lots of GuC/HuC fw refactoring - refactored i915->gt interfaces - CD clock squashing support - enable 10-bit gamma support - update ADL-P DMC fw to v2.14 - enable runtime PM autosuspend by default - ADL-P DSI support - per-lane DP drive settings for ICL+ - add support for pipe C/D DMC firmware - Atomic gamma LUT updates - remove CCS FB stride restrictions on ADL-P - VRR platform support for display 11 - add support for display audio codec keepalive - lots of display refactoring - fix runtime PM handling during PXP suspend - improved eviction performance with async TTM moves - async VMA unbinding improvements - VMA locking refactoring - improved error capture robustness - use per device iommu checks - drop bits stealing from i915_sw_fence function ptr - remove dma_resv_prune - add IC cache invalidation on DG2 nouveau: - crc fixes - validate LUTs in atomic check - set HDMI AVI RGB quant to full tegra: - buffer objects reworks for dma-buf compat - NVDEC driver uAPI support - power management improvements etnaviv: - IOMMU enabled system support - fix > 4GB command buffer mapping - close a DoS vector - fix spurious GPU resets ast: - fix i2c initialization rcar-du: - DSI output support exynos: - replace legacy gpio interface - implement generic GEM object mmap msm: - dpu plane state cleanup in prep for multirect - dpu debugfs cleanups - dp support for sc7280 - a506 support - removal of struct_mutex - remove old eDP sub-driver anx7625: - support MIPI DSI input - support HDMI audio - fix reading EDID lvds: - fix bridge DT bindings megachips: - probe both bridges before registering dw-hdmi: - allow interlace on bridge ps8640: - enable runtime PM - support aux-bus tx358768: - enable reference clock - add pulse mode support ti-sn65dsi86: - use regmap bulk write - add PWM support etnaviv: - get all fences at once gma500: - gem object cleanups kmb: - enable fb console radeon: - use dma_resv_wait_timeout rockchip: - add DSP hold timeout - suspend/resume fixes - PLL clock fixes - implement mmap in GEM object functions - use generic fbdev emulation sun4i: - use CMA helpers without vmap support vc4: - fix HDMI-CEC hang with display is off - power on HDMI controller while disabling - support 4K@60Hz modes - support 10-bit YUV 4:2:0 output vmwgfx: - fix leak on probe errors - fail probing on broken hosts - new placement for MOB page tables - hide internal BOs from userspace - implement GEM support - implement GL 4.3 support virtio: - overflow fixes xen: - implement mmap as GEM object function omapdrm: - fix scatterlist export - support virtual planes mediatek: - MT8192 support - CMDQ refinement" * tag 'drm-next-2022-01-07' of git://anongit.freedesktop.org/drm/drm: (1241 commits) drm/amdgpu: no DC support for headless chips drm/amd/display: fix dereference before NULL check drm/amdgpu: always reset the asic in suspend (v2) drm/amdgpu: put SMU into proper state on runpm suspending for BOCO capable platform drm/amd/display: Fix the uninitialized variable in enable_stream_features() drm/amdgpu: fix runpm documentation amdgpu/pm: Make sysfs pm attributes as read-only for VFs drm/amdgpu: save error count in RAS poison handler drm/amdgpu: drop redundant semicolon drm/amd/display: get and restore link res map drm/amd/display: support dynamic HPO DP link encoder allocation drm/amd/display: access hpo dp link encoder only through link resource drm/amd/display: populate link res in both detection and validation drm/amd/display: define link res and make it accessible to all link interfaces drm/amd/display: 3.2.167 drm/amd/display: [FW Promotion] Release 0.0.98 drm/amd/display: Undo ODM combine drm/amd/display: Add reg defs for DCN303 drm/amd/display: Changed pipe split policy to allow for multi-display pipe split drm/amd/display: Set optimize_pwr_state for DCN31 ...
This commit is contained in:
commit
8d0749b4f8
8
.mailmap
8
.mailmap
|
@ -10,10 +10,12 @@
|
|||
# Please keep this list dictionary sorted.
|
||||
#
|
||||
Aaron Durbin <adurbin@google.com>
|
||||
Abhinav Kumar <quic_abhinavk@quicinc.com> <abhinavk@codeaurora.org>
|
||||
Adam Oldham <oldhamca@gmail.com>
|
||||
Adam Radford <aradford@gmail.com>
|
||||
Adriana Reus <adi.reus@gmail.com> <adriana.reus@intel.com>
|
||||
Adrian Bunk <bunk@stusta.de>
|
||||
Akhil P Oommen <quic_akhilpo@quicinc.com> <akhilpo@codeaurora.org>
|
||||
Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||
Alan Cox <root@hraefn.swansea.linux.org.uk>
|
||||
Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com>
|
||||
|
@ -172,6 +174,7 @@ Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com>
|
|||
Jens Axboe <axboe@suse.de>
|
||||
Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
|
||||
Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
|
||||
Jessica Zhang <quic_jesszhan@quicinc.com> <jesszhan@codeaurora.org>
|
||||
Jiri Slaby <jirislaby@kernel.org> <jirislaby@gmail.com>
|
||||
Jiri Slaby <jirislaby@kernel.org> <jslaby@novell.com>
|
||||
Jiri Slaby <jirislaby@kernel.org> <jslaby@suse.com>
|
||||
|
@ -191,6 +194,7 @@ Juha Yrjola <at solidboot.com>
|
|||
Juha Yrjola <juha.yrjola@nokia.com>
|
||||
Juha Yrjola <juha.yrjola@solidboot.com>
|
||||
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
|
||||
Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org>
|
||||
Kay Sievers <kay.sievers@vrfy.org>
|
||||
Kees Cook <keescook@chromium.org> <kees.cook@canonical.com>
|
||||
Kees Cook <keescook@chromium.org> <keescook@google.com>
|
||||
|
@ -202,9 +206,11 @@ Kenneth W Chen <kenneth.w.chen@intel.com>
|
|||
Konstantin Khlebnikov <koct9i@gmail.com> <khlebnikov@yandex-team.ru>
|
||||
Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
|
||||
Koushik <raghavendra.koushik@neterion.com>
|
||||
Krishna Manikandan <quic_mkrishn@quicinc.com> <mkrishn@codeaurora.org>
|
||||
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski.k@gmail.com>
|
||||
Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com>
|
||||
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org>
|
||||
Leonardo Bras <leobras.c@gmail.com> <leonardo@linux.ibm.com>
|
||||
Leonid I Ananiev <leonid.i.ananiev@intel.com>
|
||||
Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
|
||||
|
@ -311,6 +317,7 @@ Qais Yousef <qsyousef@gmail.com> <qais.yousef@imgtec.com>
|
|||
Quentin Monnet <quentin@isovalent.com> <quentin.monnet@netronome.com>
|
||||
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
||||
Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
|
||||
Rajeev Nandan <quic_rajeevny@quicinc.com> <rajeevny@codeaurora.org>
|
||||
Rajesh Shah <rajesh.shah@intel.com>
|
||||
Ralf Baechle <ralf@linux-mips.org>
|
||||
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||
|
@ -325,6 +332,7 @@ Rui Saraiva <rmps@joel.ist.utl.pt>
|
|||
Sachin P Sant <ssant@in.ibm.com>
|
||||
Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
|
||||
Sam Ravnborg <sam@mars.ravnborg.org>
|
||||
Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org>
|
||||
Santosh Shilimkar <santosh.shilimkar@oracle.org>
|
||||
Santosh Shilimkar <ssantosh@kernel.org>
|
||||
Sarangdhar Joshi <spjoshi@codeaurora.org>
|
||||
|
|
|
@ -3551,6 +3551,13 @@
|
|||
shutdown the other cpus. Instead use the REBOOT_VECTOR
|
||||
irq.
|
||||
|
||||
nomodeset Disable kernel modesetting. DRM drivers will not perform
|
||||
display-mode changes or accelerated rendering. Only the
|
||||
system framebuffer will be available for use if this was
|
||||
set-up by the firmware or boot loader.
|
||||
|
||||
Useful as fallback, or for testing and debugging.
|
||||
|
||||
nomodule Disable module load
|
||||
|
||||
nopat [X86] Disable PAT (page attribute table extension of
|
||||
|
|
|
@ -43,14 +43,70 @@ properties:
|
|||
vdd33-supply:
|
||||
description: Regulator that provides the supply 3.3V power.
|
||||
|
||||
analogix,lane0-swing:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
minItems: 1
|
||||
maxItems: 20
|
||||
description:
|
||||
an array of swing register setting for DP tx lane0 PHY.
|
||||
Registers 0~9 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
|
||||
Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
|
||||
Swing1_Pre2, Swing0_Pre3, they are for [Boost control] and
|
||||
[Swing control] setting.
|
||||
Registers 0~9, bit 3:0 is [Boost control], these bits control
|
||||
post cursor manual, increase the [Boost control] to increase
|
||||
Pre-emphasis value.
|
||||
Registers 0~9, bit 6:4 is [Swing control], these bits control
|
||||
swing manual, increase [Swing control] setting to add Vp-p value
|
||||
for each Swing, Pre.
|
||||
Registers 10~19 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
|
||||
Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
|
||||
Swing1_Pre2, Swing0_Pre3, they are for [R select control] and
|
||||
[R Termination control] setting.
|
||||
Registers 10~19, bit 4:0 is [R select control], these bits are
|
||||
compensation manual, increase it can enhance IO driven strength
|
||||
and Vp-p.
|
||||
Registers 10~19, bit 5:6 is [R termination control], these bits
|
||||
adjust 50ohm impedance of DP tx termination. 00:55 ohm,
|
||||
01:50 ohm(default), 10:45 ohm, 11:40 ohm.
|
||||
|
||||
analogix,lane1-swing:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
minItems: 1
|
||||
maxItems: 20
|
||||
description:
|
||||
an array of swing register setting for DP tx lane1 PHY.
|
||||
DP TX lane1 swing register setting same with lane0
|
||||
swing, please refer lane0-swing property description.
|
||||
|
||||
analogix,audio-enable:
|
||||
type: boolean
|
||||
description: let the driver enable audio HDMI codec function or not.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
Video port for MIPI DSI input.
|
||||
MIPI DSI/DPI input.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
bus-type:
|
||||
enum: [1, 5]
|
||||
default: 1
|
||||
|
||||
data-lanes: true
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
@ -87,6 +143,9 @@ examples:
|
|||
vdd10-supply = <&pp1000_mipibrdg>;
|
||||
vdd18-supply = <&pp1800_mipibrdg>;
|
||||
vdd33-supply = <&pp3300_mipibrdg>;
|
||||
analogix,audio-enable;
|
||||
analogix,lane0-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
|
||||
analogix,lane1-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
|
@ -96,6 +155,8 @@ examples:
|
|||
reg = <0>;
|
||||
anx7625_in: endpoint {
|
||||
remote-endpoint = <&mipi_dsi>;
|
||||
bus-type = <5>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -79,6 +79,14 @@ properties:
|
|||
- port@0
|
||||
- port@1
|
||||
|
||||
pclk-sample:
|
||||
description:
|
||||
Data sampling on rising or falling edge.
|
||||
enum:
|
||||
- 0 # Falling edge
|
||||
- 1 # Rising edge
|
||||
default: 0
|
||||
|
||||
powerdown-gpios:
|
||||
description:
|
||||
The GPIO used to control the power down line of this device.
|
||||
|
@ -86,21 +94,32 @@ properties:
|
|||
|
||||
power-supply: true
|
||||
|
||||
if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: lvds-decoder
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
allOf:
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: lvds-decoder
|
||||
then:
|
||||
properties:
|
||||
port@0:
|
||||
ports:
|
||||
properties:
|
||||
endpoint:
|
||||
port@0:
|
||||
properties:
|
||||
data-mapping: false
|
||||
endpoint:
|
||||
properties:
|
||||
data-mapping: false
|
||||
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: lvds-encoder
|
||||
then:
|
||||
properties:
|
||||
pclk-sample: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/nxp,ptn3460.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP PTN3460 eDP to LVDS bridge
|
||||
|
||||
maintainers:
|
||||
- Sean Paul <seanpaul@chromium.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nxp,ptn3460
|
||||
|
||||
reg:
|
||||
description: I2C address of the bridge
|
||||
maxItems: 1
|
||||
|
||||
edid-emulation:
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description:
|
||||
The EDID emulation entry to use
|
||||
Value Resolution Description
|
||||
0 1024x768 NXP Generic
|
||||
1 1920x1080 NXP Generic
|
||||
2 1920x1080 NXP Generic
|
||||
3 1600x900 Samsung LTM200KT
|
||||
4 1920x1080 Samsung LTM230HT
|
||||
5 1366x768 NXP Generic
|
||||
6 1600x900 ChiMei M215HGE
|
||||
enum: [0, 1, 2, 3, 4, 5, 6]
|
||||
|
||||
powerdown-gpios:
|
||||
description: GPIO connected to the PD_N signal.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO connected to the RST_N signal.
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Video port for LVDS output
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Video port for eDP input
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- edid-emulation
|
||||
- powerdown-gpios
|
||||
- reset-gpios
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@20 {
|
||||
compatible = "nxp,ptn3460";
|
||||
reg = <0x20>;
|
||||
edid-emulation = <5>;
|
||||
powerdown-gpios = <&gpy2 5 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpx1 5 GPIO_ACTIVE_LOW>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
bridge_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
bridge_in: endpoint {
|
||||
remote-endpoint = <&dp_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,39 +0,0 @@
|
|||
ptn3460 bridge bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: "nxp,ptn3460"
|
||||
- reg: i2c address of the bridge
|
||||
- powerdown-gpio: OF device-tree gpio specification for PD_N pin.
|
||||
- reset-gpio: OF device-tree gpio specification for RST_N pin.
|
||||
- edid-emulation: The EDID emulation entry to use
|
||||
+-------+------------+------------------+
|
||||
| Value | Resolution | Description |
|
||||
| 0 | 1024x768 | NXP Generic |
|
||||
| 1 | 1920x1080 | NXP Generic |
|
||||
| 2 | 1920x1080 | NXP Generic |
|
||||
| 3 | 1600x900 | Samsung LTM200KT |
|
||||
| 4 | 1920x1080 | Samsung LTM230HT |
|
||||
| 5 | 1366x768 | NXP Generic |
|
||||
| 6 | 1600x900 | ChiMei M215HGE |
|
||||
+-------+------------+------------------+
|
||||
|
||||
- video interfaces: Device node can contain video interface port
|
||||
nodes for panel according to [1].
|
||||
|
||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
Example:
|
||||
lvds-bridge@20 {
|
||||
compatible = "nxp,ptn3460";
|
||||
reg = <0x20>;
|
||||
powerdown-gpio = <&gpy2 5 1 0 0>;
|
||||
reset-gpio = <&gpx1 5 1 0 0>;
|
||||
edid-emulation = <5>;
|
||||
ports {
|
||||
port@0 {
|
||||
bridge_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,118 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/renesas,dsi-csi2-tx.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car MIPI DSI/CSI-2 Encoder
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
|
||||
description: |
|
||||
This binding describes the MIPI DSI/CSI-2 encoder embedded in the Renesas
|
||||
R-Car V3U SoC. The encoder can operate in either DSI or CSI-2 mode, with up
|
||||
to four data lanes.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r8a779a0-dsi-csi2-tx # for V3U
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Functional clock
|
||||
- description: DSI (and CSI-2) functional clock
|
||||
- description: PLL reference clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fck
|
||||
- const: dsi
|
||||
- const: pll
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Parallel input port
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: DSI/CSI-2 output port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- power-domains
|
||||
- resets
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a779a0-sysc.h>
|
||||
|
||||
dsi0: dsi-encoder@fed80000 {
|
||||
compatible = "renesas,r8a779a0-dsi-csi2-tx";
|
||||
reg = <0xfed80000 0x10000>;
|
||||
power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
|
||||
clocks = <&cpg CPG_MOD 415>,
|
||||
<&cpg CPG_CORE R8A779A0_CLK_DSI>,
|
||||
<&cpg CPG_CORE R8A779A0_CLK_CP>;
|
||||
clock-names = "fck", "dsi", "pll";
|
||||
resets = <&cpg 415>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi0_in: endpoint {
|
||||
remote-endpoint = <&du_out_dsi0>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dsi0_out: endpoint {
|
||||
data-lanes = <1 2>;
|
||||
remote-endpoint = <&sn65dsi86_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -1,49 +0,0 @@
|
|||
Silicon Image SiI9234 HDMI/MHL bridge bindings
|
||||
|
||||
Required properties:
|
||||
- compatible : "sil,sii9234".
|
||||
- reg : I2C address for TPI interface, use 0x39
|
||||
- avcc33-supply : MHL/USB Switch Supply Voltage (3.3V)
|
||||
- iovcc18-supply : I/O Supply Voltage (1.8V)
|
||||
- avcc12-supply : TMDS Analog Supply Voltage (1.2V)
|
||||
- cvcc12-supply : Digital Core Supply Voltage (1.2V)
|
||||
- interrupts: interrupt specifier of INT pin
|
||||
- reset-gpios: gpio specifier of RESET pin (active low)
|
||||
- video interfaces: Device node can contain two video interface port
|
||||
nodes for HDMI encoder and connector according to [1].
|
||||
- port@0 - MHL to HDMI
|
||||
- port@1 - MHL to connector
|
||||
|
||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
|
||||
Example:
|
||||
sii9234@39 {
|
||||
compatible = "sil,sii9234";
|
||||
reg = <0x39>;
|
||||
avcc33-supply = <&vcc33mhl>;
|
||||
iovcc18-supply = <&vcc18mhl>;
|
||||
avcc12-supply = <&vsil12>;
|
||||
cvcc12-supply = <&vsil12>;
|
||||
reset-gpios = <&gpf3 4 GPIO_ACTIVE_LOW>;
|
||||
interrupt-parent = <&gpf3>;
|
||||
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
mhl_to_hdmi: endpoint {
|
||||
remote-endpoint = <&hdmi_to_mhl>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
mhl_to_connector: endpoint {
|
||||
remote-endpoint = <&connector_to_mhl>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,110 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/sil,sii9234.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Silicon Image SiI9234 HDMI/MHL bridge
|
||||
|
||||
maintainers:
|
||||
- Maciej Purski <m.purski@samsung.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sil,sii9234
|
||||
|
||||
reg:
|
||||
description: I2C address for TPI interface
|
||||
maxItems: 1
|
||||
|
||||
avcc12-supply:
|
||||
description: TMDS Analog Supply Voltage, 1.2V
|
||||
|
||||
avcc33-supply:
|
||||
description: MHL/USB Switch Supply Voltage, 3.3V
|
||||
|
||||
cvcc12-supply:
|
||||
description: Digital Core Supply Voltage, 1.2V
|
||||
|
||||
iovcc18-supply:
|
||||
description: I/O voltage supply, 1.8V
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO connected to the reset pin.
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Video port for HDMI (encoder) input
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
MHL to connector port
|
||||
|
||||
required:
|
||||
- port@0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- avcc12-supply
|
||||
- avcc33-supply
|
||||
- cvcc12-supply
|
||||
- iovcc18-supply
|
||||
- interrupts
|
||||
- reset-gpios
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@39 {
|
||||
compatible = "sil,sii9234";
|
||||
reg = <0x39>;
|
||||
avcc12-supply = <&vsil12>;
|
||||
avcc33-supply = <&vcc33mhl>;
|
||||
cvcc12-supply = <&vsil12>;
|
||||
iovcc18-supply = <&vcc18mhl>;
|
||||
interrupt-parent = <&gpf3>;
|
||||
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpios = <&gpf3 4 GPIO_ACTIVE_LOW>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
mhl_to_hdmi: endpoint {
|
||||
remote-endpoint = <&hdmi_to_mhl>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
mhl_to_connector: endpoint {
|
||||
remote-endpoint = <&connector_to_mhl>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -17,6 +17,8 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- qcom,sc7180-dp
|
||||
- qcom,sc7280-dp
|
||||
- qcom,sc7280-edp
|
||||
- qcom,sc8180x-dp
|
||||
- qcom,sc8180x-edp
|
||||
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
Qualcomm Technologies Inc. adreno/snapdragon eDP output
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
* "qcom,mdss-edp"
|
||||
- reg: Physical base address and length of the registers of controller and PLL
|
||||
- reg-names: The names of register regions. The following regions are required:
|
||||
* "edp"
|
||||
* "pll_base"
|
||||
- interrupts: The interrupt signal from the eDP block.
|
||||
- power-domains: Should be <&mmcc MDSS_GDSC>.
|
||||
- clocks: device clocks
|
||||
See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
|
||||
- clock-names: the following clocks are required:
|
||||
* "core"
|
||||
* "iface"
|
||||
* "mdp_core"
|
||||
* "pixel"
|
||||
* "link"
|
||||
- #clock-cells: The value should be 1.
|
||||
- vdda-supply: phandle to vdda regulator device node
|
||||
- lvl-vdd-supply: phandle to regulator device node which is used to supply power
|
||||
to HPD receiving chip
|
||||
- panel-en-gpios: GPIO pin to supply power to panel.
|
||||
- panel-hpd-gpios: GPIO pin used for eDP hpd.
|
||||
|
||||
|
||||
Example:
|
||||
mdss_edp: qcom,mdss_edp@fd923400 {
|
||||
compatible = "qcom,mdss-edp";
|
||||
reg-names =
|
||||
"edp",
|
||||
"pll_base";
|
||||
reg = <0xfd923400 0x700>,
|
||||
<0xfd923a00 0xd4>;
|
||||
interrupt-parent = <&mdss_mdp>;
|
||||
interrupts = <12 0>;
|
||||
power-domains = <&mmcc MDSS_GDSC>;
|
||||
clock-names =
|
||||
"core",
|
||||
"pixel",
|
||||
"iface",
|
||||
"link",
|
||||
"mdp_core";
|
||||
clocks =
|
||||
<&mmcc MDSS_EDPAUX_CLK>,
|
||||
<&mmcc MDSS_EDPPIXEL_CLK>,
|
||||
<&mmcc MDSS_AHB_CLK>,
|
||||
<&mmcc MDSS_EDPLINK_CLK>,
|
||||
<&mmcc MDSS_MDP_CLK>;
|
||||
#clock-cells = <1>;
|
||||
vdda-supply = <&pma8084_l12>;
|
||||
lvl-vdd-supply = <&lvl_vreg>;
|
||||
panel-en-gpios = <&tlmm 137 0>;
|
||||
panel-hpd-gpios = <&tlmm 103 0>;
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/boe,bf060y8m-aj0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: BOE BF060Y8M-AJ0 5.99" 1080x2160 AMOLED Panel
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
This is a 5.99" 1080x2160 16.7M Color active matrix AMOLED
|
||||
video mode panel module on MIPI-DSI 4-Lane interface, GGRB
|
||||
pixel arrangement, 63 micrometers pitch, with an active
|
||||
area of 68.04 x 136.08 millimeters.
|
||||
Each pixel is divided into red and green dots, or blue and
|
||||
green dots, and two pixels share red or blue dots which are
|
||||
arranged in vertical stripe.
|
||||
The DriverIC for this panel module is SW43404.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: boe,bf060y8m-aj0
|
||||
|
||||
elvdd-supply:
|
||||
description: EL Driving positive (VDD) supply (4.40-4.80V)
|
||||
elvss-supply:
|
||||
description: EL Driving negative (VSS) supply (-5.00V to -1.40V)
|
||||
vcc-supply:
|
||||
description: Core (TSP) voltage supply (2.70-3.60V)
|
||||
vci-supply:
|
||||
description: DriverIC Operation supply (2.60-3.60V)
|
||||
vddio-supply:
|
||||
description: I/O voltage supply (1.62-1.98V)
|
||||
|
||||
port: true
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- elvdd-supply
|
||||
- elvss-supply
|
||||
- vcc-supply
|
||||
- vci-supply
|
||||
- vddio-supply
|
||||
- reg
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "boe,bf060y8m-aj0";
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
vcc-supply = <&disp_vcc_vreg>;
|
||||
vddio-supply = <&disp_vddio_vreg>;
|
||||
vci-supply = <&disp_vci_vreg>;
|
||||
elvdd-supply = <&disp_elvdd_vreg>;
|
||||
elvss-supply = <&disp_elvss_vreg>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/ilitek,ili9163.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ilitek ILI9163 display panels device tree bindings
|
||||
|
||||
maintainers:
|
||||
- Daniel Mack <daniel@zonque.org>
|
||||
|
||||
description:
|
||||
This binding is for display panels using an Ilitek ILI9163 controller in SPI
|
||||
mode.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- newhaven,1.8-128160EF
|
||||
- const: ilitek,ili9163
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 32000000
|
||||
|
||||
dc-gpios:
|
||||
maxItems: 1
|
||||
description: Display data/command selection (D/CX)
|
||||
|
||||
backlight: true
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
rotation: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- dc-gpios
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
backlight: backlight {
|
||||
compatible = "gpio-backlight";
|
||||
gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
display@0 {
|
||||
compatible = "newhaven,1.8-128160EF", "ilitek,ili9163";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <32000000>;
|
||||
dc-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
|
||||
rotation = <180>;
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -9,24 +9,28 @@ title: Ilitek ILI9881c based MIPI-DSI panels
|
|||
maintainers:
|
||||
- Maxime Ripard <mripard@kernel.org>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- bananapi,lhr050h41
|
||||
- feixin,k101-im2byl02
|
||||
- wanchanglong,w552946aba
|
||||
- const: ilitek,ili9881c
|
||||
|
||||
backlight: true
|
||||
power-supply: true
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
rotation: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- power-supply
|
||||
- reg
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/novatek,nt35950.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Novatek NT35950-based display panels
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
|
||||
|
||||
description: |
|
||||
The nt35950 IC from Novatek is a Driver IC used to drive MIPI-DSI panels,
|
||||
with Static RAM for content retention in command mode and also supports
|
||||
video mode with VESA Frame Buffer Compression or Display Stream Compression
|
||||
on single, or dual dsi port(s).
|
||||
This DDIC is also capable of upscaling an input image to the panel's native
|
||||
resolution, for example it can upscale a 1920x1080 input to 3840x2160 with
|
||||
either bilinear interpolation or pixel duplication.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- sharp,ls055d1sx04
|
||||
- const: novatek,nt35950
|
||||
description: This indicates the panel manufacturer of the panel
|
||||
that is in turn using the NT35950 panel driver. The compatible
|
||||
string determines how the NT35950 panel driver shall be configured
|
||||
to work with the indicated panel. The novatek,nt35950 compatible shall
|
||||
always be provided as a fallback.
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: phandle of gpio for reset line - This should be 8mA, gpio
|
||||
can be configured using mux, pinctrl, pinctrl-names (active high)
|
||||
|
||||
avdd-supply:
|
||||
description: positive boost supply regulator
|
||||
avee-supply:
|
||||
description: negative boost supply regulator
|
||||
dvdd-supply:
|
||||
description: regulator that supplies the digital voltage
|
||||
vddio-supply:
|
||||
description: regulator that supplies the I/O voltage
|
||||
|
||||
backlight: true
|
||||
ports: true
|
||||
reg: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- avdd-supply
|
||||
- avee-supply
|
||||
- dvdd-supply
|
||||
- vddio-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "sharp,ls055d1sx04", "novatek,nt35950";
|
||||
reg = <0>;
|
||||
|
||||
backlight = <&pmi8998_wled>;
|
||||
reset-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
avdd-supply = <&lab>;
|
||||
avee-supply = <&ibb>;
|
||||
dvdd-supply = <&disp_dvdd_vreg>;
|
||||
vddio-supply = <&vreg_l14a_1p85>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
panel_in0: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
panel_in1: endpoint {
|
||||
remote-endpoint = <&dsi1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -35,6 +35,8 @@ properties:
|
|||
- boe,tv080wum-nl0
|
||||
# Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||
- innolux,p079zca
|
||||
# JDI FHD_R63452 1080x1920 5.2" IPS LCD Panel
|
||||
- jdi,fhd-r63452
|
||||
# Khadas TS050 5" 1080x1920 LCD panel
|
||||
- khadas,ts050
|
||||
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
||||
|
|
|
@ -290,6 +290,8 @@ properties:
|
|||
- starry,kr070pe2t
|
||||
# Starry 12.2" (1920x1200 pixels) TFT LCD panel
|
||||
- starry,kr122ea0sra
|
||||
# Team Source Display Technology TST043015CMHX 4.3" WQVGA TFT LCD panel
|
||||
- team-source-display,tst043015cmhx
|
||||
# Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel
|
||||
- tianma,tm070jdhg30
|
||||
# Tianma Micro-electronics TM070JVHG33 7.0" WXGA TFT LCD panel
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/sony,tulip-truly-nt35521.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony Tulip Truly NT35521 5.24" 1280x720 MIPI-DSI Panel
|
||||
|
||||
maintainers:
|
||||
- Shawn Guo <shawn.guo@linaro.org>
|
||||
|
||||
description: |
|
||||
The Sony Tulip Truly NT35521 is a 5.24" 1280x720 MIPI-DSI panel, which
|
||||
can be found no Sony Xperia M4 phone. The panel backlight is managed
|
||||
through DSI link.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,tulip-truly-nt35521
|
||||
|
||||
reg: true
|
||||
|
||||
positive5-supply:
|
||||
description: Positive 5V supply
|
||||
|
||||
negative5-supply:
|
||||
description: Negative 5V supply
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
enable-gpios: true
|
||||
|
||||
port: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- positive5-supply
|
||||
- negative5-supply
|
||||
- reset-gpios
|
||||
- enable-gpios
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "sony,tulip-truly-nt35521";
|
||||
reg = <0>;
|
||||
positive5-supply = <&positive5_reg>;
|
||||
negative5-supply = <&negative5_reg>;
|
||||
reset-gpios = <&msmgpio 25 GPIO_ACTIVE_LOW>;
|
||||
enable-gpios = <&msmgpio 10 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -0,0 +1,64 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/sprd/sprd,display-subsystem.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Unisoc DRM master device
|
||||
|
||||
maintainers:
|
||||
- Kevin Tang <kevin.tang@unisoc.com>
|
||||
|
||||
description: |
|
||||
The Unisoc DRM master device is a virtual device needed to list all
|
||||
DPU devices or other display interface nodes that comprise the
|
||||
graphics subsystem.
|
||||
|
||||
Unisoc's display pipeline have several components as below description,
|
||||
multi display controllers and corresponding physical interfaces.
|
||||
For different display scenarios, dpu0 and dpu1 maybe binding to different
|
||||
encoder.
|
||||
|
||||
E.g:
|
||||
dpu0 and dpu1 both binding to DSI for dual mipi-dsi display;
|
||||
dpu0 binding to DSI for primary display, and dpu1 binding to DP for external display;
|
||||
|
||||
+-----------------------------------------+
|
||||
| |
|
||||
| +---------+ |
|
||||
+----+ | +----+ +---------+ |DPHY/CPHY| | +------+
|
||||
| +----->+dpu0+--->+MIPI|DSI +--->+Combo +----->+Panel0|
|
||||
|AXI | | +----+ +---------+ +---------+ | +------+
|
||||
| | | ^ |
|
||||
| | | | |
|
||||
| | | +-----------+ |
|
||||
| | | | |
|
||||
|APB | | +--+-+ +-----------+ +---+ | +------+
|
||||
| +----->+dpu1+--->+DisplayPort+--->+PHY+--------->+Panel1|
|
||||
| | | +----+ +-----------+ +---+ | +------+
|
||||
+----+ | |
|
||||
+-----------------------------------------+
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sprd,display-subsystem
|
||||
|
||||
ports:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description:
|
||||
Should contain a list of phandles pointing to display interface port
|
||||
of DPU devices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
display-subsystem {
|
||||
compatible = "sprd,display-subsystem";
|
||||
ports = <&dpu_out>;
|
||||
};
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/sprd/sprd,sharkl3-dpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Unisoc Sharkl3 Display Processor Unit (DPU)
|
||||
|
||||
maintainers:
|
||||
- Kevin Tang <kevin.tang@unisoc.com>
|
||||
|
||||
description: |
|
||||
DPU (Display Processor Unit) is the Display Controller for the Unisoc SoCs
|
||||
which transfers the image data from a video memory buffer to an internal
|
||||
LCD interface.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sprd,sharkl3-dpu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: clk_src_128m
|
||||
- const: clk_src_384m
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
description:
|
||||
A port node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
That port should be the output endpoint, usually output to
|
||||
the associated DSI.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/sprd,sc9860-clk.h>
|
||||
dpu: dpu@63000000 {
|
||||
compatible = "sprd,sharkl3-dpu";
|
||||
reg = <0x63000000 0x1000>;
|
||||
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "clk_src_128m", "clk_src_384m";
|
||||
|
||||
clocks = <&pll CLK_TWPLL_128M>,
|
||||
<&pll CLK_TWPLL_384M>;
|
||||
|
||||
dpu_port: port {
|
||||
dpu_out: endpoint {
|
||||
remote-endpoint = <&dsi_in>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,88 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/sprd/sprd,sharkl3-dsi-host.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Unisoc MIPI DSI Controller
|
||||
|
||||
maintainers:
|
||||
- Kevin Tang <kevin.tang@unisoc.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sprd,sharkl3-dsi-host
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 2
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: clk_src_96m
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
description:
|
||||
A port node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
That port should be the input endpoint, usually coming from
|
||||
the associated DPU.
|
||||
|
||||
required:
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- port@0
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/sprd,sc9860-clk.h>
|
||||
dsi: dsi@63100000 {
|
||||
compatible = "sprd,sharkl3-dsi-host";
|
||||
reg = <0x63100000 0x1000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "clk_src_96m";
|
||||
clocks = <&pll CLK_TWPLL_96M>;
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi_in: endpoint {
|
||||
remote-endpoint = <&dpu_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1240,6 +1240,8 @@ patternProperties:
|
|||
description: Truly Semiconductors Limited
|
||||
"^visionox,.*":
|
||||
description: Visionox
|
||||
"^team-source-display,.*":
|
||||
description: Shenzhen Team Source Display Technology Co., Ltd. (TSD)
|
||||
"^tsd,.*":
|
||||
description: Theobroma Systems Design und Consulting GmbH
|
||||
"^tyan,.*":
|
||||
|
@ -1334,6 +1336,8 @@ patternProperties:
|
|||
description: Wondermedia Technologies, Inc.
|
||||
"^wobo,.*":
|
||||
description: Wobo
|
||||
"^wanchanglong,.*":
|
||||
description: Wanchanglong Electronics Technology(SHENZHEN)Co.,Ltd.
|
||||
"^x-powers,.*":
|
||||
description: X-Powers
|
||||
"^xes,.*":
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
===================================
|
||||
drm/amd/display - Display Core (DC)
|
||||
===================================
|
||||
|
||||
*placeholder - general description of supported platforms, what dc is, etc.*
|
||||
|
||||
Because it is partially shared with other operating systems, the Display Core
|
||||
Driver is divided in two pieces.
|
||||
|
||||
1. **Display Core (DC)** contains the OS-agnostic components. Things like
|
||||
hardware programming and resource management are handled here.
|
||||
2. **Display Manager (DM)** contains the OS-dependent components. Hooks to the
|
||||
amdgpu base driver and DRM are implemented here.
|
||||
|
||||
It doesn't help that the entire package is frequently referred to as DC. But
|
||||
with the context in mind, it should be clear.
|
||||
|
||||
When CONFIG_DRM_AMD_DC is enabled, DC will be initialized by default for
|
||||
supported ASICs. To force disable, set `amdgpu.dc=0` on kernel command line.
|
||||
Likewise, to force enable on unsupported ASICs, set `amdgpu.dc=1`.
|
||||
|
||||
To determine if DC is loaded, search dmesg for the following entry:
|
||||
|
||||
``Display Core initialized with <version number here>``
|
||||
|
||||
AMDgpu Display Manager
|
||||
======================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
|
||||
:internal:
|
||||
|
||||
Lifecycle
|
||||
---------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: DM Lifecycle
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:functions: dm_hw_init dm_hw_fini
|
||||
|
||||
Interrupts
|
||||
----------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:functions: register_hpd_handlers dm_crtc_high_irq dm_pflip_high_irq
|
||||
|
||||
Atomic Implementation
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: atomic
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:functions: amdgpu_dm_atomic_check amdgpu_dm_atomic_commit_tail
|
||||
|
||||
Display Core
|
||||
============
|
||||
|
||||
**WIP**
|
||||
|
||||
FreeSync Video
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: FreeSync Video
|
|
@ -1,324 +0,0 @@
|
|||
=========================
|
||||
drm/amdgpu AMDgpu driver
|
||||
=========================
|
||||
|
||||
The drm/amdgpu driver supports all AMD Radeon GPUs based on the Graphics Core
|
||||
Next (GCN) architecture.
|
||||
|
||||
Module Parameters
|
||||
=================
|
||||
|
||||
The amdgpu driver supports the following module parameters:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
||||
|
||||
Core Driver Infrastructure
|
||||
==========================
|
||||
|
||||
This section covers core driver infrastructure.
|
||||
|
||||
.. _amdgpu_memory_domains:
|
||||
|
||||
Memory Domains
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/amdgpu_drm.h
|
||||
:doc: memory domains
|
||||
|
||||
Buffer Objects
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
||||
:doc: amdgpu_object
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
||||
:internal:
|
||||
|
||||
PRIME Buffer Sharing
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
||||
:doc: PRIME Buffer Sharing
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
||||
:internal:
|
||||
|
||||
MMU Notifier
|
||||
------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
||||
:doc: MMU Notifier
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
||||
:internal:
|
||||
|
||||
AMDGPU Virtual Memory
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
||||
:doc: GPUVM
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
||||
:internal:
|
||||
|
||||
Interrupt Handling
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
||||
:doc: Interrupt Handling
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
||||
:internal:
|
||||
|
||||
IP Blocks
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||
:doc: IP Blocks
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||
:identifiers: amd_ip_block_type amd_ip_funcs
|
||||
|
||||
AMDGPU XGMI Support
|
||||
===================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
||||
|
||||
AMDGPU RAS Support
|
||||
==================
|
||||
|
||||
The AMDGPU RAS interfaces are exposed via sysfs (for informational queries) and
|
||||
debugfs (for error injection).
|
||||
|
||||
RAS debugfs/sysfs Control and Error Injection Interfaces
|
||||
--------------------------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS debugfs control interface
|
||||
|
||||
RAS Reboot Behavior for Unrecoverable Errors
|
||||
--------------------------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS Reboot Behavior for Unrecoverable Errors
|
||||
|
||||
RAS Error Count sysfs Interface
|
||||
-------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS sysfs Error Count Interface
|
||||
|
||||
RAS EEPROM debugfs Interface
|
||||
----------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS debugfs EEPROM table reset interface
|
||||
|
||||
RAS VRAM Bad Pages sysfs Interface
|
||||
----------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
|
||||
|
||||
Sample Code
|
||||
-----------
|
||||
Sample code for testing error injection can be found here:
|
||||
https://cgit.freedesktop.org/mesa/drm/tree/tests/amdgpu/ras_tests.c
|
||||
|
||||
This is part of the libdrm amdgpu unit tests which cover several areas of the GPU.
|
||||
There are four sets of tests:
|
||||
|
||||
RAS Basic Test
|
||||
|
||||
The test verifies the RAS feature enabled status and makes sure the necessary sysfs and debugfs files
|
||||
are present.
|
||||
|
||||
RAS Query Test
|
||||
|
||||
This test checks the RAS availability and enablement status for each supported IP block as well as
|
||||
the error counts.
|
||||
|
||||
RAS Inject Test
|
||||
|
||||
This test injects errors for each IP.
|
||||
|
||||
RAS Disable Test
|
||||
|
||||
This test tests disabling of RAS features for each IP block.
|
||||
|
||||
|
||||
GPU Power/Thermal Controls and Monitoring
|
||||
=========================================
|
||||
|
||||
This section covers hwmon and power/thermal controls.
|
||||
|
||||
HWMON Interfaces
|
||||
----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: hwmon
|
||||
|
||||
GPU sysfs Power State Interfaces
|
||||
--------------------------------
|
||||
|
||||
GPU power controls are exposed via sysfs files.
|
||||
|
||||
power_dpm_state
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: power_dpm_state
|
||||
|
||||
power_dpm_force_performance_level
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: power_dpm_force_performance_level
|
||||
|
||||
pp_table
|
||||
~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_table
|
||||
|
||||
pp_od_clk_voltage
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_od_clk_voltage
|
||||
|
||||
pp_dpm_*
|
||||
~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie
|
||||
|
||||
pp_power_profile_mode
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_power_profile_mode
|
||||
|
||||
\*_busy_percent
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: gpu_busy_percent
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: mem_busy_percent
|
||||
|
||||
gpu_metrics
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: gpu_metrics
|
||||
|
||||
GPU Product Information
|
||||
=======================
|
||||
|
||||
Information about the GPU can be obtained on certain cards
|
||||
via sysfs
|
||||
|
||||
product_name
|
||||
------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: product_name
|
||||
|
||||
product_number
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: product_name
|
||||
|
||||
serial_number
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: serial_number
|
||||
|
||||
unique_id
|
||||
---------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: unique_id
|
||||
|
||||
GPU Memory Usage Information
|
||||
============================
|
||||
|
||||
Various memory accounting can be accessed via sysfs
|
||||
|
||||
mem_info_vram_total
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vram_total
|
||||
|
||||
mem_info_vram_used
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vram_used
|
||||
|
||||
mem_info_vis_vram_total
|
||||
-----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vis_vram_total
|
||||
|
||||
mem_info_vis_vram_used
|
||||
----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vis_vram_used
|
||||
|
||||
mem_info_gtt_total
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
||||
:doc: mem_info_gtt_total
|
||||
|
||||
mem_info_gtt_used
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
||||
:doc: mem_info_gtt_used
|
||||
|
||||
PCIe Accounting Information
|
||||
===========================
|
||||
|
||||
pcie_bw
|
||||
-------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pcie_bw
|
||||
|
||||
pcie_replay_count
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: pcie_replay_count
|
||||
|
||||
GPU SmartShift Information
|
||||
==========================
|
||||
|
||||
GPU SmartShift information via sysfs
|
||||
|
||||
smartshift_apu_power
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: smartshift_apu_power
|
||||
|
||||
smartshift_dgpu_power
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: smartshift_dgpu_power
|
||||
|
||||
smartshift_bias
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: smartshift_bias
|
|
@ -0,0 +1,87 @@
|
|||
===============
|
||||
AMDGPU Glossary
|
||||
===============
|
||||
|
||||
Here you can find some generic acronyms used in the amdgpu driver. Notice that
|
||||
we have a dedicated glossary for Display Core at
|
||||
'Documentation/gpu/amdgpu/display/dc-glossary.rst'.
|
||||
|
||||
.. glossary::
|
||||
|
||||
CP
|
||||
Command Processor
|
||||
|
||||
CPLIB
|
||||
Content Protection Library
|
||||
|
||||
DFS
|
||||
Digital Frequency Synthesizer
|
||||
|
||||
ECP
|
||||
Enhanced Content Protection
|
||||
|
||||
EOP
|
||||
End Of Pipe/Pipeline
|
||||
|
||||
GC
|
||||
Graphics and Compute
|
||||
|
||||
GMC
|
||||
Graphic Memory Controller
|
||||
|
||||
IH
|
||||
Interrupt Handler
|
||||
|
||||
HQD
|
||||
Hardware Queue Descriptor
|
||||
|
||||
IB
|
||||
Indirect Buffer
|
||||
|
||||
IP
|
||||
Intellectual Property blocks
|
||||
|
||||
KCQ
|
||||
Kernel Compute Queue
|
||||
|
||||
KGQ
|
||||
Kernel Graphics Queue
|
||||
|
||||
KIQ
|
||||
Kernel Interface Queue
|
||||
|
||||
MEC
|
||||
MicroEngine Compute
|
||||
|
||||
MES
|
||||
MicroEngine Scheduler
|
||||
|
||||
MMHUB
|
||||
Multi-Media HUB
|
||||
|
||||
MQD
|
||||
Memory Queue Descriptor
|
||||
|
||||
PPLib
|
||||
PowerPlay Library - PowerPlay is the power management component.
|
||||
|
||||
PSP
|
||||
Platform Security Processor
|
||||
|
||||
RCL
|
||||
RunList Controller
|
||||
|
||||
SDMA
|
||||
System DMA
|
||||
|
||||
SMU
|
||||
System Management Unit
|
||||
|
||||
SS
|
||||
Spread Spectrum
|
||||
|
||||
VCE
|
||||
Video Compression Engine
|
||||
|
||||
VCN
|
||||
Video Codec Next
|
|
@ -0,0 +1,414 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="144.63406mm"
|
||||
height="66.596054mm"
|
||||
viewBox="0 0 144.15195 66.596054"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="config_example.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4547"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-3"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4547-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-3-5"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4547-6-3"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-3-5-0"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4547-6-3-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-3-5-7"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4547-6-3-3"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.98994949"
|
||||
inkscape:cx="518.91791"
|
||||
inkscape:cy="172.50112"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
viewbox-width="209.3"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="1136"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid817"
|
||||
originx="4.390216"
|
||||
originy="-208.88856" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(4.4048992,-21.515392)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 20.816662,35.062492 h 23.8125 v -5.291667 h 5.291667 v 5.291667 h 10.583334 v -5.291667 h 5.291667 v 5.291667 h 2.645833 v -5.291667 h 5.291667 v 5.291667 h 66.14583"
|
||||
id="path4522"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 20.816662,48.291659 h 7.9375 v -5.291667 h 5.291667 v 5.291667 h 58.208335 v -5.291667 h 5.291666 v 5.291667 h 42.33333"
|
||||
id="path4524"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 20.816662,61.520826 h 26.458334 v -5.291667 h 44.979168 v 5.291667 h 47.624996"
|
||||
id="path4526"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 20.816662,72.104159 H 139.87916"
|
||||
id="path4528"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 20.816662,77.395826 H 139.87916"
|
||||
id="path4530"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 20.816662,82.687493 H 139.87916"
|
||||
id="path4532"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 20.816662,87.97916 H 139.87916"
|
||||
id="path4534"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916668, 0.52916668;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
|
||||
d="m 47.274996,29.770826 c 3.836215,14.933158 3.472151,27.586643 0.264583,41.010418"
|
||||
id="path4536"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916669, 0.52916669;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3)"
|
||||
d="m 63.149996,29.770826 c 3.836214,14.933158 5.059652,27.586642 1.852084,41.010418"
|
||||
id="path4536-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.5291667, 0.5291667;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3-5)"
|
||||
d="m 71.087496,29.770825 c 3.836214,14.933158 5.059652,27.586643 1.852084,41.010419"
|
||||
id="path4536-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="59.359009"
|
||||
y="24.195677"
|
||||
id="text6572"><tspan
|
||||
sodipodi:role="line"
|
||||
x="59.359009"
|
||||
y="24.195677"
|
||||
style="font-size:3.52777791px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan6574">Configurations</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="46.825508"
|
||||
y="28.542402"
|
||||
id="text6572-6"><tspan
|
||||
sodipodi:role="line"
|
||||
x="46.825508"
|
||||
y="28.542402"
|
||||
style="font-size:3.52777815px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#008000;stroke-width:0.26458335"
|
||||
id="tspan6574-2">A</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="62.8895"
|
||||
y="28.825886"
|
||||
id="text6572-6-2"><tspan
|
||||
sodipodi:role="line"
|
||||
x="62.8895"
|
||||
y="28.825886"
|
||||
style="font-size:3.52777839px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#0000ff;stroke-width:0.26458335"
|
||||
id="tspan6574-2-7">B</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="70.827003"
|
||||
y="29.109362"
|
||||
id="text6572-6-2-3"><tspan
|
||||
sodipodi:role="line"
|
||||
x="70.827003"
|
||||
y="29.109362"
|
||||
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#c87137;stroke-width:0.26458335"
|
||||
id="tspan6574-2-7-6">C</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916671, 0.52916671;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3-5-0)"
|
||||
d="m 92.254164,42.999993 c 9.142136,12.745655 4.411987,28.608461 0.529167,38.364584"
|
||||
id="path4536-7-5-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 47.274996,72.104159 v 5.291667"
|
||||
id="path8053"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 64.472913,72.10416 v 5.291667"
|
||||
id="path8053-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 72.410413,72.10416 v 5.291667"
|
||||
id="path8053-6-1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 92.254164,82.687494 v 5.291667"
|
||||
id="path8053-6-1-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="55.802444"
|
||||
y="76.167412"
|
||||
id="text6572-6-7"><tspan
|
||||
sodipodi:role="line"
|
||||
x="55.802444"
|
||||
y="76.167412"
|
||||
style="font-size:3.52777839px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#008000;stroke-width:0.26458335"
|
||||
id="tspan6574-2-9">A</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="68.559143"
|
||||
y="75.883926"
|
||||
id="text6572-6-2-2"><tspan
|
||||
sodipodi:role="line"
|
||||
x="68.559143"
|
||||
y="75.883926"
|
||||
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#0000ff;stroke-width:0.26458335"
|
||||
id="tspan6574-2-7-0">B</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="84.812119"
|
||||
y="75.883911"
|
||||
id="text6572-6-2-3-2"><tspan
|
||||
sodipodi:role="line"
|
||||
x="84.812119"
|
||||
y="75.883911"
|
||||
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#c87137;stroke-width:0.26458335"
|
||||
id="tspan6574-2-7-6-3">C</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="98.513756"
|
||||
y="86.845222"
|
||||
id="text6572-6-2-3-2-7"><tspan
|
||||
sodipodi:role="line"
|
||||
x="98.513756"
|
||||
y="86.845222"
|
||||
style="font-size:3.52777863px;line-height:5.39999962;text-align:center;text-anchor:middle;fill:#c87137;stroke-width:0.26458335"
|
||||
id="tspan6574-2-7-6-3-5">C</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="35.452015"
|
||||
y="75.694931"
|
||||
id="text6572-9"><tspan
|
||||
sodipodi:role="line"
|
||||
x="35.452015"
|
||||
y="75.694931"
|
||||
style="font-size:3.52777815px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan6574-22">Old config</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="55.484753"
|
||||
y="86.656235"
|
||||
id="text6572-9-8"><tspan
|
||||
sodipodi:role="line"
|
||||
x="55.484753"
|
||||
y="86.656235"
|
||||
style="font-size:3.52777839px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan6574-22-9">Old config</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916671, 0.52916671;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-3-5-7)"
|
||||
d="m 92.254164,42.999993 c 4.233333,4.7625 2.645833,13.229167 0.79375,17.197917"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.58333397px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="3.7020128"
|
||||
y="33.550579"
|
||||
id="text6572-1"><tspan
|
||||
sodipodi:role="line"
|
||||
x="3.7020128"
|
||||
y="42.914349"
|
||||
style="font-size:3.52777815px;line-height:5.39999962;text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15310" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17500019px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="13.366468"
|
||||
y="46.590767"
|
||||
id="text15316"><tspan
|
||||
sodipodi:role="line"
|
||||
x="13.366468"
|
||||
y="46.590767"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15318">VUpdate</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17500043px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="14.45245"
|
||||
y="29.676321"
|
||||
id="text15316-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan15314-1"
|
||||
x="14.45245"
|
||||
y="29.676321"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335">Update</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="14.45245"
|
||||
y="33.645073"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15318-9">Lock</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17500043px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="7.5676007"
|
||||
y="56.985115"
|
||||
id="text15316-4"><tspan
|
||||
sodipodi:role="line"
|
||||
x="7.5676007"
|
||||
y="56.985115"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15318-7">Register update</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="7.5676007"
|
||||
y="60.953865"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15361">Pending Status</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17500043px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="16.074829"
|
||||
y="76.167404"
|
||||
id="text15316-8"><tspan
|
||||
sodipodi:role="line"
|
||||
x="16.074829"
|
||||
y="76.167404"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15318-4">Buf 0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17500067px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
|
||||
x="16.156994"
|
||||
y="86.089279"
|
||||
id="text15316-8-5"><tspan
|
||||
sodipodi:role="line"
|
||||
x="16.156994"
|
||||
y="86.089279"
|
||||
style="text-align:center;text-anchor:middle;stroke-width:0.26458335"
|
||||
id="tspan15318-4-0">Buf 1</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 19 KiB |
|
@ -0,0 +1,77 @@
|
|||
========================
|
||||
Display Core Debug tools
|
||||
========================
|
||||
|
||||
DC Visual Confirmation
|
||||
======================
|
||||
|
||||
Display core provides a feature named visual confirmation, which is a set of
|
||||
bars added at the scanout time by the driver to convey some specific
|
||||
information. In general, you can enable this debug option by using::
|
||||
|
||||
echo <N> > /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
|
||||
|
||||
Where `N` is an integer number for some specific scenarios that the developer
|
||||
wants to enable, you will see some of these debug cases in the following
|
||||
subsection.
|
||||
|
||||
Multiple Planes Debug
|
||||
---------------------
|
||||
|
||||
If you want to enable or debug multiple planes in a specific user-space
|
||||
application, you can leverage a debug feature named visual confirm. For
|
||||
enabling it, you will need::
|
||||
|
||||
echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
|
||||
|
||||
You need to reload your GUI to see the visual confirmation. When the plane
|
||||
configuration changes or a full update occurs there will be a colored bar at
|
||||
the bottom of each hardware plane being drawn on the screen.
|
||||
|
||||
* The color indicates the format - For example, red is AR24 and green is NV12
|
||||
* The height of the bar indicates the index of the plane
|
||||
* Pipe split can be observed if there are two bars with a difference in height
|
||||
covering the same plane
|
||||
|
||||
Consider the video playback case in which a video is played in a specific
|
||||
plane, and the desktop is drawn in another plane. The video plane should
|
||||
feature one or two green bars at the bottom of the video depending on pipe
|
||||
split configuration.
|
||||
|
||||
* There should **not** be any visual corruption
|
||||
* There should **not** be any underflow or screen flashes
|
||||
* There should **not** be any black screens
|
||||
* There should **not** be any cursor corruption
|
||||
* Multiple plane **may** be briefly disabled during window transitions or
|
||||
resizing but should come back after the action has finished
|
||||
|
||||
Pipe Split Debug
|
||||
----------------
|
||||
|
||||
Sometimes we need to debug if DCN is splitting pipes correctly, and visual
|
||||
confirmation is also handy for this case. Similar to the MPO case, you can use
|
||||
the below command to enable visual confirmation::
|
||||
|
||||
echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_visual_confirm
|
||||
|
||||
In this case, if you have a pipe split, you will see one small red bar at the
|
||||
bottom of the display covering the entire display width and another bar
|
||||
covering the second pipe. In other words, you will see a bit high bar in the
|
||||
second pipe.
|
||||
|
||||
DTN Debug
|
||||
=========
|
||||
|
||||
DC (DCN) provides an extensive log that dumps multiple details from our
|
||||
hardware configuration. Via debugfs, you can capture those status values by
|
||||
using Display Test Next (DTN) log, which can be captured via debugfs by using::
|
||||
|
||||
cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
|
||||
|
||||
Since this log is updated accordingly with DCN status, you can also follow the
|
||||
change in real-time by using something like::
|
||||
|
||||
sudo watch -d cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
|
||||
|
||||
When reporting a bug related to DC, consider attaching this log before and
|
||||
after you reproduce the bug.
|
|
@ -0,0 +1,237 @@
|
|||
===========
|
||||
DC Glossary
|
||||
===========
|
||||
|
||||
On this page, we try to keep track of acronyms related to the display
|
||||
component. If you do not find what you are looking for, look at the
|
||||
'Documentation/gpu/amdgpu/amdgpu-glossary.rst'; if you cannot find it anywhere,
|
||||
consider asking in the amdgfx and update this page.
|
||||
|
||||
.. glossary::
|
||||
|
||||
ABM
|
||||
Adaptive Backlight Modulation
|
||||
|
||||
APU
|
||||
Accelerated Processing Unit
|
||||
|
||||
ASIC
|
||||
Application-Specific Integrated Circuit
|
||||
|
||||
ASSR
|
||||
Alternate Scrambler Seed Reset
|
||||
|
||||
AZ
|
||||
Azalia (HD audio DMA engine)
|
||||
|
||||
BPC
|
||||
Bits Per Colour/Component
|
||||
|
||||
BPP
|
||||
Bits Per Pixel
|
||||
|
||||
Clocks
|
||||
* PCLK: Pixel Clock
|
||||
* SYMCLK: Symbol Clock
|
||||
* SOCCLK: GPU Engine Clock
|
||||
* DISPCLK: Display Clock
|
||||
* DPPCLK: DPP Clock
|
||||
* DCFCLK: Display Controller Fabric Clock
|
||||
* REFCLK: Real Time Reference Clock
|
||||
* PPLL: Pixel PLL
|
||||
* FCLK: Fabric Clock
|
||||
* MCLK: Memory Clock
|
||||
|
||||
CRC
|
||||
Cyclic Redundancy Check
|
||||
|
||||
CRTC
|
||||
Cathode Ray Tube Controller - commonly called "Controller" - Generates
|
||||
raw stream of pixels, clocked at pixel clock
|
||||
|
||||
CVT
|
||||
Coordinated Video Timings
|
||||
|
||||
DAL
|
||||
Display Abstraction layer
|
||||
|
||||
DC (Software)
|
||||
Display Core
|
||||
|
||||
DC (Hardware)
|
||||
Display Controller
|
||||
|
||||
DCC
|
||||
Delta Colour Compression
|
||||
|
||||
DCE
|
||||
Display Controller Engine
|
||||
|
||||
DCHUB
|
||||
Display Controller HUB
|
||||
|
||||
ARB
|
||||
Arbiter
|
||||
|
||||
VTG
|
||||
Vertical Timing Generator
|
||||
|
||||
DCN
|
||||
Display Core Next
|
||||
|
||||
DCCG
|
||||
Display Clock Generator block
|
||||
|
||||
DDC
|
||||
Display Data Channel
|
||||
|
||||
DIO
|
||||
Display IO
|
||||
|
||||
DPP
|
||||
Display Pipes and Planes
|
||||
|
||||
DSC
|
||||
Display Stream Compression (Reduce the amount of bits to represent pixel
|
||||
count while at the same pixel clock)
|
||||
|
||||
dGPU
|
||||
discrete GPU
|
||||
|
||||
DMIF
|
||||
Display Memory Interface
|
||||
|
||||
DML
|
||||
Display Mode Library
|
||||
|
||||
DMCU
|
||||
Display Micro-Controller Unit
|
||||
|
||||
DMCUB
|
||||
Display Micro-Controller Unit, version B
|
||||
|
||||
DPCD
|
||||
DisplayPort Configuration Data
|
||||
|
||||
DPM(S)
|
||||
Display Power Management (Signaling)
|
||||
|
||||
DRR
|
||||
Dynamic Refresh Rate
|
||||
|
||||
DWB
|
||||
Display Writeback
|
||||
|
||||
FB
|
||||
Frame Buffer
|
||||
|
||||
FBC
|
||||
Frame Buffer Compression
|
||||
|
||||
FEC
|
||||
Forward Error Correction
|
||||
|
||||
FRL
|
||||
Fixed Rate Link
|
||||
|
||||
GCO
|
||||
Graphical Controller Object
|
||||
|
||||
GSL
|
||||
Global Swap Lock
|
||||
|
||||
iGPU
|
||||
integrated GPU
|
||||
|
||||
ISR
|
||||
Interrupt Service Request
|
||||
|
||||
ISV
|
||||
Independent Software Vendor
|
||||
|
||||
KMD
|
||||
Kernel Mode Driver
|
||||
|
||||
LB
|
||||
Line Buffer
|
||||
|
||||
LFC
|
||||
Low Framerate Compensation
|
||||
|
||||
LTTPR
|
||||
Link Training Tunable Phy Repeater
|
||||
|
||||
LUT
|
||||
Lookup Table
|
||||
|
||||
MALL
|
||||
Memory Access at Last Level
|
||||
|
||||
MC
|
||||
Memory Controller
|
||||
|
||||
MPC
|
||||
Multiple pipes and plane combine
|
||||
|
||||
MPO
|
||||
Multi Plane Overlay
|
||||
|
||||
MST
|
||||
Multi Stream Transport
|
||||
|
||||
NBP State
|
||||
Northbridge Power State
|
||||
|
||||
NBIO
|
||||
North Bridge Input/Output
|
||||
|
||||
ODM
|
||||
Output Data Mapping
|
||||
|
||||
OPM
|
||||
Output Protection Manager
|
||||
|
||||
OPP
|
||||
Output Plane Processor
|
||||
|
||||
OPTC
|
||||
Output Pipe Timing Combiner
|
||||
|
||||
OTG
|
||||
Output Timing Generator
|
||||
|
||||
PCON
|
||||
Power Controller
|
||||
|
||||
PGFSM
|
||||
Power Gate Finite State Machine
|
||||
|
||||
PSR
|
||||
Panel Self Refresh
|
||||
|
||||
SCL
|
||||
Scaler
|
||||
|
||||
SDP
|
||||
Scalable Data Port
|
||||
|
||||
SLS
|
||||
Single Large Surface
|
||||
|
||||
SST
|
||||
Single Stream Transport
|
||||
|
||||
TMDS
|
||||
Transition-Minimized Differential Signaling
|
||||
|
||||
TMZ
|
||||
Trusted Memory Zone
|
||||
|
||||
TTU
|
||||
Time to Underflow
|
||||
|
||||
VRR
|
||||
Variable Refresh Rate
|
||||
|
||||
UVD
|
||||
Unified Video Decoder
|
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 54 KiB |
|
@ -0,0 +1,171 @@
|
|||
=======================
|
||||
Display Core Next (DCN)
|
||||
=======================
|
||||
|
||||
To equip our readers with the basic knowledge of how AMD Display Core Next
|
||||
(DCN) works, we need to start with an overview of the hardware pipeline. Below
|
||||
you can see a picture that provides a DCN overview, keep in mind that this is a
|
||||
generic diagram, and we have variations per ASIC.
|
||||
|
||||
.. kernel-figure:: dc_pipeline_overview.svg
|
||||
|
||||
Based on this diagram, we can pass through each block and briefly describe
|
||||
them:
|
||||
|
||||
* **Display Controller Hub (DCHUB)**: This is the gateway between the Scalable
|
||||
Data Port (SDP) and DCN. This component has multiple features, such as memory
|
||||
arbitration, rotation, and cursor manipulation.
|
||||
|
||||
* **Display Pipe and Plane (DPP)**: This block provides pre-blend pixel
|
||||
processing such as color space conversion, linearization of pixel data, tone
|
||||
mapping, and gamut mapping.
|
||||
|
||||
* **Multiple Pipe/Plane Combined (MPC)**: This component performs blending of
|
||||
multiple planes, using global or per-pixel alpha.
|
||||
|
||||
* **Output Pixel Processing (OPP)**: Process and format pixels to be sent to
|
||||
the display.
|
||||
|
||||
* **Output Pipe Timing Combiner (OPTC)**: It generates time output to combine
|
||||
streams or divide capabilities. CRC values are generated in this block.
|
||||
|
||||
* **Display Output (DIO)**: Codify the output to the display connected to our
|
||||
GPU.
|
||||
|
||||
* **Display Writeback (DWB)**: It provides the ability to write the output of
|
||||
the display pipe back to memory as video frames.
|
||||
|
||||
* **Multi-Media HUB (MMHUBBUB)**: Memory controller interface for DMCUB and DWB
|
||||
(Note that DWB is not hooked yet).
|
||||
|
||||
* **DCN Management Unit (DMU)**: It provides registers with access control and
|
||||
interrupts the controller to the SOC host interrupt unit. This block includes
|
||||
the Display Micro-Controller Unit - version B (DMCUB), which is handled via
|
||||
firmware.
|
||||
|
||||
* **DCN Clock Generator Block (DCCG)**: It provides the clocks and resets
|
||||
for all of the display controller clock domains.
|
||||
|
||||
* **Azalia (AZ)**: Audio engine.
|
||||
|
||||
The above diagram is an architecture generalization of DCN, which means that
|
||||
every ASIC has variations around this base model. Notice that the display
|
||||
pipeline is connected to the Scalable Data Port (SDP) via DCHUB; you can see
|
||||
the SDP as the element from our Data Fabric that feeds the display pipe.
|
||||
|
||||
Always approach the DCN architecture as something flexible that can be
|
||||
configured and reconfigured in multiple ways; in other words, each block can be
|
||||
setup or ignored accordingly with userspace demands. For example, if we
|
||||
want to drive an 8k@60Hz with a DSC enabled, our DCN may require 4 DPP and 2
|
||||
OPP. It is DC's responsibility to drive the best configuration for each
|
||||
specific scenario. Orchestrate all of these components together requires a
|
||||
sophisticated communication interface which is highlighted in the diagram by
|
||||
the edges that connect each block; from the chart, each connection between
|
||||
these blocks represents:
|
||||
|
||||
1. Pixel data interface (red): Represents the pixel data flow;
|
||||
2. Global sync signals (green): It is a set of synchronization signals composed
|
||||
by VStartup, VUpdate, and VReady;
|
||||
3. Config interface: Responsible to configure blocks;
|
||||
4. Sideband signals: All other signals that do not fit the previous one.
|
||||
|
||||
These signals are essential and play an important role in DCN. Nevertheless,
|
||||
the Global Sync deserves an extra level of detail described in the next
|
||||
section.
|
||||
|
||||
All of these components are represented by a data structure named dc_state.
|
||||
From DCHUB to MPC, we have a representation called dc_plane; from MPC to OPTC,
|
||||
we have dc_stream, and the output (DIO) is handled by dc_link. Keep in mind
|
||||
that HUBP accesses a surface using a specific format read from memory, and our
|
||||
dc_plane should work to convert all pixels in the plane to something that can
|
||||
be sent to the display via dc_stream and dc_link.
|
||||
|
||||
Front End and Back End
|
||||
----------------------
|
||||
|
||||
Display pipeline can be broken down into two components that are usually
|
||||
referred as **Front End (FE)** and **Back End (BE)**, where FE consists of:
|
||||
|
||||
* DCHUB (Mainly referring to a subcomponent named HUBP)
|
||||
* DPP
|
||||
* MPC
|
||||
|
||||
On the other hand, BE consist of
|
||||
|
||||
* OPP
|
||||
* OPTC
|
||||
* DIO (DP/HDMI stream encoder and link encoder)
|
||||
|
||||
OPP and OPTC are two joining blocks between FE and BE. On a side note, this is
|
||||
a one-to-one mapping of the link encoder to PHY, but we can configure the DCN
|
||||
to choose which link encoder to connect to which PHY. FE's main responsibility
|
||||
is to change, blend and compose pixel data, while BE's job is to frame a
|
||||
generic pixel stream to a specific display's pixel stream.
|
||||
|
||||
Data Flow
|
||||
---------
|
||||
|
||||
Initially, data is passed in from VRAM through Data Fabric (DF) in native pixel
|
||||
formats. Such data format stays through till HUBP in DCHUB, where HUBP unpacks
|
||||
different pixel formats and outputs them to DPP in uniform streams through 4
|
||||
channels (1 for alpha + 3 for colors).
|
||||
|
||||
The Converter and Cursor (CNVC) in DPP would then normalize the data
|
||||
representation and convert them to a DCN specific floating-point format (i.e.,
|
||||
different from the IEEE floating-point format). In the process, CNVC also
|
||||
applies a degamma function to transform the data from non-linear to linear
|
||||
space to relax the floating-point calculations following. Data would stay in
|
||||
this floating-point format from DPP to OPP.
|
||||
|
||||
Starting OPP, because color transformation and blending have been completed
|
||||
(i.e alpha can be dropped), and the end sinks do not require the precision and
|
||||
dynamic range that floating points provide (i.e. all displays are in integer
|
||||
depth format), bit-depth reduction/dithering would kick in. In OPP, we would
|
||||
also apply a regamma function to introduce the gamma removed earlier back.
|
||||
Eventually, we output data in integer format at DIO.
|
||||
|
||||
Global Sync
|
||||
-----------
|
||||
|
||||
Many DCN registers are double buffered, most importantly the surface address.
|
||||
This allows us to update DCN hardware atomically for page flips, as well as
|
||||
for most other updates that don't require enabling or disabling of new pipes.
|
||||
|
||||
(Note: There are many scenarios when DC will decide to reserve extra pipes
|
||||
in order to support outputs that need a very high pixel clock, or for
|
||||
power saving purposes.)
|
||||
|
||||
These atomic register updates are driven by global sync signals in DCN. In
|
||||
order to understand how atomic updates interact with DCN hardware, and how DCN
|
||||
signals page flip and vblank events it is helpful to understand how global sync
|
||||
is programmed.
|
||||
|
||||
Global sync consists of three signals, VSTARTUP, VUPDATE, and VREADY. These are
|
||||
calculated by the Display Mode Library - DML (drivers/gpu/drm/amd/display/dc/dml)
|
||||
based on a large number of parameters and ensure our hardware is able to feed
|
||||
the DCN pipeline without underflows or hangs in any given system configuration.
|
||||
The global sync signals always happen during VBlank, are independent from the
|
||||
VSync signal, and do not overlap each other.
|
||||
|
||||
VUPDATE is the only signal that is of interest to the rest of the driver stack
|
||||
or userspace clients as it signals the point at which hardware latches to
|
||||
atomically programmed (i.e. double buffered) registers. Even though it is
|
||||
independent of the VSync signal we use VUPDATE to signal the VSync event as it
|
||||
provides the best indication of how atomic commits and hardware interact.
|
||||
|
||||
Since DCN hardware is double-buffered the DC driver is able to program the
|
||||
hardware at any point during the frame.
|
||||
|
||||
The below picture illustrates the global sync signals:
|
||||
|
||||
.. kernel-figure:: global_sync_vblank.svg
|
||||
|
||||
These signals affect core DCN behavior. Programming them incorrectly will lead
|
||||
to a number of negative consequences, most of them quite catastrophic.
|
||||
|
||||
The following picture shows how global sync allows for a mailbox style of
|
||||
updates, i.e. it allows for multiple re-configurations between VUpdate
|
||||
events where only the last configuration programmed before the VUpdate signal
|
||||
becomes effective.
|
||||
|
||||
.. kernel-figure:: config_example.svg
|
|
@ -0,0 +1,42 @@
|
|||
======================
|
||||
AMDgpu Display Manager
|
||||
======================
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:depth: 3
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
|
||||
:internal:
|
||||
|
||||
Lifecycle
|
||||
=========
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: DM Lifecycle
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:functions: dm_hw_init dm_hw_fini
|
||||
|
||||
Interrupts
|
||||
==========
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:functions: register_hpd_handlers dm_crtc_high_irq dm_pflip_high_irq
|
||||
|
||||
Atomic Implementation
|
||||
=====================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:doc: atomic
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
:functions: amdgpu_dm_atomic_check amdgpu_dm_atomic_commit_tail
|
|
@ -0,0 +1,485 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="232.24133mm"
|
||||
height="96.174995mm"
|
||||
viewBox="0 0 232.24133 96.174995"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="global_sync_vblank.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path862"
|
||||
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Send"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path868"
|
||||
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path856"
|
||||
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker1719"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path1717"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker1661"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path1659"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#ff00ff;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible"
|
||||
id="marker1311"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
inkscape:collect="always">
|
||||
<path
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
id="path1309"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible"
|
||||
id="marker1253"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lstart">
|
||||
<path
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
id="path1251"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always">
|
||||
<path
|
||||
id="path838"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always">
|
||||
<path
|
||||
id="path835"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path850"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Sstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path865"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-2"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path862-3"
|
||||
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-2-5"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path862-3-9"
|
||||
style="fill:#800080;fill-opacity:1;fill-rule:evenodd;stroke:#800080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="747.52324"
|
||||
inkscape:cy="319.84503"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2096"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid815"
|
||||
originx="15.282997"
|
||||
originy="-184.54792" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(15.282998,-16.277083)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 15.875,27.125001 V 16.541666 H 26.458333 V 27.125001 H 177.27084 V 16.541666 h 10.58333 v 10.583335 h 29.10416"
|
||||
id="path817"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 15.875,37.708334 H 44.979166 V 48.291667 H 100.54167 V 37.708334 H 206.375 v 10.583333 h 10.58333"
|
||||
id="path819"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 15.875,66.8125 h 97.89583 V 56.229167 h 7.9375 V 66.8125 h 92.60417"
|
||||
id="path821"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 15.875,85.333334 c 0,0 132.29166,0 132.29166,0 V 74.75 h 15.875 v 10.583334 h 47.625"
|
||||
id="path823"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 15.875,101.20833 H 187.85416 V 90.625 h 10.58334 v 10.58333 h 10.58333"
|
||||
id="path825"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916667;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 100.54167,48.291667 V 111.79167"
|
||||
id="path827"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916667;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 113.77083,66.8125 v 44.97917"
|
||||
id="path829"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916667;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 206.375,48.291667 V 109.14583"
|
||||
id="path831"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
|
||||
d="m 100.54167,106.5 h 13.22916"
|
||||
id="path833"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker1253);marker-end:url(#marker1311)"
|
||||
d="M 113.77083,106.5 H 206.375"
|
||||
id="path1243"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="105.83333"
|
||||
y="111.79166"
|
||||
id="text1405"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1403"
|
||||
x="105.83333"
|
||||
y="111.79166"
|
||||
style="stroke-width:0.26458332">To</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="145.52083"
|
||||
y="111.79166"
|
||||
id="text1409"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1407"
|
||||
x="145.52083"
|
||||
y="111.79166"
|
||||
style="stroke-width:0.26458332">VStartup Period</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="156.01123"
|
||||
y="78.71875"
|
||||
id="text1413"><tspan
|
||||
sodipodi:role="line"
|
||||
x="156.01123"
|
||||
y="78.71875"
|
||||
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||
id="tspan1415">VUpdate</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="156.01123"
|
||||
y="82.6875"
|
||||
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||
id="tspan1440">Width</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="173.77611"
|
||||
y="92.703873"
|
||||
id="text1413-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1411-6"
|
||||
x="173.77611"
|
||||
y="92.703873"
|
||||
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332">VReady</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="173.77611"
|
||||
y="96.672623"
|
||||
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||
id="tspan1415-7">Offset</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="135.78951"
|
||||
y="70.78125"
|
||||
id="text1413-5"><tspan
|
||||
sodipodi:role="line"
|
||||
x="135.78951"
|
||||
y="70.78125"
|
||||
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||
id="tspan1440-5">VUpdate</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="135.78951"
|
||||
y="74.75"
|
||||
style="font-weight:bold;text-align:center;text-anchor:middle;stroke-width:0.26458332"
|
||||
id="tspan1465">Offset</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="137.39433"
|
||||
y="48.291664"
|
||||
id="text1479"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1477"
|
||||
x="137.39433"
|
||||
y="48.291664"
|
||||
style="font-weight:bold;stroke-width:0.26458332">VSTARTUP_START</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="-5.4806676"
|
||||
y="22.778271"
|
||||
id="text1479-1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1477-2"
|
||||
x="-5.4806676"
|
||||
y="22.778271"
|
||||
style="font-weight:bold;font-size:4.93888903px;stroke-width:0.26458332">VSYNC</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="-9.3767252"
|
||||
y="45.64584"
|
||||
id="text1479-1-7"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1477-2-0"
|
||||
x="-9.3767252"
|
||||
y="45.64584"
|
||||
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VBlank</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="-15.310558"
|
||||
y="64.92263"
|
||||
id="text1479-1-7-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1477-2-0-3"
|
||||
x="-15.310558"
|
||||
y="64.92263"
|
||||
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VStartup</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="-14.17781"
|
||||
y="85.144356"
|
||||
id="text1479-1-7-9-6"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1477-2-0-3-0"
|
||||
x="-14.17781"
|
||||
y="85.144356"
|
||||
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VUpdate</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.17499995px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="-11.052421"
|
||||
y="101.39733"
|
||||
id="text1479-1-7-9-6-6"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1477-2-0-3-0-2"
|
||||
x="-11.052421"
|
||||
y="101.39733"
|
||||
style="font-weight:bold;font-size:5.64444447px;stroke-width:0.26458332">VReady</tspan></text>
|
||||
<g
|
||||
id="g5189"
|
||||
transform="translate(269.875,-14.287499)">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5143"
|
||||
d="m -202.40625,45.645828 3.96875,-7.9375"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5143-2"
|
||||
d="m -199.76042,45.645828 3.96874,-7.937499"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g5189-3"
|
||||
transform="translate(268.55209,7.9375003)">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5143-6"
|
||||
d="m -202.40625,45.645828 3.96875,-7.9375"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5143-2-1"
|
||||
d="m -199.76042,45.645828 3.96874,-7.937499"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,31 @@
|
|||
.. _amdgpu-display-core:
|
||||
|
||||
===================================
|
||||
drm/amd/display - Display Core (DC)
|
||||
===================================
|
||||
|
||||
AMD display engine is partially shared with other operating systems; for this
|
||||
reason, our Display Core Driver is divided into two pieces:
|
||||
|
||||
1. **Display Core (DC)** contains the OS-agnostic components. Things like
|
||||
hardware programming and resource management are handled here.
|
||||
2. **Display Manager (DM)** contains the OS-dependent components. Hooks to the
|
||||
amdgpu base driver and DRM are implemented here.
|
||||
|
||||
The display pipe is responsible for "scanning out" a rendered frame from the
|
||||
GPU memory (also called VRAM, FrameBuffer, etc.) to a display. In other words,
|
||||
it would:
|
||||
|
||||
1. Read frame information from memory;
|
||||
2. Perform required transformation;
|
||||
3. Send pixel data to sink devices.
|
||||
|
||||
If you want to learn more about our driver details, take a look at the below
|
||||
table of content:
|
||||
|
||||
.. toctree::
|
||||
|
||||
display-manager.rst
|
||||
dc-debug.rst
|
||||
dcn-overview.rst
|
||||
dc-glossary.rst
|
|
@ -0,0 +1,182 @@
|
|||
============================
|
||||
Core Driver Infrastructure
|
||||
============================
|
||||
|
||||
GPU Hardware Structure
|
||||
======================
|
||||
|
||||
Each ASIC is a collection of hardware blocks. We refer to them as
|
||||
"IPs" (Intellectual Property blocks). Each IP encapsulates certain
|
||||
functionality. IPs are versioned and can also be mixed and matched.
|
||||
E.g., you might have two different ASICs that both have System DMA (SDMA) 5.x IPs.
|
||||
The driver is arranged by IPs. There are driver components to handle
|
||||
the initialization and operation of each IP. There are also a bunch
|
||||
of smaller IPs that don't really need much if any driver interaction.
|
||||
Those end up getting lumped into the common stuff in the soc files.
|
||||
The soc files (e.g., vi.c, soc15.c nv.c) contain code for aspects of
|
||||
the SoC itself rather than specific IPs. E.g., things like GPU resets
|
||||
and register access functions are SoC dependent.
|
||||
|
||||
An APU contains more than just CPU and GPU, it also contains all of
|
||||
the platform stuff (audio, usb, gpio, etc.). Also, a lot of
|
||||
components are shared between the CPU, platform, and the GPU (e.g.,
|
||||
SMU, PSP, etc.). Specific components (CPU, GPU, etc.) usually have
|
||||
their interface to interact with those common components. For things
|
||||
like S0i3 there is a ton of coordination required across all the
|
||||
components, but that is probably a bit beyond the scope of this
|
||||
section.
|
||||
|
||||
With respect to the GPU, we have the following major IPs:
|
||||
|
||||
GMC (Graphics Memory Controller)
|
||||
This was a dedicated IP on older pre-vega chips, but has since
|
||||
become somewhat decentralized on vega and newer chips. They now
|
||||
have dedicated memory hubs for specific IPs or groups of IPs. We
|
||||
still treat it as a single component in the driver however since
|
||||
the programming model is still pretty similar. This is how the
|
||||
different IPs on the GPU get the memory (VRAM or system memory).
|
||||
It also provides the support for per process GPU virtual address
|
||||
spaces.
|
||||
|
||||
IH (Interrupt Handler)
|
||||
This is the interrupt controller on the GPU. All of the IPs feed
|
||||
their interrupts into this IP and it aggregates them into a set of
|
||||
ring buffers that the driver can parse to handle interrupts from
|
||||
different IPs.
|
||||
|
||||
PSP (Platform Security Processor)
|
||||
This handles security policy for the SoC and executes trusted
|
||||
applications, and validates and loads firmwares for other blocks.
|
||||
|
||||
SMU (System Management Unit)
|
||||
This is the power management microcontroller. It manages the entire
|
||||
SoC. The driver interacts with it to control power management
|
||||
features like clocks, voltages, power rails, etc.
|
||||
|
||||
DCN (Display Controller Next)
|
||||
This is the display controller. It handles the display hardware.
|
||||
It is described in more details in :ref:`Display Core <amdgpu-display-core>`.
|
||||
|
||||
SDMA (System DMA)
|
||||
This is a multi-purpose DMA engine. The kernel driver uses it for
|
||||
various things including paging and GPU page table updates. It's also
|
||||
exposed to userspace for use by user mode drivers (OpenGL, Vulkan,
|
||||
etc.)
|
||||
|
||||
GC (Graphics and Compute)
|
||||
This is the graphics and compute engine, i.e., the block that
|
||||
encompasses the 3D pipeline and and shader blocks. This is by far the
|
||||
largest block on the GPU. The 3D pipeline has tons of sub-blocks. In
|
||||
addition to that, it also contains the CP microcontrollers (ME, PFP,
|
||||
CE, MEC) and the RLC microcontroller. It's exposed to userspace for
|
||||
user mode drivers (OpenGL, Vulkan, OpenCL, etc.)
|
||||
|
||||
VCN (Video Core Next)
|
||||
This is the multi-media engine. It handles video and image encode and
|
||||
decode. It's exposed to userspace for user mode drivers (VA-API,
|
||||
OpenMAX, etc.)
|
||||
|
||||
Graphics and Compute Microcontrollers
|
||||
-------------------------------------
|
||||
|
||||
CP (Command Processor)
|
||||
The name for the hardware block that encompasses the front end of the
|
||||
GFX/Compute pipeline. Consists mainly of a bunch of microcontrollers
|
||||
(PFP, ME, CE, MEC). The firmware that runs on these microcontrollers
|
||||
provides the driver interface to interact with the GFX/Compute engine.
|
||||
|
||||
MEC (MicroEngine Compute)
|
||||
This is the microcontroller that controls the compute queues on the
|
||||
GFX/compute engine.
|
||||
|
||||
MES (MicroEngine Scheduler)
|
||||
This is a new engine for managing queues. This is currently unused.
|
||||
|
||||
RLC (RunList Controller)
|
||||
This is another microcontroller in the GFX/Compute engine. It handles
|
||||
power management related functionality within the GFX/Compute engine.
|
||||
The name is a vestige of old hardware where it was originally added
|
||||
and doesn't really have much relation to what the engine does now.
|
||||
|
||||
Driver Structure
|
||||
================
|
||||
|
||||
In general, the driver has a list of all of the IPs on a particular
|
||||
SoC and for things like init/fini/suspend/resume, more or less just
|
||||
walks the list and handles each IP.
|
||||
|
||||
Some useful constructs:
|
||||
|
||||
KIQ (Kernel Interface Queue)
|
||||
This is a control queue used by the kernel driver to manage other gfx
|
||||
and compute queues on the GFX/compute engine. You can use it to
|
||||
map/unmap additional queues, etc.
|
||||
|
||||
IB (Indirect Buffer)
|
||||
A command buffer for a particular engine. Rather than writing
|
||||
commands directly to the queue, you can write the commands into a
|
||||
piece of memory and then put a pointer to the memory into the queue.
|
||||
The hardware will then follow the pointer and execute the commands in
|
||||
the memory, then returning to the rest of the commands in the ring.
|
||||
|
||||
.. _amdgpu_memory_domains:
|
||||
|
||||
Memory Domains
|
||||
==============
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/amdgpu_drm.h
|
||||
:doc: memory domains
|
||||
|
||||
Buffer Objects
|
||||
==============
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
||||
:doc: amdgpu_object
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
|
||||
:internal:
|
||||
|
||||
PRIME Buffer Sharing
|
||||
====================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
||||
:doc: PRIME Buffer Sharing
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
|
||||
:internal:
|
||||
|
||||
MMU Notifier
|
||||
============
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
||||
:doc: MMU Notifier
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
|
||||
:internal:
|
||||
|
||||
AMDGPU Virtual Memory
|
||||
=====================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
||||
:doc: GPUVM
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
||||
:internal:
|
||||
|
||||
Interrupt Handling
|
||||
==================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
||||
:doc: Interrupt Handling
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
|
||||
:internal:
|
||||
|
||||
IP Blocks
|
||||
=========
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||
:doc: IP Blocks
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||
:identifiers: amd_ip_block_type amd_ip_funcs
|
|
@ -0,0 +1,112 @@
|
|||
================================
|
||||
Misc AMDGPU driver information
|
||||
================================
|
||||
|
||||
GPU Product Information
|
||||
=======================
|
||||
|
||||
Information about the GPU can be obtained on certain cards
|
||||
via sysfs
|
||||
|
||||
product_name
|
||||
------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: product_name
|
||||
|
||||
product_number
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: product_name
|
||||
|
||||
serial_number
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: serial_number
|
||||
|
||||
unique_id
|
||||
---------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: unique_id
|
||||
|
||||
GPU Memory Usage Information
|
||||
============================
|
||||
|
||||
Various memory accounting can be accessed via sysfs
|
||||
|
||||
mem_info_vram_total
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vram_total
|
||||
|
||||
mem_info_vram_used
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vram_used
|
||||
|
||||
mem_info_vis_vram_total
|
||||
-----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vis_vram_total
|
||||
|
||||
mem_info_vis_vram_used
|
||||
----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
|
||||
:doc: mem_info_vis_vram_used
|
||||
|
||||
mem_info_gtt_total
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
||||
:doc: mem_info_gtt_total
|
||||
|
||||
mem_info_gtt_used
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
|
||||
:doc: mem_info_gtt_used
|
||||
|
||||
PCIe Accounting Information
|
||||
===========================
|
||||
|
||||
pcie_bw
|
||||
-------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pcie_bw
|
||||
|
||||
pcie_replay_count
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
||||
:doc: pcie_replay_count
|
||||
|
||||
GPU SmartShift Information
|
||||
==========================
|
||||
|
||||
GPU SmartShift information via sysfs
|
||||
|
||||
smartshift_apu_power
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: smartshift_apu_power
|
||||
|
||||
smartshift_dgpu_power
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: smartshift_dgpu_power
|
||||
|
||||
smartshift_bias
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: smartshift_bias
|
|
@ -0,0 +1,17 @@
|
|||
==========================
|
||||
drm/amdgpu AMDgpu driver
|
||||
==========================
|
||||
|
||||
The drm/amdgpu driver supports all AMD Radeon GPUs based on the Graphics Core
|
||||
Next (GCN) architecture.
|
||||
|
||||
.. toctree::
|
||||
|
||||
module-parameters
|
||||
driver-core
|
||||
display/index
|
||||
xgmi
|
||||
ras
|
||||
thermal
|
||||
driver-misc
|
||||
amdgpu-glossary
|
|
@ -0,0 +1,7 @@
|
|||
===================
|
||||
Module Parameters
|
||||
===================
|
||||
|
||||
The amdgpu driver supports the following module parameters:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
|
@ -0,0 +1,62 @@
|
|||
====================
|
||||
AMDGPU RAS Support
|
||||
====================
|
||||
|
||||
The AMDGPU RAS interfaces are exposed via sysfs (for informational queries) and
|
||||
debugfs (for error injection).
|
||||
|
||||
RAS debugfs/sysfs Control and Error Injection Interfaces
|
||||
========================================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS debugfs control interface
|
||||
|
||||
RAS Reboot Behavior for Unrecoverable Errors
|
||||
============================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS Reboot Behavior for Unrecoverable Errors
|
||||
|
||||
RAS Error Count sysfs Interface
|
||||
===============================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS sysfs Error Count Interface
|
||||
|
||||
RAS EEPROM debugfs Interface
|
||||
============================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS debugfs EEPROM table reset interface
|
||||
|
||||
RAS VRAM Bad Pages sysfs Interface
|
||||
==================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
||||
:doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
|
||||
|
||||
Sample Code
|
||||
===========
|
||||
Sample code for testing error injection can be found here:
|
||||
https://cgit.freedesktop.org/mesa/drm/tree/tests/amdgpu/ras_tests.c
|
||||
|
||||
This is part of the libdrm amdgpu unit tests which cover several areas of the GPU.
|
||||
There are four sets of tests:
|
||||
|
||||
RAS Basic Test
|
||||
|
||||
The test verifies the RAS feature enabled status and makes sure the necessary sysfs and debugfs files
|
||||
are present.
|
||||
|
||||
RAS Query Test
|
||||
|
||||
This test checks the RAS availability and enablement status for each supported IP block as well as
|
||||
the error counts.
|
||||
|
||||
RAS Inject Test
|
||||
|
||||
This test injects errors for each IP.
|
||||
|
||||
RAS Disable Test
|
||||
|
||||
This test tests disabling of RAS features for each IP block.
|
|
@ -0,0 +1,65 @@
|
|||
===========================================
|
||||
GPU Power/Thermal Controls and Monitoring
|
||||
===========================================
|
||||
|
||||
HWMON Interfaces
|
||||
================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: hwmon
|
||||
|
||||
GPU sysfs Power State Interfaces
|
||||
================================
|
||||
|
||||
GPU power controls are exposed via sysfs files.
|
||||
|
||||
power_dpm_state
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: power_dpm_state
|
||||
|
||||
power_dpm_force_performance_level
|
||||
---------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: power_dpm_force_performance_level
|
||||
|
||||
pp_table
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_table
|
||||
|
||||
pp_od_clk_voltage
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_od_clk_voltage
|
||||
|
||||
pp_dpm_*
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie
|
||||
|
||||
pp_power_profile_mode
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: pp_power_profile_mode
|
||||
|
||||
\*_busy_percent
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: gpu_busy_percent
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: mem_busy_percent
|
||||
|
||||
gpu_metrics
|
||||
-----------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
||||
:doc: gpu_metrics
|
|
@ -0,0 +1,5 @@
|
|||
=====================
|
||||
AMDGPU XGMI Support
|
||||
=====================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
|
|
@ -4,8 +4,7 @@ GPU Driver Documentation
|
|||
|
||||
.. toctree::
|
||||
|
||||
amdgpu
|
||||
amdgpu-dc
|
||||
amdgpu/index
|
||||
i915
|
||||
mcde
|
||||
meson
|
||||
|
|
|
@ -435,3 +435,18 @@ Legacy CRTC/Modeset Helper Functions Reference
|
|||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:export:
|
||||
|
||||
Privacy-screen class
|
||||
====================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/drm/drm_privacy_screen_driver.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_privacy_screen_machine.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c
|
||||
:export:
|
||||
|
|
|
@ -506,6 +506,8 @@ Property Types and Blob Property Support
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_property.c
|
||||
:export:
|
||||
|
||||
.. _standard_connector_properties:
|
||||
|
||||
Standard Connector Properties
|
||||
-----------------------------
|
||||
|
||||
|
|
|
@ -268,17 +268,6 @@ Contact: Daniel Vetter
|
|||
|
||||
Level: Intermediate
|
||||
|
||||
Clean up mmap forwarding
|
||||
------------------------
|
||||
|
||||
A lot of drivers forward gem mmap calls to dma-buf mmap for imported buffers.
|
||||
And also a lot of them forward dma-buf mmap to the gem mmap implementations.
|
||||
There's drm_gem_prime_mmap() for this now, but still needs to be rolled out.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Generic fbdev defio support
|
||||
---------------------------
|
||||
|
||||
|
@ -463,6 +452,21 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>, Christian König, Daniel Vette
|
|||
|
||||
Level: Intermediate
|
||||
|
||||
Review all drivers for setting struct drm_mode_config.{max_width,max_height} correctly
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
The values in struct drm_mode_config.{max_width,max_height} describe the
|
||||
maximum supported framebuffer size. It's the virtual screen size, but many
|
||||
drivers treat it like limitations of the physical resolution.
|
||||
|
||||
The maximum width depends on the hardware's maximum scanline pitch. The
|
||||
maximum height depends on the amount of addressable video memory. Review all
|
||||
drivers to initialize the fields to the correct values.
|
||||
|
||||
Contact: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
@ -642,6 +646,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks.
|
|||
|
||||
Contact: Harry Wentland, Alex Deucher
|
||||
|
||||
vmwgfx: Replace hashtable with Linux' implementation
|
||||
----------------------------------------------------
|
||||
|
||||
The vmwgfx driver uses its own hashtable implementation. Replace the
|
||||
code with Linux' implementation and update the callers. It's mostly a
|
||||
refactoring task, but the interfaces are different.
|
||||
|
||||
Contact: Zack Rusin, Thomas Zimmermann <tzimmermann@suse.de>
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Bootsplash
|
||||
==========
|
||||
|
||||
|
|
23
MAINTAINERS
23
MAINTAINERS
|
@ -966,6 +966,7 @@ F: drivers/gpu/drm/amd/include/kgd_kfd_interface.h
|
|||
F: drivers/gpu/drm/amd/include/v9_structs.h
|
||||
F: drivers/gpu/drm/amd/include/vi_structs.h
|
||||
F: include/uapi/linux/kfd_ioctl.h
|
||||
F: include/uapi/linux/kfd_sysfs.h
|
||||
|
||||
AMD SPI DRIVER
|
||||
M: Sanjay R Mehta <sanju.mehta@amd.com>
|
||||
|
@ -6057,6 +6058,7 @@ F: drivers/gpu/drm/tiny/mi0283qt.c
|
|||
DRM DRIVER FOR MSM ADRENO GPU
|
||||
M: Rob Clark <robdclark@gmail.com>
|
||||
M: Sean Paul <sean@poorly.run>
|
||||
R: Abhinav Kumar <quic_abhinavk@quicinc.com>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: freedreno@lists.freedesktop.org
|
||||
|
@ -6082,10 +6084,17 @@ F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
|
|||
|
||||
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
|
||||
M: Ben Skeggs <bskeggs@redhat.com>
|
||||
M: Karol Herbst <kherbst@redhat.com>
|
||||
M: Lyude Paul <lyude@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: nouveau@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://github.com/skeggsb/linux
|
||||
W: https://nouveau.freedesktop.org/
|
||||
Q: https://patchwork.freedesktop.org/project/nouveau/
|
||||
Q: https://gitlab.freedesktop.org/drm/nouveau/-/merge_requests
|
||||
B: https://gitlab.freedesktop.org/drm/nouveau/-/issues
|
||||
C: irc://irc.oftc.net/nouveau
|
||||
T: git https://gitlab.freedesktop.org/drm/nouveau.git
|
||||
F: drivers/gpu/drm/nouveau/
|
||||
F: include/uapi/drm/nouveau_drm.h
|
||||
|
||||
|
@ -6425,6 +6434,7 @@ L: dri-devel@lists.freedesktop.org
|
|||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://linuxtv.org/pinchartl/media drm/du/next
|
||||
F: Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
|
||||
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
|
||||
F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
|
||||
F: Documentation/devicetree/bindings/display/renesas,du.yaml
|
||||
|
@ -6543,6 +6553,14 @@ F: drivers/gpu/drm/drm_panel.c
|
|||
F: drivers/gpu/drm/panel/
|
||||
F: include/drm/drm_panel.h
|
||||
|
||||
DRM PRIVACY-SCREEN CLASS
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: drivers/gpu/drm/drm_privacy_screen*
|
||||
F: include/drm/drm_privacy_screen*
|
||||
|
||||
DRM TTM SUBSYSTEM
|
||||
M: Christian Koenig <christian.koenig@amd.com>
|
||||
M: Huang Rui <ray.huang@amd.com>
|
||||
|
@ -9499,6 +9517,7 @@ INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
|
|||
M: Jani Nikula <jani.nikula@linux.intel.com>
|
||||
M: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
|
||||
M: Rodrigo Vivi <rodrigo.vivi@intel.com>
|
||||
M: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
|
||||
L: intel-gfx@lists.freedesktop.org
|
||||
S: Supported
|
||||
W: https://01.org/linuxgraphics/
|
||||
|
@ -20228,6 +20247,8 @@ F: include/uapi/linux/virtio_gpio.h
|
|||
VIRTIO GPU DRIVER
|
||||
M: David Airlie <airlied@linux.ie>
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
R: Gurchetan Singh <gurchetansingh@chromium.org>
|
||||
R: Chia-I Wu <olvaffe@gmail.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: virtualization@lists.linux-foundation.org
|
||||
S: Maintained
|
||||
|
|
|
@ -554,6 +554,7 @@ static const struct pci_device_id intel_early_ids[] __initconst = {
|
|||
INTEL_RKL_IDS(&gen11_early_ops),
|
||||
INTEL_ADLS_IDS(&gen11_early_ops),
|
||||
INTEL_ADLP_IDS(&gen11_early_ops),
|
||||
INTEL_RPLS_IDS(&gen11_early_ops),
|
||||
};
|
||||
|
||||
struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/agp_backend.h>
|
||||
#include <linux/intel-iommu.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/smp.h>
|
||||
#include "agp.h"
|
||||
|
|
|
@ -932,8 +932,7 @@ static int bcm2835_clock_is_on(struct clk_hw *hw)
|
|||
|
||||
static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate,
|
||||
bool round_up)
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
const struct bcm2835_clock_data *data = clock->data;
|
||||
|
@ -945,10 +944,6 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
|||
|
||||
rem = do_div(temp, rate);
|
||||
div = temp;
|
||||
|
||||
/* Round up and mask off the unused bits */
|
||||
if (round_up && ((div & unused_frac_mask) != 0 || rem != 0))
|
||||
div += unused_frac_mask + 1;
|
||||
div &= ~unused_frac_mask;
|
||||
|
||||
/* different clamping limits apply for a mash clock */
|
||||
|
@ -1079,7 +1074,7 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
|
|||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
struct bcm2835_cprman *cprman = clock->cprman;
|
||||
const struct bcm2835_clock_data *data = clock->data;
|
||||
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
|
||||
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
|
||||
u32 ctl;
|
||||
|
||||
spin_lock(&cprman->regs_lock);
|
||||
|
@ -1130,7 +1125,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
|
|||
|
||||
if (!(BIT(parent_idx) & data->set_rate_parent)) {
|
||||
*prate = clk_hw_get_rate(parent);
|
||||
*div = bcm2835_clock_choose_div(hw, rate, *prate, true);
|
||||
*div = bcm2835_clock_choose_div(hw, rate, *prate);
|
||||
|
||||
*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
|
||||
|
||||
|
@ -1216,7 +1211,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
|
|||
rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
|
||||
&div, &prate,
|
||||
&avgrate);
|
||||
if (rate > best_rate && rate <= req->rate) {
|
||||
if (abs(req->rate - rate) < abs(req->rate - best_rate)) {
|
||||
best_parent = parent;
|
||||
best_prate = prate;
|
||||
best_rate = rate;
|
||||
|
|
|
@ -11,6 +11,7 @@ obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o
|
|||
dmabuf_selftests-y := \
|
||||
selftest.o \
|
||||
st-dma-fence.o \
|
||||
st-dma-fence-chain.o
|
||||
st-dma-fence-chain.o \
|
||||
st-dma-resv.o
|
||||
|
||||
obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
|
||||
|
|
|
@ -299,10 +299,8 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
|
|||
|
||||
/**
|
||||
* dma_buf_set_name - Set a name to a specific dma_buf to track the usage.
|
||||
* The name of the dma-buf buffer can only be set when the dma-buf is not
|
||||
* attached to any devices. It could theoritically support changing the
|
||||
* name of the dma-buf if the same piece of memory is used for multiple
|
||||
* purpose between different devices.
|
||||
* It could support changing the name of the dma-buf if the same
|
||||
* piece of memory is used for multiple purpose between different devices.
|
||||
*
|
||||
* @dmabuf: [in] dmabuf buffer that will be renamed.
|
||||
* @buf: [in] A piece of userspace memory that contains the name of
|
||||
|
@ -315,25 +313,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
|
|||
static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
|
||||
{
|
||||
char *name = strndup_user(buf, DMA_BUF_NAME_LEN);
|
||||
long ret = 0;
|
||||
|
||||
if (IS_ERR(name))
|
||||
return PTR_ERR(name);
|
||||
|
||||
dma_resv_lock(dmabuf->resv, NULL);
|
||||
if (!list_empty(&dmabuf->attachments)) {
|
||||
ret = -EBUSY;
|
||||
kfree(name);
|
||||
goto out_unlock;
|
||||
}
|
||||
spin_lock(&dmabuf->name_lock);
|
||||
kfree(dmabuf->name);
|
||||
dmabuf->name = name;
|
||||
spin_unlock(&dmabuf->name_lock);
|
||||
|
||||
out_unlock:
|
||||
dma_resv_unlock(dmabuf->resv);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long dma_buf_ioctl(struct file *file,
|
||||
|
@ -1058,8 +1047,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF);
|
|||
*
|
||||
* Interfaces::
|
||||
*
|
||||
* void \*dma_buf_vmap(struct dma_buf \*dmabuf)
|
||||
* void dma_buf_vunmap(struct dma_buf \*dmabuf, void \*vaddr)
|
||||
* void \*dma_buf_vmap(struct dma_buf \*dmabuf, struct dma_buf_map \*map)
|
||||
* void dma_buf_vunmap(struct dma_buf \*dmabuf, struct dma_buf_map \*map)
|
||||
*
|
||||
* The vmap call can fail if there is no vmap support in the exporter, or if
|
||||
* it runs out of vmalloc space. Note that the dma-buf layer keeps a reference
|
||||
|
@ -1338,8 +1327,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||
{
|
||||
struct dma_buf *buf_obj;
|
||||
struct dma_buf_attachment *attach_obj;
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *fence;
|
||||
int count = 0, attach_count;
|
||||
size_t size = 0;
|
||||
int ret;
|
||||
|
@ -1370,14 +1357,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||
buf_obj->name ?: "");
|
||||
spin_unlock(&buf_obj->name_lock);
|
||||
|
||||
dma_resv_for_each_fence(&cursor, buf_obj->resv, true, fence) {
|
||||
seq_printf(s, "\t%s fence: %s %s %ssignalled\n",
|
||||
dma_resv_iter_is_exclusive(&cursor) ?
|
||||
"Exclusive" : "Shared",
|
||||
fence->ops->get_driver_name(fence),
|
||||
fence->ops->get_timeline_name(fence),
|
||||
dma_fence_is_signaled(fence) ? "" : "un");
|
||||
}
|
||||
dma_resv_describe(buf_obj->resv, s);
|
||||
|
||||
seq_puts(s, "\tAttached Devices:\n");
|
||||
attach_count = 0;
|
||||
|
|
|
@ -104,7 +104,11 @@ static bool dma_fence_array_signaled(struct dma_fence *fence)
|
|||
{
|
||||
struct dma_fence_array *array = to_dma_fence_array(fence);
|
||||
|
||||
return atomic_read(&array->num_pending) <= 0;
|
||||
if (atomic_read(&array->num_pending) > 0)
|
||||
return false;
|
||||
|
||||
dma_fence_array_clear_pending_error(array);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dma_fence_array_release(struct dma_fence *fence)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/atomic.h>
|
||||
#include <linux/dma-fence.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/dma_fence.h>
|
||||
|
@ -907,6 +908,22 @@ err_free_cb:
|
|||
}
|
||||
EXPORT_SYMBOL(dma_fence_wait_any_timeout);
|
||||
|
||||
/**
|
||||
* dma_fence_describe - Dump fence describtion into seq_file
|
||||
* @fence: the 6fence to describe
|
||||
* @seq: the seq_file to put the textual description into
|
||||
*
|
||||
* Dump a textual description of the fence and it's state into the seq_file.
|
||||
*/
|
||||
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
|
||||
{
|
||||
seq_printf(seq, "%s %s seq %llu %ssignalled\n",
|
||||
fence->ops->get_driver_name(fence),
|
||||
fence->ops->get_timeline_name(fence), fence->seqno,
|
||||
dma_fence_is_signaled(fence) ? "" : "un");
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_describe);
|
||||
|
||||
/**
|
||||
* dma_fence_init - Initialize a custom fence.
|
||||
* @fence: the fence to initialize
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
/**
|
||||
* DOC: Reservation Object Overview
|
||||
|
@ -304,8 +305,7 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
|
|||
if (old)
|
||||
i = old->shared_count;
|
||||
|
||||
if (fence)
|
||||
dma_fence_get(fence);
|
||||
dma_fence_get(fence);
|
||||
|
||||
write_seqcount_begin(&obj->seq);
|
||||
/* write_seqcount_begin provides the necessary memory barrier */
|
||||
|
@ -666,6 +666,28 @@ bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dma_resv_test_signaled);
|
||||
|
||||
/**
|
||||
* dma_resv_describe - Dump description of the resv object into seq_file
|
||||
* @obj: the reservation object
|
||||
* @seq: the seq_file to dump the description into
|
||||
*
|
||||
* Dump a textual description of the fences inside an dma_resv object into the
|
||||
* seq_file.
|
||||
*/
|
||||
void dma_resv_describe(struct dma_resv *obj, struct seq_file *seq)
|
||||
{
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *fence;
|
||||
|
||||
dma_resv_for_each_fence(&cursor, obj, true, fence) {
|
||||
seq_printf(seq, "\t%s fence:",
|
||||
dma_resv_iter_is_exclusive(&cursor) ?
|
||||
"Exclusive" : "Shared");
|
||||
dma_fence_describe(fence, seq);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_resv_describe);
|
||||
|
||||
#if IS_ENABLED(CONFIG_LOCKDEP)
|
||||
static int __init dma_resv_lockdep(void)
|
||||
{
|
||||
|
|
|
@ -12,3 +12,4 @@
|
|||
selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
|
||||
selftest(dma_fence, dma_fence)
|
||||
selftest(dma_fence_chain, dma_fence_chain)
|
||||
selftest(dma_resv, dma_resv)
|
||||
|
|
|
@ -0,0 +1,371 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
* Copyright © 2021 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/dma-resv.h>
|
||||
|
||||
#include "selftest.h"
|
||||
|
||||
static struct spinlock fence_lock;
|
||||
|
||||
static const char *fence_name(struct dma_fence *f)
|
||||
{
|
||||
return "selftest";
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops fence_ops = {
|
||||
.get_driver_name = fence_name,
|
||||
.get_timeline_name = fence_name,
|
||||
};
|
||||
|
||||
static struct dma_fence *alloc_fence(void)
|
||||
{
|
||||
struct dma_fence *f;
|
||||
|
||||
f = kmalloc(sizeof(*f), GFP_KERNEL);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
dma_fence_init(f, &fence_ops, &fence_lock, 0, 0);
|
||||
return f;
|
||||
}
|
||||
|
||||
static int sanitycheck(void *arg)
|
||||
{
|
||||
struct dma_resv resv;
|
||||
struct dma_fence *f;
|
||||
int r;
|
||||
|
||||
f = alloc_fence();
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_fence_signal(f);
|
||||
dma_fence_put(f);
|
||||
|
||||
dma_resv_init(&resv);
|
||||
r = dma_resv_lock(&resv, NULL);
|
||||
if (r)
|
||||
pr_err("Resv locking failed\n");
|
||||
else
|
||||
dma_resv_unlock(&resv);
|
||||
dma_resv_fini(&resv);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_signaling(void *arg, bool shared)
|
||||
{
|
||||
struct dma_resv resv;
|
||||
struct dma_fence *f;
|
||||
int r;
|
||||
|
||||
f = alloc_fence();
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_resv_init(&resv);
|
||||
r = dma_resv_lock(&resv, NULL);
|
||||
if (r) {
|
||||
pr_err("Resv locking failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
r = dma_resv_reserve_shared(&resv, 1);
|
||||
if (r) {
|
||||
pr_err("Resv shared slot allocation failed\n");
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
dma_resv_add_shared_fence(&resv, f);
|
||||
} else {
|
||||
dma_resv_add_excl_fence(&resv, f);
|
||||
}
|
||||
|
||||
if (dma_resv_test_signaled(&resv, shared)) {
|
||||
pr_err("Resv unexpectedly signaled\n");
|
||||
r = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
dma_fence_signal(f);
|
||||
if (!dma_resv_test_signaled(&resv, shared)) {
|
||||
pr_err("Resv not reporting signaled\n");
|
||||
r = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
err_unlock:
|
||||
dma_resv_unlock(&resv);
|
||||
err_free:
|
||||
dma_resv_fini(&resv);
|
||||
dma_fence_put(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_excl_signaling(void *arg)
|
||||
{
|
||||
return test_signaling(arg, false);
|
||||
}
|
||||
|
||||
static int test_shared_signaling(void *arg)
|
||||
{
|
||||
return test_signaling(arg, true);
|
||||
}
|
||||
|
||||
static int test_for_each(void *arg, bool shared)
|
||||
{
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *f, *fence;
|
||||
struct dma_resv resv;
|
||||
int r;
|
||||
|
||||
f = alloc_fence();
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_resv_init(&resv);
|
||||
r = dma_resv_lock(&resv, NULL);
|
||||
if (r) {
|
||||
pr_err("Resv locking failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
r = dma_resv_reserve_shared(&resv, 1);
|
||||
if (r) {
|
||||
pr_err("Resv shared slot allocation failed\n");
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
dma_resv_add_shared_fence(&resv, f);
|
||||
} else {
|
||||
dma_resv_add_excl_fence(&resv, f);
|
||||
}
|
||||
|
||||
r = -ENOENT;
|
||||
dma_resv_for_each_fence(&cursor, &resv, shared, fence) {
|
||||
if (!r) {
|
||||
pr_err("More than one fence found\n");
|
||||
r = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
if (f != fence) {
|
||||
pr_err("Unexpected fence\n");
|
||||
r = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
|
||||
pr_err("Unexpected fence usage\n");
|
||||
r = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
r = 0;
|
||||
}
|
||||
if (r) {
|
||||
pr_err("No fence found\n");
|
||||
goto err_unlock;
|
||||
}
|
||||
dma_fence_signal(f);
|
||||
err_unlock:
|
||||
dma_resv_unlock(&resv);
|
||||
err_free:
|
||||
dma_resv_fini(&resv);
|
||||
dma_fence_put(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_excl_for_each(void *arg)
|
||||
{
|
||||
return test_for_each(arg, false);
|
||||
}
|
||||
|
||||
static int test_shared_for_each(void *arg)
|
||||
{
|
||||
return test_for_each(arg, true);
|
||||
}
|
||||
|
||||
static int test_for_each_unlocked(void *arg, bool shared)
|
||||
{
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *f, *fence;
|
||||
struct dma_resv resv;
|
||||
int r;
|
||||
|
||||
f = alloc_fence();
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_resv_init(&resv);
|
||||
r = dma_resv_lock(&resv, NULL);
|
||||
if (r) {
|
||||
pr_err("Resv locking failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
r = dma_resv_reserve_shared(&resv, 1);
|
||||
if (r) {
|
||||
pr_err("Resv shared slot allocation failed\n");
|
||||
dma_resv_unlock(&resv);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
dma_resv_add_shared_fence(&resv, f);
|
||||
} else {
|
||||
dma_resv_add_excl_fence(&resv, f);
|
||||
}
|
||||
dma_resv_unlock(&resv);
|
||||
|
||||
r = -ENOENT;
|
||||
dma_resv_iter_begin(&cursor, &resv, shared);
|
||||
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
||||
if (!r) {
|
||||
pr_err("More than one fence found\n");
|
||||
r = -EINVAL;
|
||||
goto err_iter_end;
|
||||
}
|
||||
if (!dma_resv_iter_is_restarted(&cursor)) {
|
||||
pr_err("No restart flag\n");
|
||||
goto err_iter_end;
|
||||
}
|
||||
if (f != fence) {
|
||||
pr_err("Unexpected fence\n");
|
||||
r = -EINVAL;
|
||||
goto err_iter_end;
|
||||
}
|
||||
if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
|
||||
pr_err("Unexpected fence usage\n");
|
||||
r = -EINVAL;
|
||||
goto err_iter_end;
|
||||
}
|
||||
|
||||
/* We use r as state here */
|
||||
if (r == -ENOENT) {
|
||||
r = -EINVAL;
|
||||
/* That should trigger an restart */
|
||||
cursor.seq--;
|
||||
} else if (r == -EINVAL) {
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
if (r)
|
||||
pr_err("No fence found\n");
|
||||
err_iter_end:
|
||||
dma_resv_iter_end(&cursor);
|
||||
dma_fence_signal(f);
|
||||
err_free:
|
||||
dma_resv_fini(&resv);
|
||||
dma_fence_put(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_excl_for_each_unlocked(void *arg)
|
||||
{
|
||||
return test_for_each_unlocked(arg, false);
|
||||
}
|
||||
|
||||
static int test_shared_for_each_unlocked(void *arg)
|
||||
{
|
||||
return test_for_each_unlocked(arg, true);
|
||||
}
|
||||
|
||||
static int test_get_fences(void *arg, bool shared)
|
||||
{
|
||||
struct dma_fence *f, *excl = NULL, **fences = NULL;
|
||||
struct dma_resv resv;
|
||||
int r, i;
|
||||
|
||||
f = alloc_fence();
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
dma_resv_init(&resv);
|
||||
r = dma_resv_lock(&resv, NULL);
|
||||
if (r) {
|
||||
pr_err("Resv locking failed\n");
|
||||
goto err_resv;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
r = dma_resv_reserve_shared(&resv, 1);
|
||||
if (r) {
|
||||
pr_err("Resv shared slot allocation failed\n");
|
||||
dma_resv_unlock(&resv);
|
||||
goto err_resv;
|
||||
}
|
||||
|
||||
dma_resv_add_shared_fence(&resv, f);
|
||||
} else {
|
||||
dma_resv_add_excl_fence(&resv, f);
|
||||
}
|
||||
dma_resv_unlock(&resv);
|
||||
|
||||
r = dma_resv_get_fences(&resv, &excl, &i, &fences);
|
||||
if (r) {
|
||||
pr_err("get_fences failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
if (excl != NULL) {
|
||||
pr_err("get_fences returned unexpected excl fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
if (i != 1 || fences[0] != f) {
|
||||
pr_err("get_fences returned unexpected shared fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
} else {
|
||||
if (excl != f) {
|
||||
pr_err("get_fences returned unexpected excl fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
if (i != 0) {
|
||||
pr_err("get_fences returned unexpected shared fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
||||
dma_fence_signal(f);
|
||||
err_free:
|
||||
dma_fence_put(excl);
|
||||
while (i--)
|
||||
dma_fence_put(fences[i]);
|
||||
kfree(fences);
|
||||
err_resv:
|
||||
dma_resv_fini(&resv);
|
||||
dma_fence_put(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int test_excl_get_fences(void *arg)
|
||||
{
|
||||
return test_get_fences(arg, false);
|
||||
}
|
||||
|
||||
static int test_shared_get_fences(void *arg)
|
||||
{
|
||||
return test_get_fences(arg, true);
|
||||
}
|
||||
|
||||
int dma_resv(void)
|
||||
{
|
||||
static const struct subtest tests[] = {
|
||||
SUBTEST(sanitycheck),
|
||||
SUBTEST(test_excl_signaling),
|
||||
SUBTEST(test_shared_signaling),
|
||||
SUBTEST(test_excl_for_each),
|
||||
SUBTEST(test_shared_for_each),
|
||||
SUBTEST(test_excl_for_each_unlocked),
|
||||
SUBTEST(test_shared_for_each_unlocked),
|
||||
SUBTEST(test_excl_get_fences),
|
||||
SUBTEST(test_shared_get_fences),
|
||||
};
|
||||
|
||||
spin_lock_init(&fence_lock);
|
||||
return subtests(tests, NULL);
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
menuconfig DRM
|
||||
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
|
||||
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA
|
||||
select DRM_NOMODESET
|
||||
select DRM_PANEL_ORIENTATION_QUIRKS
|
||||
select HDMI
|
||||
select FB_CMDLINE
|
||||
|
@ -211,20 +212,13 @@ config DRM_TTM_HELPER
|
|||
Helpers for ttm-based gem objects
|
||||
|
||||
config DRM_GEM_CMA_HELPER
|
||||
bool
|
||||
tristate
|
||||
depends on DRM
|
||||
help
|
||||
Choose this if you need the GEM CMA helper functions
|
||||
|
||||
config DRM_KMS_CMA_HELPER
|
||||
bool
|
||||
depends on DRM
|
||||
select DRM_GEM_CMA_HELPER
|
||||
help
|
||||
Choose this if you need the KMS CMA helper functions
|
||||
|
||||
config DRM_GEM_SHMEM_HELPER
|
||||
bool
|
||||
tristate
|
||||
depends on DRM && MMU
|
||||
help
|
||||
Choose this if you need the GEM shmem helper functions
|
||||
|
@ -394,6 +388,8 @@ source "drivers/gpu/drm/xlnx/Kconfig"
|
|||
|
||||
source "drivers/gpu/drm/gud/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/sprd/Kconfig"
|
||||
|
||||
config DRM_HYPERV
|
||||
tristate "DRM Support for Hyper-V synthetic video device"
|
||||
depends on DRM && PCI && MMU && HYPERV
|
||||
|
@ -492,6 +488,15 @@ config DRM_EXPORT_FOR_TESTS
|
|||
config DRM_PANEL_ORIENTATION_QUIRKS
|
||||
tristate
|
||||
|
||||
# Separate option because nomodeset parameter is global and expected built-in
|
||||
config DRM_NOMODESET
|
||||
bool
|
||||
default n
|
||||
|
||||
config DRM_LIB_RANDOM
|
||||
bool
|
||||
default n
|
||||
|
||||
config DRM_PRIVACY_SCREEN
|
||||
bool
|
||||
default n
|
||||
|
|
|
@ -4,37 +4,44 @@
|
|||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
drm-y := drm_aperture.o drm_auth.o drm_cache.o \
|
||||
drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \
|
||||
drm_file.o drm_gem.o drm_ioctl.o \
|
||||
drm_drv.o \
|
||||
drm_sysfs.o drm_hashtab.o drm_mm.o \
|
||||
drm_sysfs.o drm_mm.o \
|
||||
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \
|
||||
drm_encoder_slave.o \
|
||||
drm_trace_points.o drm_prime.o \
|
||||
drm_rect.o drm_vma_manager.o drm_flip_work.o \
|
||||
drm_vma_manager.o \
|
||||
drm_modeset_lock.o drm_atomic.o drm_bridge.o \
|
||||
drm_framebuffer.o drm_connector.o drm_blend.o \
|
||||
drm_encoder.o drm_mode_object.o drm_property.o \
|
||||
drm_plane.o drm_color_mgmt.o drm_print.o \
|
||||
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
|
||||
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
|
||||
drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
|
||||
drm_client_modeset.o drm_atomic_uapi.o \
|
||||
drm_managed.o drm_vblank_work.o
|
||||
|
||||
drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o drm_dma.o \
|
||||
drm_legacy_misc.o drm_lock.o drm_memory.o drm_scatter.o \
|
||||
drm_vm.o
|
||||
drm_hashtab.o drm_irq.o drm_legacy_misc.o drm_lock.o \
|
||||
drm_memory.o drm_scatter.o drm_vm.o
|
||||
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
||||
drm-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_gem_shmem_helper.o
|
||||
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
|
||||
drm-$(CONFIG_OF) += drm_of.o
|
||||
drm-$(CONFIG_PCI) += drm_pci.o
|
||||
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
|
||||
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||
drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o
|
||||
|
||||
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
|
||||
|
||||
obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
|
||||
|
||||
drm_cma_helper-y := drm_gem_cma_helper.o
|
||||
drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o
|
||||
obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o
|
||||
|
||||
drm_shmem_helper-y := drm_gem_shmem_helper.o
|
||||
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
|
||||
|
||||
drm_vram_helper-y := drm_gem_vram_helper.o
|
||||
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
|
||||
|
||||
|
@ -42,18 +49,18 @@ drm_ttm_helper-y := drm_gem_ttm_helper.o
|
|||
obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
|
||||
|
||||
drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
|
||||
drm_dsc.o drm_probe_helper.o \
|
||||
drm_dsc.o drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \
|
||||
drm_probe_helper.o \
|
||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
||||
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
|
||||
drm_simple_kms_helper.o drm_modeset_helper.o \
|
||||
drm_scdc_helper.o drm_gem_atomic_helper.o \
|
||||
drm_gem_framebuffer_helper.o \
|
||||
drm_atomic_state_helper.o drm_damage_helper.o \
|
||||
drm_format_helper.o drm_self_refresh_helper.o
|
||||
drm_format_helper.o drm_self_refresh_helper.o drm_rect.o
|
||||
|
||||
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
|
||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
||||
drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
|
||||
|
||||
|
@ -127,3 +134,4 @@ obj-$(CONFIG_DRM_TIDSS) += tidss/
|
|||
obj-y += xlnx/
|
||||
obj-y += gud/
|
||||
obj-$(CONFIG_DRM_HYPERV) += hyperv/
|
||||
obj-$(CONFIG_DRM_SPRD) += sprd/
|
||||
|
|
|
@ -45,7 +45,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
|
|||
amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \
|
||||
atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \
|
||||
amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \
|
||||
amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \
|
||||
amdgpu_gem.o amdgpu_ring.o \
|
||||
amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \
|
||||
atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \
|
||||
atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
|
||||
|
|
|
@ -458,7 +458,6 @@ struct amdgpu_flip_work {
|
|||
uint64_t base;
|
||||
struct drm_pending_vblank_event *event;
|
||||
struct amdgpu_bo *old_abo;
|
||||
struct dma_fence *excl;
|
||||
unsigned shared_count;
|
||||
struct dma_fence **shared;
|
||||
struct dma_fence_cb cb;
|
||||
|
@ -813,6 +812,7 @@ struct amd_powerplay {
|
|||
|
||||
#define AMDGPU_RESET_MAGIC_NUM 64
|
||||
#define AMDGPU_MAX_DF_PERFMONS 4
|
||||
#define AMDGPU_PRODUCT_NAME_LEN 64
|
||||
struct amdgpu_device {
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
|
@ -1084,7 +1084,7 @@ struct amdgpu_device {
|
|||
|
||||
/* Chip product information */
|
||||
char product_number[16];
|
||||
char product_name[32];
|
||||
char product_name[AMDGPU_PRODUCT_NAME_LEN];
|
||||
char serial[20];
|
||||
|
||||
atomic_t throttling_logging_enabled;
|
||||
|
@ -1097,7 +1097,9 @@ struct amdgpu_device {
|
|||
pci_channel_state_t pci_channel_state;
|
||||
|
||||
struct amdgpu_reset_control *reset_cntl;
|
||||
uint32_t ip_versions[HW_ID_MAX][HWIP_MAX_INSTANCE];
|
||||
uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE];
|
||||
|
||||
bool ram_is_direct_mapped;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
||||
|
@ -1318,6 +1320,8 @@ void amdgpu_device_flush_hdp(struct amdgpu_device *adev,
|
|||
void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring);
|
||||
|
||||
void amdgpu_device_halt(struct amdgpu_device *adev);
|
||||
|
||||
/* atpx handler */
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
void amdgpu_register_atpx_handler(void);
|
||||
|
@ -1361,8 +1365,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
|
|||
u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc);
|
||||
int amdgpu_enable_vblank_kms(struct drm_crtc *crtc);
|
||||
void amdgpu_disable_vblank_kms(struct drm_crtc *crtc);
|
||||
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
int amdgpu_info_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp);
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
|||
if (!kfd_initialized)
|
||||
return;
|
||||
|
||||
adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev, vf);
|
||||
adev->kfd.dev = kgd2kfd_probe(adev, vf);
|
||||
|
||||
if (adev->kfd.dev)
|
||||
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
|
||||
|
@ -233,19 +233,16 @@ int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev)
|
|||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd)
|
||||
void amdgpu_amdkfd_gpu_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
if (amdgpu_device_should_recover_gpu(adev))
|
||||
amdgpu_device_gpu_recover(adev, NULL);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
|
||||
void **mem_obj, uint64_t *gpu_addr,
|
||||
void **cpu_ptr, bool cp_mqd_gfx9)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
struct amdgpu_bo_param bp;
|
||||
int r;
|
||||
|
@ -314,7 +311,7 @@ allocate_mem_reserve_bo_failed:
|
|||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj)
|
||||
{
|
||||
struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj;
|
||||
|
||||
|
@ -325,10 +322,9 @@ void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)
|
|||
amdgpu_bo_unref(&(bo));
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size,
|
||||
int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
|
||||
void **mem_obj)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
struct amdgpu_bo_user *ubo;
|
||||
struct amdgpu_bo_param bp;
|
||||
|
@ -355,18 +351,16 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj)
|
||||
void amdgpu_amdkfd_free_gws(struct amdgpu_device *adev, void *mem_obj)
|
||||
{
|
||||
struct amdgpu_bo *bo = (struct amdgpu_bo *)mem_obj;
|
||||
|
||||
amdgpu_bo_unref(&bo);
|
||||
}
|
||||
|
||||
uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd,
|
||||
uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
|
||||
enum kgd_engine_type type)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
switch (type) {
|
||||
case KGD_ENGINE_PFP:
|
||||
return adev->gfx.pfp_fw_version;
|
||||
|
@ -399,11 +393,9 @@ uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
||||
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
|
||||
struct kfd_local_mem_info *mem_info)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
memset(mem_info, 0, sizeof(*mem_info));
|
||||
|
||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||
|
@ -428,19 +420,15 @@ void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
|||
mem_info->mem_clk_max = 100;
|
||||
}
|
||||
|
||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct kgd_dev *kgd)
|
||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
if (adev->gfx.funcs->get_gpu_clock_counter)
|
||||
return adev->gfx.funcs->get_gpu_clock_counter(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
|
||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
/* the sclk is in quantas of 10kHz */
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return adev->clock.default_sclk / 100;
|
||||
|
@ -450,9 +438,8 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
|
|||
return 100;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info)
|
||||
void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev, struct kfd_cu_info *cu_info)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_cu_info acu_info = adev->gfx.cu_info;
|
||||
|
||||
memset(cu_info, 0, sizeof(*cu_info));
|
||||
|
@ -473,13 +460,12 @@ void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info)
|
|||
cu_info->lds_size = acu_info.lds_size;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
||||
struct kgd_dev **dma_buf_kgd,
|
||||
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
struct amdgpu_device **dmabuf_adev,
|
||||
uint64_t *bo_size, void *metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct dma_buf *dma_buf;
|
||||
struct drm_gem_object *obj;
|
||||
struct amdgpu_bo *bo;
|
||||
|
@ -507,8 +493,8 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
|||
goto out_put;
|
||||
|
||||
r = 0;
|
||||
if (dma_buf_kgd)
|
||||
*dma_buf_kgd = (struct kgd_dev *)adev;
|
||||
if (dmabuf_adev)
|
||||
*dmabuf_adev = adev;
|
||||
if (bo_size)
|
||||
*bo_size = amdgpu_bo_size(bo);
|
||||
if (metadata_buffer)
|
||||
|
@ -528,32 +514,18 @@ out_put:
|
|||
return r;
|
||||
}
|
||||
|
||||
uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd)
|
||||
uint64_t amdgpu_amdkfd_get_vram_usage(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
|
||||
return amdgpu_vram_mgr_usage(vram_man);
|
||||
}
|
||||
|
||||
uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd)
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->gmc.xgmi.hive_id;
|
||||
}
|
||||
|
||||
uint64_t amdgpu_amdkfd_get_unique_id(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->unique_id;
|
||||
}
|
||||
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src)
|
||||
{
|
||||
struct amdgpu_device *peer_adev = (struct amdgpu_device *)src;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)dst;
|
||||
struct amdgpu_device *peer_adev = src;
|
||||
struct amdgpu_device *adev = dst;
|
||||
int ret = amdgpu_xgmi_get_hops_count(adev, peer_adev);
|
||||
|
||||
if (ret < 0) {
|
||||
|
@ -565,16 +537,18 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
|
|||
return (uint8_t)ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min)
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src,
|
||||
bool is_min)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)dst, *peer_adev;
|
||||
struct amdgpu_device *adev = dst, *peer_adev;
|
||||
int num_links;
|
||||
|
||||
if (adev->asic_type != CHIP_ALDEBARAN)
|
||||
return 0;
|
||||
|
||||
if (src)
|
||||
peer_adev = (struct amdgpu_device *)src;
|
||||
peer_adev = src;
|
||||
|
||||
/* num links returns 0 for indirect peers since indirect route is unknown. */
|
||||
num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev);
|
||||
|
@ -589,9 +563,8 @@ int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev
|
|||
return (num_links * 16 * 25000)/BITS_PER_BYTE;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min)
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)dev;
|
||||
int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) :
|
||||
fls(adev->pm.pcie_mlw_mask)) - 1;
|
||||
int gen_speed_shift = (is_min ? ffs(adev->pm.pcie_gen_mask &
|
||||
|
@ -647,39 +620,11 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min)
|
|||
return (num_lanes_factor * gen_speed_mbits_factor)/BITS_PER_BYTE;
|
||||
}
|
||||
|
||||
uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->rmmio_remap.bus_addr;
|
||||
}
|
||||
|
||||
uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->gds.gws_size;
|
||||
}
|
||||
|
||||
uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->rev_id;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->gmc.noretry;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
||||
int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||
enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
uint32_t *ib_cmd, uint32_t ib_len)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
struct amdgpu_ring *ring;
|
||||
|
@ -730,10 +675,8 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
|
||||
void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
amdgpu_dpm_switch_power_profile(adev,
|
||||
PP_SMC_POWER_PROFILE_COMPUTE,
|
||||
!idle);
|
||||
|
@ -747,10 +690,9 @@ bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
|
|||
return false;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
|
||||
uint16_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
if (adev->family == AMDGPU_FAMILY_AI) {
|
||||
int i;
|
||||
|
||||
|
@ -763,10 +705,9 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
|
||||
enum TLB_FLUSH_TYPE flush_type)
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
bool all_hub = false;
|
||||
|
||||
if (adev->family == AMDGPU_FAMILY_AI)
|
||||
|
@ -775,21 +716,18 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
|
|||
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd)
|
||||
bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
return adev->have_atomics_support;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct kgd_dev *kgd)
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct ras_err_data err_data = {0, 0, 0, NULL};
|
||||
|
||||
/* CPU MCA will handle page retirement if connected_to_cpu is 1 */
|
||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||
amdgpu_umc_process_ras_data_cb(adev, &err_data, NULL);
|
||||
else
|
||||
amdgpu_amdkfd_gpu_reset(kgd);
|
||||
amdgpu_umc_poison_handler(adev, &err_data, reset);
|
||||
else if (reset)
|
||||
amdgpu_amdkfd_gpu_reset(adev);
|
||||
}
|
||||
|
|
|
@ -144,14 +144,16 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
|
|||
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
||||
int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
|
||||
enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
uint32_t *ib_cmd, uint32_t ib_len);
|
||||
void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle);
|
||||
bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd);
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid);
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
|
||||
enum TLB_FLUSH_TYPE flush_type);
|
||||
void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle);
|
||||
bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev);
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev,
|
||||
uint16_t vmid);
|
||||
int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
||||
uint16_t pasid, enum TLB_FLUSH_TYPE flush_type);
|
||||
|
||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
|
||||
|
||||
|
@ -159,7 +161,7 @@ int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev);
|
|||
|
||||
int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd);
|
||||
void amdgpu_amdkfd_gpu_reset(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
|
||||
int queue_bit);
|
||||
|
@ -198,37 +200,36 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm)
|
|||
}
|
||||
#endif
|
||||
/* Shared API */
|
||||
int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
|
||||
void **mem_obj, uint64_t *gpu_addr,
|
||||
void **cpu_ptr, bool mqd_gfx9);
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj);
|
||||
int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, void **mem_obj);
|
||||
void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj);
|
||||
void amdgpu_amdkfd_free_gtt_mem(struct amdgpu_device *adev, void *mem_obj);
|
||||
int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
|
||||
void **mem_obj);
|
||||
void amdgpu_amdkfd_free_gws(struct amdgpu_device *adev, void *mem_obj);
|
||||
int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem);
|
||||
int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem);
|
||||
uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd,
|
||||
uint32_t amdgpu_amdkfd_get_fw_version(struct amdgpu_device *adev,
|
||||
enum kgd_engine_type type);
|
||||
void amdgpu_amdkfd_get_local_mem_info(struct kgd_dev *kgd,
|
||||
void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev,
|
||||
struct kfd_local_mem_info *mem_info);
|
||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct kgd_dev *kgd);
|
||||
uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
|
||||
|
||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd);
|
||||
void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info);
|
||||
int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
||||
struct kgd_dev **dmabuf_kgd,
|
||||
uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev,
|
||||
struct kfd_cu_info *cu_info);
|
||||
int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
|
||||
struct amdgpu_device **dmabuf_adev,
|
||||
uint64_t *bo_size, void *metadata_buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint32_t *flags);
|
||||
uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd);
|
||||
uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd);
|
||||
uint64_t amdgpu_amdkfd_get_unique_id(struct kgd_dev *kgd);
|
||||
uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd);
|
||||
uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd);
|
||||
uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd);
|
||||
int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd);
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src);
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min);
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min);
|
||||
uint64_t amdgpu_amdkfd_get_vram_usage(struct amdgpu_device *adev);
|
||||
uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src);
|
||||
int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst,
|
||||
struct amdgpu_device *src,
|
||||
bool is_min);
|
||||
int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
|
||||
|
||||
/* Read user wptr from a specified user address space with page fault
|
||||
* disabled. The memory must be pinned and mapped to the hardware when
|
||||
|
@ -258,45 +259,55 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min);
|
|||
(&((struct amdgpu_fpriv *) \
|
||||
((struct drm_file *)(drm_priv))->driver_priv)->vm)
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid,
|
||||
void **process_info,
|
||||
struct dma_fence **ef);
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *drm_priv);
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||
void *drm_priv);
|
||||
uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv);
|
||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
struct kgd_dev *kgd, uint64_t va, uint64_t size,
|
||||
struct amdgpu_device *adev, uint64_t va, uint64_t size,
|
||||
void *drm_priv, struct kgd_mem **mem,
|
||||
uint64_t *offset, uint32_t flags);
|
||||
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv,
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||
uint64_t *size);
|
||||
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, bool *table_freed);
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||
bool *table_freed);
|
||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv);
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);
|
||||
int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr);
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device *adev,
|
||||
struct kgd_mem *mem, void **kptr, uint64_t *size);
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem);
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct amdgpu_device *adev,
|
||||
struct kgd_mem *mem);
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
||||
struct dma_fence **ef);
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct amdgpu_device *adev,
|
||||
struct kfd_vm_fault_info *info);
|
||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||
struct dma_buf *dmabuf,
|
||||
uint64_t va, void *drm_priv,
|
||||
struct kgd_mem **mem, uint64_t *size,
|
||||
uint64_t *mmap_offset);
|
||||
int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||
struct tile_config *config);
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct kgd_dev *kgd);
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
bool reset);
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
|
||||
/**
|
||||
* @amdgpu_amdkfd_release_notify() - Notify KFD when GEM object is released
|
||||
*
|
||||
* Allows KFD to release its resources associated with the GEM object.
|
||||
*/
|
||||
void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo);
|
||||
void amdgpu_amdkfd_reserve_system_mem(uint64_t size);
|
||||
#else
|
||||
|
@ -324,7 +335,7 @@ int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
|
|||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
int kgd2kfd_init(void);
|
||||
void kgd2kfd_exit(void);
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, bool vf);
|
||||
struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf);
|
||||
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
struct drm_device *ddev,
|
||||
const struct kgd2kfd_shared_resources *gpu_resources);
|
||||
|
@ -348,7 +359,7 @@ static inline void kgd2kfd_exit(void)
|
|||
}
|
||||
|
||||
static inline
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, bool vf)
|
||||
struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -57,11 +57,6 @@
|
|||
(*dump)[i++][1] = RREG32(addr); \
|
||||
} while (0)
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
{
|
||||
return (struct v9_sdma_mqd *)mqd;
|
||||
|
@ -123,10 +118,9 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
|
|||
return sdma_rlc_reg_offset;
|
||||
}
|
||||
|
||||
int kgd_arcturus_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
int kgd_arcturus_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
unsigned long end_jiffies;
|
||||
|
@ -193,11 +187,10 @@ int kgd_arcturus_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kgd_arcturus_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
int kgd_arcturus_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||
engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
|
@ -225,9 +218,9 @@ int kgd_arcturus_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool kgd_arcturus_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
||||
bool kgd_arcturus_hqd_sdma_is_occupied(struct amdgpu_device *adev,
|
||||
void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
@ -244,10 +237,9 @@ bool kgd_arcturus_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||
return false;
|
||||
}
|
||||
|
||||
int kgd_arcturus_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
int kgd_arcturus_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
|
|
|
@ -20,11 +20,12 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
int kgd_arcturus_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
int kgd_arcturus_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm);
|
||||
int kgd_arcturus_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
int kgd_arcturus_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||
bool kgd_arcturus_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
|
||||
int kgd_arcturus_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
bool kgd_arcturus_hqd_sdma_is_occupied(struct amdgpu_device *adev,
|
||||
void *mqd);
|
||||
int kgd_arcturus_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout);
|
||||
|
|
|
@ -39,37 +39,26 @@ enum hqd_dequeue_request_type {
|
|||
SAVE_WAVES
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
static void unlock_srbm(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||
|
@ -81,33 +70,29 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
|||
return 1ull << bit;
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
static void release_queue(struct amdgpu_device *adev)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
|
||||
WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
|
||||
/* APE1 no longer exists on GFX9 */
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||
|
@ -150,22 +135,21 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||
* but still works
|
||||
*/
|
||||
|
||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
lock_srbm(adev, mec, pipe, 0, 0);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -218,12 +202,11 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||
return (struct v10_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, hqd_base, data;
|
||||
|
@ -231,7 +214,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
m = get_mqd(mqd);
|
||||
|
||||
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||
|
@ -296,16 +279,15 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, data);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
|
@ -313,7 +295,7 @@ static int kgd_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
@ -349,16 +331,15 @@ static int kgd_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
#define DUMP_REG(addr) do { \
|
||||
|
@ -372,13 +353,13 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
@ -386,10 +367,9 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
unsigned long end_jiffies;
|
||||
|
@ -456,11 +436,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||
engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
|
@ -488,15 +467,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
|
@ -506,13 +485,12 @@ static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
|||
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
||||
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
@ -529,12 +507,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t temp;
|
||||
|
@ -548,7 +525,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
int retry;
|
||||
#endif
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
if (m->cp_hqd_vmid == 0)
|
||||
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||
|
@ -633,20 +610,19 @@ loop:
|
|||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue preemption time out.\n");
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
|
@ -683,11 +659,10 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid)
|
||||
{
|
||||
uint32_t value;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
||||
+ vmid);
|
||||
|
@ -696,12 +671,12 @@ static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
||||
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
||||
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
|
@ -710,11 +685,10 @@ static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
@ -735,18 +709,16 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID %u\n",
|
||||
vmid);
|
||||
|
@ -757,12 +729,10 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
|||
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
}
|
||||
|
||||
static void program_trap_handler_settings(struct kgd_dev *kgd,
|
||||
static void program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
/*
|
||||
* Program TBA registers
|
||||
|
@ -781,7 +751,7 @@ static void program_trap_handler_settings(struct kgd_dev *kgd,
|
|||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
||||
upper_32_bits(tma_addr >> 8));
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
|
||||
|
|
|
@ -38,37 +38,26 @@ enum hqd_dequeue_request_type {
|
|||
SAVE_WAVES
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
static void unlock_srbm(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||
|
@ -80,34 +69,30 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
|||
return 1ull << bit;
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
static void release_queue(struct amdgpu_device *adev)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static void program_sh_mem_settings_v10_3(struct kgd_dev *kgd, uint32_t vmid,
|
||||
static void program_sh_mem_settings_v10_3(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
|
||||
WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
|
||||
/* APE1 no longer exists on GFX9 */
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
/* ATC is defeatured on Sienna_Cichlid */
|
||||
static int set_pasid_vmid_mapping_v10_3(struct kgd_dev *kgd, unsigned int pasid,
|
||||
static int set_pasid_vmid_mapping_v10_3(struct amdgpu_device *adev, unsigned int pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
|
||||
|
||||
/* Mapping vmid to pasid also for IH block */
|
||||
|
@ -118,22 +103,21 @@ static int set_pasid_vmid_mapping_v10_3(struct kgd_dev *kgd, unsigned int pasid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int init_interrupts_v10_3(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
static int init_interrupts_v10_3(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
lock_srbm(adev, mec, pipe, 0, 0);
|
||||
|
||||
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -188,12 +172,11 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||
return (struct v10_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
static int hqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, hqd_base, data;
|
||||
|
@ -201,7 +184,7 @@ static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
m = get_mqd(mqd);
|
||||
|
||||
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
/* HIQ is set during driver init period with vmid set to 0*/
|
||||
if (m->cp_hqd_vmid == 0) {
|
||||
|
@ -281,16 +264,15 @@ static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, data);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
static int hiq_mqd_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
|
@ -298,7 +280,7 @@ static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
@ -334,16 +316,15 @@ static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
||||
static int hqd_dump_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
#define DUMP_REG(addr) do { \
|
||||
|
@ -357,13 +338,13 @@ static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
|||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
@ -371,10 +352,9 @@ static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hqd_sdma_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
static int hqd_sdma_load_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
unsigned long end_jiffies;
|
||||
|
@ -441,11 +421,10 @@ static int hqd_sdma_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hqd_sdma_dump_v10_3(struct kgd_dev *kgd,
|
||||
static int hqd_sdma_dump_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||
engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
|
@ -473,15 +452,15 @@ static int hqd_sdma_dump_v10_3(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool hqd_is_occupied_v10_3(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
static bool hqd_is_occupied_v10_3(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
|
@ -491,13 +470,13 @@ static bool hqd_is_occupied_v10_3(struct kgd_dev *kgd, uint64_t queue_address,
|
|||
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool hqd_sdma_is_occupied_v10_3(struct kgd_dev *kgd, void *mqd)
|
||||
static bool hqd_sdma_is_occupied_v10_3(struct amdgpu_device *adev,
|
||||
void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
@ -514,18 +493,17 @@ static bool hqd_sdma_is_occupied_v10_3(struct kgd_dev *kgd, void *mqd)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
static int hqd_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t temp;
|
||||
struct v10_compute_mqd *m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
if (m->cp_hqd_vmid == 0)
|
||||
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||
|
@ -555,20 +533,19 @@ static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue pipe %d queue %d preemption failed\n",
|
||||
pipe_id, queue_id);
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hqd_sdma_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
static int hqd_sdma_destroy_v10_3(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
|
@ -606,12 +583,12 @@ static int hqd_sdma_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
|||
}
|
||||
|
||||
|
||||
static int address_watch_disable_v10_3(struct kgd_dev *kgd)
|
||||
static int address_watch_disable_v10_3(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int address_watch_execute_v10_3(struct kgd_dev *kgd,
|
||||
static int address_watch_execute_v10_3(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
|
@ -620,11 +597,10 @@ static int address_watch_execute_v10_3(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wave_control_execute_v10_3(struct kgd_dev *kgd,
|
||||
static int wave_control_execute_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
@ -645,28 +621,24 @@ static int wave_control_execute_v10_3(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t address_watch_get_offset_v10_3(struct kgd_dev *kgd,
|
||||
static uint32_t address_watch_get_offset_v10_3(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base_v10_3(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
static void set_vm_context_page_table_base_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/* SDMA is on gfxhub as well for Navi1* series */
|
||||
adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
}
|
||||
|
||||
static void program_trap_handler_settings_v10_3(struct kgd_dev *kgd,
|
||||
static void program_trap_handler_settings_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
/*
|
||||
* Program TBA registers
|
||||
|
@ -685,15 +657,14 @@ static void program_trap_handler_settings_v10_3(struct kgd_dev *kgd,
|
|||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
||||
upper_32_bits(tma_addr >> 8));
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t enable_debug_trap_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t trap_debug_wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
uint32_t orig_wave_cntl_value;
|
||||
uint32_t orig_stall_vmid;
|
||||
|
@ -720,10 +691,8 @@ uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t disable_debug_trap_v10_3(struct kgd_dev *kgd)
|
||||
uint32_t disable_debug_trap_v10_3(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
@ -733,11 +702,10 @@ uint32_t disable_debug_trap_v10_3(struct kgd_dev *kgd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_wave_launch_trap_override_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t set_wave_launch_trap_override_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
@ -762,11 +730,10 @@ uint32_t set_wave_launch_trap_override_v10_3(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_wave_launch_mode_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t set_wave_launch_mode_v10_3(struct amdgpu_device *adev,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
bool is_stall_mode;
|
||||
bool is_mode_set;
|
||||
|
@ -805,16 +772,14 @@ uint32_t set_wave_launch_mode_v10_3(struct kgd_dev *kgd,
|
|||
* sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
|
||||
* deq_retry_wait_time -- Wait Count for Global Wave Syncs.
|
||||
*/
|
||||
void get_iq_wait_times_v10_3(struct kgd_dev *kgd,
|
||||
void get_iq_wait_times_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t *wait_times)
|
||||
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
*wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
|
||||
}
|
||||
|
||||
void build_grace_period_packet_info_v10_3(struct kgd_dev *kgd,
|
||||
void build_grace_period_packet_info_v10_3(struct amdgpu_device *adev,
|
||||
uint32_t wait_times,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
|
|
|
@ -82,68 +82,54 @@ union TCP_WATCH_CNTL_BITS {
|
|||
float f32All;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
WREG32(mmSRBM_GFX_CNTL, value);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
static void unlock_srbm(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
WREG32(mmSRBM_GFX_CNTL, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
static void release_queue(struct amdgpu_device *adev)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
WREG32(mmSH_MEM_CONFIG, sh_mem_config);
|
||||
WREG32(mmSH_MEM_APE1_BASE, sh_mem_ape1_base);
|
||||
WREG32(mmSH_MEM_APE1_LIMIT, sh_mem_ape1_limit);
|
||||
WREG32(mmSH_MEM_BASES, sh_mem_bases);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||
|
@ -165,21 +151,20 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
lock_srbm(adev, mec, pipe, 0, 0);
|
||||
|
||||
WREG32(mmCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -207,12 +192,11 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
|
|||
return (struct cik_sdma_rlc_registers *)mqd;
|
||||
}
|
||||
|
||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct cik_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, wptr_val, data;
|
||||
|
@ -220,7 +204,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_MQD_CONTROL. */
|
||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||
|
@ -239,25 +223,24 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
* release srbm_mutex to avoid circular dependency between
|
||||
* srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex.
|
||||
*/
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
valid_wptr = read_user_wptr(mm, wptr, wptr_val);
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
if (valid_wptr)
|
||||
WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask);
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32(mmCP_HQD_ACTIVE, data);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS (35+4)
|
||||
#define DUMP_REG(addr) do { \
|
||||
|
@ -271,7 +254,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE0);
|
||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE1);
|
||||
|
@ -281,7 +264,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
for (reg = mmCP_MQD_BASE_ADDR; reg <= mmCP_MQD_CONTROL; reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
@ -289,10 +272,9 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct cik_sdma_rlc_registers *m;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
|
@ -345,11 +327,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_offset = engine_id * SDMA1_REGISTER_OFFSET +
|
||||
queue_id * KFD_CIK_SDMA_QUEUE_OFFSET;
|
||||
uint32_t i = 0, reg;
|
||||
|
@ -372,15 +353,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
act = RREG32(mmCP_HQD_ACTIVE);
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
|
@ -390,13 +371,12 @@ static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
|||
high == RREG32(mmCP_HQD_PQ_BASE_HI))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
||||
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct cik_sdma_rlc_registers *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
@ -412,12 +392,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t temp;
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long flags, end_jiffies;
|
||||
|
@ -426,7 +405,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
if (amdgpu_in_reset(adev))
|
||||
return -EIO;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, 0);
|
||||
|
||||
switch (reset_type) {
|
||||
|
@ -504,20 +483,19 @@ loop:
|
|||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue preemption time out\n");
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct cik_sdma_rlc_registers *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
|
@ -551,9 +529,8 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
||||
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
union TCP_WATCH_CNTL_BITS cntl;
|
||||
unsigned int i;
|
||||
|
||||
|
@ -571,13 +548,12 @@ static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
||||
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
union TCP_WATCH_CNTL_BITS cntl;
|
||||
|
||||
cntl.u32All = cntl_val;
|
||||
|
@ -602,11 +578,10 @@ static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
@ -627,18 +602,17 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset];
|
||||
}
|
||||
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid)
|
||||
{
|
||||
uint32_t value;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||
*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||
|
@ -646,21 +620,17 @@ static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
||||
static void set_scratch_backing_va(struct amdgpu_device *adev,
|
||||
uint64_t va, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID\n");
|
||||
return;
|
||||
|
@ -676,10 +646,8 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
|||
* @vmid: vmid pointer
|
||||
* read vmid from register (CIK).
|
||||
*/
|
||||
static uint32_t read_vmid_from_vmfault_reg(struct kgd_dev *kgd)
|
||||
static uint32_t read_vmid_from_vmfault_reg(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
||||
|
||||
return REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID);
|
||||
|
|
|
@ -39,68 +39,54 @@ enum hqd_dequeue_request_type {
|
|||
RESET_WAVES
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
WREG32(mmSRBM_GFX_CNTL, value);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
static void unlock_srbm(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
WREG32(mmSRBM_GFX_CNTL, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
static void release_queue(struct amdgpu_device *adev)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
static void kgd_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
WREG32(mmSH_MEM_CONFIG, sh_mem_config);
|
||||
WREG32(mmSH_MEM_APE1_BASE, sh_mem_ape1_base);
|
||||
WREG32(mmSH_MEM_APE1_LIMIT, sh_mem_ape1_limit);
|
||||
WREG32(mmSH_MEM_BASES, sh_mem_bases);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
static int kgd_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||
|
@ -123,21 +109,20 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
static int kgd_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
lock_srbm(adev, mec, pipe, 0, 0);
|
||||
|
||||
WREG32(mmCPC_INT_CNTL, CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -165,12 +150,11 @@ static inline struct vi_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||
return (struct vi_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
static int kgd_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct vi_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, wptr_val, data;
|
||||
|
@ -178,7 +162,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
/* HIQ is set during driver init period with vmid set to 0*/
|
||||
if (m->cp_hqd_vmid == 0) {
|
||||
|
@ -206,7 +190,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
* on ASICs that do not support context-save.
|
||||
* EOP writes/reads can start anywhere in the ring.
|
||||
*/
|
||||
if (get_amdgpu_device(kgd)->asic_type != CHIP_TONGA) {
|
||||
if (adev->asic_type != CHIP_TONGA) {
|
||||
WREG32(mmCP_HQD_EOP_RPTR, m->cp_hqd_eop_rptr);
|
||||
WREG32(mmCP_HQD_EOP_WPTR, m->cp_hqd_eop_wptr);
|
||||
WREG32(mmCP_HQD_EOP_WPTR_MEM, m->cp_hqd_eop_wptr_mem);
|
||||
|
@ -226,25 +210,24 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
* release srbm_mutex to avoid circular dependency between
|
||||
* srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex.
|
||||
*/
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
valid_wptr = read_user_wptr(mm, wptr, wptr_val);
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
if (valid_wptr)
|
||||
WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask);
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32(mmCP_HQD_ACTIVE, data);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS (54+4)
|
||||
#define DUMP_REG(addr) do { \
|
||||
|
@ -258,7 +241,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE0);
|
||||
DUMP_REG(mmCOMPUTE_STATIC_THREAD_MGMT_SE1);
|
||||
|
@ -268,7 +251,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
for (reg = mmCP_MQD_BASE_ADDR; reg <= mmCP_HQD_EOP_DONES; reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
@ -276,10 +259,9 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct vi_sdma_mqd *m;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
|
@ -331,11 +313,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_offset = engine_id * SDMA1_REGISTER_OFFSET +
|
||||
queue_id * KFD_VI_SDMA_QUEUE_OFFSET;
|
||||
uint32_t i = 0, reg;
|
||||
|
@ -367,15 +348,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
static bool kgd_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
act = RREG32(mmCP_HQD_ACTIVE);
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
|
@ -385,13 +366,12 @@ static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
|||
high == RREG32(mmCP_HQD_PQ_BASE_HI))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
||||
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct vi_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
@ -407,12 +387,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t temp;
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long flags, end_jiffies;
|
||||
|
@ -422,7 +401,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
if (amdgpu_in_reset(adev))
|
||||
return -EIO;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
if (m->cp_hqd_vmid == 0)
|
||||
WREG32_FIELD(RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||
|
@ -502,20 +481,19 @@ loop:
|
|||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue preemption time out.\n");
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct vi_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
|
@ -549,11 +527,10 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
||||
static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid)
|
||||
{
|
||||
uint32_t value;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||
*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||
|
@ -561,12 +538,12 @@ static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
||||
static int kgd_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
||||
static int kgd_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
|
@ -575,11 +552,10 @@ static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
||||
static int kgd_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
@ -600,28 +576,24 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
||||
static void set_scratch_backing_va(struct amdgpu_device *adev,
|
||||
uint64_t va, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
static void set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID\n");
|
||||
return;
|
||||
|
|
|
@ -46,37 +46,26 @@ enum hqd_dequeue_request_type {
|
|||
SAVE_WAVES
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
soc15_grbm_select(adev, mec, pipe, queue, vmid);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
static void unlock_srbm(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
soc15_grbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
static void acquire_queue(struct amdgpu_device *adev, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
lock_srbm(adev, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||
|
@ -88,33 +77,29 @@ static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
|||
return 1ull << bit;
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
static void release_queue(struct amdgpu_device *adev)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
void kgd_gfx_v9_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
|
||||
/* APE1 no longer exists on GFX9 */
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/*
|
||||
* We have to assume that there is no outstanding mapping.
|
||||
* The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 because
|
||||
|
@ -171,22 +156,21 @@ int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
|||
* but still works
|
||||
*/
|
||||
|
||||
int kgd_gfx_v9_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
lock_srbm(adev, mec, pipe, 0, 0);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL),
|
||||
WREG32_SOC15(GC, 0, mmCPC_INT_CNTL,
|
||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -233,19 +217,18 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
|||
return (struct v9_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t __user *wptr, uint32_t wptr_shift,
|
||||
uint32_t wptr_mask, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, hqd_base, data;
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||
|
@ -296,7 +279,7 @@ int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
lower_32_bits((uintptr_t)wptr));
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
upper_32_bits((uintptr_t)wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1),
|
||||
WREG32_SOC15(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1,
|
||||
(uint32_t)get_queue_mask(adev, pipe_id, queue_id));
|
||||
}
|
||||
|
||||
|
@ -308,16 +291,15 @@ int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
|||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), data);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
||||
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct v9_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
|
@ -325,7 +307,7 @@ int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
@ -361,16 +343,15 @@ int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
||||
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
#define DUMP_REG(addr) do { \
|
||||
|
@ -384,13 +365,13 @@ int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
|||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
@ -398,10 +379,9 @@ int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
unsigned long end_jiffies;
|
||||
|
@ -468,11 +448,10 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
||||
static int kgd_hqd_sdma_dump(struct amdgpu_device *adev,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||
engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
|
@ -500,31 +479,30 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool kgd_gfx_v9_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
act = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
act = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
high = upper_32_bits(queue_address >> 8);
|
||||
|
||||
if (low == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE)) &&
|
||||
high == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI)))
|
||||
if (low == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE) &&
|
||||
high == RREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
||||
static bool kgd_hqd_sdma_is_occupied(struct amdgpu_device *adev, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
@ -541,12 +519,11 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
|
|||
return false;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t temp;
|
||||
|
@ -555,7 +532,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
if (amdgpu_in_reset(adev))
|
||||
return -EIO;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
acquire_queue(adev, pipe_id, queue_id);
|
||||
|
||||
if (m->cp_hqd_vmid == 0)
|
||||
WREG32_FIELD15_RLC(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||
|
@ -579,25 +556,24 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
|
||||
end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
while (true) {
|
||||
temp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
||||
temp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
|
||||
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue preemption time out.\n");
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
release_queue(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v9_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
|
@ -634,11 +610,10 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid)
|
||||
{
|
||||
uint32_t value;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
|
||||
+ vmid);
|
||||
|
@ -647,12 +622,12 @@ bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
|||
return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_address_watch_disable(struct kgd_dev *kgd)
|
||||
int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_address_watch_execute(struct kgd_dev *kgd,
|
||||
int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
|
@ -661,17 +636,16 @@ int kgd_gfx_v9_address_watch_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kgd_gfx_v9_wave_control_execute(struct kgd_dev *kgd,
|
||||
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_INDEX, gfx_index_val);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CMD), sq_cmd);
|
||||
WREG32_SOC15(GC, 0, mmSQ_CMD, sq_cmd);
|
||||
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
INSTANCE_BROADCAST_WRITES, 1);
|
||||
|
@ -686,18 +660,16 @@ int kgd_gfx_v9_wave_control_execute(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd,
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID %u\n",
|
||||
vmid);
|
||||
|
@ -750,7 +722,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
|||
pipe_idx = queue_idx / adev->gfx.mec.num_queue_per_pipe;
|
||||
queue_slot = queue_idx % adev->gfx.mec.num_queue_per_pipe;
|
||||
soc15_grbm_select(adev, 1, pipe_idx, queue_slot, 0);
|
||||
reg_val = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_CSQ_WF_ACTIVE_COUNT_0) +
|
||||
reg_val = RREG32_SOC15_IP(GC, SOC15_REG_OFFSET(GC, 0, mmSPI_CSQ_WF_ACTIVE_COUNT_0) +
|
||||
queue_slot);
|
||||
*wave_cnt = reg_val & SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT_MASK;
|
||||
if (*wave_cnt != 0)
|
||||
|
@ -804,7 +776,7 @@ static void get_wave_count(struct amdgpu_device *adev, int queue_idx,
|
|||
*
|
||||
* Reading registers referenced above involves programming GRBM appropriately
|
||||
*/
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
|
||||
int *pasid_wave_cnt, int *max_waves_per_cu)
|
||||
{
|
||||
int qidx;
|
||||
|
@ -818,10 +790,8 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
|||
int pasid_tmp;
|
||||
int max_queue_cnt;
|
||||
int vmid_wave_cnt = 0;
|
||||
struct amdgpu_device *adev;
|
||||
DECLARE_BITMAP(cp_queue_bitmap, KGD_MAX_QUEUES);
|
||||
|
||||
adev = get_amdgpu_device(kgd);
|
||||
lock_spi_csq_mutexes(adev);
|
||||
soc15_grbm_select(adev, 1, 0, 0, 0);
|
||||
|
||||
|
@ -839,8 +809,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
|||
for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) {
|
||||
|
||||
gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
|
||||
queue_map = RREG32(SOC15_REG_OFFSET(GC, 0,
|
||||
mmSPI_CSQ_WF_ACTIVE_STATUS));
|
||||
queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS);
|
||||
|
||||
/*
|
||||
* Assumption: queue map encodes following schema: four
|
||||
|
@ -882,30 +851,28 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
|||
adev->gfx.cu_info.max_waves_per_simd;
|
||||
}
|
||||
|
||||
void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd,
|
||||
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
lock_srbm(adev, 0, 0, 0, vmid);
|
||||
|
||||
/*
|
||||
* Program TBA registers
|
||||
*/
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO),
|
||||
WREG32_SOC15(GC, 0, mmSQ_SHADER_TBA_LO,
|
||||
lower_32_bits(tba_addr >> 8));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI),
|
||||
WREG32_SOC15(GC, 0, mmSQ_SHADER_TBA_HI,
|
||||
upper_32_bits(tba_addr >> 8));
|
||||
|
||||
/*
|
||||
* Program TMA registers
|
||||
*/
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO),
|
||||
WREG32_SOC15(GC, 0, mmSQ_SHADER_TMA_LO,
|
||||
lower_32_bits(tma_addr >> 8));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI),
|
||||
WREG32_SOC15(GC, 0, mmSQ_SHADER_TMA_HI,
|
||||
upper_32_bits(tma_addr >> 8));
|
||||
|
||||
unlock_srbm(kgd);
|
||||
unlock_srbm(adev);
|
||||
}
|
||||
|
||||
const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
|
||||
|
|
|
@ -22,48 +22,49 @@
|
|||
|
||||
|
||||
|
||||
void kgd_gfx_v9_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
|
||||
void kgd_gfx_v9_program_sh_mem_settings(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases);
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct kgd_dev *kgd, u32 pasid,
|
||||
int kgd_gfx_v9_set_pasid_vmid_mapping(struct amdgpu_device *adev, u32 pasid,
|
||||
unsigned int vmid);
|
||||
int kgd_gfx_v9_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
|
||||
int kgd_gfx_v9_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
int kgd_gfx_v9_init_interrupts(struct amdgpu_device *adev, uint32_t pipe_id);
|
||||
int kgd_gfx_v9_hqd_load(struct amdgpu_device *adev, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm);
|
||||
int kgd_gfx_v9_hiq_mqd_load(struct kgd_dev *kgd, void *mqd,
|
||||
int kgd_gfx_v9_hiq_mqd_load(struct amdgpu_device *adev, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off);
|
||||
int kgd_gfx_v9_hqd_dump(struct kgd_dev *kgd,
|
||||
int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs);
|
||||
bool kgd_gfx_v9_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id);
|
||||
int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
bool kgd_gfx_v9_hqd_is_occupied(struct amdgpu_device *adev,
|
||||
uint64_t queue_address, uint32_t pipe_id,
|
||||
uint32_t queue_id);
|
||||
int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id);
|
||||
int kgd_gfx_v9_address_watch_disable(struct kgd_dev *kgd);
|
||||
int kgd_gfx_v9_address_watch_execute(struct kgd_dev *kgd,
|
||||
int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev);
|
||||
int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo);
|
||||
int kgd_gfx_v9_wave_control_execute(struct kgd_dev *kgd,
|
||||
int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd);
|
||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset);
|
||||
|
||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
|
||||
bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
||||
uint8_t vmid, uint16_t *p_pasid);
|
||||
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd,
|
||||
void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t page_table_base);
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid,
|
||||
void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
|
||||
int *pasid_wave_cnt, int *max_waves_per_cu);
|
||||
void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd,
|
||||
void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
|
||||
uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr);
|
||||
|
|
|
@ -60,12 +60,6 @@ static const char * const domain_bit_to_string[] = {
|
|||
|
||||
static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work);
|
||||
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static bool kfd_mem_is_attached(struct amdgpu_vm *avm,
|
||||
struct kgd_mem *mem)
|
||||
{
|
||||
|
@ -126,8 +120,19 @@ static size_t amdgpu_amdkfd_acc_size(uint64_t size)
|
|||
PAGE_ALIGN(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @amdgpu_amdkfd_reserve_mem_limit() - Decrease available memory by size
|
||||
* of buffer including any reserved for control structures
|
||||
*
|
||||
* @adev: Device to which allocated BO belongs to
|
||||
* @size: Size of buffer, in bytes, encapsulated by B0. This should be
|
||||
* equivalent to amdgpu_bo_size(BO)
|
||||
* @alloc_flag: Flag used in allocating a BO as noted above
|
||||
*
|
||||
* Return: returns -ENOMEM in case of error, ZERO otherwise
|
||||
*/
|
||||
static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 domain, bool sg)
|
||||
uint64_t size, u32 alloc_flag)
|
||||
{
|
||||
uint64_t reserved_for_pt =
|
||||
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
|
||||
|
@ -137,20 +142,24 @@ static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
|||
acc_size = amdgpu_amdkfd_acc_size(size);
|
||||
|
||||
vram_needed = 0;
|
||||
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
||||
/* TTM GTT memory */
|
||||
if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
|
||||
system_mem_needed = acc_size + size;
|
||||
ttm_mem_needed = acc_size + size;
|
||||
} else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) {
|
||||
/* Userptr */
|
||||
system_mem_needed = acc_size + size;
|
||||
ttm_mem_needed = acc_size;
|
||||
} else {
|
||||
/* VRAM and SG */
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
|
||||
system_mem_needed = acc_size;
|
||||
ttm_mem_needed = acc_size;
|
||||
if (domain == AMDGPU_GEM_DOMAIN_VRAM)
|
||||
vram_needed = size;
|
||||
vram_needed = size;
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
|
||||
system_mem_needed = acc_size + size;
|
||||
ttm_mem_needed = acc_size;
|
||||
} else if (alloc_flag &
|
||||
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||
system_mem_needed = acc_size;
|
||||
ttm_mem_needed = acc_size;
|
||||
} else {
|
||||
pr_err("%s: Invalid BO type %#x\n", __func__, alloc_flag);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||
|
@ -166,64 +175,72 @@ static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
|||
(adev->kfd.vram_used + vram_needed >
|
||||
adev->gmc.real_vram_size - reserved_for_pt)) {
|
||||
ret = -ENOMEM;
|
||||
} else {
|
||||
kfd_mem_limit.system_mem_used += system_mem_needed;
|
||||
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
|
||||
adev->kfd.vram_used += vram_needed;
|
||||
goto release;
|
||||
}
|
||||
|
||||
/* Update memory accounting by decreasing available system
|
||||
* memory, TTM memory and GPU memory as computed above
|
||||
*/
|
||||
adev->kfd.vram_used += vram_needed;
|
||||
kfd_mem_limit.system_mem_used += system_mem_needed;
|
||||
kfd_mem_limit.ttm_mem_used += ttm_mem_needed;
|
||||
|
||||
release:
|
||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 domain, bool sg)
|
||||
uint64_t size, u32 alloc_flag)
|
||||
{
|
||||
size_t acc_size;
|
||||
|
||||
acc_size = amdgpu_amdkfd_acc_size(size);
|
||||
|
||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||
if (domain == AMDGPU_GEM_DOMAIN_GTT) {
|
||||
|
||||
if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
|
||||
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||
kfd_mem_limit.ttm_mem_used -= (acc_size + size);
|
||||
} else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) {
|
||||
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||
} else {
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
|
||||
kfd_mem_limit.system_mem_used -= acc_size;
|
||||
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
|
||||
adev->kfd.vram_used -= size;
|
||||
WARN_ONCE(adev->kfd.vram_used < 0,
|
||||
"kfd VRAM memory accounting unbalanced");
|
||||
}
|
||||
adev->kfd.vram_used -= size;
|
||||
} else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
|
||||
kfd_mem_limit.system_mem_used -= (acc_size + size);
|
||||
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||
} else if (alloc_flag &
|
||||
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||
kfd_mem_limit.system_mem_used -= acc_size;
|
||||
kfd_mem_limit.ttm_mem_used -= acc_size;
|
||||
} else {
|
||||
pr_err("%s: Invalid BO type %#x\n", __func__, alloc_flag);
|
||||
goto release;
|
||||
}
|
||||
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
||||
"kfd system memory accounting unbalanced");
|
||||
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
||||
"kfd TTM memory accounting unbalanced");
|
||||
|
||||
WARN_ONCE(adev->kfd.vram_used < 0,
|
||||
"KFD VRAM memory accounting unbalanced");
|
||||
WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0,
|
||||
"KFD TTM memory accounting unbalanced");
|
||||
WARN_ONCE(kfd_mem_limit.system_mem_used < 0,
|
||||
"KFD system memory accounting unbalanced");
|
||||
|
||||
release:
|
||||
spin_unlock(&kfd_mem_limit.mem_limit_lock);
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
u32 domain = bo->preferred_domains;
|
||||
bool sg = (bo->preferred_domains == AMDGPU_GEM_DOMAIN_CPU);
|
||||
u32 alloc_flags = bo->kfd_bo->alloc_flags;
|
||||
u64 size = amdgpu_bo_size(bo);
|
||||
|
||||
if (bo->flags & AMDGPU_AMDKFD_CREATE_USERPTR_BO) {
|
||||
domain = AMDGPU_GEM_DOMAIN_CPU;
|
||||
sg = false;
|
||||
}
|
||||
|
||||
unreserve_mem_limit(adev, amdgpu_bo_size(bo), domain, sg);
|
||||
unreserve_mem_limit(adev, size, alloc_flags);
|
||||
|
||||
kfree(bo->kfd_bo);
|
||||
}
|
||||
|
||||
|
||||
/* amdgpu_amdkfd_remove_eviction_fence - Removes eviction fence from BO's
|
||||
* reservation object.
|
||||
*
|
||||
|
@ -691,10 +708,12 @@ static int kfd_mem_attach(struct amdgpu_device *adev, struct kgd_mem *mem,
|
|||
pr_debug("\t add VA 0x%llx - 0x%llx to vm %p\n", va,
|
||||
va + bo_size, vm);
|
||||
|
||||
if (adev == bo_adev || (mem->domain == AMDGPU_GEM_DOMAIN_VRAM &&
|
||||
amdgpu_xgmi_same_hive(adev, bo_adev))) {
|
||||
/* Mappings on the local GPU and VRAM mappings in the
|
||||
* local hive share the original BO
|
||||
if (adev == bo_adev ||
|
||||
(amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) && adev->ram_is_direct_mapped) ||
|
||||
(mem->domain == AMDGPU_GEM_DOMAIN_VRAM && amdgpu_xgmi_same_hive(adev, bo_adev))) {
|
||||
/* Mappings on the local GPU, or VRAM mappings in the
|
||||
* local hive, or userptr mapping IOMMU direct map mode
|
||||
* share the original BO
|
||||
*/
|
||||
attachment[i]->type = KFD_MEM_ATT_SHARED;
|
||||
bo[i] = mem->bo;
|
||||
|
@ -1272,12 +1291,60 @@ create_evict_fence_fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
||||
/**
|
||||
* amdgpu_amdkfd_gpuvm_pin_bo() - Pins a BO using following criteria
|
||||
* @bo: Handle of buffer object being pinned
|
||||
* @domain: Domain into which BO should be pinned
|
||||
*
|
||||
* - USERPTR BOs are UNPINNABLE and will return error
|
||||
* - All other BO types (GTT, VRAM, MMIO and DOORBELL) will have their
|
||||
* PIN count incremented. It is valid to PIN a BO multiple times
|
||||
*
|
||||
* Return: ZERO if successful in pinning, Non-Zero in case of error.
|
||||
*/
|
||||
static int amdgpu_amdkfd_gpuvm_pin_bo(struct amdgpu_bo *bo, u32 domain)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = amdgpu_bo_reserve(bo, false);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
ret = amdgpu_bo_pin_restricted(bo, domain, 0, 0);
|
||||
if (ret)
|
||||
pr_err("Error in Pinning BO to domain: %d\n", domain);
|
||||
|
||||
amdgpu_bo_sync_wait(bo, AMDGPU_FENCE_OWNER_KFD, false);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_amdkfd_gpuvm_unpin_bo() - Unpins BO using following criteria
|
||||
* @bo: Handle of buffer object being unpinned
|
||||
*
|
||||
* - Is a illegal request for USERPTR BOs and is ignored
|
||||
* - All other BO types (GTT, VRAM, MMIO and DOORBELL) will have their
|
||||
* PIN count decremented. Calls to UNPIN must balance calls to PIN
|
||||
*/
|
||||
static void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = amdgpu_bo_reserve(bo, false);
|
||||
if (unlikely(ret))
|
||||
return;
|
||||
|
||||
amdgpu_bo_unpin(bo);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid,
|
||||
void **process_info,
|
||||
struct dma_fence **ef)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_fpriv *drv_priv;
|
||||
struct amdgpu_vm *avm;
|
||||
int ret;
|
||||
|
@ -1353,12 +1420,12 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
|||
}
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *drm_priv)
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||
void *drm_priv)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_vm *avm;
|
||||
|
||||
if (WARN_ON(!kgd || !drm_priv))
|
||||
if (WARN_ON(!adev || !drm_priv))
|
||||
return;
|
||||
|
||||
avm = drm_priv_to_vm(drm_priv);
|
||||
|
@ -1386,11 +1453,10 @@ uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv)
|
|||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
struct kgd_dev *kgd, uint64_t va, uint64_t size,
|
||||
struct amdgpu_device *adev, uint64_t va, uint64_t size,
|
||||
void *drm_priv, struct kgd_mem **mem,
|
||||
uint64_t *offset, uint32_t flags)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||
enum ttm_bo_type bo_type = ttm_bo_type_device;
|
||||
struct sg_table *sg = NULL;
|
||||
|
@ -1454,7 +1520,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||
|
||||
amdgpu_sync_create(&(*mem)->sync);
|
||||
|
||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, alloc_domain, !!sg);
|
||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, flags);
|
||||
if (ret) {
|
||||
pr_debug("Insufficient memory\n");
|
||||
goto err_reserve_limit;
|
||||
|
@ -1495,6 +1561,15 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||
ret = init_user_pages(*mem, user_addr);
|
||||
if (ret)
|
||||
goto allocate_init_user_pages_failed;
|
||||
} else if (flags & (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||
ret = amdgpu_amdkfd_gpuvm_pin_bo(bo, AMDGPU_GEM_DOMAIN_GTT);
|
||||
if (ret) {
|
||||
pr_err("Pinning MMIO/DOORBELL BO during ALLOC FAILED\n");
|
||||
goto err_pin_bo;
|
||||
}
|
||||
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
|
||||
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
|
||||
}
|
||||
|
||||
if (offset)
|
||||
|
@ -1503,13 +1578,14 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||
return 0;
|
||||
|
||||
allocate_init_user_pages_failed:
|
||||
err_pin_bo:
|
||||
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
|
||||
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
|
||||
err_node_allow:
|
||||
/* Don't unreserve system mem limit twice */
|
||||
goto err_reserve_limit;
|
||||
err_bo_create:
|
||||
unreserve_mem_limit(adev, size, alloc_domain, !!sg);
|
||||
unreserve_mem_limit(adev, size, flags);
|
||||
err_reserve_limit:
|
||||
mutex_destroy(&(*mem)->lock);
|
||||
if (gobj)
|
||||
|
@ -1525,7 +1601,7 @@ err:
|
|||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv,
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv,
|
||||
uint64_t *size)
|
||||
{
|
||||
struct amdkfd_process_info *process_info = mem->process_info;
|
||||
|
@ -1538,6 +1614,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
|||
bool is_imported = false;
|
||||
|
||||
mutex_lock(&mem->lock);
|
||||
|
||||
/* Unpin MMIO/DOORBELL BO's that were pinnned during allocation */
|
||||
if (mem->alloc_flags &
|
||||
(KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
|
||||
amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
|
||||
}
|
||||
|
||||
mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
|
||||
is_imported = mem->is_imported;
|
||||
mutex_unlock(&mem->lock);
|
||||
|
@ -1617,10 +1701,9 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
|||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem,
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem,
|
||||
void *drm_priv, bool *table_freed)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||
int ret;
|
||||
struct amdgpu_bo *bo;
|
||||
|
@ -1747,7 +1830,7 @@ out:
|
|||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv)
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv)
|
||||
{
|
||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||
struct amdkfd_process_info *process_info = avm->process_info;
|
||||
|
@ -1808,7 +1891,7 @@ out:
|
|||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr)
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr)
|
||||
{
|
||||
struct amdgpu_sync sync;
|
||||
int ret;
|
||||
|
@ -1824,7 +1907,7 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
|
|||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device *adev,
|
||||
struct kgd_mem *mem, void **kptr, uint64_t *size)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1880,7 +1963,8 @@ bo_reserve_failed:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem)
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct amdgpu_device *adev,
|
||||
struct kgd_mem *mem)
|
||||
{
|
||||
struct amdgpu_bo *bo = mem->bo;
|
||||
|
||||
|
@ -1890,12 +1974,9 @@ void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kg
|
|||
amdgpu_bo_unreserve(bo);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
||||
struct kfd_vm_fault_info *mem)
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct amdgpu_device *adev,
|
||||
struct kfd_vm_fault_info *mem)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
|
||||
adev = (struct amdgpu_device *)kgd;
|
||||
if (atomic_read(&adev->gmc.vm_fault_info_updated) == 1) {
|
||||
*mem = *adev->gmc.vm_fault_info;
|
||||
mb();
|
||||
|
@ -1904,13 +1985,12 @@ int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
|
||||
struct dma_buf *dma_buf,
|
||||
uint64_t va, void *drm_priv,
|
||||
struct kgd_mem **mem, uint64_t *size,
|
||||
uint64_t *mmap_offset)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
|
||||
struct drm_gem_object *obj;
|
||||
struct amdgpu_bo *bo;
|
||||
|
@ -2537,11 +2617,9 @@ int amdgpu_amdkfd_remove_gws_from_process(void *info, void *mem)
|
|||
}
|
||||
|
||||
/* Returns GPU-specific tiling mode information */
|
||||
int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
|
||||
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||
struct tile_config *config)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
config->gb_addr_config = adev->gfx.config.gb_addr_config;
|
||||
config->tile_config_ptr = adev->gfx.config.tile_mode_array;
|
||||
config->num_tile_configs =
|
||||
|
|
|
@ -470,8 +470,8 @@ bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *ade
|
|||
|
||||
/**
|
||||
* amdgpu_atomfirmware_ras_rom_addr -- Get the RAS EEPROM addr from VBIOS
|
||||
* adev: amdgpu_device pointer
|
||||
* i2c_address: pointer to u8; if not NULL, will contain
|
||||
* @adev: amdgpu_device pointer
|
||||
* @i2c_address: pointer to u8; if not NULL, will contain
|
||||
* the RAS EEPROM address if the function returns true
|
||||
*
|
||||
* Return true if VBIOS supports RAS EEPROM address reporting,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amd_acpi.h"
|
||||
|
||||
#define AMDGPU_PX_QUIRK_FORCE_ATPX (1 << 0)
|
||||
|
@ -165,7 +166,7 @@ static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mas
|
|||
}
|
||||
|
||||
/**
|
||||
* amdgpu_atpx_validate_functions - validate ATPX functions
|
||||
* amdgpu_atpx_validate - validate ATPX functions
|
||||
*
|
||||
* @atpx: amdgpu atpx struct
|
||||
*
|
||||
|
|
|
@ -108,7 +108,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_HDMIB:
|
||||
if (amdgpu_connector->use_digital) {
|
||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
if (connector->display_info.is_hdmi) {
|
||||
if (connector->display_info.bpc)
|
||||
bpc = connector->display_info.bpc;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||
break;
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
if (connector->display_info.is_hdmi) {
|
||||
if (connector->display_info.bpc)
|
||||
bpc = connector->display_info.bpc;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||
dig_connector = amdgpu_connector->con_priv;
|
||||
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
|
||||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
|
||||
drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
connector->display_info.is_hdmi) {
|
||||
if (connector->display_info.bpc)
|
||||
bpc = connector->display_info.bpc;
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||
break;
|
||||
}
|
||||
|
||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
if (connector->display_info.is_hdmi) {
|
||||
/*
|
||||
* Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
|
||||
* much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
|
||||
|
@ -315,8 +315,10 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||
if (!amdgpu_connector->edid) {
|
||||
/* some laptops provide a hardcoded edid in rom for LCDs */
|
||||
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
|
||||
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
|
||||
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,6 +328,7 @@ static void amdgpu_connector_free_edid(struct drm_connector *connector)
|
|||
|
||||
kfree(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
drm_connector_update_edid_property(connector, NULL);
|
||||
}
|
||||
|
||||
static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
|
||||
|
@ -387,6 +390,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
|
|||
native_mode->vdisplay != 0 &&
|
||||
native_mode->clock != 0) {
|
||||
mode = drm_mode_duplicate(dev, native_mode);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
|
@ -401,6 +407,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
|
|||
* simpler.
|
||||
*/
|
||||
mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
|
||||
DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
|
||||
}
|
||||
|
@ -1171,7 +1180,7 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector
|
|||
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
|
||||
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) {
|
||||
return MODE_OK;
|
||||
} else if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
} else if (connector->display_info.is_hdmi) {
|
||||
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
||||
if (mode->clock > 340000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
@ -1463,7 +1472,7 @@ static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector
|
|||
(amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
|
||||
return amdgpu_atombios_dp_mode_valid_helper(connector, mode);
|
||||
} else {
|
||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
if (connector->display_info.is_hdmi) {
|
||||
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
||||
if (mode->clock > 340000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
|
|
@ -1618,6 +1618,9 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
|||
if (!debugfs_initialized())
|
||||
return 0;
|
||||
|
||||
debugfs_create_x32("amdgpu_smu_debug", 0600, root,
|
||||
&adev->pm.smu_debug_mask);
|
||||
|
||||
ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev,
|
||||
&fops_ib_preempt);
|
||||
if (IS_ERR(ent)) {
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/iommu.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
@ -331,7 +332,7 @@ void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos,
|
|||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_vram_access - access vram by vram aperature
|
||||
* amdgpu_device_aper_access - access vram by vram aperature
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @pos: offset of the buffer in vram
|
||||
|
@ -550,11 +551,11 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
|||
trace_amdgpu_device_wreg(adev->pdev->device, reg, v);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* amdgpu_mm_wreg_mmio_rlc - write register either with mmio or with RLC path if in range
|
||||
*
|
||||
* this function is invoked only the debugfs register access
|
||||
* */
|
||||
*/
|
||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v)
|
||||
{
|
||||
|
@ -1100,7 +1101,7 @@ static void amdgpu_device_wb_fini(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_wb_init- Init Writeback driver info and allocate memory
|
||||
* amdgpu_device_wb_init - Init Writeback driver info and allocate memory
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
|
@ -2316,6 +2317,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
|
||||
/* need to do gmc hw init early so we can allocate gpu mem */
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
|
||||
/* Try to reserve bad pages early */
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_exchange_data(adev);
|
||||
|
||||
r = amdgpu_device_vram_scratch_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
|
||||
|
@ -2347,7 +2352,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
amdgpu_virt_exchange_data(adev);
|
||||
|
||||
r = amdgpu_ib_pool_init(adev);
|
||||
if (r) {
|
||||
|
@ -2614,11 +2619,10 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
|||
if (r)
|
||||
DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
|
||||
|
||||
/* For XGMI + passthrough configuration on arcturus, enable light SBR */
|
||||
if (adev->asic_type == CHIP_ARCTURUS &&
|
||||
amdgpu_passthrough(adev) &&
|
||||
adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
smu_set_light_sbr(&adev->smu, true);
|
||||
/* For passthrough configuration on arcturus and aldebaran, enable special handling SBR */
|
||||
if (amdgpu_passthrough(adev) && ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1)||
|
||||
adev->asic_type == CHIP_ALDEBARAN ))
|
||||
smu_handle_passthrough_sbr(&adev->smu, true);
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
mutex_lock(&mgpu_info.mutex);
|
||||
|
@ -2657,6 +2661,36 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_smu_fini_early - smu hw_fini wrapper
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* For ASICs need to disable SMC first
|
||||
*/
|
||||
static void amdgpu_device_smu_fini_early(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))
|
||||
return;
|
||||
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!adev->ip_blocks[i].status.hw)
|
||||
continue;
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
|
||||
r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
|
||||
/* XXX handle errors */
|
||||
if (r) {
|
||||
DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
}
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
@ -2677,21 +2711,8 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
|||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
|
||||
/* need to disable SMC first */
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!adev->ip_blocks[i].status.hw)
|
||||
continue;
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
|
||||
r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
|
||||
/* XXX handle errors */
|
||||
if (r) {
|
||||
DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
}
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Workaroud for ASICs need to disable SMC first */
|
||||
amdgpu_device_smu_fini_early(adev);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.hw)
|
||||
|
@ -2733,8 +2754,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
|||
if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
|
||||
amdgpu_virt_release_ras_err_handler_data(adev);
|
||||
|
||||
amdgpu_ras_pre_fini(adev);
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
amdgpu_xgmi_remove_device(adev);
|
||||
|
||||
|
@ -3373,6 +3392,22 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_check_iommu_direct_map - check if RAM direct mapped to GPU
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* RAM direct mapped to GPU if IOMMU is not enabled or is pass through mode
|
||||
*/
|
||||
static void amdgpu_device_check_iommu_direct_map(struct amdgpu_device *adev)
|
||||
{
|
||||
struct iommu_domain *domain;
|
||||
|
||||
domain = iommu_get_domain_for_dev(adev->dev);
|
||||
if (!domain || domain->type == IOMMU_DOMAIN_IDENTITY)
|
||||
adev->ram_is_direct_mapped = true;
|
||||
}
|
||||
|
||||
static const struct attribute *amdgpu_dev_attributes[] = {
|
||||
&dev_attr_product_name.attr,
|
||||
&dev_attr_product_number.attr,
|
||||
|
@ -3547,6 +3582,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
/* Need to get xgmi info early to decide the reset behavior*/
|
||||
if (adev->gmc.xgmi.supported) {
|
||||
r = adev->gfxhub.funcs->get_xgmi_info(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* enable PCIE atomic ops */
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
|
||||
|
@ -3693,8 +3735,6 @@ fence_driver_init:
|
|||
/* Get a log2 for easy divisions. */
|
||||
adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
|
||||
|
||||
amdgpu_fbdev_init(adev);
|
||||
|
||||
r = amdgpu_pm_sysfs_init(adev);
|
||||
if (r) {
|
||||
adev->pm_sysfs_en = false;
|
||||
|
@ -3778,6 +3818,8 @@ fence_driver_init:
|
|||
queue_delayed_work(system_wq, &mgpu_info.delayed_reset_work,
|
||||
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
||||
|
||||
amdgpu_device_check_iommu_direct_map(adev);
|
||||
|
||||
return 0;
|
||||
|
||||
release_ras_con:
|
||||
|
@ -3811,7 +3853,7 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_fini - tear down the driver
|
||||
* amdgpu_device_fini_hw - tear down the driver
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
|
@ -3852,17 +3894,21 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
|||
amdgpu_ucode_sysfs_fini(adev);
|
||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||
|
||||
amdgpu_fbdev_fini(adev);
|
||||
/* disable ras feature must before hw fini */
|
||||
amdgpu_ras_pre_fini(adev);
|
||||
|
||||
amdgpu_device_ip_fini_early(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
||||
ttm_device_clear_dma_mappings(&adev->mman.bdev);
|
||||
if (adev->mman.initialized)
|
||||
ttm_device_clear_dma_mappings(&adev->mman.bdev);
|
||||
|
||||
amdgpu_gart_dummy_page_fini(adev);
|
||||
|
||||
amdgpu_device_unmap_mmio(adev);
|
||||
if (drm_dev_is_unplugged(adev_to_drm(adev)))
|
||||
amdgpu_device_unmap_mmio(adev);
|
||||
|
||||
}
|
||||
|
||||
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
||||
|
@ -3948,7 +3994,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
|||
drm_kms_helper_poll_disable(dev);
|
||||
|
||||
if (fbcon)
|
||||
amdgpu_fbdev_set_suspend(adev, 1);
|
||||
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
|
||||
|
||||
cancel_delayed_work_sync(&adev->delayed_init_work);
|
||||
|
||||
|
@ -4025,7 +4071,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
|||
flush_delayed_work(&adev->delayed_init_work);
|
||||
|
||||
if (fbcon)
|
||||
amdgpu_fbdev_set_suspend(adev, 0);
|
||||
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
|
||||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
|
@ -4294,6 +4340,9 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||
bool from_hypervisor)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_hive_info *hive = NULL;
|
||||
|
||||
amdgpu_amdkfd_pre_reset(adev);
|
||||
|
||||
amdgpu_amdkfd_pre_reset(adev);
|
||||
|
||||
|
@ -4322,9 +4371,19 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||
if (r)
|
||||
goto error;
|
||||
|
||||
amdgpu_irq_gpu_reset_resume_helper(adev);
|
||||
r = amdgpu_ib_ring_tests(adev);
|
||||
amdgpu_amdkfd_post_reset(adev);
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
/* Update PSP FW topology after reset */
|
||||
if (hive && adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
r = amdgpu_xgmi_update_topology(hive, adev);
|
||||
|
||||
if (hive)
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
|
||||
if (!r) {
|
||||
amdgpu_irq_gpu_reset_resume_helper(adev);
|
||||
r = amdgpu_ib_ring_tests(adev);
|
||||
amdgpu_amdkfd_post_reset(adev);
|
||||
}
|
||||
|
||||
error:
|
||||
if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
|
||||
|
@ -4650,7 +4709,7 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
amdgpu_fbdev_set_suspend(tmp_adev, 0);
|
||||
drm_fb_helper_set_suspend_unlocked(adev_to_drm(tmp_adev)->fb_helper, false);
|
||||
|
||||
/*
|
||||
* The GPU enters bad state once faulty pages
|
||||
|
@ -4749,7 +4808,7 @@ static int amdgpu_device_lock_hive_adev(struct amdgpu_device *adev, struct amdgp
|
|||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1)) {
|
||||
if (!hive) {
|
||||
dev_err(adev->dev, "Hive is NULL while device has multiple xgmi nodes");
|
||||
return -ENODEV;
|
||||
|
@ -4961,7 +5020,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
* We always reset all schedulers for device and all devices for XGMI
|
||||
* hive so that should take care of them too.
|
||||
*/
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (hive) {
|
||||
if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) {
|
||||
DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
|
||||
|
@ -5002,7 +5062,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
* to put adev in the 1st position.
|
||||
*/
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1)) {
|
||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
|
||||
list_add_tail(&tmp_adev->reset_list, &device_list);
|
||||
if (!list_is_first(&adev->reset_list, &device_list))
|
||||
|
@ -5041,7 +5101,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
*/
|
||||
amdgpu_unregister_gpu_instance(tmp_adev);
|
||||
|
||||
amdgpu_fbdev_set_suspend(tmp_adev, 1);
|
||||
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
|
||||
|
||||
/* disable ras on ALL IPs */
|
||||
if (!need_emergency_restart &&
|
||||
|
@ -5636,3 +5696,42 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev,
|
|||
|
||||
amdgpu_asic_invalidate_hdp(adev, ring);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_halt() - bring hardware to some kind of halt state
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Bring hardware to some kind of halt state so that no one can touch it
|
||||
* any more. It will help to maintain error context when error occurred.
|
||||
* Compare to a simple hang, the system will keep stable at least for SSH
|
||||
* access. Then it should be trivial to inspect the hardware state and
|
||||
* see what's going on. Implemented as following:
|
||||
*
|
||||
* 1. drm_dev_unplug() makes device inaccessible to user space(IOCTLs, etc),
|
||||
* clears all CPU mappings to device, disallows remappings through page faults
|
||||
* 2. amdgpu_irq_disable_all() disables all interrupts
|
||||
* 3. amdgpu_fence_driver_hw_fini() signals all HW fences
|
||||
* 4. set adev->no_hw_access to avoid potential crashes after setp 5
|
||||
* 5. amdgpu_device_unmap_mmio() clears all MMIO mappings
|
||||
* 6. pci_disable_device() and pci_wait_for_pending_transaction()
|
||||
* flush any in flight DMA operations
|
||||
*/
|
||||
void amdgpu_device_halt(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pci_dev *pdev = adev->pdev;
|
||||
struct drm_device *ddev = adev_to_drm(adev);
|
||||
|
||||
drm_dev_unplug(ddev);
|
||||
|
||||
amdgpu_irq_disable_all(adev);
|
||||
|
||||
amdgpu_fence_driver_hw_fini(adev);
|
||||
|
||||
adev->no_hw_access = true;
|
||||
|
||||
amdgpu_device_unmap_mmio(adev);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
pci_wait_for_pending_transaction(pdev);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@
|
|||
#include "smuio_v11_0_6.h"
|
||||
#include "smuio_v13_0.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/ip_discovery.bin");
|
||||
#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
|
||||
MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
|
||||
|
||||
#define mmRCC_CONFIG_MEMSIZE 0xde3
|
||||
#define mmMM_INDEX 0x0
|
||||
|
@ -179,7 +180,7 @@ static int hw_id_map[MAX_HWIP] = {
|
|||
[DCI_HWIP] = DCI_HWID,
|
||||
};
|
||||
|
||||
static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
|
||||
static int amdgpu_discovery_read_binary_from_vram(struct amdgpu_device *adev, uint8_t *binary)
|
||||
{
|
||||
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
|
||||
|
@ -189,6 +190,34 @@ static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *bin
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const char *fw_name;
|
||||
int r;
|
||||
|
||||
switch (amdgpu_discovery) {
|
||||
case 2:
|
||||
fw_name = FIRMWARE_IP_DISCOVERY;
|
||||
break;
|
||||
default:
|
||||
dev_warn(adev->dev, "amdgpu_discovery is not set properly\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = request_firmware(&fw, fw_name, adev->dev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "can't load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
memcpy((u8 *)binary, (u8 *)fw->data, adev->mman.discovery_tmr_size);
|
||||
release_firmware(fw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size)
|
||||
{
|
||||
uint16_t checksum = 0;
|
||||
|
@ -206,13 +235,20 @@ static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size
|
|||
return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);
|
||||
}
|
||||
|
||||
static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
bhdr = (struct binary_header *)binary;
|
||||
|
||||
return (le32_to_cpu(bhdr->binary_signature) == BINARY_SIGNATURE);
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct table_info *info;
|
||||
struct binary_header *bhdr;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct gpu_info_header *ghdr;
|
||||
const struct firmware *fw;
|
||||
uint16_t offset;
|
||||
uint16_t size;
|
||||
uint16_t checksum;
|
||||
|
@ -223,31 +259,32 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
if (!adev->mman.discovery_bin)
|
||||
return -ENOMEM;
|
||||
|
||||
if (amdgpu_discovery == 2) {
|
||||
r = request_firmware(&fw, "amdgpu/ip_discovery.bin", adev->dev);
|
||||
if (r)
|
||||
goto get_from_vram;
|
||||
dev_info(adev->dev, "Using IP discovery from file\n");
|
||||
memcpy((u8 *)adev->mman.discovery_bin, (u8 *)fw->data,
|
||||
adev->mman.discovery_tmr_size);
|
||||
release_firmware(fw);
|
||||
} else {
|
||||
get_from_vram:
|
||||
r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin);
|
||||
r = amdgpu_discovery_read_binary_from_vram(adev, adev->mman.discovery_bin);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "failed to read ip discovery binary from vram\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
|
||||
dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n");
|
||||
/* retry read ip discovery binary from file */
|
||||
r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to read ip discovery binary\n");
|
||||
dev_err(adev->dev, "failed to read ip discovery binary from file\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* check the ip discovery binary signature */
|
||||
if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
|
||||
dev_warn(adev->dev, "get invalid ip discovery binary signature from file\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)adev->mman.discovery_bin;
|
||||
|
||||
if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) {
|
||||
DRM_ERROR("invalid ip discovery binary signature\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset = offsetof(struct binary_header, binary_checksum) +
|
||||
sizeof(bhdr->binary_checksum);
|
||||
size = le16_to_cpu(bhdr->binary_size) - offset;
|
||||
|
@ -255,7 +292,7 @@ get_from_vram:
|
|||
|
||||
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
||||
size, checksum)) {
|
||||
DRM_ERROR("invalid ip discovery binary checksum\n");
|
||||
dev_err(adev->dev, "invalid ip discovery binary checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -266,14 +303,14 @@ get_from_vram:
|
|||
ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);
|
||||
|
||||
if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) {
|
||||
DRM_ERROR("invalid ip discovery data table signature\n");
|
||||
dev_err(adev->dev, "invalid ip discovery data table signature\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
||||
le16_to_cpu(ihdr->size), checksum)) {
|
||||
DRM_ERROR("invalid ip discovery data table checksum\n");
|
||||
dev_err(adev->dev, "invalid ip discovery data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -285,7 +322,7 @@ get_from_vram:
|
|||
|
||||
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
|
||||
le32_to_cpu(ghdr->size), checksum)) {
|
||||
DRM_ERROR("invalid gc data table checksum\n");
|
||||
dev_err(adev->dev, "invalid gc data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -379,8 +416,18 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
|||
ip->major, ip->minor,
|
||||
ip->revision);
|
||||
|
||||
if (le16_to_cpu(ip->hw_id) == VCN_HWID)
|
||||
if (le16_to_cpu(ip->hw_id) == VCN_HWID) {
|
||||
/* Bit [5:0]: original revision value
|
||||
* Bit [7:6]: en/decode capability:
|
||||
* 0b00 : VCN function normally
|
||||
* 0b10 : encode is disabled
|
||||
* 0b01 : decode is disabled
|
||||
*/
|
||||
adev->vcn.vcn_config[adev->vcn.num_vcn_inst] =
|
||||
ip->revision & 0xc0;
|
||||
ip->revision &= ~0xc0;
|
||||
adev->vcn.num_vcn_inst++;
|
||||
}
|
||||
if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||
|
||||
le16_to_cpu(ip->hw_id) == SDMA1_HWID ||
|
||||
le16_to_cpu(ip->hw_id) == SDMA2_HWID ||
|
||||
|
@ -472,14 +519,6 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int n
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance,
|
||||
int *major, int *minor, int *revision)
|
||||
{
|
||||
return amdgpu_discovery_get_ip_version(adev, VCN_HWID,
|
||||
vcn_instance, major, minor, revision);
|
||||
}
|
||||
|
||||
void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
||||
{
|
||||
struct binary_header *bhdr;
|
||||
|
@ -949,7 +988,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
|
|||
break;
|
||||
case IP_VERSION(3, 0, 0):
|
||||
case IP_VERSION(3, 0, 16):
|
||||
case IP_VERSION(3, 0, 64):
|
||||
case IP_VERSION(3, 1, 1):
|
||||
case IP_VERSION(3, 0, 2):
|
||||
case IP_VERSION(3, 0, 192):
|
||||
|
@ -986,7 +1024,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||
break;
|
||||
default:
|
||||
break;;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,8 +33,6 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev);
|
|||
int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, int number_instance,
|
||||
int *major, int *minor, int *revision);
|
||||
|
||||
int amdgpu_discovery_get_vcn_version(struct amdgpu_device *adev, int vcn_instance,
|
||||
int *major, int *minor, int *revision);
|
||||
int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev);
|
||||
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);
|
||||
|
||||
|
|
|
@ -83,9 +83,6 @@ static void amdgpu_display_flip_work_func(struct work_struct *__work)
|
|||
unsigned i;
|
||||
int vpos, hpos;
|
||||
|
||||
if (amdgpu_display_flip_handle_fence(work, &work->excl))
|
||||
return;
|
||||
|
||||
for (i = 0; i < work->shared_count; ++i)
|
||||
if (amdgpu_display_flip_handle_fence(work, &work->shared[i]))
|
||||
return;
|
||||
|
@ -203,7 +200,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
goto unpin;
|
||||
}
|
||||
|
||||
r = dma_resv_get_fences(new_abo->tbo.base.resv, &work->excl,
|
||||
r = dma_resv_get_fences(new_abo->tbo.base.resv, NULL,
|
||||
&work->shared_count, &work->shared);
|
||||
if (unlikely(r != 0)) {
|
||||
DRM_ERROR("failed to get fences for buffer\n");
|
||||
|
@ -253,7 +250,6 @@ unreserve:
|
|||
|
||||
cleanup:
|
||||
amdgpu_bo_unref(&work->old_abo);
|
||||
dma_fence_put(work->excl);
|
||||
for (i = 0; i < work->shared_count; ++i)
|
||||
dma_fence_put(work->shared[i]);
|
||||
kfree(work->shared);
|
||||
|
@ -1364,7 +1360,7 @@ bool amdgpu_display_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
|||
if ((!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
|
||||
((amdgpu_encoder->underscan_type == UNDERSCAN_ON) ||
|
||||
((amdgpu_encoder->underscan_type == UNDERSCAN_AUTO) &&
|
||||
drm_detect_hdmi_monitor(amdgpu_connector_edid(connector)) &&
|
||||
connector->display_info.is_hdmi &&
|
||||
amdgpu_display_is_hdtv_mode(mode)))) {
|
||||
if (amdgpu_encoder->underscan_hborder != 0)
|
||||
amdgpu_crtc->h_border = amdgpu_encoder->underscan_hborder;
|
||||
|
@ -1603,13 +1599,10 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
|||
continue;
|
||||
}
|
||||
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||
/* don't unpin kernel fb objects */
|
||||
if (!amdgpu_fbdev_robj_is_fb(adev, robj)) {
|
||||
r = amdgpu_bo_reserve(robj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(robj);
|
||||
amdgpu_bo_unreserve(robj);
|
||||
}
|
||||
r = amdgpu_bo_reserve(robj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(robj);
|
||||
amdgpu_bo_unreserve(robj);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -61,9 +61,6 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
|
|||
if (pci_p2pdma_distance_many(adev->pdev, &attach->dev, 1, true) < 0)
|
||||
attach->peer2peer = false;
|
||||
|
||||
if (attach->dev->driver == adev->dev->driver)
|
||||
return 0;
|
||||
|
||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "amdgpu_drv.h"
|
||||
|
||||
#include <drm/drm_pciids.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
|
@ -315,9 +314,12 @@ module_param_named(dpm, amdgpu_dpm, int, 0444);
|
|||
|
||||
/**
|
||||
* DOC: fw_load_type (int)
|
||||
* Set different firmware loading type for debugging (0 = direct, 1 = SMU, 2 = PSP). The default is -1 (auto).
|
||||
* Set different firmware loading type for debugging, if supported.
|
||||
* Set to 0 to force direct loading if supported by the ASIC. Set
|
||||
* to -1 to select the default loading mode for the ASIC, as defined
|
||||
* by the driver. The default is -1 (auto).
|
||||
*/
|
||||
MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = direct, 1 = SMU, 2 = PSP, -1 = auto)");
|
||||
MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = force direct if supported, -1 = auto)");
|
||||
module_param_named(fw_load_type, amdgpu_fw_load_type, int, 0444);
|
||||
|
||||
/**
|
||||
|
@ -2031,6 +2033,19 @@ retry_init:
|
|||
goto err_pci;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. don't init fbdev on hw without DCE
|
||||
* 2. don't init fbdev if there are no connectors
|
||||
*/
|
||||
if (adev->mode_info.mode_config_initialized &&
|
||||
!list_empty(&adev_to_drm(adev)->mode_config.connector_list)) {
|
||||
/* select 8 bpp console on low vram cards */
|
||||
if (adev->gmc.real_vram_size <= (32*1024*1024))
|
||||
drm_fbdev_generic_setup(adev_to_drm(adev), 8);
|
||||
else
|
||||
drm_fbdev_generic_setup(adev_to_drm(adev), 32);
|
||||
}
|
||||
|
||||
ret = amdgpu_debugfs_init(adev);
|
||||
if (ret)
|
||||
DRM_ERROR("Creating debugfs files failed (%d).\n", ret);
|
||||
|
@ -2563,10 +2578,8 @@ static int __init amdgpu_init(void)
|
|||
{
|
||||
int r;
|
||||
|
||||
if (vgacon_text_force()) {
|
||||
DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n");
|
||||
if (drm_firmware_drivers_only())
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = amdgpu_sync_init();
|
||||
if (r)
|
||||
|
|
|
@ -45,4 +45,7 @@
|
|||
long amdgpu_drm_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
long amdgpu_kms_compat_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -222,7 +222,7 @@ bool amdgpu_dig_monitor_is_duallink(struct drm_encoder *encoder,
|
|||
case DRM_MODE_CONNECTOR_HDMIB:
|
||||
if (amdgpu_connector->use_digital) {
|
||||
/* HDMI 1.3 supports up to 340 Mhz over single link */
|
||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
if (connector->display_info.is_hdmi) {
|
||||
if (pixel_clock > 340000)
|
||||
return true;
|
||||
else
|
||||
|
@ -244,7 +244,7 @@ bool amdgpu_dig_monitor_is_duallink(struct drm_encoder *encoder,
|
|||
return false;
|
||||
else {
|
||||
/* HDMI 1.3 supports up to 340 Mhz over single link */
|
||||
if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
|
||||
if (connector->display_info.is_hdmi) {
|
||||
if (pixel_clock > 340000)
|
||||
return true;
|
||||
else
|
||||
|
|
|
@ -1,388 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2007 David Airlie
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* David Airlie
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "cikd.h"
|
||||
#include "amdgpu_gem.h"
|
||||
|
||||
#include "amdgpu_display.h"
|
||||
|
||||
/* object hierarchy -
|
||||
this contains a helper + a amdgpu fb
|
||||
the helper contains a pointer to amdgpu framebuffer baseclass.
|
||||
*/
|
||||
|
||||
static int
|
||||
amdgpufb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
int ret = pm_runtime_get_sync(fb_helper->dev->dev);
|
||||
if (ret < 0 && ret != -EACCES) {
|
||||
pm_runtime_mark_last_busy(fb_helper->dev->dev);
|
||||
pm_runtime_put_autosuspend(fb_helper->dev->dev);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amdgpufb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
|
||||
pm_runtime_mark_last_busy(fb_helper->dev->dev);
|
||||
pm_runtime_put_autosuspend(fb_helper->dev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fb_ops amdgpufb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_open = amdgpufb_open,
|
||||
.fb_release = amdgpufb_release,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
};
|
||||
|
||||
|
||||
int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled)
|
||||
{
|
||||
int aligned = width;
|
||||
int pitch_mask = 0;
|
||||
|
||||
switch (cpp) {
|
||||
case 1:
|
||||
pitch_mask = 255;
|
||||
break;
|
||||
case 2:
|
||||
pitch_mask = 127;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
pitch_mask = 63;
|
||||
break;
|
||||
}
|
||||
|
||||
aligned += pitch_mask;
|
||||
aligned &= ~pitch_mask;
|
||||
return aligned * cpp;
|
||||
}
|
||||
|
||||
static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
|
||||
{
|
||||
struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj);
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_bo_reserve(abo, true);
|
||||
if (likely(ret == 0)) {
|
||||
amdgpu_bo_kunmap(abo);
|
||||
amdgpu_bo_unpin(abo);
|
||||
amdgpu_bo_unreserve(abo);
|
||||
}
|
||||
drm_gem_object_put(gobj);
|
||||
}
|
||||
|
||||
static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
const struct drm_format_info *info;
|
||||
struct amdgpu_device *adev = rfbdev->adev;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct amdgpu_bo *abo = NULL;
|
||||
bool fb_tiled = false; /* useful for testing */
|
||||
u32 tiling_flags = 0, domain;
|
||||
int ret;
|
||||
int aligned_size, size;
|
||||
int height = mode_cmd->height;
|
||||
u32 cpp;
|
||||
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
||||
AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
||||
|
||||
info = drm_get_format_info(adev_to_drm(adev), mode_cmd);
|
||||
cpp = info->cpp[0];
|
||||
|
||||
/* need to align pitch with crtc limits */
|
||||
mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
|
||||
fb_tiled);
|
||||
domain = amdgpu_display_supported_domains(adev, flags);
|
||||
height = ALIGN(mode_cmd->height, 8);
|
||||
size = mode_cmd->pitches[0] * height;
|
||||
aligned_size = ALIGN(size, PAGE_SIZE);
|
||||
ret = amdgpu_gem_object_create(adev, aligned_size, 0, domain, flags,
|
||||
ttm_bo_type_device, NULL, &gobj);
|
||||
if (ret) {
|
||||
pr_err("failed to allocate framebuffer (%d)\n", aligned_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
abo = gem_to_amdgpu_bo(gobj);
|
||||
|
||||
if (fb_tiled)
|
||||
tiling_flags = AMDGPU_TILING_SET(ARRAY_MODE, GRPH_ARRAY_2D_TILED_THIN1);
|
||||
|
||||
ret = amdgpu_bo_reserve(abo, false);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_unref;
|
||||
|
||||
if (tiling_flags) {
|
||||
ret = amdgpu_bo_set_tiling_flags(abo,
|
||||
tiling_flags);
|
||||
if (ret)
|
||||
dev_err(adev->dev, "FB failed to set tiling flags\n");
|
||||
}
|
||||
|
||||
ret = amdgpu_bo_pin(abo, domain);
|
||||
if (ret) {
|
||||
amdgpu_bo_unreserve(abo);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
ret = amdgpu_ttm_alloc_gart(&abo->tbo);
|
||||
if (ret) {
|
||||
amdgpu_bo_unreserve(abo);
|
||||
dev_err(adev->dev, "%p bind failed\n", abo);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
ret = amdgpu_bo_kmap(abo, NULL);
|
||||
amdgpu_bo_unreserve(abo);
|
||||
if (ret) {
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
*gobj_p = gobj;
|
||||
return 0;
|
||||
out_unref:
|
||||
amdgpufb_destroy_pinned_object(gobj);
|
||||
*gobj_p = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpufb_create(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct amdgpu_fbdev *rfbdev = (struct amdgpu_fbdev *)helper;
|
||||
struct amdgpu_device *adev = rfbdev->adev;
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct amdgpu_bo *abo = NULL;
|
||||
int ret;
|
||||
|
||||
memset(&mode_cmd, 0, sizeof(mode_cmd));
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
|
||||
if (sizes->surface_bpp == 24)
|
||||
sizes->surface_bpp = 32;
|
||||
|
||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
ret = amdgpufb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create fbcon object %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
abo = gem_to_amdgpu_bo(gobj);
|
||||
|
||||
/* okay we have an object now allocate the framebuffer */
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = amdgpu_display_gem_fb_init(adev_to_drm(adev), &rfbdev->rfb,
|
||||
&mode_cmd, gobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize framebuffer %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fb = &rfbdev->rfb.base;
|
||||
|
||||
/* setup helper */
|
||||
rfbdev->helper.fb = fb;
|
||||
|
||||
info->fbops = &amdgpufb_ops;
|
||||
|
||||
info->fix.smem_start = amdgpu_gmc_vram_cpu_pa(adev, abo);
|
||||
info->fix.smem_len = amdgpu_bo_size(abo);
|
||||
info->screen_base = amdgpu_bo_kptr(abo);
|
||||
info->screen_size = amdgpu_bo_size(abo);
|
||||
|
||||
drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->apertures->ranges[0].base = adev_to_drm(adev)->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = adev->gmc.aper_size;
|
||||
|
||||
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
|
||||
|
||||
if (info->screen_base == NULL) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
|
||||
DRM_INFO("vram apper at 0x%lX\n", (unsigned long)adev->gmc.aper_base);
|
||||
DRM_INFO("size %lu\n", (unsigned long)amdgpu_bo_size(abo));
|
||||
DRM_INFO("fb depth is %d\n", fb->format->depth);
|
||||
DRM_INFO(" pitch is %d\n", fb->pitches[0]);
|
||||
|
||||
vga_switcheroo_client_fb_set(adev->pdev, info);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (fb && ret) {
|
||||
drm_gem_object_put(gobj);
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
|
||||
{
|
||||
struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
|
||||
int i;
|
||||
|
||||
drm_fb_helper_unregister_fbi(&rfbdev->helper);
|
||||
|
||||
if (rfb->base.obj[0]) {
|
||||
for (i = 0; i < rfb->base.format->num_planes; i++)
|
||||
drm_gem_object_put(rfb->base.obj[0]);
|
||||
amdgpufb_destroy_pinned_object(rfb->base.obj[0]);
|
||||
rfb->base.obj[0] = NULL;
|
||||
drm_framebuffer_unregister_private(&rfb->base);
|
||||
drm_framebuffer_cleanup(&rfb->base);
|
||||
}
|
||||
drm_fb_helper_fini(&rfbdev->helper);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_fb_helper_funcs amdgpu_fb_helper_funcs = {
|
||||
.fb_probe = amdgpufb_create,
|
||||
};
|
||||
|
||||
int amdgpu_fbdev_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_fbdev *rfbdev;
|
||||
int bpp_sel = 32;
|
||||
int ret;
|
||||
|
||||
/* don't init fbdev on hw without DCE */
|
||||
if (!adev->mode_info.mode_config_initialized)
|
||||
return 0;
|
||||
|
||||
/* don't init fbdev if there are no connectors */
|
||||
if (list_empty(&adev_to_drm(adev)->mode_config.connector_list))
|
||||
return 0;
|
||||
|
||||
/* select 8 bpp console on low vram cards */
|
||||
if (adev->gmc.real_vram_size <= (32*1024*1024))
|
||||
bpp_sel = 8;
|
||||
|
||||
rfbdev = kzalloc(sizeof(struct amdgpu_fbdev), GFP_KERNEL);
|
||||
if (!rfbdev)
|
||||
return -ENOMEM;
|
||||
|
||||
rfbdev->adev = adev;
|
||||
adev->mode_info.rfbdev = rfbdev;
|
||||
|
||||
drm_fb_helper_prepare(adev_to_drm(adev), &rfbdev->helper,
|
||||
&amdgpu_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(adev_to_drm(adev), &rfbdev->helper);
|
||||
if (ret) {
|
||||
kfree(rfbdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||
if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
|
||||
drm_helper_disable_unused_functions(adev_to_drm(adev));
|
||||
|
||||
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_fbdev_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!adev->mode_info.rfbdev)
|
||||
return;
|
||||
|
||||
amdgpu_fbdev_destroy(adev_to_drm(adev), adev->mode_info.rfbdev);
|
||||
kfree(adev->mode_info.rfbdev);
|
||||
adev->mode_info.rfbdev = NULL;
|
||||
}
|
||||
|
||||
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state)
|
||||
{
|
||||
if (adev->mode_info.rfbdev)
|
||||
drm_fb_helper_set_suspend_unlocked(&adev->mode_info.rfbdev->helper,
|
||||
state);
|
||||
}
|
||||
|
||||
int amdgpu_fbdev_total_size(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_bo *robj;
|
||||
int size = 0;
|
||||
|
||||
if (!adev->mode_info.rfbdev)
|
||||
return 0;
|
||||
|
||||
robj = gem_to_amdgpu_bo(adev->mode_info.rfbdev->rfb.base.obj[0]);
|
||||
size += amdgpu_bo_size(robj);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
|
||||
{
|
||||
if (!adev->mode_info.rfbdev)
|
||||
return false;
|
||||
if (robj == gem_to_amdgpu_bo(adev->mode_info.rfbdev->rfb.base.obj[0]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
|
@ -56,6 +56,9 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
|||
return true;
|
||||
else
|
||||
return false;
|
||||
case CHIP_ALDEBARAN:
|
||||
/* All Aldebaran SKUs have the FRU */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -88,13 +91,17 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
|||
|
||||
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned char buff[34];
|
||||
unsigned char buff[AMDGPU_PRODUCT_NAME_LEN+2];
|
||||
u32 addrptr;
|
||||
int size, len;
|
||||
int offset = 2;
|
||||
|
||||
if (!is_fru_eeprom_supported(adev))
|
||||
return 0;
|
||||
|
||||
if (adev->asic_type == CHIP_ALDEBARAN)
|
||||
offset = 0;
|
||||
|
||||
/* If algo exists, it means that the i2c_adapter's initialized */
|
||||
if (!adev->pm.smu_i2c.algo) {
|
||||
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
|
||||
|
@ -131,15 +138,13 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
len = size;
|
||||
/* Product name should only be 32 characters. Any more,
|
||||
* and something could be wrong. Cap it at 32 to be safe
|
||||
*/
|
||||
if (len >= sizeof(adev->product_name)) {
|
||||
DRM_WARN("FRU Product Number is larger than 32 characters. This is likely a mistake");
|
||||
len = sizeof(adev->product_name) - 1;
|
||||
if (len >= AMDGPU_PRODUCT_NAME_LEN) {
|
||||
DRM_WARN("FRU Product Name is larger than %d characters. This is likely a mistake",
|
||||
AMDGPU_PRODUCT_NAME_LEN);
|
||||
len = AMDGPU_PRODUCT_NAME_LEN - 1;
|
||||
}
|
||||
/* Start at 2 due to buff using fields 0 and 1 for the address */
|
||||
memcpy(adev->product_name, &buff[2], len);
|
||||
memcpy(adev->product_name, &buff[offset], len);
|
||||
adev->product_name[len] = '\0';
|
||||
|
||||
addrptr += size + 1;
|
||||
|
@ -157,7 +162,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||
DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
|
||||
len = sizeof(adev->product_number) - 1;
|
||||
}
|
||||
memcpy(adev->product_number, &buff[2], len);
|
||||
memcpy(adev->product_number, &buff[offset], len);
|
||||
adev->product_number[len] = '\0';
|
||||
|
||||
addrptr += size + 1;
|
||||
|
@ -184,7 +189,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||
DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
|
||||
len = sizeof(adev->serial) - 1;
|
||||
}
|
||||
memcpy(adev->serial, &buff[2], len);
|
||||
memcpy(adev->serial, &buff[offset], len);
|
||||
adev->serial[len] = '\0';
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -264,6 +264,9 @@ static int amdgpu_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_str
|
|||
!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
|
||||
vma->vm_flags &= ~VM_MAYWRITE;
|
||||
|
||||
if (bo->kfd_bo)
|
||||
vma->vm_flags |= VM_DONTCOPY;
|
||||
|
||||
return drm_gem_ttm_mmap(obj, vma);
|
||||
}
|
||||
|
||||
|
@ -877,6 +880,32 @@ out:
|
|||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_gem_align_pitch(struct amdgpu_device *adev,
|
||||
int width,
|
||||
int cpp,
|
||||
bool tiled)
|
||||
{
|
||||
int aligned = width;
|
||||
int pitch_mask = 0;
|
||||
|
||||
switch (cpp) {
|
||||
case 1:
|
||||
pitch_mask = 255;
|
||||
break;
|
||||
case 2:
|
||||
pitch_mask = 127;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
pitch_mask = 63;
|
||||
break;
|
||||
}
|
||||
|
||||
aligned += pitch_mask;
|
||||
aligned &= ~pitch_mask;
|
||||
return aligned * cpp;
|
||||
}
|
||||
|
||||
int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
|
@ -885,7 +914,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
|||
struct drm_gem_object *gobj;
|
||||
uint32_t handle;
|
||||
u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC |
|
||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
u32 domain;
|
||||
int r;
|
||||
|
||||
|
@ -897,8 +927,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
|||
if (adev->mman.buffer_funcs_enabled)
|
||||
flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
||||
|
||||
args->pitch = amdgpu_align_pitch(adev, args->width,
|
||||
DIV_ROUND_UP(args->bpp, 8), 0);
|
||||
args->pitch = amdgpu_gem_align_pitch(adev, args->width,
|
||||
DIV_ROUND_UP(args->bpp, 8), 0);
|
||||
args->size = (u64)args->pitch * args->height;
|
||||
args->size = ALIGN(args->size, PAGE_SIZE);
|
||||
domain = amdgpu_bo_get_preferred_domain(adev,
|
||||
|
|
|
@ -350,6 +350,7 @@ static inline uint64_t amdgpu_gmc_fault_key(uint64_t addr, uint16_t pasid)
|
|||
* amdgpu_gmc_filter_faults - filter VM faults
|
||||
*
|
||||
* @adev: amdgpu device structure
|
||||
* @ih: interrupt ring that the fault received from
|
||||
* @addr: address of the VM fault
|
||||
* @pasid: PASID of the process causing the fault
|
||||
* @timestamp: timestamp of the fault
|
||||
|
@ -358,7 +359,8 @@ static inline uint64_t amdgpu_gmc_fault_key(uint64_t addr, uint16_t pasid)
|
|||
* True if the fault was filtered and should not be processed further.
|
||||
* False if the fault is a new one and needs to be handled.
|
||||
*/
|
||||
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
|
||||
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih, uint64_t addr,
|
||||
uint16_t pasid, uint64_t timestamp)
|
||||
{
|
||||
struct amdgpu_gmc *gmc = &adev->gmc;
|
||||
|
@ -366,6 +368,10 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
|
|||
struct amdgpu_gmc_fault *fault;
|
||||
uint32_t hash;
|
||||
|
||||
/* Stale retry fault if timestamp goes backward */
|
||||
if (amdgpu_ih_ts_after(timestamp, ih->processed_timestamp))
|
||||
return true;
|
||||
|
||||
/* If we don't have space left in the ring buffer return immediately */
|
||||
stamp = max(timestamp, AMDGPU_GMC_FAULT_TIMEOUT + 1) -
|
||||
AMDGPU_GMC_FAULT_TIMEOUT;
|
||||
|
|
|
@ -316,7 +316,8 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev,
|
|||
struct amdgpu_gmc *mc);
|
||||
void amdgpu_gmc_agp_location(struct amdgpu_device *adev,
|
||||
struct amdgpu_gmc *mc);
|
||||
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
|
||||
bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih, uint64_t addr,
|
||||
uint16_t pasid, uint64_t timestamp);
|
||||
void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
|
||||
uint16_t pasid);
|
||||
|
|
|
@ -164,52 +164,32 @@ void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
|
|||
}
|
||||
}
|
||||
|
||||
/* Waiter helper that checks current rptr matches or passes checkpoint wptr */
|
||||
static bool amdgpu_ih_has_checkpoint_processed(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih,
|
||||
uint32_t checkpoint_wptr,
|
||||
uint32_t *prev_rptr)
|
||||
{
|
||||
uint32_t cur_rptr = ih->rptr | (*prev_rptr & ~ih->ptr_mask);
|
||||
|
||||
/* rptr has wrapped. */
|
||||
if (cur_rptr < *prev_rptr)
|
||||
cur_rptr += ih->ptr_mask + 1;
|
||||
*prev_rptr = cur_rptr;
|
||||
|
||||
/* check ring is empty to workaround missing wptr overflow flag */
|
||||
return cur_rptr >= checkpoint_wptr ||
|
||||
(cur_rptr & ih->ptr_mask) == amdgpu_ih_get_wptr(adev, ih);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ih_wait_on_checkpoint_process - wait to process IVs up to checkpoint
|
||||
* amdgpu_ih_wait_on_checkpoint_process_ts - wait to process IVs up to checkpoint
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @ih: ih ring to process
|
||||
*
|
||||
* Used to ensure ring has processed IVs up to the checkpoint write pointer.
|
||||
*/
|
||||
int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev,
|
||||
int amdgpu_ih_wait_on_checkpoint_process_ts(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
uint32_t checkpoint_wptr, rptr;
|
||||
uint32_t checkpoint_wptr;
|
||||
uint64_t checkpoint_ts;
|
||||
long timeout = HZ;
|
||||
|
||||
if (!ih->enabled || adev->shutdown)
|
||||
return -ENODEV;
|
||||
|
||||
checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
|
||||
/* Order wptr with rptr. */
|
||||
/* Order wptr with ring data. */
|
||||
rmb();
|
||||
rptr = READ_ONCE(ih->rptr);
|
||||
checkpoint_ts = amdgpu_ih_decode_iv_ts(adev, ih, checkpoint_wptr, -1);
|
||||
|
||||
/* wptr has wrapped. */
|
||||
if (rptr > checkpoint_wptr)
|
||||
checkpoint_wptr += ih->ptr_mask + 1;
|
||||
|
||||
return wait_event_interruptible(ih->wait_process,
|
||||
amdgpu_ih_has_checkpoint_processed(adev, ih,
|
||||
checkpoint_wptr, &rptr));
|
||||
return wait_event_interruptible_timeout(ih->wait_process,
|
||||
amdgpu_ih_ts_after(checkpoint_ts, ih->processed_timestamp) ||
|
||||
ih->rptr == amdgpu_ih_get_wptr(adev, ih), timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,3 +279,18 @@ void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
|
|||
/* wptr/rptr are in bytes! */
|
||||
ih->rptr += 32;
|
||||
}
|
||||
|
||||
uint64_t amdgpu_ih_decode_iv_ts_helper(struct amdgpu_ih_ring *ih, u32 rptr,
|
||||
signed int offset)
|
||||
{
|
||||
uint32_t iv_size = 32;
|
||||
uint32_t ring_index;
|
||||
uint32_t dw1, dw2;
|
||||
|
||||
rptr += iv_size * offset;
|
||||
ring_index = (rptr & ih->ptr_mask) >> 2;
|
||||
|
||||
dw1 = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw2 = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
return dw1 | ((u64)(dw2 & 0xffff) << 32);
|
||||
}
|
||||
|
|
|
@ -68,20 +68,30 @@ struct amdgpu_ih_ring {
|
|||
|
||||
/* For waiting on IH processing at checkpoint. */
|
||||
wait_queue_head_t wait_process;
|
||||
uint64_t processed_timestamp;
|
||||
};
|
||||
|
||||
/* return true if time stamp t2 is after t1 with 48bit wrap around */
|
||||
#define amdgpu_ih_ts_after(t1, t2) \
|
||||
(((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL)
|
||||
|
||||
/* provided by the ih block */
|
||||
struct amdgpu_ih_funcs {
|
||||
/* ring read/write ptr handling, called from interrupt context */
|
||||
u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
uint64_t (*decode_iv_ts)(struct amdgpu_ih_ring *ih, u32 rptr,
|
||||
signed int offset);
|
||||
void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
};
|
||||
|
||||
#define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
|
||||
#define amdgpu_ih_decode_iv(adev, iv) \
|
||||
(adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
|
||||
#define amdgpu_ih_decode_iv_ts(adev, ih, rptr, offset) \
|
||||
(WARN_ON_ONCE(!(adev)->irq.ih_funcs->decode_iv_ts) ? 0 : \
|
||||
(adev)->irq.ih_funcs->decode_iv_ts((ih), (rptr), (offset)))
|
||||
#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))
|
||||
|
||||
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
|
@ -89,10 +99,12 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||
void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
|
||||
unsigned int num_dw);
|
||||
int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih);
|
||||
int amdgpu_ih_wait_on_checkpoint_process_ts(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih);
|
||||
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
uint64_t amdgpu_ih_decode_iv_ts_helper(struct amdgpu_ih_ring *ih, u32 rptr,
|
||||
signed int offset);
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*
|
||||
* \file amdgpu_ioc32.c
|
||||
*
|
||||
* 32-bit ioctl compatibility routines for the AMDGPU DRM.
|
||||
|
@ -37,12 +37,9 @@
|
|||
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||
int ret;
|
||||
|
||||
if (nr < DRM_COMMAND_BASE)
|
||||
return drm_compat_ioctl(filp, cmd, arg);
|
||||
|
||||
ret = amdgpu_drm_ioctl(filp, cmd, arg);
|
||||
|
||||
return ret;
|
||||
return amdgpu_drm_ioctl(filp, cmd, arg);
|
||||
}
|
||||
|
|
|
@ -333,7 +333,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
if (!adev->enable_virtual_display)
|
||||
/* Disable vblank IRQs aggressively for power-saving */
|
||||
/* XXX: can this be enabled for DC? */
|
||||
adev_to_drm(adev)->vblank_disable_immediate = true;
|
||||
|
||||
r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
|
||||
|
@ -391,7 +390,7 @@ void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_fini - shut down interrupt handling
|
||||
* amdgpu_irq_fini_sw - shut down interrupt handling
|
||||
*
|
||||
* @adev: amdgpu device pointer
|
||||
*
|
||||
|
@ -529,6 +528,9 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
|||
/* Send it to amdkfd as well if it isn't already handled */
|
||||
if (!handled)
|
||||
amdgpu_amdkfd_interrupt(adev, entry.iv_entry);
|
||||
|
||||
if (amdgpu_ih_ts_after(ih->processed_timestamp, entry.timestamp))
|
||||
ih->processed_timestamp = entry.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -232,8 +232,6 @@ struct amdgpu_i2c_chan {
|
|||
struct mutex mutex;
|
||||
};
|
||||
|
||||
struct amdgpu_fbdev;
|
||||
|
||||
struct amdgpu_afmt {
|
||||
bool enabled;
|
||||
int offset;
|
||||
|
@ -309,13 +307,6 @@ struct amdgpu_framebuffer {
|
|||
uint64_t address;
|
||||
};
|
||||
|
||||
struct amdgpu_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct amdgpu_framebuffer rfb;
|
||||
struct list_head fbdev_list;
|
||||
struct amdgpu_device *adev;
|
||||
};
|
||||
|
||||
struct amdgpu_mode_info {
|
||||
struct atom_context *atom_context;
|
||||
struct card_info *atom_card_info;
|
||||
|
@ -341,8 +332,6 @@ struct amdgpu_mode_info {
|
|||
struct edid *bios_hardcoded_edid;
|
||||
int bios_hardcoded_edid_size;
|
||||
|
||||
/* pointer to fbdev info structure */
|
||||
struct amdgpu_fbdev *rfbdev;
|
||||
/* firmware flags */
|
||||
u32 firmware_flags;
|
||||
/* pointer to backlight encoder */
|
||||
|
@ -631,15 +620,6 @@ bool amdgpu_crtc_get_scanout_position(struct drm_crtc *crtc,
|
|||
int *hpos, ktime_t *stime, ktime_t *etime,
|
||||
const struct drm_display_mode *mode);
|
||||
|
||||
/* fbdev layer */
|
||||
int amdgpu_fbdev_init(struct amdgpu_device *adev);
|
||||
void amdgpu_fbdev_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
|
||||
int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
|
||||
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj);
|
||||
|
||||
int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tiled);
|
||||
|
||||
/* amdgpu_display.c */
|
||||
void amdgpu_display_print_display_setup(struct drm_device *dev);
|
||||
int amdgpu_display_modeset_create_props(struct amdgpu_device *adev);
|
||||
|
|
|
@ -1032,9 +1032,14 @@ int amdgpu_bo_init(struct amdgpu_device *adev)
|
|||
/* On A+A platform, VRAM can be mapped as WB */
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
/* reserve PAT memory space to WC for VRAM */
|
||||
arch_io_reserve_memtype_wc(adev->gmc.aper_base,
|
||||
int r = arch_io_reserve_memtype_wc(adev->gmc.aper_base,
|
||||
adev->gmc.aper_size);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("Unable to set WC memtype for the aperture base\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Add an MTRR for the VRAM */
|
||||
adev->gmc.vram_mtrr = arch_phys_wc_add(adev->gmc.aper_base,
|
||||
adev->gmc.aper_size);
|
||||
|
|
|
@ -69,6 +69,7 @@ static void amdgpu_pll_reduce_ratio(unsigned *nom, unsigned *den,
|
|||
/**
|
||||
* amdgpu_pll_get_fb_ref_div - feedback and ref divider calculation
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @nom: nominator
|
||||
* @den: denominator
|
||||
* @post_div: post divider
|
||||
|
@ -106,6 +107,7 @@ static void amdgpu_pll_get_fb_ref_div(struct amdgpu_device *adev, unsigned int n
|
|||
/**
|
||||
* amdgpu_pll_compute - compute PLL paramaters
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @pll: information about the PLL
|
||||
* @freq: requested frequency
|
||||
* @dot_clock_p: resulting pixel clock
|
||||
|
|
|
@ -233,6 +233,10 @@ static void amdgpu_perf_start(struct perf_event *event, int flags)
|
|||
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
||||
return;
|
||||
|
||||
if ((!pe->adev->df.funcs) ||
|
||||
(!pe->adev->df.funcs->pmc_start))
|
||||
return;
|
||||
|
||||
WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
|
||||
hwc->state = 0;
|
||||
|
||||
|
@ -268,6 +272,10 @@ static void amdgpu_perf_read(struct perf_event *event)
|
|||
pmu);
|
||||
u64 count, prev;
|
||||
|
||||
if ((!pe->adev->df.funcs) ||
|
||||
(!pe->adev->df.funcs->pmc_get_count))
|
||||
return;
|
||||
|
||||
do {
|
||||
prev = local64_read(&hwc->prev_count);
|
||||
|
||||
|
@ -297,6 +305,10 @@ static void amdgpu_perf_stop(struct perf_event *event, int flags)
|
|||
if (hwc->state & PERF_HES_UPTODATE)
|
||||
return;
|
||||
|
||||
if ((!pe->adev->df.funcs) ||
|
||||
(!pe->adev->df.funcs->pmc_stop))
|
||||
return;
|
||||
|
||||
switch (hwc->config_base) {
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_DF:
|
||||
case AMDGPU_PMU_EVENT_CONFIG_TYPE_XGMI:
|
||||
|
@ -326,6 +338,10 @@ static int amdgpu_perf_add(struct perf_event *event, int flags)
|
|||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
|
||||
if ((!pe->adev->df.funcs) ||
|
||||
(!pe->adev->df.funcs->pmc_start))
|
||||
return -EINVAL;
|
||||
|
||||
switch (pe->pmu_perf_type) {
|
||||
case AMDGPU_PMU_PERF_TYPE_DF:
|
||||
hwc->config_base = AMDGPU_PMU_EVENT_CONFIG_TYPE_DF;
|
||||
|
@ -371,6 +387,9 @@ static void amdgpu_perf_del(struct perf_event *event, int flags)
|
|||
struct amdgpu_pmu_entry *pe = container_of(event->pmu,
|
||||
struct amdgpu_pmu_entry,
|
||||
pmu);
|
||||
if ((!pe->adev->df.funcs) ||
|
||||
(!pe->adev->df.funcs->pmc_stop))
|
||||
return;
|
||||
|
||||
amdgpu_perf_stop(event, PERF_EF_UPDATE);
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ static DEVICE_ATTR_RO(mem_info_preempt_used);
|
|||
* @man: TTM memory type manager
|
||||
* @tbo: TTM BO we need this range for
|
||||
* @place: placement flags and restrictions
|
||||
* @mem: the resulting mem object
|
||||
* @res: TTM memory object
|
||||
*
|
||||
* Dummy, just count the space used without allocating resources or any limit.
|
||||
*/
|
||||
|
@ -85,7 +85,7 @@ static int amdgpu_preempt_mgr_new(struct ttm_resource_manager *man,
|
|||
* amdgpu_preempt_mgr_del - free ranges
|
||||
*
|
||||
* @man: TTM memory type manager
|
||||
* @mem: TTM memory object
|
||||
* @res: TTM memory object
|
||||
*
|
||||
* Free the allocated GTT again.
|
||||
*/
|
||||
|
|
|
@ -518,7 +518,7 @@ static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp)
|
|||
return cmd;
|
||||
}
|
||||
|
||||
void release_psp_cmd_buf(struct psp_context *psp)
|
||||
static void release_psp_cmd_buf(struct psp_context *psp)
|
||||
{
|
||||
mutex_unlock(&psp->mutex);
|
||||
}
|
||||
|
@ -2017,12 +2017,16 @@ static int psp_hw_start(struct psp_context *psp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
|
||||
goto skip_pin_bo;
|
||||
|
||||
ret = psp_tmr_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP tmr init failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
skip_pin_bo:
|
||||
/*
|
||||
* For ASICs with DF Cstate management centralized
|
||||
* to PMFW, TMR setup should be performed after PMFW
|
||||
|
@ -2452,6 +2456,18 @@ skip_memalloc:
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) {
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
ret = psp_xgmi_initialize(psp, false, true);
|
||||
/* Warning the XGMI seesion initialize failure
|
||||
* Instead of stop driver initialization
|
||||
*/
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"XGMI: Failed to initialize XGMI session\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (psp->ta_fw) {
|
||||
ret = psp_ras_initialize(psp);
|
||||
if (ret)
|
||||
|
|
|
@ -867,9 +867,9 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev,
|
|||
/* feature ctl end */
|
||||
|
||||
|
||||
void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_err_data *err_data)
|
||||
static void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
struct ras_err_data *err_data)
|
||||
{
|
||||
switch (ras_block->sub_block_index) {
|
||||
case AMDGPU_RAS_MCA_BLOCK__MP0:
|
||||
|
@ -892,6 +892,38 @@ void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev,
|
|||
}
|
||||
}
|
||||
|
||||
static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_data *err_data)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* choosing right query method according to
|
||||
* whether smu support query error information
|
||||
*/
|
||||
ret = smu_get_ecc_info(&adev->smu, (void *)&(ras->umc_ecc));
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_count)
|
||||
adev->umc.ras_funcs->query_ras_error_count(adev, err_data);
|
||||
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_address)
|
||||
adev->umc.ras_funcs->query_ras_error_address(adev, err_data);
|
||||
} else if (!ret) {
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_count)
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_count(adev, err_data);
|
||||
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_address)
|
||||
adev->umc.ras_funcs->ecc_info_query_ras_error_address(adev, err_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* query/inject/cure begin */
|
||||
int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info)
|
||||
|
@ -905,15 +937,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
|||
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__UMC:
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_count)
|
||||
adev->umc.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_address)
|
||||
adev->umc.ras_funcs->query_ras_error_address(adev, &err_data);
|
||||
amdgpu_ras_get_ecc_info(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
if (adev->sdma.funcs->query_ras_error_count) {
|
||||
|
@ -1137,9 +1161,9 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
|||
|
||||
/**
|
||||
* amdgpu_ras_query_error_count -- Get error counts of all IPs
|
||||
* adev: pointer to AMD GPU device
|
||||
* ce_count: pointer to an integer to be set to the count of correctible errors.
|
||||
* ue_count: pointer to an integer to be set to the count of uncorrectible
|
||||
* @adev: pointer to AMD GPU device
|
||||
* @ce_count: pointer to an integer to be set to the count of correctible errors.
|
||||
* @ue_count: pointer to an integer to be set to the count of uncorrectible
|
||||
* errors.
|
||||
*
|
||||
* If set, @ce_count or @ue_count, count and return the corresponding
|
||||
|
@ -1723,6 +1747,16 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
|
|||
if (info.head.block == AMDGPU_RAS_BLOCK__PCIE_BIF)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* this is a workaround for aldebaran, skip send msg to
|
||||
* smu to get ecc_info table due to smu handle get ecc
|
||||
* info table failed temporarily.
|
||||
* should be removed until smu fix handle ecc_info table.
|
||||
*/
|
||||
if ((info.head.block == AMDGPU_RAS_BLOCK__UMC) &&
|
||||
(adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)))
|
||||
continue;
|
||||
|
||||
amdgpu_ras_query_error_status(adev, &info);
|
||||
}
|
||||
}
|
||||
|
@ -1935,9 +1969,11 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
|
|||
if (!con || !con->eh_data)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
control = &con->eeprom_control;
|
||||
data = con->eh_data;
|
||||
save_count = data->count - control->ras_num_recs;
|
||||
mutex_unlock(&con->recovery_lock);
|
||||
/* only new entries are saved */
|
||||
if (save_count > 0) {
|
||||
if (amdgpu_ras_eeprom_append(control,
|
||||
|
@ -2336,7 +2372,11 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
/* Init poison supported flag, the default value is false */
|
||||
if (adev->df.funcs &&
|
||||
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||
/* enabled by default when GPU is connected to CPU */
|
||||
con->poison_supported = true;
|
||||
}
|
||||
else if (adev->df.funcs &&
|
||||
adev->df.funcs->query_ras_poison_mode &&
|
||||
adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_poison_mode) {
|
||||
|
@ -2477,7 +2517,6 @@ void amdgpu_ras_late_fini(struct amdgpu_device *adev,
|
|||
amdgpu_ras_sysfs_remove(adev, ras_block);
|
||||
if (ih_info->cb)
|
||||
amdgpu_ras_interrupt_remove_handler(adev, ih_info);
|
||||
amdgpu_ras_feature_enable(adev, ras_block, 0);
|
||||
}
|
||||
|
||||
/* do some init work after IP late init as dependence.
|
||||
|
|
|
@ -319,6 +319,19 @@ struct ras_common_if {
|
|||
char name[32];
|
||||
};
|
||||
|
||||
#define MAX_UMC_CHANNEL_NUM 32
|
||||
|
||||
struct ecc_info_per_ch {
|
||||
uint16_t ce_count_lo_chip;
|
||||
uint16_t ce_count_hi_chip;
|
||||
uint64_t mca_umc_status;
|
||||
uint64_t mca_umc_addr;
|
||||
};
|
||||
|
||||
struct umc_ecc_info {
|
||||
struct ecc_info_per_ch ecc[MAX_UMC_CHANNEL_NUM];
|
||||
};
|
||||
|
||||
struct amdgpu_ras {
|
||||
/* ras infrastructure */
|
||||
/* for ras itself. */
|
||||
|
@ -358,6 +371,9 @@ struct amdgpu_ras {
|
|||
struct delayed_work ras_counte_delay_work;
|
||||
atomic_t ras_ue_count;
|
||||
atomic_t ras_ce_count;
|
||||
|
||||
/* record umc error info queried from smu */
|
||||
struct umc_ecc_info umc_ecc;
|
||||
};
|
||||
|
||||
struct ras_fs_data {
|
||||
|
|
|
@ -252,41 +252,25 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
|
|||
struct dma_resv *resv, enum amdgpu_sync_mode mode,
|
||||
void *owner)
|
||||
{
|
||||
struct dma_resv_list *flist;
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *f;
|
||||
unsigned i;
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
if (resv == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* always sync to the exclusive fence */
|
||||
f = dma_resv_excl_fence(resv);
|
||||
dma_fence_chain_for_each(f, f) {
|
||||
struct dma_fence_chain *chain = to_dma_fence_chain(f);
|
||||
dma_resv_for_each_fence(&cursor, resv, true, f) {
|
||||
dma_fence_chain_for_each(f, f) {
|
||||
struct dma_fence_chain *chain = to_dma_fence_chain(f);
|
||||
|
||||
if (amdgpu_sync_test_fence(adev, mode, owner, chain ?
|
||||
chain->fence : f)) {
|
||||
r = amdgpu_sync_fence(sync, f);
|
||||
dma_fence_put(f);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flist = dma_resv_shared_list(resv);
|
||||
if (!flist)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < flist->shared_count; ++i) {
|
||||
f = rcu_dereference_protected(flist->shared[i],
|
||||
dma_resv_held(resv));
|
||||
|
||||
if (amdgpu_sync_test_fence(adev, mode, owner, f)) {
|
||||
r = amdgpu_sync_fence(sync, f);
|
||||
if (r)
|
||||
return r;
|
||||
if (amdgpu_sync_test_fence(adev, mode, owner, chain ?
|
||||
chain->fence : f)) {
|
||||
r = amdgpu_sync_fence(sync, f);
|
||||
dma_fence_put(f);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue