mirror of
https://github.com/torvalds/linux.git
synced 2026-03-14 00:56:20 +01:00
drm for 6.10-rc1
new drivers: - panthor: ARM Mali/Immortalis CSF-based GPU driver core: - add a CONFIG_DRM_WERROR option - make more headers self-contained - grab resv lock in pin/unpin - fix vmap resv locking - EDID/eDP panel matching - Kconfig cleanups - DT sound bindings - Add SIZE_HINTS property for cursor planes - Add struct drm_edid_product_id and helpers. - Use drm device based logging in more drm functions. - drop seq_file.h from a bunch of places - use drm_edid driver conversions dp: - DP Tunnel documentation - MST read sideband cap - Adaptive sync SDP prep work ttm: - improve placement for TTM BOs in idle/busy handling panic: - Fixes for drm-panic, and option to test it. - Add drm panic to simpledrm, mgag200, imx, ast bridge: - improve init ordering - adv7511: allow GPIO pin sharing - tc358775: add tc358675 support panel: - AUO B120XAN01.0 - Samsung s6e3fa7 - BOE NT116WHM-N44 - CMN N116BCA-EA1, - CrystalClear CMT430B19N00 - Startek KD050HDFIA020-C020A - powertip PH128800T006-ZHC01 - Innolux G121X1-L03 - LG sw43408 - Khadas TS050 V2 - EDO RM69380 OLED - CSOT MNB601LS1-1 amdgpu: - HDCP/ODM/RAS fixes - Devcoredump improvements - Expose VCN activity via sysfs - SMY 13.0.x updates - Enable fast updates on DCN 3.1.4 - Add dclk and vclk reporting on additional devices - Add ACA RAS infrastructure - Implement TLB flush fence - EEPROM handling fixes - SMUIO 14.0.2 support - SMU 14.0.1 Updates - SMU 14.0.2 support - Sync page table freeing with TLB flushes - DML2 refactor - DC debug improvements - DCN 3.5.x Updates - GPU reset fixes - HDP fix for second GFX pipe on GC 10.x - Enable secondary GFX pipe on GC 10.3 - Refactor and clean up BACO/BOCO/BAMACO handling - Remove invalid TTM resource start check - UAF fix in VA IOCTL - GPUVM page fault redirection to secondary IH rings for IH 6.x - Initial support for mapping kernel queues via MES - Fix VRAM memory accounting amdkfd: - MQD handling cleanup - Preemption handling fixes for XCDs - TLB flush fix for GC 9.4.2 - Properly clean up workqueue during module unload - Fix memory leak process create failure - Range check CP bad op exception targets to avoid reporting invalid exceptions to userspace - Fix eviction fence handling - Fix leak in GPU memory allocation failure case - DMABuf import handling fix - Enable SQ watchpoint for gfx10 i915: - Adding new DG2 PCI ID - add context hints for GT frequency - enable only one CCS for compute workloads - new workarounds - Fix UAF on destroy against retire race and remove two earlier partial fixes - Limit the reserved VM space to only the platforms that need it - Fix gt reset with GuC submission is disable - Add and use gt_to_guc() wrapper i915/xe display: - Lunar Lake display enabling, including cdclk and other refactors - BIOS/VBT/opregion related refactor - Digital port related refactor/clean-up - Fix 2s boot time regression on DP panel replay init - Remove duplication on audio enable/disable on SDVO and g4x+ DP - Disable AuxCCS framebuffers if built for Xe - Make crtc disable more atomic - Increase DP idle pattern wait timeout to 2ms - Start using container_of_const() for some extra const safety - Fix Jasper Lake boot freeze - Enable MST mode for 128b/132b single-stream sideband - Enable Adaptive Sync SDP Support for DP - Fix MTL supported DP rates - removal of UHBR13.5 - PLL refactoring - Limit eDP MSO pipe only for display version 20 - More display refactor towards independence from i915 dev_priv - Convert i915/xe fbdev to DRM client - More initial work to make display code more independent from i915 xe: - improved error capture - clean up some uAPI leftovers - devcoredump update - Add BMG mocs table - Handle GSCCS ER interrupt - Implement xe2- and GuC workarounds - struct xe_device cleanup - Hwmon updates - Add LRC parsing for more GPU instruction - Increase VM_BIND number of per-ioctl Ops - drm/xe: Add XE_BO_GGTT_INVALIDATE flag - Initial development for SR-IOV support - Add new PCI IDs to DG2 platform - Move userptr over to start using hmm_range_fault msm: - Switched to generating register header files during build process instead of shipping pre-generated headers - Merged DPU and MDP4 format databases. - DP: - Stop using compat string to distinguish DP and eDP cases - Added support for X Elite platform (X1E80100) - Reworked DP aux/audio support - Added SM6350 DP to the bindings - GPU: - a7xx perfcntr reg fixes - MAINTAINERS updates - a750 devcoredump support radeon: - Silence UBSAN warnings related to flexible arrays nouveau: - move some uAPI objects to uapi headers omapdrm: - console fix ast: - add i2c polling qaic: - add debugfs entries exynos: - fix platform_driver .owner - drop cleanup code mediatek: - Use devm_platform_get_and_ioremap_resource() in mtk_hdmi_ddc_probe() - Add GAMMA 12-bit LUT support for MT8188 - Rename mtk_drm_* to mtk_* - Drop driver owner initialization - Correct calculation formula of PHY Timing -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmZEUU0ACgkQDHTzWXnE hr5qMBAAjUFF0w3YOQMsn0LEAm628kMRHpoVeSXmIfO9z9lTyad30EtiS4ggFgj7 Q/oQ6hHCd5jdsvGSJDgtTTAsTQX+aCkXrgf/18ENbqR5mM3MdefUAPR/zawZ7HR4 8+b2h6p7gHBw8wDjuIvQ5e9InHcnIkKWJc82qnJG5Urgxa05SDh3mu3cosPTJiBw a851vlWaYcxC0yAUwJlWaXDdN8yzdFaSQNboZBS/CMLXF/WE6Ht257uxJmaouc0Y Z0kBybok5x0TPQEXF9IV+kuSW3EYpYcwRi0BFFM9sJjkEBdH3rYRZwuYP1LR+7VZ HKsmIkie8YzCm2VwTquYzUvHgF+swZX4RRch9XJlGz7UvBLc0eBO/2n4X6fNd8Kl QGNNqEfsnUQrAHKvGsOUgoGjSCmEo8voGcMZ3JPIAdJ/GcnJwpMvNxtF6XB08hEu rDxuU6o7WkM4dJbtiaFEHNh0Fmjj6aXdBL23UD9pcqPT1fc9cT3xnUd5RJIRuRwV /tpb2WfkFAoxCkKFiunaC4rE8oG6ME6wr/trYjvoYuhCI5hCVaXRBGzJEtC30IP6 lG2YZ8r0jHjktbgjZ0Cz/hY424H4sxSN9SJAnXXFDzcfjBJ/nOgo5nMD1jKajAD5 SYfqWaD5Y+YygtyLJPMfZQI2XMOpCzteXD8uaNXXFJfpV7Apeyg= =ocVM -----END PGP SIGNATURE----- Merge tag 'drm-next-2024-05-15' of https://gitlab.freedesktop.org/drm/kernel Pull drm updates from Dave Airlie: "This is the main pull request for the drm subsystems for 6.10. In drivers the main thing is a new driver for ARM Mali firmware based GPUs, otherwise there are a lot of changes to amdgpu/xe/i915/msm and scattered changes to everything else. In the core a bunch of headers and Kconfig was refactored, along with the addition of a new panic handler which is meant to provide a user friendly message when a panic happens and graphical display is enabled. New drivers: - panthor: ARM Mali/Immortalis CSF-based GPU driver Core: - add a CONFIG_DRM_WERROR option - make more headers self-contained - grab resv lock in pin/unpin - fix vmap resv locking - EDID/eDP panel matching - Kconfig cleanups - DT sound bindings - Add SIZE_HINTS property for cursor planes - Add struct drm_edid_product_id and helpers. - Use drm device based logging in more drm functions. - drop seq_file.h from a bunch of places - use drm_edid driver conversions dp: - DP Tunnel documentation - MST read sideband cap - Adaptive sync SDP prep work ttm: - improve placement for TTM BOs in idle/busy handling panic: - Fixes for drm-panic, and option to test it. - Add drm panic to simpledrm, mgag200, imx, ast bridge: - improve init ordering - adv7511: allow GPIO pin sharing - tc358775: add tc358675 support panel: - AUO B120XAN01.0 - Samsung s6e3fa7 - BOE NT116WHM-N44 - CMN N116BCA-EA1, - CrystalClear CMT430B19N00 - Startek KD050HDFIA020-C020A - powertip PH128800T006-ZHC01 - Innolux G121X1-L03 - LG sw43408 - Khadas TS050 V2 - EDO RM69380 OLED - CSOT MNB601LS1-1 amdgpu: - HDCP/ODM/RAS fixes - Devcoredump improvements - Expose VCN activity via sysfs - SMY 13.0.x updates - Enable fast updates on DCN 3.1.4 - Add dclk and vclk reporting on additional devices - Add ACA RAS infrastructure - Implement TLB flush fence - EEPROM handling fixes - SMUIO 14.0.2 support - SMU 14.0.1 Updates - SMU 14.0.2 support - Sync page table freeing with TLB flushes - DML2 refactor - DC debug improvements - DCN 3.5.x Updates - GPU reset fixes - HDP fix for second GFX pipe on GC 10.x - Enable secondary GFX pipe on GC 10.3 - Refactor and clean up BACO/BOCO/BAMACO handling - Remove invalid TTM resource start check - UAF fix in VA IOCTL - GPUVM page fault redirection to secondary IH rings for IH 6.x - Initial support for mapping kernel queues via MES - Fix VRAM memory accounting amdkfd: - MQD handling cleanup - Preemption handling fixes for XCDs - TLB flush fix for GC 9.4.2 - Properly clean up workqueue during module unload - Fix memory leak process create failure - Range check CP bad op exception targets to avoid reporting invalid exceptions to userspace - Fix eviction fence handling - Fix leak in GPU memory allocation failure case - DMABuf import handling fix - Enable SQ watchpoint for gfx10 i915: - Adding new DG2 PCI ID - add context hints for GT frequency - enable only one CCS for compute workloads - new workarounds - Fix UAF on destroy against retire race and remove two earlier partial fixes - Limit the reserved VM space to only the platforms that need it - Fix gt reset with GuC submission is disable - Add and use gt_to_guc() wrapper i915/xe display: - Lunar Lake display enabling, including cdclk and other refactors - BIOS/VBT/opregion related refactor - Digital port related refactor/clean-up - Fix 2s boot time regression on DP panel replay init - Remove duplication on audio enable/disable on SDVO and g4x+ DP - Disable AuxCCS framebuffers if built for Xe - Make crtc disable more atomic - Increase DP idle pattern wait timeout to 2ms - Start using container_of_const() for some extra const safety - Fix Jasper Lake boot freeze - Enable MST mode for 128b/132b single-stream sideband - Enable Adaptive Sync SDP Support for DP - Fix MTL supported DP rates - removal of UHBR13.5 - PLL refactoring - Limit eDP MSO pipe only for display version 20 - More display refactor towards independence from i915 dev_priv - Convert i915/xe fbdev to DRM client - More initial work to make display code more independent from i915 xe: - improved error capture - clean up some uAPI leftovers - devcoredump update - Add BMG mocs table - Handle GSCCS ER interrupt - Implement xe2- and GuC workarounds - struct xe_device cleanup - Hwmon updates - Add LRC parsing for more GPU instruction - Increase VM_BIND number of per-ioctl Ops - drm/xe: Add XE_BO_GGTT_INVALIDATE flag - Initial development for SR-IOV support - Add new PCI IDs to DG2 platform - Move userptr over to start using hmm_range_fault msm: - Switched to generating register header files during build process instead of shipping pre-generated headers - Merged DPU and MDP4 format databases. - DP: - Stop using compat string to distinguish DP and eDP cases - Added support for X Elite platform (X1E80100) - Reworked DP aux/audio support - Added SM6350 DP to the bindings - GPU: - a7xx perfcntr reg fixes - MAINTAINERS updates - a750 devcoredump support radeon: - Silence UBSAN warnings related to flexible arrays nouveau: - move some uAPI objects to uapi headers omapdrm: - console fix ast: - add i2c polling qaic: - add debugfs entries exynos: - fix platform_driver .owner - drop cleanup code mediatek: - Use devm_platform_get_and_ioremap_resource() in mtk_hdmi_ddc_probe() - Add GAMMA 12-bit LUT support for MT8188 - Rename mtk_drm_* to mtk_* - Drop driver owner initialization - Correct calculation formula of PHY Timing" * tag 'drm-next-2024-05-15' of https://gitlab.freedesktop.org/drm/kernel: (1477 commits) drm/xe/ads: Use flexible-array drm/xe: Use ordered WQ for G2H handler drm/msm/gen_header: allow skipping the validation drm/msm/a6xx: Cleanup indexed regs const'ness drm/msm: Add devcoredump support for a750 drm/msm: Adjust a7xx GBIF debugbus dumping drm/msm: Update a6xx registers XML drm/msm: Fix imported a750 snapshot header for upstream drm/msm: Import a750 snapshot registers from kgsl MAINTAINERS: Add Konrad Dybcio as a reviewer for the Adreno driver MAINTAINERS: Add a separate entry for Qualcomm Adreno GPU drivers drm/msm/a6xx: Avoid a nullptr dereference when speedbin setting fails drm/msm/adreno: fix CP cycles stat retrieval on a7xx drm/msm/a7xx: allow writing to CP_BV counter selection registers drm: zynqmp_dpsub: Always register bridge Revert "drm/bridge: ti-sn65dsi83: Fix enable error path" drm/fb_dma: Add checks in drm_fb_dma_get_scanout_buffer() drm/fbdev-generic: Do not set physical framebuffer address drm/panthor: Fix the FW reset logic drm/panthor: Make sure we handle 'unknown group state' case properly ...
This commit is contained in:
commit
db5d28c0bf
1373 changed files with 77527 additions and 55665 deletions
|
|
@ -10,7 +10,7 @@ Description: RW. Card reactive sustained (PL1) power limit in microwatts.
|
|||
power limit is disabled, writing 0 disables the
|
||||
limit. Writing values > 0 and <= TDP will enable the power limit.
|
||||
|
||||
Only supported for particular Intel xe graphics platforms.
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_rated_max
|
||||
Date: September 2023
|
||||
|
|
@ -18,53 +18,93 @@ KernelVersion: 6.5
|
|||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RO. Card default power limit (default TDP setting).
|
||||
|
||||
Only supported for particular Intel xe graphics platforms.
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_crit
|
||||
Date: September 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Card reactive critical (I1) power limit in microwatts.
|
||||
|
||||
Card reactive critical (I1) power limit in microwatts is exposed
|
||||
for client products. The power controller will throttle the
|
||||
operating frequency if the power averaged over a window exceeds
|
||||
this limit.
|
||||
|
||||
Only supported for particular Intel xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/curr1_crit
|
||||
Date: September 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Card reactive critical (I1) power limit in milliamperes.
|
||||
|
||||
Card reactive critical (I1) power limit in milliamperes is
|
||||
exposed for server products. The power controller will throttle
|
||||
the operating frequency if the power averaged over a window
|
||||
exceeds this limit.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/in0_input
|
||||
Date: September 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RO. Current Voltage in millivolt.
|
||||
|
||||
Only supported for particular Intel xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/energy1_input
|
||||
Date: September 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RO. Energy input of device in microjoules.
|
||||
Description: RO. Card energy input of device in microjoules.
|
||||
|
||||
Only supported for particular Intel xe graphics platforms.
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_max_interval
|
||||
Date: October 2023
|
||||
KernelVersion: 6.6
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Sustained power limit interval (Tau in PL1/Tau) in
|
||||
Description: RW. Card sustained power limit interval (Tau in PL1/Tau) in
|
||||
milliseconds over which sustained power is averaged.
|
||||
|
||||
Only supported for particular Intel xe graphics platforms.
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power2_max
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Package reactive sustained (PL1) power limit in microwatts.
|
||||
|
||||
The power controller will throttle the operating frequency
|
||||
if the power averaged over a window (typically seconds)
|
||||
exceeds this limit. A read value of 0 means that the PL1
|
||||
power limit is disabled, writing 0 disables the
|
||||
limit. Writing values > 0 and <= TDP will enable the power limit.
|
||||
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power2_rated_max
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RO. Package default power limit (default TDP setting).
|
||||
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power2_crit
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Package reactive critical (I1) power limit in microwatts.
|
||||
|
||||
Package reactive critical (I1) power limit in microwatts is exposed
|
||||
for client products. The power controller will throttle the
|
||||
operating frequency if the power averaged over a window exceeds
|
||||
this limit.
|
||||
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/curr2_crit
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Package reactive critical (I1) power limit in milliamperes.
|
||||
|
||||
Package reactive critical (I1) power limit in milliamperes is
|
||||
exposed for server products. The power controller will throttle
|
||||
the operating frequency if the power averaged over a window
|
||||
exceeds this limit.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/energy2_input
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RO. Package energy input of device in microjoules.
|
||||
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power2_max_interval
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RW. Package sustained power limit interval (Tau in PL1/Tau) in
|
||||
milliseconds over which sustained power is averaged.
|
||||
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
||||
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/in1_input
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8
|
||||
Contact: intel-xe@lists.freedesktop.org
|
||||
Description: RO. Package current voltage in millivolt.
|
||||
|
||||
Only supported for particular Intel Xe graphics platforms.
|
||||
|
|
|
|||
10
Documentation/ABI/testing/sysfs-driver-panfrost-profiling
Normal file
10
Documentation/ABI/testing/sysfs-driver-panfrost-profiling
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
What: /sys/bus/platform/drivers/panfrost/.../profiling
|
||||
Date: February 2024
|
||||
KernelVersion: 6.8.0
|
||||
Contact: Adrian Larumbe <adrian.larumbe@collabora.com>
|
||||
Description:
|
||||
Get/set drm fdinfo's engine and cycles profiling status.
|
||||
Valid values are:
|
||||
0: Don't enable fdinfo job profiling sources.
|
||||
1: Enable fdinfo job profiling sources, this enables both the GPU's
|
||||
timestamp and cycle counter registers.
|
||||
|
|
@ -9,6 +9,9 @@ title: ITE it6505
|
|||
maintainers:
|
||||
- Allen Chen <allen.chen@ite.com.tw>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/sound/dai-common.yaml#
|
||||
|
||||
description: |
|
||||
The IT6505 is a high-performance DisplayPort 1.1a transmitter,
|
||||
fully compliant with DisplayPort 1.1a, HDCP 1.3 specifications.
|
||||
|
|
@ -52,6 +55,9 @@ properties:
|
|||
maxItems: 1
|
||||
description: extcon specifier for the Power Delivery
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
|
|
@ -105,7 +111,7 @@ required:
|
|||
- extcon
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ properties:
|
|||
- enum:
|
||||
- ti,ds90cf364a # For the DS90CF364A FPD-Link LVDS Receiver
|
||||
- ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver
|
||||
- ti,sn65lvds94 # For the SN65DS94 LVDS serdes
|
||||
- const: lvds-decoder # Generic LVDS decoders compatible fallback
|
||||
- enum:
|
||||
- thine,thc63lvdm83d # For the THC63LVDM83D LVDS serializer
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/microchip,sam9x75-lvds.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip SAM9X75 LVDS Controller
|
||||
|
||||
maintainers:
|
||||
- Dharma Balasubiramani <dharma.b@microchip.com>
|
||||
|
||||
description:
|
||||
The Low Voltage Differential Signaling Controller (LVDSC) manages data
|
||||
format conversion from the LCD Controller internal DPI bus to OpenLDI
|
||||
LVDS output signals. LVDSC functions include bit mapping, balanced mode
|
||||
management, and serializer.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,sam9x75-lvds
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Peripheral Bus Clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
lvds-controller@f8060000 {
|
||||
compatible = "microchip,sam9x75-lvds";
|
||||
reg = <0xf8060000 0x100>;
|
||||
interrupts = <56 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 56>;
|
||||
clock-names = "pclk";
|
||||
};
|
||||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Vinay Simha BN <simhavcs@gmail.com>
|
||||
|
||||
description: |
|
||||
This binding supports DSI to LVDS bridge TC358775
|
||||
This binding supports DSI to LVDS bridges TC358765 and TC358775
|
||||
|
||||
MIPI DSI-RX Data 4-lane, CLK 1-lane with data rates up to 800 Mbps/lane.
|
||||
Video frame size:
|
||||
|
|
@ -21,7 +21,9 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: toshiba,tc358775
|
||||
enum:
|
||||
- toshiba,tc358765
|
||||
- toshiba,tc358775
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
@ -46,11 +48,27 @@ properties:
|
|||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
DSI Input. The remote endpoint phandle should be a
|
||||
reference to a valid mipi_dsi_host device node.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
description: array of physical DSI data lane indexes.
|
||||
minItems: 1
|
||||
items:
|
||||
- const: 1
|
||||
- const: 2
|
||||
- const: 3
|
||||
- const: 4
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: |
|
||||
|
|
@ -70,10 +88,19 @@ required:
|
|||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
- stby-gpios
|
||||
- reset-gpios
|
||||
- ports
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: toshiba,tc358765
|
||||
then:
|
||||
properties:
|
||||
stby-gpios: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
@ -108,6 +135,7 @@ examples:
|
|||
reg = <0>;
|
||||
d2l_in_test: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -132,7 +160,6 @@ examples:
|
|||
reg = <1>;
|
||||
dsi0_out: endpoint {
|
||||
remote-endpoint = <&d2l_in_test>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -167,6 +194,7 @@ examples:
|
|||
reg = <0>;
|
||||
d2l_in_dual: endpoint {
|
||||
remote-endpoint = <&dsi0_out_dual>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -198,7 +226,6 @@ examples:
|
|||
reg = <1>;
|
||||
dsi0_out_dual: endpoint {
|
||||
remote-endpoint = <&d2l_in_dual>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ properties:
|
|||
- enum:
|
||||
- mediatek,mt8173-disp-gamma
|
||||
- mediatek,mt8183-disp-gamma
|
||||
- mediatek,mt8195-disp-gamma
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt6795-disp-gamma
|
||||
|
|
@ -35,6 +36,10 @@ properties:
|
|||
- mediatek,mt8192-disp-gamma
|
||||
- mediatek,mt8195-disp-gamma
|
||||
- const: mediatek,mt8183-disp-gamma
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8188-disp-gamma
|
||||
- const: mediatek,mt8195-disp-gamma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ properties:
|
|||
- qcom,sm8650-dp
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sm6350-dp
|
||||
- qcom,sm8150-dp
|
||||
- qcom,sm8250-dp
|
||||
- qcom,sm8450-dp
|
||||
|
|
|
|||
|
|
@ -53,6 +53,15 @@ patternProperties:
|
|||
compatible:
|
||||
const: qcom,sm6350-dpu
|
||||
|
||||
"^displayport-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,sm6350-dp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ properties:
|
|||
- ampire,am8001280g
|
||||
- bananapi,lhr050h41
|
||||
- feixin,k101-im2byl02
|
||||
- startek,kd050hdfia020
|
||||
- tdo,tl050hdv35
|
||||
- wanchanglong,w552946aba
|
||||
- const: ilitek,ili9881c
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/lg,sw43408.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: LG SW43408 1080x2160 DSI panel
|
||||
|
||||
maintainers:
|
||||
- Caleb Connolly <caleb.connolly@linaro.org>
|
||||
|
||||
description:
|
||||
This panel is used on the Pixel 3, it is a 60hz OLED panel which
|
||||
required DSC (Display Stream Compression) and has rounded corners.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: lg,sw43408
|
||||
|
||||
reg: true
|
||||
port: true
|
||||
vddi-supply: true
|
||||
vpnl-supply: true
|
||||
reset-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vddi-supply
|
||||
- vpnl-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "lg,sw43408";
|
||||
reg = <0>;
|
||||
|
||||
vddi-supply = <&vreg_l14a_1p88>;
|
||||
vpnl-supply = <&vreg_l28a_3p0>;
|
||||
|
||||
reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&mdss_dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -19,7 +19,7 @@ description: |
|
|||
either bilinear interpolation or pixel duplication.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
- $ref: panel-common-dual.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -59,6 +59,7 @@ required:
|
|||
- avee-supply
|
||||
- dvdd-supply
|
||||
- vddio-supply
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ description: |
|
|||
panels. Support video mode panels from China Star Optoelectronics
|
||||
Technology (CSOT) and BOE Technology.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
|
|
@ -38,7 +35,6 @@ properties:
|
|||
description: regulator that supplies the I/O voltage
|
||||
|
||||
reg: true
|
||||
ports: true
|
||||
rotation: true
|
||||
backlight: true
|
||||
|
||||
|
|
@ -47,7 +43,26 @@ required:
|
|||
- reg
|
||||
- vddio-supply
|
||||
- reset-gpios
|
||||
- ports
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common-dual.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- novatek,nt36523w
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
properties:
|
||||
port@1: false
|
||||
else:
|
||||
properties:
|
||||
port: false
|
||||
ports:
|
||||
required:
|
||||
- port@1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/panel-common-dual.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common Properties for Dual-Link Display Panels
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
|
||||
description:
|
||||
Properties common for Panel IC supporting dual link panels. Devices might
|
||||
support also single link.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: First link
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Second link
|
||||
|
||||
"#address-cells": true
|
||||
"#size-cells": true
|
||||
|
||||
required:
|
||||
- port@0
|
||||
|
||||
# Single-panel setups are still allowed.
|
||||
oneOf:
|
||||
- required:
|
||||
- ports
|
||||
- required:
|
||||
- port
|
||||
|
||||
additionalProperties: true
|
||||
|
|
@ -36,6 +36,8 @@ properties:
|
|||
- jdi,fhd-r63452
|
||||
# Khadas TS050 5" 1080x1920 LCD panel
|
||||
- khadas,ts050
|
||||
# Khadas TS050 V2 5" 1080x1920 LCD panel
|
||||
- khadas,ts050v2
|
||||
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
||||
- kingdisplay,kd097d04
|
||||
# LG ACX467AKM-7 4.95" 1080×1920 LCD Panel
|
||||
|
|
@ -50,6 +52,8 @@ properties:
|
|||
- panasonic,vvx10f004b00
|
||||
# Panasonic 10" WUXGA TFT LCD panel
|
||||
- panasonic,vvx10f034n00
|
||||
# Samsung s6e3fa7 1080x2220 based AMS559NK06 AMOLED panel
|
||||
- samsung,s6e3fa7-ams559nk06
|
||||
# Samsung s6e3fc2x01 1080x2340 AMOLED panel
|
||||
- samsung,s6e3fc2x01
|
||||
# Samsung sofef00 1080x2280 AMOLED panel
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ properties:
|
|||
- boe,nv133fhm-n62
|
||||
# BOE NV140FHM-N49 14.0" FHD a-Si FT panel
|
||||
- boe,nv140fhmn49
|
||||
# Crystal Clear Technology CMT430B19N00 4.3" 480x272 TFT-LCD panel
|
||||
- cct,cmt430b19n00
|
||||
# CDTech(H.K.) Electronics Limited 4.3" 480x272 color TFT-LCD panel
|
||||
- cdtech,s043wq26h-ct7
|
||||
# CDTech(H.K.) Electronics Limited 7" WSVGA (1024x600) TFT LCD Panel
|
||||
|
|
@ -188,6 +190,8 @@ properties:
|
|||
- innolux,g121i1-l01
|
||||
# Innolux Corporation 12.1" G121X1-L03 XGA (1024x768) TFT LCD panel
|
||||
- innolux,g121x1-l03
|
||||
# Innolux Corporation 12.1" G121XCE-L01 XGA (1024x768) TFT LCD panel
|
||||
- innolux,g121xce-l01
|
||||
# Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
|
||||
- innolux,n116bca-ea1
|
||||
# Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
|
||||
|
|
@ -272,6 +276,8 @@ properties:
|
|||
- osddisplays,osd070t1718-19ts
|
||||
# One Stop Displays OSD101T2045-53TS 10.1" 1920x1200 panel
|
||||
- osddisplays,osd101t2045-53ts
|
||||
# POWERTIP PH128800T006-ZHC01 10.1" WXGA TFT LCD panel
|
||||
- powertip,ph128800t006-zhc01
|
||||
# POWERTIP PH800480T013-IDF2 7.0" WVGA TFT LCD panel
|
||||
- powertip,ph800480t013-idf02
|
||||
# QiaoDian XianShi Corporation 4"3 TFT LCD panel
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/raydium,rm69380.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Raydium RM69380-based DSI display panels
|
||||
|
||||
maintainers:
|
||||
- David Wronek <david@mainlining.org>
|
||||
|
||||
description:
|
||||
The Raydium RM69380 is a generic DSI panel IC used to control
|
||||
OLED panels.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common-dual.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- lenovo,j716f-edo-rm69380
|
||||
- const: raydium,rm69380
|
||||
description: This indicates the panel manufacturer of the panel
|
||||
that is in turn using the RM69380 panel driver. The compatible
|
||||
string determines how the RM69380 panel driver shall be configured
|
||||
to work with the indicated panel. The raydium,rm69380 compatible shall
|
||||
always be provided as a fallback.
|
||||
|
||||
avdd-supply:
|
||||
description: Analog voltage rail
|
||||
|
||||
vddio-supply:
|
||||
description: I/O voltage rail
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: phandle of gpio for reset line - This should be active low
|
||||
|
||||
reg: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- avdd-supply
|
||||
- vddio-supply
|
||||
- reset-gpios
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "lenovo,j716f-edo-rm69380", "raydium,rm69380";
|
||||
reg = <0>;
|
||||
|
||||
avdd-supply = <&panel_avdd_regulator>;
|
||||
vddio-supply = <&vreg_l14a>;
|
||||
reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
panel_in_0: endpoint {
|
||||
remote-endpoint = <&mdss_dsi0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
panel_in_1: endpoint {
|
||||
remote-endpoint = <&mdss_dsi1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -22,6 +22,8 @@ properties:
|
|||
enum:
|
||||
# Anberic RG353V-V2 5.0" 640x480 TFT LCD panel
|
||||
- anbernic,rg353v-panel-v2
|
||||
# GameForce Chi 3.5" 640x480 TFT LCD panel
|
||||
- gameforce,chi-panel
|
||||
# Powkiddy RGB10MAX3 5.0" 720x1280 TFT LCD panel
|
||||
- powkiddy,rgb10max3-panel
|
||||
# Powkiddy RGB30 3.0" 720x720 TFT LCD panel
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ properties:
|
|||
reg: true
|
||||
|
||||
backlight: true
|
||||
width-mm: true
|
||||
height-mm: true
|
||||
|
||||
vddio-supply:
|
||||
description: VDDIO 1.8V supply
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ description: |
|
|||
|
||||
allOf:
|
||||
- $ref: ../bridge/synopsys,dw-hdmi.yaml#
|
||||
- $ref: /schemas/sound/dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -124,6 +125,9 @@ properties:
|
|||
description:
|
||||
phandle to the GRF to mux vopl/vopb.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -153,6 +157,7 @@ examples:
|
|||
ddc-i2c-bus = <&i2c5>;
|
||||
power-domains = <&power RK3288_PD_VIO>;
|
||||
rockchip,grf = <&grf>;
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ properties:
|
|||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
|
|
@ -66,6 +69,7 @@ required:
|
|||
- ports
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/sound/dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -106,6 +110,7 @@ examples:
|
|||
clock-names = "pclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hdmi_ctl>;
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ maintainers:
|
|||
- Sandy Huang <hjc@rock-chips.com>
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/sound/dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rockchip,rk3066-hdmi
|
||||
|
|
@ -34,6 +37,9 @@ properties:
|
|||
description:
|
||||
This soc uses GRF regs to switch the HDMI TX input between vop0 and vop1.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
|
|
@ -83,6 +89,7 @@ examples:
|
|||
pinctrl-names = "default";
|
||||
power-domains = <&power RK3066_PD_VIO>;
|
||||
rockchip,grf = <&grf>;
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
|
|
|
|||
147
Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
Normal file
147
Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/gpu/arm,mali-valhall-csf.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ARM Mali Valhall GPU
|
||||
|
||||
maintainers:
|
||||
- Liviu Dudau <liviu.dudau@arm.com>
|
||||
- Boris Brezillon <boris.brezillon@collabora.com>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: '^gpu@[a-f0-9]+$'
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3588-mali
|
||||
- const: arm,mali-valhall-csf # Mali Valhall GPU model/revision is fully discoverable
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Job interrupt
|
||||
- description: MMU interrupt
|
||||
- description: GPU interrupt
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: job
|
||||
- const: mmu
|
||||
- const: gpu
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: core
|
||||
- const: coregroup
|
||||
- const: stacks
|
||||
|
||||
mali-supply: true
|
||||
|
||||
operating-points-v2: true
|
||||
opp-table:
|
||||
type: object
|
||||
|
||||
power-domains:
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
|
||||
power-domain-names:
|
||||
minItems: 1
|
||||
maxItems: 5
|
||||
|
||||
sram-supply: true
|
||||
|
||||
"#cooling-cells":
|
||||
const: 2
|
||||
|
||||
dynamic-power-coefficient:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
A u32 value that represents the running time dynamic
|
||||
power coefficient in units of uW/MHz/V^2. The
|
||||
coefficient can either be calculated from power
|
||||
measurements or derived by analysis.
|
||||
|
||||
The dynamic power consumption of the GPU is
|
||||
proportional to the square of the Voltage (V) and
|
||||
the clock frequency (f). The coefficient is used to
|
||||
calculate the dynamic power as below -
|
||||
|
||||
Pdyn = dynamic-power-coefficient * V^2 * f
|
||||
|
||||
where voltage is in V, frequency is in MHz.
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- clocks
|
||||
- mali-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3588-mali
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
power-domain-names: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/rk3588-power.h>
|
||||
|
||||
gpu: gpu@fb000000 {
|
||||
compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf";
|
||||
reg = <0xfb000000 0x200000>;
|
||||
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||
<GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||
<GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
interrupt-names = "job", "mmu", "gpu";
|
||||
clock-names = "core", "coregroup", "stacks";
|
||||
clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>,
|
||||
<&cru CLK_GPU_STACKS>;
|
||||
power-domains = <&power RK3588_PD_GPU>;
|
||||
operating-points-v2 = <&gpu_opp_table>;
|
||||
mali-supply = <&vdd_gpu_s0>;
|
||||
sram-supply = <&vdd_gpu_mem_s0>;
|
||||
|
||||
gpu_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
opp-microvolt = <675000 675000 850000>;
|
||||
};
|
||||
opp-400000000 {
|
||||
opp-hz = /bits/ 64 <400000000>;
|
||||
opp-microvolt = <675000 675000 850000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -258,6 +258,8 @@ patternProperties:
|
|||
description: Catalyst Semiconductor, Inc.
|
||||
"^cavium,.*":
|
||||
description: Cavium, Inc.
|
||||
"^cct,.*":
|
||||
description: Crystal Clear Technology Sdn. Bhd.
|
||||
"^cdns,.*":
|
||||
description: Cadence Design Systems Inc.
|
||||
"^cdtech,.*":
|
||||
|
|
@ -533,6 +535,8 @@ patternProperties:
|
|||
description: FX Technology Ltd.
|
||||
"^galaxycore,.*":
|
||||
description: GalaxyCore Inc.
|
||||
"^gameforce,.*":
|
||||
description: GameForce
|
||||
"^gardena,.*":
|
||||
description: GARDENA GmbH
|
||||
"^gateway,.*":
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ consider though:
|
|||
the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other
|
||||
llseek operation will report -EINVAL.
|
||||
|
||||
If llseek on dma-buf FDs isn't support the kernel will report -ESPIPE for all
|
||||
If llseek on dma-buf FDs isn't supported the kernel will report -ESPIPE for all
|
||||
cases. Userspace can use this to detect support for discovering the dma-buf
|
||||
size using llseek.
|
||||
|
||||
|
|
|
|||
80
Documentation/gpu/amdgpu/debugging.rst
Normal file
80
Documentation/gpu/amdgpu/debugging.rst
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
===============
|
||||
GPU Debugging
|
||||
===============
|
||||
|
||||
GPUVM Debugging
|
||||
===============
|
||||
|
||||
To aid in debugging GPU virtual memory related problems, the driver supports a
|
||||
number of options module parameters:
|
||||
|
||||
`vm_fault_stop` - If non-0, halt the GPU memory controller on a GPU page fault.
|
||||
|
||||
`vm_update_mode` - If non-0, use the CPU to update GPU page tables rather than
|
||||
the GPU.
|
||||
|
||||
|
||||
Decoding a GPUVM Page Fault
|
||||
===========================
|
||||
|
||||
If you see a GPU page fault in the kernel log, you can decode it to figure
|
||||
out what is going wrong in your application. A page fault in your kernel
|
||||
log may look something like this:
|
||||
|
||||
::
|
||||
|
||||
[gfxhub0] no-retry page fault (src_id:0 ring:24 vmid:3 pasid:32777, for process glxinfo pid 2424 thread glxinfo:cs0 pid 2425)
|
||||
in page starting at address 0x0000800102800000 from IH client 0x1b (UTCL2)
|
||||
VM_L2_PROTECTION_FAULT_STATUS:0x00301030
|
||||
Faulty UTCL2 client ID: TCP (0x8)
|
||||
MORE_FAULTS: 0x0
|
||||
WALKER_ERROR: 0x0
|
||||
PERMISSION_FAULTS: 0x3
|
||||
MAPPING_ERROR: 0x0
|
||||
RW: 0x0
|
||||
|
||||
First you have the memory hub, gfxhub and mmhub. gfxhub is the memory
|
||||
hub used for graphics, compute, and sdma on some chips. mmhub is the
|
||||
memory hub used for multi-media and sdma on some chips.
|
||||
|
||||
Next you have the vmid and pasid. If the vmid is 0, this fault was likely
|
||||
caused by the kernel driver or firmware. If the vmid is non-0, it is generally
|
||||
a fault in a user application. The pasid is used to link a vmid to a system
|
||||
process id. If the process is active when the fault happens, the process
|
||||
information will be printed.
|
||||
|
||||
The GPU virtual address that caused the fault comes next.
|
||||
|
||||
The client ID indicates the GPU block that caused the fault.
|
||||
Some common client IDs:
|
||||
|
||||
- CB/DB: The color/depth backend of the graphics pipe
|
||||
- CPF: Command Processor Frontend
|
||||
- CPC: Command Processor Compute
|
||||
- CPG: Command Processor Graphics
|
||||
- TCP/SQC/SQG: Shaders
|
||||
- SDMA: SDMA engines
|
||||
- VCN: Video encode/decode engines
|
||||
- JPEG: JPEG engines
|
||||
|
||||
PERMISSION_FAULTS describe what faults were encountered:
|
||||
|
||||
- bit 0: the PTE was not valid
|
||||
- bit 1: the PTE read bit was not set
|
||||
- bit 2: the PTE write bit was not set
|
||||
- bit 3: the PTE execute bit was not set
|
||||
|
||||
Finally, RW, indicates whether the access was a read (0) or a write (1).
|
||||
|
||||
In the example above, a shader (cliend id = TCP) generated a read (RW = 0x0) to
|
||||
an invalid page (PERMISSION_FAULTS = 0x3) at GPU virtual address
|
||||
0x0000800102800000. The user can then inspect their shader code and resource
|
||||
descriptor state to determine what caused the GPU page fault.
|
||||
|
||||
UMR
|
||||
===
|
||||
|
||||
`umr <https://gitlab.freedesktop.org/tomstdenis/umr>`_ is a general purpose
|
||||
GPU debugging and diagnostics tool. Please see the umr
|
||||
`documentation <https://umr.readthedocs.io/en/main/>`_ for more information
|
||||
about its capabilities.
|
||||
|
|
@ -135,7 +135,7 @@ Enable underlay
|
|||
---------------
|
||||
|
||||
AMD display has this feature called underlay (which you can read more about at
|
||||
'Documentation/GPU/amdgpu/display/mpo-overview.rst') which is intended to
|
||||
'Documentation/gpu/amdgpu/display/mpo-overview.rst') which is intended to
|
||||
save power when playing a video. The basic idea is to put a video in the
|
||||
underlay plane at the bottom and the desktop in the plane above it with a hole
|
||||
in the video area. This feature is enabled in ChromeOS, and from our data
|
||||
|
|
|
|||
|
|
@ -15,4 +15,5 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
|
|||
ras
|
||||
thermal
|
||||
driver-misc
|
||||
debugging
|
||||
amdgpu-glossary
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ VM_BIND / EXEC uAPI
|
|||
|
||||
.. kernel-doc:: include/uapi/drm/nouveau_drm.h
|
||||
|
||||
drm/panthor uAPI
|
||||
================
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/panthor_drm.h
|
||||
|
||||
drm/xe uAPI
|
||||
===========
|
||||
|
||||
|
|
|
|||
|
|
@ -398,6 +398,21 @@ Plane Damage Tracking Functions Reference
|
|||
.. kernel-doc:: include/drm/drm_damage_helper.h
|
||||
:internal:
|
||||
|
||||
Plane Panic Feature
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panic.c
|
||||
:doc: overview
|
||||
|
||||
Plane Panic Functions Reference
|
||||
-------------------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_panic.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panic.c
|
||||
:export:
|
||||
|
||||
Display Modes Function Reference
|
||||
================================
|
||||
|
||||
|
|
@ -496,6 +511,13 @@ addition to the one mentioned above:
|
|||
|
||||
* An IGT test must be submitted where reasonable.
|
||||
|
||||
For historical reasons, non-standard, driver-specific properties exist. If a KMS
|
||||
driver wants to add support for one of those properties, the requirements for
|
||||
new properties apply where possible. Additionally, the documented behavior must
|
||||
match the de facto semantics of the existing property to ensure compatibility.
|
||||
Developers of the driver that first added the property should help with those
|
||||
tasks and must ACK the documented behavior if possible.
|
||||
|
||||
Property Types and Blob Property Support
|
||||
----------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -204,6 +204,15 @@ DMC Firmware Support
|
|||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc.c
|
||||
:internal:
|
||||
|
||||
DMC wakelock support
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc_wl.c
|
||||
:doc: DMC wakelock support
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc_wl.c
|
||||
:internal:
|
||||
|
||||
Video BIOS Table (VBT)
|
||||
----------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -38,3 +38,12 @@ the currently possible format options:
|
|||
|
||||
Possible `drm-engine-` key names are: `fragment`, and `vertex-tiler`.
|
||||
`drm-curfreq-` values convey the current operating frequency for that engine.
|
||||
|
||||
Users must bear in mind that engine and cycle sampling are disabled by default,
|
||||
because of power saving concerns. `fdinfo` users and benchmark applications which
|
||||
query the fdinfo file must make sure to toggle the job profiling status of the
|
||||
driver by writing into the appropriate sysfs node::
|
||||
|
||||
echo <N> > /sys/bus/platform/drivers/panfrost/[a-f0-9]*.gpu/profiling
|
||||
|
||||
Where `N` is either `0` or `1`, depending on the desired enablement status.
|
||||
|
|
|
|||
|
|
@ -93,12 +93,11 @@ struct drm_i915_gem_timeline_fence {
|
|||
* Multiple VA mappings can be created to the same section of the object
|
||||
* (aliasing).
|
||||
*
|
||||
* The @start, @offset and @length must be 4K page aligned. However the DG2
|
||||
* and XEHPSDV has 64K page size for device local memory and has compact page
|
||||
* table. On those platforms, for binding device local-memory objects, the
|
||||
* @start, @offset and @length must be 64K aligned. Also, UMDs should not mix
|
||||
* the local memory 64K page and the system memory 4K page bindings in the same
|
||||
* 2M range.
|
||||
* The @start, @offset and @length must be 4K page aligned. However the DG2 has
|
||||
* 64K page size for device local memory and has compact page table. On that
|
||||
* platform, for binding device local-memory objects, the @start, @offset and
|
||||
* @length must be 64K aligned. Also, UMDs should not mix the local memory 64K
|
||||
* page and the system memory 4K page bindings in the same 2M range.
|
||||
*
|
||||
* Error code -EINVAL will be returned if @start, @offset and @length are not
|
||||
* properly aligned. In version 1 (See I915_PARAM_VM_BIND_VERSION), error code
|
||||
|
|
|
|||
220
MAINTAINERS
220
MAINTAINERS
|
|
@ -1690,7 +1690,7 @@ F: drivers/soc/versatile/
|
|||
ARM KOMEDA DRM-KMS DRIVER
|
||||
M: Liviu Dudau <liviu.dudau@arm.com>
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/arm,komeda.yaml
|
||||
F: Documentation/gpu/komeda-kms.rst
|
||||
F: drivers/gpu/drm/arm/display/include/
|
||||
|
|
@ -1702,15 +1702,26 @@ M: Rob Herring <robh@kernel.org>
|
|||
R: Steven Price <steven.price@arm.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/gpu/panfrost.rst
|
||||
F: drivers/gpu/drm/panfrost/
|
||||
F: include/uapi/drm/panfrost_drm.h
|
||||
|
||||
ARM MALI PANTHOR DRM DRIVER
|
||||
M: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
M: Steven Price <steven.price@arm.com>
|
||||
M: Liviu Dudau <liviu.dudau@arm.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
|
||||
F: drivers/gpu/drm/panthor/
|
||||
F: include/uapi/drm/panthor_drm.h
|
||||
|
||||
ARM MALI-DP DRM DRIVER
|
||||
M: Liviu Dudau <liviu.dudau@arm.com>
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/arm,malidp.yaml
|
||||
F: Documentation/gpu/afbc.rst
|
||||
F: drivers/gpu/drm/arm/
|
||||
|
|
@ -6373,7 +6384,7 @@ L: linux-media@vger.kernel.org
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/driver-api/dma-buf.rst
|
||||
F: Documentation/userspace-api/dma-buf-alloc-exchange.rst
|
||||
F: drivers/dma-buf/
|
||||
|
|
@ -6427,7 +6438,7 @@ L: linux-media@vger.kernel.org
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/dma-buf/dma-heap.c
|
||||
F: drivers/dma-buf/heaps/*
|
||||
F: include/linux/dma-heap.h
|
||||
|
|
@ -6637,7 +6648,7 @@ M: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
|
|||
M: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/accel/ivpu/
|
||||
F: include/uapi/drm/ivpu_accel.h
|
||||
|
||||
|
|
@ -6657,18 +6668,18 @@ M: Chen-Yu Tsai <wens@csie.org>
|
|||
R: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/sun4i/sun8i*
|
||||
|
||||
DRM DRIVER FOR ARM PL111 CLCD
|
||||
S: Orphan
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/pl111/
|
||||
|
||||
DRM DRIVER FOR ARM VERSATILE TFT PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml
|
||||
F: drivers/gpu/drm/panel/panel-arm-versatile.c
|
||||
|
||||
|
|
@ -6676,7 +6687,7 @@ DRM DRIVER FOR ASPEED BMC GFX
|
|||
M: Joel Stanley <joel@jms.id.au>
|
||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/gpu/aspeed-gfx.txt
|
||||
F: drivers/gpu/drm/aspeed/
|
||||
|
||||
|
|
@ -6686,14 +6697,14 @@ R: Thomas Zimmermann <tzimmermann@suse.de>
|
|||
R: Jocelyn Falempe <jfalempe@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/ast/
|
||||
|
||||
DRM DRIVER FOR BOCHS VIRTUAL GPU
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
L: virtualization@lists.linux.dev
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/tiny/bochs.c
|
||||
|
||||
DRM DRIVER FOR BOE HIMAX8279D PANELS
|
||||
|
|
@ -6711,14 +6722,14 @@ F: drivers/gpu/drm/bridge/chipone-icn6211.c
|
|||
DRM DRIVER FOR EBBG FT8719 PANEL
|
||||
M: Joel Selvaraj <jo@jsfamily.in>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/ebbg,ft8719.yaml
|
||||
F: drivers/gpu/drm/panel/panel-ebbg-ft8719.c
|
||||
|
||||
DRM DRIVER FOR FARADAY TVE200 TV ENCODER
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/tve200/
|
||||
|
||||
DRM DRIVER FOR FEIXIN K101 IM2BA02 MIPI-DSI LCD PANELS
|
||||
|
|
@ -6738,7 +6749,7 @@ M: Thomas Zimmermann <tzimmermann@suse.de>
|
|||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/drm_aperture.c
|
||||
F: drivers/gpu/drm/tiny/ofdrm.c
|
||||
F: drivers/gpu/drm/tiny/simpledrm.c
|
||||
|
|
@ -6757,27 +6768,27 @@ DRM DRIVER FOR GENERIC USB DISPLAY
|
|||
M: Noralf Trønnes <noralf@tronnes.org>
|
||||
S: Maintained
|
||||
W: https://github.com/notro/gud/wiki
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/gud/
|
||||
F: include/drm/gud.h
|
||||
|
||||
DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/tiny/gm12u320.c
|
||||
|
||||
DRM DRIVER FOR HIMAX HX8394 MIPI-DSI LCD panels
|
||||
M: Ondrej Jirman <megi@xff.cz>
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
|
||||
F: drivers/gpu/drm/panel/panel-himax-hx8394.c
|
||||
|
||||
DRM DRIVER FOR HX8357D PANELS
|
||||
S: Orphan
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/himax,hx8357d.txt
|
||||
F: drivers/gpu/drm/tiny/hx8357d.c
|
||||
|
||||
|
|
@ -6786,20 +6797,20 @@ M: Deepak Rawat <drawat.floss@gmail.com>
|
|||
L: linux-hyperv@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/hyperv
|
||||
|
||||
DRM DRIVER FOR ILITEK ILI9225 PANELS
|
||||
M: David Lechner <david@lechnology.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/ilitek,ili9225.txt
|
||||
F: drivers/gpu/drm/tiny/ili9225.c
|
||||
|
||||
DRM DRIVER FOR ILITEK ILI9486 PANELS
|
||||
M: Kamlesh Gurudasani <kamlesh.gurudasani@gmail.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/ilitek,ili9486.yaml
|
||||
F: drivers/gpu/drm/tiny/ili9486.c
|
||||
|
||||
|
|
@ -6815,17 +6826,25 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
|
||||
F: drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
|
||||
|
||||
DRM DRIVER FOR LG SW43408 PANELS
|
||||
M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
M: Caleb Connolly <caleb.connolly@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
|
||||
F: drivers/gpu/drm/panel/panel-lg-sw43408.c
|
||||
|
||||
DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER
|
||||
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/logicvc/
|
||||
|
||||
DRM DRIVER FOR LVDS PANELS
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/lvds.yaml
|
||||
F: Documentation/devicetree/bindings/display/panel/panel-lvds.yaml
|
||||
F: drivers/gpu/drm/panel/panel-lvds.c
|
||||
|
|
@ -6843,13 +6862,13 @@ R: Thomas Zimmermann <tzimmermann@suse.de>
|
|||
R: Jocelyn Falempe <jfalempe@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/mgag200/
|
||||
|
||||
DRM DRIVER FOR MI0283QT
|
||||
M: Noralf Trønnes <noralf@tronnes.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
|
||||
F: drivers/gpu/drm/tiny/mi0283qt.c
|
||||
|
||||
|
|
@ -6857,11 +6876,29 @@ DRM DRIVER FOR MIPI DBI compatible panels
|
|||
M: Noralf Trønnes <noralf@tronnes.org>
|
||||
S: Maintained
|
||||
W: https://github.com/notro/panel-mipi-dbi/wiki
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml
|
||||
F: drivers/gpu/drm/tiny/panel-mipi-dbi.c
|
||||
|
||||
DRM DRIVER FOR MSM ADRENO GPU
|
||||
DRM DRIVER for Qualcomm Adreno GPUs
|
||||
M: Rob Clark <robdclark@gmail.com>
|
||||
R: Sean Paul <sean@poorly.run>
|
||||
R: Konrad Dybcio <konrad.dybcio@linaro.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: freedreno@lists.freedesktop.org
|
||||
S: Maintained
|
||||
B: https://gitlab.freedesktop.org/drm/msm/-/issues
|
||||
T: git https://gitlab.freedesktop.org/drm/msm.git
|
||||
F: Documentation/devicetree/bindings/display/msm/gpu.yaml
|
||||
F: drivers/gpu/drm/msm/adreno/
|
||||
F: drivers/gpu/drm/msm/msm_gpu.*
|
||||
F: drivers/gpu/drm/msm/msm_gpu_devfreq.*
|
||||
F: drivers/gpu/drm/msm/msm_ringbuffer.*
|
||||
F: drivers/gpu/drm/msm/registers/adreno/
|
||||
F: include/uapi/drm/msm_drm.h
|
||||
|
||||
DRM DRIVER for Qualcomm display hardware
|
||||
M: Rob Clark <robdclark@gmail.com>
|
||||
M: Abhinav Kumar <quic_abhinavk@quicinc.com>
|
||||
M: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||
|
|
@ -6881,28 +6918,28 @@ F: include/uapi/drm/msm_drm.h
|
|||
DRM DRIVER FOR NOVATEK NT35510 PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt35510.c
|
||||
|
||||
DRM DRIVER FOR NOVATEK NT35560 PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt35560.c
|
||||
|
||||
DRM DRIVER FOR NOVATEK NT36523 PANELS
|
||||
M: Jianhua Lu <lujianhua000@gmail.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt36523.c
|
||||
|
||||
DRM DRIVER FOR NOVATEK NT36672A PANELS
|
||||
M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
|
||||
F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
|
||||
|
||||
|
|
@ -6936,7 +6973,7 @@ F: drivers/gpu/drm/bridge/parade-ps8640.c
|
|||
DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS
|
||||
M: Noralf Trønnes <noralf@tronnes.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/repaper.txt
|
||||
F: drivers/gpu/drm/tiny/repaper.c
|
||||
|
||||
|
|
@ -6946,7 +6983,7 @@ M: Gerd Hoffmann <kraxel@redhat.com>
|
|||
L: virtualization@lists.linux.dev
|
||||
S: Obsolete
|
||||
W: https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/tiny/cirrus.c
|
||||
|
||||
DRM DRIVER FOR QXL VIRTUAL GPU
|
||||
|
|
@ -6955,7 +6992,7 @@ M: Gerd Hoffmann <kraxel@redhat.com>
|
|||
L: virtualization@lists.linux.dev
|
||||
L: spice-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/qxl/
|
||||
F: include/uapi/drm/qxl_drm.h
|
||||
|
||||
|
|
@ -6968,7 +7005,7 @@ F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
|
|||
DRM DRIVER FOR SAMSUNG DB7430 PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
|
||||
F: drivers/gpu/drm/panel/panel-samsung-db7430.c
|
||||
|
||||
|
|
@ -6977,7 +7014,7 @@ M: Inki Dae <inki.dae@samsung.com>
|
|||
M: Jagan Teki <jagan@amarulasolutions.com>
|
||||
M: Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
|
||||
F: drivers/gpu/drm/bridge/samsung-dsim.c
|
||||
F: include/drm/bridge/samsung-dsim.h
|
||||
|
|
@ -6997,7 +7034,7 @@ F: drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
|
|||
DRM DRIVER FOR SITRONIX ST7586 PANELS
|
||||
M: David Lechner <david@lechnology.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/sitronix,st7586.txt
|
||||
F: drivers/gpu/drm/tiny/st7586.c
|
||||
|
||||
|
|
@ -7018,14 +7055,14 @@ F: drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
|||
DRM DRIVER FOR SITRONIX ST7735R PANELS
|
||||
M: David Lechner <david@lechnology.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/sitronix,st7735r.yaml
|
||||
F: drivers/gpu/drm/tiny/st7735r.c
|
||||
|
||||
DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/solomon,ssd-common.yaml
|
||||
F: Documentation/devicetree/bindings/display/solomon,ssd13*.yaml
|
||||
F: drivers/gpu/drm/solomon/ssd130x*
|
||||
|
|
@ -7033,7 +7070,7 @@ F: drivers/gpu/drm/solomon/ssd130x*
|
|||
DRM DRIVER FOR ST-ERICSSON MCDE
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/ste,mcde.yaml
|
||||
F: drivers/gpu/drm/mcde/
|
||||
|
||||
|
|
@ -7057,7 +7094,7 @@ F: drivers/gpu/drm/bridge/ti-sn65dsi86.c
|
|||
DRM DRIVER FOR TPO TPG110 PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
|
||||
F: drivers/gpu/drm/panel/panel-tpo-tpg110.c
|
||||
|
||||
|
|
@ -7067,7 +7104,7 @@ R: Sean Paul <sean@poorly.run>
|
|||
R: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/udl/
|
||||
|
||||
DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
|
||||
|
|
@ -7078,7 +7115,7 @@ R: Haneen Mohammed <hamohammed.sa@gmail.com>
|
|||
R: Daniel Vetter <daniel@ffwll.ch>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/gpu/vkms.rst
|
||||
F: drivers/gpu/drm/vkms/
|
||||
|
||||
|
|
@ -7086,7 +7123,7 @@ DRM DRIVER FOR VIRTUALBOX VIRTUAL GPU
|
|||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/vboxvideo/
|
||||
|
||||
DRM DRIVER FOR VMWARE VIRTUAL GPU
|
||||
|
|
@ -7094,14 +7131,14 @@ M: Zack Rusin <zack.rusin@broadcom.com>
|
|||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/vmwgfx/
|
||||
F: include/uapi/drm/vmwgfx_drm.h
|
||||
|
||||
DRM DRIVER FOR WIDECHIPS WS2401 PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
|
||||
F: drivers/gpu/drm/panel/panel-widechips-ws2401.c
|
||||
|
||||
|
|
@ -7126,8 +7163,8 @@ M: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
|
|||
M: Maxime Ripard <mripard@kernel.org>
|
||||
M: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
S: Maintained
|
||||
W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
W: https://drm.pages.freedesktop.org/maintainer-tools/drm-misc.html
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/
|
||||
F: Documentation/devicetree/bindings/gpu/
|
||||
F: Documentation/gpu/
|
||||
|
|
@ -7154,7 +7191,7 @@ M: Maxime Ripard <mripard@kernel.org>
|
|||
M: Chen-Yu Tsai <wens@csie.org>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/allwinner*
|
||||
F: drivers/gpu/drm/sun4i/
|
||||
|
||||
|
|
@ -7164,7 +7201,7 @@ L: dri-devel@lists.freedesktop.org
|
|||
L: linux-amlogic@lists.infradead.org
|
||||
S: Supported
|
||||
W: http://linux-meson.com/
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
|
||||
F: Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
|
||||
F: Documentation/gpu/meson.rst
|
||||
|
|
@ -7176,7 +7213,7 @@ M: Sam Ravnborg <sam@ravnborg.org>
|
|||
M: Boris Brezillon <bbrezillon@kernel.org>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/atmel/
|
||||
F: drivers/gpu/drm/atmel-hlcdc/
|
||||
|
||||
|
|
@ -7188,7 +7225,7 @@ R: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
|||
R: Jonas Karlman <jonas@kwiboo.se>
|
||||
R: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/bridge/
|
||||
F: drivers/gpu/drm/bridge/
|
||||
F: drivers/gpu/drm/drm_bridge.c
|
||||
|
|
@ -7213,7 +7250,7 @@ M: Stefan Agner <stefan@agner.ch>
|
|||
M: Alison Wang <alison.wang@nxp.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/fsl,dcu.txt
|
||||
F: Documentation/devicetree/bindings/display/fsl,tcon.txt
|
||||
F: drivers/gpu/drm/fsl-dcu/
|
||||
|
|
@ -7222,7 +7259,7 @@ DRM DRIVERS FOR FREESCALE IMX 5/6
|
|||
M: Philipp Zabel <p.zabel@pengutronix.de>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
T: git git://git.pengutronix.de/git/pza/linux
|
||||
F: Documentation/devicetree/bindings/display/imx/
|
||||
F: drivers/gpu/drm/imx/ipuv3/
|
||||
|
|
@ -7242,7 +7279,7 @@ DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
|
|||
M: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/gma500/
|
||||
|
||||
DRM DRIVERS FOR HISILICON
|
||||
|
|
@ -7254,7 +7291,7 @@ R: Yongqin Liu <yongqin.liu@linaro.org>
|
|||
R: John Stultz <jstultz@google.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/hisilicon/
|
||||
F: drivers/gpu/drm/hisilicon/
|
||||
|
||||
|
|
@ -7263,7 +7300,7 @@ M: Qiang Yu <yuq825@gmail.com>
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: lima@lists.freedesktop.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/lima/
|
||||
F: include/uapi/drm/lima_drm.h
|
||||
|
||||
|
|
@ -7271,7 +7308,7 @@ DRM DRIVERS FOR LOONGSON
|
|||
M: Sui Jingfeng <suijingfeng@loongson.cn>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/loongson/
|
||||
|
||||
DRM DRIVERS FOR MEDIATEK
|
||||
|
|
@ -7319,7 +7356,7 @@ M: Biju Das <biju.das.jz@bp.renesas.com>
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/renesas,rzg2l-du.yaml
|
||||
F: drivers/gpu/drm/renesas/rz-du/
|
||||
|
||||
|
|
@ -7329,7 +7366,7 @@ M: Geert Uytterhoeven <geert+renesas@glider.be>
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml
|
||||
F: drivers/gpu/drm/renesas/shmobile/
|
||||
F: include/linux/platform_data/shmob_drm.h
|
||||
|
|
@ -7340,7 +7377,7 @@ M: Heiko Stübner <heiko@sntech.de>
|
|||
M: Andy Yan <andy.yan@rock-chips.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/rockchip/
|
||||
F: drivers/gpu/drm/ci/xfails/rockchip*
|
||||
F: drivers/gpu/drm/rockchip/
|
||||
|
|
@ -7349,7 +7386,7 @@ DRM DRIVERS FOR STI
|
|||
M: Alain Volmat <alain.volmat@foss.st.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/st,stih4xx.txt
|
||||
F: drivers/gpu/drm/sti
|
||||
|
||||
|
|
@ -7359,7 +7396,7 @@ M: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
|
|||
M: Philippe Cornu <philippe.cornu@foss.st.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
|
||||
F: drivers/gpu/drm/stm
|
||||
|
||||
|
|
@ -7368,7 +7405,7 @@ M: Jyri Sarha <jyri.sarha@iki.fi>
|
|||
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
|
||||
F: Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml
|
||||
F: Documentation/devicetree/bindings/display/ti/ti,k2g-dss.yaml
|
||||
|
|
@ -7379,7 +7416,7 @@ M: Jyri Sarha <jyri.sarha@iki.fi>
|
|||
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/tilcdc/
|
||||
F: drivers/gpu/drm/tilcdc/
|
||||
|
||||
|
|
@ -7387,7 +7424,7 @@ DRM DRIVERS FOR TI OMAP
|
|||
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/ti/
|
||||
F: drivers/gpu/drm/omapdrm/
|
||||
|
||||
|
|
@ -7395,7 +7432,7 @@ DRM DRIVERS FOR V3D
|
|||
M: Melissa Wen <mwen@igalia.com>
|
||||
M: Maíra Canal <mcanal@igalia.com>
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml
|
||||
F: drivers/gpu/drm/v3d/
|
||||
F: include/uapi/drm/v3d_drm.h
|
||||
|
|
@ -7404,7 +7441,7 @@ DRM DRIVERS FOR VC4
|
|||
M: Maxime Ripard <mripard@kernel.org>
|
||||
S: Supported
|
||||
T: git git://github.com/anholt/linux
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/brcm,bcm2835-*.yaml
|
||||
F: drivers/gpu/drm/vc4/
|
||||
F: include/uapi/drm/vc4_drm.h
|
||||
|
|
@ -7425,15 +7462,16 @@ M: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/gpu/xen-front.rst
|
||||
F: drivers/gpu/drm/xen/
|
||||
|
||||
DRM DRIVERS FOR XILINX
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/xlnx/
|
||||
F: drivers/gpu/drm/xlnx/
|
||||
|
||||
|
|
@ -7442,7 +7480,7 @@ M: Luben Tuikov <ltuikov89@gmail.com>
|
|||
M: Matthew Brost <matthew.brost@intel.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/scheduler/
|
||||
F: include/drm/gpu_scheduler.h
|
||||
|
||||
|
|
@ -7452,7 +7490,7 @@ R: Jessica Zhang <quic_jesszhan@quicinc.com>
|
|||
R: Sam Ravnborg <sam@ravnborg.org>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/panel/
|
||||
F: drivers/gpu/drm/drm_panel.c
|
||||
F: drivers/gpu/drm/panel/
|
||||
|
|
@ -7462,7 +7500,7 @@ 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
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/drm_privacy_screen*
|
||||
F: include/drm/drm_privacy_screen*
|
||||
|
||||
|
|
@ -7471,7 +7509,7 @@ M: Christian Koenig <christian.koenig@amd.com>
|
|||
M: Huang Rui <ray.huang@amd.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/ttm/
|
||||
F: include/drm/ttm/
|
||||
|
||||
|
|
@ -7479,7 +7517,7 @@ DRM AUTOMATED TESTING
|
|||
M: Helen Koike <helen.koike@collabora.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/gpu/automated_testing.rst
|
||||
F: drivers/gpu/drm/ci/
|
||||
|
||||
|
|
@ -8542,7 +8580,7 @@ F: arch/x86/math-emu/
|
|||
FRAMEBUFFER CORE
|
||||
M: Daniel Vetter <daniel@ffwll.ch>
|
||||
S: Odd Fixes
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/video/fbdev/core/
|
||||
|
||||
FRAMEBUFFER LAYER
|
||||
|
|
@ -10644,7 +10682,7 @@ IMGTEC POWERVR DRM DRIVER
|
|||
M: Frank Binns <frank.binns@imgtec.com>
|
||||
M: Matt Coster <matt.coster@imgtec.com>
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
|
||||
F: Documentation/devicetree/bindings/gpu/img,powervr-sgx.yaml
|
||||
F: Documentation/gpu/imagination/
|
||||
|
|
@ -11426,7 +11464,7 @@ IOSYS-MAP HELPERS
|
|||
M: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: include/linux/iosys-map.h
|
||||
|
||||
IO_URING
|
||||
|
|
@ -11625,7 +11663,7 @@ ITE IT66121 HDMI BRIDGE DRIVER
|
|||
M: Phong LE <ple@baylibre.com>
|
||||
M: Neil Armstrong <neil.armstrong@linaro.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml
|
||||
F: drivers/gpu/drm/bridge/ite-it66121.c
|
||||
|
||||
|
|
@ -14661,6 +14699,14 @@ S: Supported
|
|||
F: Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml
|
||||
F: drivers/pwm/pwm-atmel.c
|
||||
|
||||
MICROCHIP SAM9x7-COMPATIBLE LVDS CONTROLLER
|
||||
M: Manikandan Muralidharan <manikandan.m@microchip.com>
|
||||
M: Dharma Balasubiramani <dharma.b@microchip.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.yaml
|
||||
F: drivers/gpu/drm/bridge/microchip-lvds.c
|
||||
|
||||
MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER
|
||||
M: Eugen Hristev <eugen.hristev@microchip.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
|
@ -15248,7 +15294,7 @@ M: Marek Vasut <marex@denx.de>
|
|||
M: Stefan Agner <stefan@agner.ch>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/fsl,lcdif.yaml
|
||||
F: drivers/gpu/drm/mxsfb/
|
||||
|
||||
|
|
@ -15969,7 +16015,7 @@ M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
|
|||
R: Lucas Stach <l.stach@pengutronix.de>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml
|
||||
F: drivers/gpu/drm/imx/dcss/
|
||||
|
||||
|
|
@ -18272,7 +18318,7 @@ R: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com>
|
|||
L: linux-arm-msm@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/accel/qaic/
|
||||
F: drivers/accel/qaic/
|
||||
F: include/uapi/drm/qaic_accel.h
|
||||
|
|
@ -21454,7 +21500,7 @@ R: Gustavo Padovan <gustavo@padovan.org>
|
|||
L: linux-media@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/driver-api/sync_file.rst
|
||||
F: drivers/dma-buf/dma-fence*
|
||||
F: drivers/dma-buf/sw_sync.c
|
||||
|
|
@ -23256,7 +23302,7 @@ USERSPACE DMA BUFFER DRIVER
|
|||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/dma-buf/udmabuf.c
|
||||
F: include/uapi/linux/udmabuf.h
|
||||
|
||||
|
|
@ -23438,7 +23484,7 @@ F: drivers/vfio/pci/virtio
|
|||
VGA_SWITCHEROO
|
||||
R: Lukas Wunner <lukas@wunner.de>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/gpu/vga-switcheroo.rst
|
||||
F: drivers/gpu/vga/vga_switcheroo.c
|
||||
F: include/linux/vga_switcheroo.h
|
||||
|
|
@ -23632,7 +23678,7 @@ R: Chia-I Wu <olvaffe@gmail.com>
|
|||
L: dri-devel@lists.freedesktop.org
|
||||
L: virtualization@lists.linux.dev
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: drivers/gpu/drm/ci/xfails/virtio*
|
||||
F: drivers/gpu/drm/virtio/
|
||||
F: include/uapi/linux/virtio_gpu.h
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef __M68K_PGTABLE_H
|
||||
#define __M68K_PGTABLE_H
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#ifdef __uClinux__
|
||||
#include <asm/pgtable_no.h>
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ CONFIG_PPDEV=m
|
|||
CONFIG_I2C=y
|
||||
CONFIG_HWMON=m
|
||||
CONFIG_DRM=m
|
||||
CONFIG_DRM_DP_CEC=y
|
||||
CONFIG_DRM_DISPLAY_DP_AUX_CEC=y
|
||||
# CONFIG_DRM_I2C_CH7006 is not set
|
||||
# CONFIG_DRM_I2C_SIL164 is not set
|
||||
CONFIG_DRM_RADEON=m
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
|
|
|||
|
|
@ -10,4 +10,7 @@ qaic-y := \
|
|||
qaic_control.o \
|
||||
qaic_data.o \
|
||||
qaic_drv.o \
|
||||
qaic_timesync.o
|
||||
qaic_timesync.o \
|
||||
sahara.o
|
||||
|
||||
qaic-$(CONFIG_DEBUG_FS) += qaic_debugfs.o
|
||||
|
|
|
|||
|
|
@ -153,6 +153,14 @@ struct qaic_device {
|
|||
struct mhi_device *qts_ch;
|
||||
/* Work queue for tasks related to MHI "QAIC_TIMESYNC" channel */
|
||||
struct workqueue_struct *qts_wq;
|
||||
/* Head of list of page allocated by MHI bootlog device */
|
||||
struct list_head bootlog;
|
||||
/* MHI bootlog channel device */
|
||||
struct mhi_device *bootlog_ch;
|
||||
/* Work queue for tasks related to MHI bootlog device */
|
||||
struct workqueue_struct *bootlog_wq;
|
||||
/* Synchronizes access of pages in MHI bootlog device */
|
||||
struct mutex bootlog_mutex;
|
||||
};
|
||||
|
||||
struct qaic_drm_device {
|
||||
|
|
@ -280,6 +288,7 @@ int disable_dbc(struct qaic_device *qdev, u32 dbc_id, struct qaic_user *usr);
|
|||
void enable_dbc(struct qaic_device *qdev, u32 dbc_id, struct qaic_user *usr);
|
||||
void wakeup_dbc(struct qaic_device *qdev, u32 dbc_id);
|
||||
void release_dbc(struct qaic_device *qdev, u32 dbc_id);
|
||||
void qaic_data_get_fifo_info(struct dma_bridge_chan *dbc, u32 *head, u32 *tail);
|
||||
|
||||
void wake_all_cntl(struct qaic_device *qdev);
|
||||
void qaic_dev_reset_clean_local_state(struct qaic_device *qdev);
|
||||
|
|
|
|||
|
|
@ -1981,3 +1981,12 @@ void release_dbc(struct qaic_device *qdev, u32 dbc_id)
|
|||
dbc->in_use = false;
|
||||
wake_up(&dbc->dbc_release);
|
||||
}
|
||||
|
||||
void qaic_data_get_fifo_info(struct dma_bridge_chan *dbc, u32 *head, u32 *tail)
|
||||
{
|
||||
if (!dbc || !head || !tail)
|
||||
return;
|
||||
|
||||
*head = readl(dbc->dbc_base + REQHP_OFF);
|
||||
*tail = readl(dbc->dbc_base + REQTP_OFF);
|
||||
}
|
||||
|
|
|
|||
338
drivers/accel/qaic/qaic_debugfs.c
Normal file
338
drivers/accel/qaic/qaic_debugfs.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mhi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sprintf.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "qaic.h"
|
||||
#include "qaic_debugfs.h"
|
||||
|
||||
#define BOOTLOG_POOL_SIZE 16
|
||||
#define BOOTLOG_MSG_SIZE 512
|
||||
#define QAIC_DBC_DIR_NAME 9
|
||||
|
||||
struct bootlog_msg {
|
||||
/* Buffer for bootlog messages */
|
||||
char str[BOOTLOG_MSG_SIZE];
|
||||
/* Root struct of device, used to access device resources */
|
||||
struct qaic_device *qdev;
|
||||
/* Work struct to schedule work coming on QAIC_LOGGING channel */
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct bootlog_page {
|
||||
/* Node in list of bootlog pages maintained by root device struct */
|
||||
struct list_head node;
|
||||
/* Total size of the buffer that holds the bootlogs. It is PAGE_SIZE */
|
||||
unsigned int size;
|
||||
/* Offset for the next bootlog */
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
static int bootlog_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct bootlog_page *page;
|
||||
struct qaic_device *qdev;
|
||||
void *page_end;
|
||||
void *log;
|
||||
|
||||
qdev = s->private;
|
||||
mutex_lock(&qdev->bootlog_mutex);
|
||||
list_for_each_entry(page, &qdev->bootlog, node) {
|
||||
log = page + 1;
|
||||
page_end = (void *)page + page->offset;
|
||||
while (log < page_end) {
|
||||
seq_printf(s, "%s", (char *)log);
|
||||
log += strlen(log) + 1;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&qdev->bootlog_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bootlog_fops_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, bootlog_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations bootlog_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = bootlog_fops_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int read_dbc_fifo_size(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct dma_bridge_chan *dbc = s->private;
|
||||
|
||||
seq_printf(s, "%u\n", dbc->nelem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fifo_size_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, read_dbc_fifo_size, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fifo_size_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = fifo_size_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int read_dbc_queued(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct dma_bridge_chan *dbc = s->private;
|
||||
u32 tail = 0, head = 0;
|
||||
|
||||
qaic_data_get_fifo_info(dbc, &head, &tail);
|
||||
|
||||
if (head == U32_MAX || tail == U32_MAX)
|
||||
seq_printf(s, "%u\n", 0);
|
||||
else if (head > tail)
|
||||
seq_printf(s, "%u\n", dbc->nelem - head + tail);
|
||||
else
|
||||
seq_printf(s, "%u\n", tail - head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int queued_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, read_dbc_queued, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations queued_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = queued_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void qaic_debugfs_init(struct qaic_drm_device *qddev)
|
||||
{
|
||||
struct qaic_device *qdev = qddev->qdev;
|
||||
struct dentry *debugfs_root;
|
||||
struct dentry *debugfs_dir;
|
||||
char name[QAIC_DBC_DIR_NAME];
|
||||
u32 i;
|
||||
|
||||
debugfs_root = to_drm(qddev)->debugfs_root;
|
||||
|
||||
debugfs_create_file("bootlog", 0400, debugfs_root, qdev, &bootlog_fops);
|
||||
/*
|
||||
* 256 dbcs per device is likely the max we will ever see and lets static checking see a
|
||||
* reasonable range.
|
||||
*/
|
||||
for (i = 0; i < qdev->num_dbc && i < 256; ++i) {
|
||||
snprintf(name, QAIC_DBC_DIR_NAME, "dbc%03u", i);
|
||||
debugfs_dir = debugfs_create_dir(name, debugfs_root);
|
||||
debugfs_create_file("fifo_size", 0400, debugfs_dir, &qdev->dbc[i], &fifo_size_fops);
|
||||
debugfs_create_file("queued", 0400, debugfs_dir, &qdev->dbc[i], &queued_fops);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bootlog_page *alloc_bootlog_page(struct qaic_device *qdev)
|
||||
{
|
||||
struct bootlog_page *page;
|
||||
|
||||
page = (struct bootlog_page *)devm_get_free_pages(&qdev->pdev->dev, GFP_KERNEL, 0);
|
||||
if (!page)
|
||||
return page;
|
||||
|
||||
page->size = PAGE_SIZE;
|
||||
page->offset = sizeof(*page);
|
||||
list_add_tail(&page->node, &qdev->bootlog);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
static int reset_bootlog(struct qaic_device *qdev)
|
||||
{
|
||||
struct bootlog_page *page;
|
||||
struct bootlog_page *i;
|
||||
|
||||
mutex_lock(&qdev->bootlog_mutex);
|
||||
list_for_each_entry_safe(page, i, &qdev->bootlog, node) {
|
||||
list_del(&page->node);
|
||||
devm_free_pages(&qdev->pdev->dev, (unsigned long)page);
|
||||
}
|
||||
|
||||
page = alloc_bootlog_page(qdev);
|
||||
mutex_unlock(&qdev->bootlog_mutex);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *bootlog_get_space(struct qaic_device *qdev, unsigned int size)
|
||||
{
|
||||
struct bootlog_page *page;
|
||||
|
||||
page = list_last_entry(&qdev->bootlog, struct bootlog_page, node);
|
||||
|
||||
if (size_add(size, sizeof(*page)) > page->size)
|
||||
return NULL;
|
||||
|
||||
if (page->offset + size > page->size) {
|
||||
page = alloc_bootlog_page(qdev);
|
||||
if (!page)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)page + page->offset;
|
||||
}
|
||||
|
||||
static void bootlog_commit(struct qaic_device *qdev, unsigned int size)
|
||||
{
|
||||
struct bootlog_page *page;
|
||||
|
||||
page = list_last_entry(&qdev->bootlog, struct bootlog_page, node);
|
||||
|
||||
page->offset += size;
|
||||
}
|
||||
|
||||
static void bootlog_log(struct work_struct *work)
|
||||
{
|
||||
struct bootlog_msg *msg = container_of(work, struct bootlog_msg, work);
|
||||
unsigned int len = strlen(msg->str) + 1;
|
||||
struct qaic_device *qdev = msg->qdev;
|
||||
void *log;
|
||||
|
||||
mutex_lock(&qdev->bootlog_mutex);
|
||||
log = bootlog_get_space(qdev, len);
|
||||
if (log) {
|
||||
memcpy(log, msg, len);
|
||||
bootlog_commit(qdev, len);
|
||||
}
|
||||
mutex_unlock(&qdev->bootlog_mutex);
|
||||
|
||||
if (mhi_queue_buf(qdev->bootlog_ch, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT))
|
||||
devm_kfree(&qdev->pdev->dev, msg);
|
||||
}
|
||||
|
||||
static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
|
||||
{
|
||||
struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev));
|
||||
struct bootlog_msg *msg;
|
||||
int i, ret;
|
||||
|
||||
qdev->bootlog_wq = alloc_ordered_workqueue("qaic_bootlog", 0);
|
||||
if (!qdev->bootlog_wq) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = reset_bootlog(qdev);
|
||||
if (ret)
|
||||
goto destroy_workqueue;
|
||||
|
||||
ret = mhi_prepare_for_transfer(mhi_dev);
|
||||
if (ret)
|
||||
goto destroy_workqueue;
|
||||
|
||||
for (i = 0; i < BOOTLOG_POOL_SIZE; i++) {
|
||||
msg = devm_kzalloc(&qdev->pdev->dev, sizeof(*msg), GFP_KERNEL);
|
||||
if (!msg) {
|
||||
ret = -ENOMEM;
|
||||
goto mhi_unprepare;
|
||||
}
|
||||
|
||||
msg->qdev = qdev;
|
||||
INIT_WORK(&msg->work, bootlog_log);
|
||||
|
||||
ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, msg, BOOTLOG_MSG_SIZE, MHI_EOT);
|
||||
if (ret)
|
||||
goto mhi_unprepare;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&mhi_dev->dev, qdev);
|
||||
qdev->bootlog_ch = mhi_dev;
|
||||
return 0;
|
||||
|
||||
mhi_unprepare:
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
destroy_workqueue:
|
||||
flush_workqueue(qdev->bootlog_wq);
|
||||
destroy_workqueue(qdev->bootlog_wq);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qaic_bootlog_mhi_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct qaic_device *qdev;
|
||||
|
||||
qdev = dev_get_drvdata(&mhi_dev->dev);
|
||||
|
||||
mhi_unprepare_from_transfer(qdev->bootlog_ch);
|
||||
flush_workqueue(qdev->bootlog_wq);
|
||||
destroy_workqueue(qdev->bootlog_wq);
|
||||
qdev->bootlog_ch = NULL;
|
||||
}
|
||||
|
||||
static void qaic_bootlog_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
|
||||
{
|
||||
}
|
||||
|
||||
static void qaic_bootlog_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
|
||||
{
|
||||
struct qaic_device *qdev = dev_get_drvdata(&mhi_dev->dev);
|
||||
struct bootlog_msg *msg = mhi_result->buf_addr;
|
||||
|
||||
if (mhi_result->transaction_status) {
|
||||
devm_kfree(&qdev->pdev->dev, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Force a null at the end of the transferred string */
|
||||
msg->str[mhi_result->bytes_xferd - 1] = 0;
|
||||
|
||||
queue_work(qdev->bootlog_wq, &msg->work);
|
||||
}
|
||||
|
||||
static const struct mhi_device_id qaic_bootlog_mhi_match_table[] = {
|
||||
{ .chan = "QAIC_LOGGING", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct mhi_driver qaic_bootlog_mhi_driver = {
|
||||
.id_table = qaic_bootlog_mhi_match_table,
|
||||
.remove = qaic_bootlog_mhi_remove,
|
||||
.probe = qaic_bootlog_mhi_probe,
|
||||
.ul_xfer_cb = qaic_bootlog_mhi_ul_xfer_cb,
|
||||
.dl_xfer_cb = qaic_bootlog_mhi_dl_xfer_cb,
|
||||
.driver = {
|
||||
.name = "qaic_bootlog",
|
||||
},
|
||||
};
|
||||
|
||||
int qaic_bootlog_register(void)
|
||||
{
|
||||
return mhi_driver_register(&qaic_bootlog_mhi_driver);
|
||||
}
|
||||
|
||||
void qaic_bootlog_unregister(void)
|
||||
{
|
||||
mhi_driver_unregister(&qaic_bootlog_mhi_driver);
|
||||
}
|
||||
20
drivers/accel/qaic/qaic_debugfs.h
Normal file
20
drivers/accel/qaic/qaic_debugfs.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#ifndef __QAIC_DEBUGFS_H__
|
||||
#define __QAIC_DEBUGFS_H__
|
||||
|
||||
#include <drm/drm_file.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int qaic_bootlog_register(void);
|
||||
void qaic_bootlog_unregister(void);
|
||||
void qaic_debugfs_init(struct qaic_drm_device *qddev);
|
||||
#else
|
||||
static inline int qaic_bootlog_register(void) { return 0; }
|
||||
static inline void qaic_bootlog_unregister(void) {}
|
||||
static inline void qaic_debugfs_init(struct qaic_drm_device *qddev) {}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
#endif /* __QAIC_DEBUGFS_H__ */
|
||||
|
|
@ -28,7 +28,9 @@
|
|||
|
||||
#include "mhi_controller.h"
|
||||
#include "qaic.h"
|
||||
#include "qaic_debugfs.h"
|
||||
#include "qaic_timesync.h"
|
||||
#include "sahara.h"
|
||||
|
||||
MODULE_IMPORT_NS(DMA_BUF);
|
||||
|
||||
|
|
@ -229,8 +231,12 @@ static int qaic_create_drm_device(struct qaic_device *qdev, s32 partition_id)
|
|||
qddev->partition_id = partition_id;
|
||||
|
||||
ret = drm_dev_register(drm, 0);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pci_dbg(qdev->pdev, "drm_dev_register failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
qaic_debugfs_init(qddev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -380,6 +386,9 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_de
|
|||
if (ret)
|
||||
return NULL;
|
||||
ret = drmm_mutex_init(drm, &qdev->cntl_mutex);
|
||||
if (ret)
|
||||
return NULL;
|
||||
ret = drmm_mutex_init(drm, &qdev->bootlog_mutex);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -399,6 +408,7 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_de
|
|||
qddev->qdev = qdev;
|
||||
|
||||
INIT_LIST_HEAD(&qdev->cntl_xfer_list);
|
||||
INIT_LIST_HEAD(&qdev->bootlog);
|
||||
INIT_LIST_HEAD(&qddev->users);
|
||||
|
||||
for (i = 0; i < qdev->num_dbc; ++i) {
|
||||
|
|
@ -635,12 +645,24 @@ static int __init qaic_init(void)
|
|||
goto free_pci;
|
||||
}
|
||||
|
||||
ret = sahara_register();
|
||||
if (ret) {
|
||||
pr_debug("qaic: sahara_register failed %d\n", ret);
|
||||
goto free_mhi;
|
||||
}
|
||||
|
||||
ret = qaic_timesync_init();
|
||||
if (ret)
|
||||
pr_debug("qaic: qaic_timesync_init failed %d\n", ret);
|
||||
|
||||
ret = qaic_bootlog_register();
|
||||
if (ret)
|
||||
pr_debug("qaic: qaic_bootlog_register failed %d\n", ret);
|
||||
|
||||
return 0;
|
||||
|
||||
free_mhi:
|
||||
mhi_driver_unregister(&qaic_mhi_driver);
|
||||
free_pci:
|
||||
pci_unregister_driver(&qaic_pci_driver);
|
||||
return ret;
|
||||
|
|
@ -664,7 +686,9 @@ static void __exit qaic_exit(void)
|
|||
* reinitializing the link_up state after the cleanup is done.
|
||||
*/
|
||||
link_up = true;
|
||||
qaic_bootlog_unregister();
|
||||
qaic_timesync_deinit();
|
||||
sahara_unregister();
|
||||
mhi_driver_unregister(&qaic_mhi_driver);
|
||||
pci_unregister_driver(&qaic_pci_driver);
|
||||
}
|
||||
|
|
|
|||
449
drivers/accel/qaic/sahara.c
Normal file
449
drivers/accel/qaic/sahara.c
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/mhi.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "sahara.h"
|
||||
|
||||
#define SAHARA_HELLO_CMD 0x1 /* Min protocol version 1.0 */
|
||||
#define SAHARA_HELLO_RESP_CMD 0x2 /* Min protocol version 1.0 */
|
||||
#define SAHARA_READ_DATA_CMD 0x3 /* Min protocol version 1.0 */
|
||||
#define SAHARA_END_OF_IMAGE_CMD 0x4 /* Min protocol version 1.0 */
|
||||
#define SAHARA_DONE_CMD 0x5 /* Min protocol version 1.0 */
|
||||
#define SAHARA_DONE_RESP_CMD 0x6 /* Min protocol version 1.0 */
|
||||
#define SAHARA_RESET_CMD 0x7 /* Min protocol version 1.0 */
|
||||
#define SAHARA_RESET_RESP_CMD 0x8 /* Min protocol version 1.0 */
|
||||
#define SAHARA_MEM_DEBUG_CMD 0x9 /* Min protocol version 2.0 */
|
||||
#define SAHARA_MEM_READ_CMD 0xa /* Min protocol version 2.0 */
|
||||
#define SAHARA_CMD_READY_CMD 0xb /* Min protocol version 2.1 */
|
||||
#define SAHARA_SWITCH_MODE_CMD 0xc /* Min protocol version 2.1 */
|
||||
#define SAHARA_EXECUTE_CMD 0xd /* Min protocol version 2.1 */
|
||||
#define SAHARA_EXECUTE_RESP_CMD 0xe /* Min protocol version 2.1 */
|
||||
#define SAHARA_EXECUTE_DATA_CMD 0xf /* Min protocol version 2.1 */
|
||||
#define SAHARA_MEM_DEBUG64_CMD 0x10 /* Min protocol version 2.5 */
|
||||
#define SAHARA_MEM_READ64_CMD 0x11 /* Min protocol version 2.5 */
|
||||
#define SAHARA_READ_DATA64_CMD 0x12 /* Min protocol version 2.8 */
|
||||
#define SAHARA_RESET_STATE_CMD 0x13 /* Min protocol version 2.9 */
|
||||
#define SAHARA_WRITE_DATA_CMD 0x14 /* Min protocol version 3.0 */
|
||||
|
||||
#define SAHARA_PACKET_MAX_SIZE 0xffffU /* MHI_MAX_MTU */
|
||||
#define SAHARA_TRANSFER_MAX_SIZE 0x80000
|
||||
#define SAHARA_NUM_TX_BUF DIV_ROUND_UP(SAHARA_TRANSFER_MAX_SIZE,\
|
||||
SAHARA_PACKET_MAX_SIZE)
|
||||
#define SAHARA_IMAGE_ID_NONE U32_MAX
|
||||
|
||||
#define SAHARA_VERSION 2
|
||||
#define SAHARA_SUCCESS 0
|
||||
|
||||
#define SAHARA_MODE_IMAGE_TX_PENDING 0x0
|
||||
#define SAHARA_MODE_IMAGE_TX_COMPLETE 0x1
|
||||
#define SAHARA_MODE_MEMORY_DEBUG 0x2
|
||||
#define SAHARA_MODE_COMMAND 0x3
|
||||
|
||||
#define SAHARA_HELLO_LENGTH 0x30
|
||||
#define SAHARA_READ_DATA_LENGTH 0x14
|
||||
#define SAHARA_END_OF_IMAGE_LENGTH 0x10
|
||||
#define SAHARA_DONE_LENGTH 0x8
|
||||
#define SAHARA_RESET_LENGTH 0x8
|
||||
|
||||
struct sahara_packet {
|
||||
__le32 cmd;
|
||||
__le32 length;
|
||||
|
||||
union {
|
||||
struct {
|
||||
__le32 version;
|
||||
__le32 version_compat;
|
||||
__le32 max_length;
|
||||
__le32 mode;
|
||||
} hello;
|
||||
struct {
|
||||
__le32 version;
|
||||
__le32 version_compat;
|
||||
__le32 status;
|
||||
__le32 mode;
|
||||
} hello_resp;
|
||||
struct {
|
||||
__le32 image;
|
||||
__le32 offset;
|
||||
__le32 length;
|
||||
} read_data;
|
||||
struct {
|
||||
__le32 image;
|
||||
__le32 status;
|
||||
} end_of_image;
|
||||
};
|
||||
};
|
||||
|
||||
struct sahara_context {
|
||||
struct sahara_packet *tx[SAHARA_NUM_TX_BUF];
|
||||
struct sahara_packet *rx;
|
||||
struct work_struct work;
|
||||
struct mhi_device *mhi_dev;
|
||||
const char **image_table;
|
||||
u32 table_size;
|
||||
u32 active_image_id;
|
||||
const struct firmware *firmware;
|
||||
};
|
||||
|
||||
static const char *aic100_image_table[] = {
|
||||
[1] = "qcom/aic100/fw1.bin",
|
||||
[2] = "qcom/aic100/fw2.bin",
|
||||
[4] = "qcom/aic100/fw4.bin",
|
||||
[5] = "qcom/aic100/fw5.bin",
|
||||
[6] = "qcom/aic100/fw6.bin",
|
||||
[8] = "qcom/aic100/fw8.bin",
|
||||
[9] = "qcom/aic100/fw9.bin",
|
||||
[10] = "qcom/aic100/fw10.bin",
|
||||
};
|
||||
|
||||
static int sahara_find_image(struct sahara_context *context, u32 image_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (image_id == context->active_image_id)
|
||||
return 0;
|
||||
|
||||
if (context->active_image_id != SAHARA_IMAGE_ID_NONE) {
|
||||
dev_err(&context->mhi_dev->dev, "image id %d is not valid as %d is active\n",
|
||||
image_id, context->active_image_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (image_id >= context->table_size || !context->image_table[image_id]) {
|
||||
dev_err(&context->mhi_dev->dev, "request for unknown image: %d\n", image_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This image might be optional. The device may continue without it.
|
||||
* Only the device knows. Suppress error messages that could suggest an
|
||||
* a problem when we were actually able to continue.
|
||||
*/
|
||||
ret = firmware_request_nowarn(&context->firmware,
|
||||
context->image_table[image_id],
|
||||
&context->mhi_dev->dev);
|
||||
if (ret) {
|
||||
dev_dbg(&context->mhi_dev->dev, "request for image id %d / file %s failed %d\n",
|
||||
image_id, context->image_table[image_id], ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
context->active_image_id = image_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sahara_release_image(struct sahara_context *context)
|
||||
{
|
||||
if (context->active_image_id != SAHARA_IMAGE_ID_NONE)
|
||||
release_firmware(context->firmware);
|
||||
context->active_image_id = SAHARA_IMAGE_ID_NONE;
|
||||
}
|
||||
|
||||
static void sahara_send_reset(struct sahara_context *context)
|
||||
{
|
||||
int ret;
|
||||
|
||||
context->tx[0]->cmd = cpu_to_le32(SAHARA_RESET_CMD);
|
||||
context->tx[0]->length = cpu_to_le32(SAHARA_RESET_LENGTH);
|
||||
|
||||
ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, context->tx[0],
|
||||
SAHARA_RESET_LENGTH, MHI_EOT);
|
||||
if (ret)
|
||||
dev_err(&context->mhi_dev->dev, "Unable to send reset response %d\n", ret);
|
||||
}
|
||||
|
||||
static void sahara_hello(struct sahara_context *context)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(&context->mhi_dev->dev,
|
||||
"HELLO cmd received. length:%d version:%d version_compat:%d max_length:%d mode:%d\n",
|
||||
le32_to_cpu(context->rx->length),
|
||||
le32_to_cpu(context->rx->hello.version),
|
||||
le32_to_cpu(context->rx->hello.version_compat),
|
||||
le32_to_cpu(context->rx->hello.max_length),
|
||||
le32_to_cpu(context->rx->hello.mode));
|
||||
|
||||
if (le32_to_cpu(context->rx->length) != SAHARA_HELLO_LENGTH) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed hello packet - length %d\n",
|
||||
le32_to_cpu(context->rx->length));
|
||||
return;
|
||||
}
|
||||
if (le32_to_cpu(context->rx->hello.version) != SAHARA_VERSION) {
|
||||
dev_err(&context->mhi_dev->dev, "Unsupported hello packet - version %d\n",
|
||||
le32_to_cpu(context->rx->hello.version));
|
||||
return;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(context->rx->hello.mode) != SAHARA_MODE_IMAGE_TX_PENDING &&
|
||||
le32_to_cpu(context->rx->hello.mode) != SAHARA_MODE_IMAGE_TX_COMPLETE) {
|
||||
dev_err(&context->mhi_dev->dev, "Unsupported hello packet - mode %d\n",
|
||||
le32_to_cpu(context->rx->hello.mode));
|
||||
return;
|
||||
}
|
||||
|
||||
context->tx[0]->cmd = cpu_to_le32(SAHARA_HELLO_RESP_CMD);
|
||||
context->tx[0]->length = cpu_to_le32(SAHARA_HELLO_LENGTH);
|
||||
context->tx[0]->hello_resp.version = cpu_to_le32(SAHARA_VERSION);
|
||||
context->tx[0]->hello_resp.version_compat = cpu_to_le32(SAHARA_VERSION);
|
||||
context->tx[0]->hello_resp.status = cpu_to_le32(SAHARA_SUCCESS);
|
||||
context->tx[0]->hello_resp.mode = context->rx->hello_resp.mode;
|
||||
|
||||
ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, context->tx[0],
|
||||
SAHARA_HELLO_LENGTH, MHI_EOT);
|
||||
if (ret)
|
||||
dev_err(&context->mhi_dev->dev, "Unable to send hello response %d\n", ret);
|
||||
}
|
||||
|
||||
static void sahara_read_data(struct sahara_context *context)
|
||||
{
|
||||
u32 image_id, data_offset, data_len, pkt_data_len;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
dev_dbg(&context->mhi_dev->dev,
|
||||
"READ_DATA cmd received. length:%d image:%d offset:%d data_length:%d\n",
|
||||
le32_to_cpu(context->rx->length),
|
||||
le32_to_cpu(context->rx->read_data.image),
|
||||
le32_to_cpu(context->rx->read_data.offset),
|
||||
le32_to_cpu(context->rx->read_data.length));
|
||||
|
||||
if (le32_to_cpu(context->rx->length) != SAHARA_READ_DATA_LENGTH) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed read_data packet - length %d\n",
|
||||
le32_to_cpu(context->rx->length));
|
||||
return;
|
||||
}
|
||||
|
||||
image_id = le32_to_cpu(context->rx->read_data.image);
|
||||
data_offset = le32_to_cpu(context->rx->read_data.offset);
|
||||
data_len = le32_to_cpu(context->rx->read_data.length);
|
||||
|
||||
ret = sahara_find_image(context, image_id);
|
||||
if (ret) {
|
||||
sahara_send_reset(context);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Image is released when the device is done with it via
|
||||
* SAHARA_END_OF_IMAGE_CMD. sahara_send_reset() will either cause the
|
||||
* device to retry the operation with a modification, or decide to be
|
||||
* done with the image and trigger SAHARA_END_OF_IMAGE_CMD.
|
||||
* release_image() is called from SAHARA_END_OF_IMAGE_CMD. processing
|
||||
* and is not needed here on error.
|
||||
*/
|
||||
|
||||
if (data_len > SAHARA_TRANSFER_MAX_SIZE) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed read_data packet - data len %d exceeds max xfer size %d\n",
|
||||
data_len, SAHARA_TRANSFER_MAX_SIZE);
|
||||
sahara_send_reset(context);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data_offset >= context->firmware->size) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed read_data packet - data offset %d exceeds file size %zu\n",
|
||||
data_offset, context->firmware->size);
|
||||
sahara_send_reset(context);
|
||||
return;
|
||||
}
|
||||
|
||||
if (size_add(data_offset, data_len) > context->firmware->size) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed read_data packet - data offset %d and length %d exceeds file size %zu\n",
|
||||
data_offset, data_len, context->firmware->size);
|
||||
sahara_send_reset(context);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < SAHARA_NUM_TX_BUF && data_len; ++i) {
|
||||
pkt_data_len = min(data_len, SAHARA_PACKET_MAX_SIZE);
|
||||
|
||||
memcpy(context->tx[i], &context->firmware->data[data_offset], pkt_data_len);
|
||||
|
||||
data_offset += pkt_data_len;
|
||||
data_len -= pkt_data_len;
|
||||
|
||||
ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE,
|
||||
context->tx[i], pkt_data_len,
|
||||
!data_len ? MHI_EOT : MHI_CHAIN);
|
||||
if (ret) {
|
||||
dev_err(&context->mhi_dev->dev, "Unable to send read_data response %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sahara_end_of_image(struct sahara_context *context)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(&context->mhi_dev->dev,
|
||||
"END_OF_IMAGE cmd received. length:%d image:%d status:%d\n",
|
||||
le32_to_cpu(context->rx->length),
|
||||
le32_to_cpu(context->rx->end_of_image.image),
|
||||
le32_to_cpu(context->rx->end_of_image.status));
|
||||
|
||||
if (le32_to_cpu(context->rx->length) != SAHARA_END_OF_IMAGE_LENGTH) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed end_of_image packet - length %d\n",
|
||||
le32_to_cpu(context->rx->length));
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->active_image_id != SAHARA_IMAGE_ID_NONE &&
|
||||
le32_to_cpu(context->rx->end_of_image.image) != context->active_image_id) {
|
||||
dev_err(&context->mhi_dev->dev, "Malformed end_of_image packet - image %d is not the active image\n",
|
||||
le32_to_cpu(context->rx->end_of_image.image));
|
||||
return;
|
||||
}
|
||||
|
||||
sahara_release_image(context);
|
||||
|
||||
if (le32_to_cpu(context->rx->end_of_image.status))
|
||||
return;
|
||||
|
||||
context->tx[0]->cmd = cpu_to_le32(SAHARA_DONE_CMD);
|
||||
context->tx[0]->length = cpu_to_le32(SAHARA_DONE_LENGTH);
|
||||
|
||||
ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, context->tx[0],
|
||||
SAHARA_DONE_LENGTH, MHI_EOT);
|
||||
if (ret)
|
||||
dev_dbg(&context->mhi_dev->dev, "Unable to send done response %d\n", ret);
|
||||
}
|
||||
|
||||
static void sahara_processing(struct work_struct *work)
|
||||
{
|
||||
struct sahara_context *context = container_of(work, struct sahara_context, work);
|
||||
int ret;
|
||||
|
||||
switch (le32_to_cpu(context->rx->cmd)) {
|
||||
case SAHARA_HELLO_CMD:
|
||||
sahara_hello(context);
|
||||
break;
|
||||
case SAHARA_READ_DATA_CMD:
|
||||
sahara_read_data(context);
|
||||
break;
|
||||
case SAHARA_END_OF_IMAGE_CMD:
|
||||
sahara_end_of_image(context);
|
||||
break;
|
||||
case SAHARA_DONE_RESP_CMD:
|
||||
/* Intentional do nothing as we don't need to exit an app */
|
||||
break;
|
||||
default:
|
||||
dev_err(&context->mhi_dev->dev, "Unknown command %d\n",
|
||||
le32_to_cpu(context->rx->cmd));
|
||||
break;
|
||||
}
|
||||
|
||||
ret = mhi_queue_buf(context->mhi_dev, DMA_FROM_DEVICE, context->rx,
|
||||
SAHARA_PACKET_MAX_SIZE, MHI_EOT);
|
||||
if (ret)
|
||||
dev_err(&context->mhi_dev->dev, "Unable to requeue rx buf %d\n", ret);
|
||||
}
|
||||
|
||||
static int sahara_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
|
||||
{
|
||||
struct sahara_context *context;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
context = devm_kzalloc(&mhi_dev->dev, sizeof(*context), GFP_KERNEL);
|
||||
if (!context)
|
||||
return -ENOMEM;
|
||||
|
||||
context->rx = devm_kzalloc(&mhi_dev->dev, SAHARA_PACKET_MAX_SIZE, GFP_KERNEL);
|
||||
if (!context->rx)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* AIC100 defines SAHARA_TRANSFER_MAX_SIZE as the largest value it
|
||||
* will request for READ_DATA. This is larger than
|
||||
* SAHARA_PACKET_MAX_SIZE, and we need 9x SAHARA_PACKET_MAX_SIZE to
|
||||
* cover SAHARA_TRANSFER_MAX_SIZE. When the remote side issues a
|
||||
* READ_DATA, it requires a transfer of the exact size requested. We
|
||||
* can use MHI_CHAIN to link multiple buffers into a single transfer
|
||||
* but the remote side will not consume the buffers until it sees an
|
||||
* EOT, thus we need to allocate enough buffers to put in the tx fifo
|
||||
* to cover an entire READ_DATA request of the max size.
|
||||
*/
|
||||
for (i = 0; i < SAHARA_NUM_TX_BUF; ++i) {
|
||||
context->tx[i] = devm_kzalloc(&mhi_dev->dev, SAHARA_PACKET_MAX_SIZE, GFP_KERNEL);
|
||||
if (!context->tx[i])
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
context->mhi_dev = mhi_dev;
|
||||
INIT_WORK(&context->work, sahara_processing);
|
||||
context->image_table = aic100_image_table;
|
||||
context->table_size = ARRAY_SIZE(aic100_image_table);
|
||||
context->active_image_id = SAHARA_IMAGE_ID_NONE;
|
||||
dev_set_drvdata(&mhi_dev->dev, context);
|
||||
|
||||
ret = mhi_prepare_for_transfer(mhi_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, context->rx, SAHARA_PACKET_MAX_SIZE, MHI_EOT);
|
||||
if (ret) {
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sahara_mhi_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct sahara_context *context = dev_get_drvdata(&mhi_dev->dev);
|
||||
|
||||
cancel_work_sync(&context->work);
|
||||
sahara_release_image(context);
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
}
|
||||
|
||||
static void sahara_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
|
||||
{
|
||||
}
|
||||
|
||||
static void sahara_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
|
||||
{
|
||||
struct sahara_context *context = dev_get_drvdata(&mhi_dev->dev);
|
||||
|
||||
if (!mhi_result->transaction_status)
|
||||
schedule_work(&context->work);
|
||||
}
|
||||
|
||||
static const struct mhi_device_id sahara_mhi_match_table[] = {
|
||||
{ .chan = "QAIC_SAHARA", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct mhi_driver sahara_mhi_driver = {
|
||||
.id_table = sahara_mhi_match_table,
|
||||
.remove = sahara_mhi_remove,
|
||||
.probe = sahara_mhi_probe,
|
||||
.ul_xfer_cb = sahara_mhi_ul_xfer_cb,
|
||||
.dl_xfer_cb = sahara_mhi_dl_xfer_cb,
|
||||
.driver = {
|
||||
.name = "sahara",
|
||||
},
|
||||
};
|
||||
|
||||
int sahara_register(void)
|
||||
{
|
||||
return mhi_driver_register(&sahara_mhi_driver);
|
||||
}
|
||||
|
||||
void sahara_unregister(void)
|
||||
{
|
||||
mhi_driver_unregister(&sahara_mhi_driver);
|
||||
}
|
||||
10
drivers/accel/qaic/sahara.h
Normal file
10
drivers/accel/qaic/sahara.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#ifndef __SAHARA_H__
|
||||
#define __SAHARA_H__
|
||||
|
||||
int sahara_register(void);
|
||||
void sahara_unregister(void);
|
||||
#endif /* __SAHARA_H__ */
|
||||
|
|
@ -304,6 +304,29 @@ static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
|
|||
offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_coredump_put - remove device coredump
|
||||
* @dev: the struct device for the crashed device
|
||||
*
|
||||
* dev_coredump_put() removes coredump, if exists, for a given device from
|
||||
* the file system and free its associated data otherwise, does nothing.
|
||||
*
|
||||
* It is useful for modules that do not want to keep coredump
|
||||
* available after its unload.
|
||||
*/
|
||||
void dev_coredump_put(struct device *dev)
|
||||
{
|
||||
struct device *existing;
|
||||
|
||||
existing = class_find_device(&devcd_class, NULL, dev,
|
||||
devcd_match_failing);
|
||||
if (existing) {
|
||||
devcd_free(existing, NULL);
|
||||
put_device(existing);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_coredump_put);
|
||||
|
||||
/**
|
||||
* dev_coredumpm - create device coredump with read/free methods
|
||||
* @dev: the struct device for the crashed device
|
||||
|
|
|
|||
|
|
@ -35,12 +35,35 @@
|
|||
|
||||
static inline int is_dma_buf_file(struct file *);
|
||||
|
||||
struct dma_buf_list {
|
||||
struct list_head head;
|
||||
struct mutex lock;
|
||||
};
|
||||
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
||||
static DEFINE_MUTEX(debugfs_list_mutex);
|
||||
static LIST_HEAD(debugfs_list);
|
||||
|
||||
static struct dma_buf_list db_list;
|
||||
static void __dma_buf_debugfs_list_add(struct dma_buf *dmabuf)
|
||||
{
|
||||
mutex_lock(&debugfs_list_mutex);
|
||||
list_add(&dmabuf->list_node, &debugfs_list);
|
||||
mutex_unlock(&debugfs_list_mutex);
|
||||
}
|
||||
|
||||
static void __dma_buf_debugfs_list_del(struct dma_buf *dmabuf)
|
||||
{
|
||||
if (!dmabuf)
|
||||
return;
|
||||
|
||||
mutex_lock(&debugfs_list_mutex);
|
||||
list_del(&dmabuf->list_node);
|
||||
mutex_unlock(&debugfs_list_mutex);
|
||||
}
|
||||
#else
|
||||
static void __dma_buf_debugfs_list_add(struct dma_buf *dmabuf)
|
||||
{
|
||||
}
|
||||
|
||||
static void __dma_buf_debugfs_list_del(struct file *file)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
|
||||
{
|
||||
|
|
@ -89,17 +112,10 @@ static void dma_buf_release(struct dentry *dentry)
|
|||
|
||||
static int dma_buf_file_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dma_buf *dmabuf;
|
||||
|
||||
if (!is_dma_buf_file(file))
|
||||
return -EINVAL;
|
||||
|
||||
dmabuf = file->private_data;
|
||||
if (dmabuf) {
|
||||
mutex_lock(&db_list.lock);
|
||||
list_del(&dmabuf->list_node);
|
||||
mutex_unlock(&db_list.lock);
|
||||
}
|
||||
__dma_buf_debugfs_list_del(file->private_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -672,9 +688,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|
|||
file->f_path.dentry->d_fsdata = dmabuf;
|
||||
dmabuf->file = file;
|
||||
|
||||
mutex_lock(&db_list.lock);
|
||||
list_add(&dmabuf->list_node, &db_list.head);
|
||||
mutex_unlock(&db_list.lock);
|
||||
__dma_buf_debugfs_list_add(dmabuf);
|
||||
|
||||
return dmabuf;
|
||||
|
||||
|
|
@ -1611,7 +1625,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||
size_t size = 0;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&db_list.lock);
|
||||
ret = mutex_lock_interruptible(&debugfs_list_mutex);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1620,7 +1634,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||
seq_printf(s, "%-8s\t%-8s\t%-8s\t%-8s\texp_name\t%-8s\tname\n",
|
||||
"size", "flags", "mode", "count", "ino");
|
||||
|
||||
list_for_each_entry(buf_obj, &db_list.head, list_node) {
|
||||
list_for_each_entry(buf_obj, &debugfs_list, list_node) {
|
||||
|
||||
ret = dma_resv_lock_interruptible(buf_obj->resv, NULL);
|
||||
if (ret)
|
||||
|
|
@ -1657,11 +1671,11 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
|
|||
|
||||
seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
|
||||
|
||||
mutex_unlock(&db_list.lock);
|
||||
mutex_unlock(&debugfs_list_mutex);
|
||||
return 0;
|
||||
|
||||
error_unlock:
|
||||
mutex_unlock(&db_list.lock);
|
||||
mutex_unlock(&debugfs_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1718,8 +1732,6 @@ static int __init dma_buf_init(void)
|
|||
if (IS_ERR(dma_buf_mnt))
|
||||
return PTR_ERR(dma_buf_mnt);
|
||||
|
||||
mutex_init(&db_list.lock);
|
||||
INIT_LIST_HEAD(&db_list.head);
|
||||
dma_buf_init_debugfs();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ menuconfig DRM
|
|||
details. You should also select and configure AGP
|
||||
(/dev/agpgart) support if it is available for your platform.
|
||||
|
||||
if DRM
|
||||
|
||||
config DRM_MIPI_DBI
|
||||
tristate
|
||||
depends on DRM
|
||||
|
|
@ -102,6 +104,38 @@ config DRM_KMS_HELPER
|
|||
help
|
||||
CRTC helpers for KMS drivers.
|
||||
|
||||
config DRM_PANIC
|
||||
bool "Display a user-friendly message when a kernel panic occurs"
|
||||
depends on DRM && !FRAMEBUFFER_CONSOLE
|
||||
select DRM_KMS_HELPER
|
||||
select FONT_SUPPORT
|
||||
help
|
||||
Enable a drm panic handler, which will display a user-friendly message
|
||||
when a kernel panic occurs. It's useful when using a user-space
|
||||
console instead of fbcon.
|
||||
It will only work if your graphic driver supports this feature.
|
||||
To support Hi-DPI Display, you can enable bigger fonts like
|
||||
FONT_TER16x32
|
||||
|
||||
config DRM_PANIC_FOREGROUND_COLOR
|
||||
hex "Drm panic screen foreground color, in RGB"
|
||||
depends on DRM_PANIC
|
||||
default 0xffffff
|
||||
|
||||
config DRM_PANIC_BACKGROUND_COLOR
|
||||
hex "Drm panic screen background color, in RGB"
|
||||
depends on DRM_PANIC
|
||||
default 0x000000
|
||||
|
||||
config DRM_PANIC_DEBUG
|
||||
bool "Add a debug fs entry to trigger drm_panic"
|
||||
depends on DRM_PANIC && DEBUG_FS
|
||||
help
|
||||
Add dri/[device]/drm_panic_plane_x in the kernel debugfs, to force the
|
||||
panic handler to write the panic message to this plane scanout buffer.
|
||||
This is unsafe and should not be enabled on a production build.
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
|
||||
bool "Enable refcount backtrace history in the DP MST helpers"
|
||||
depends on STACKTRACE_SUPPORT
|
||||
|
|
@ -371,6 +405,8 @@ source "drivers/gpu/drm/lima/Kconfig"
|
|||
|
||||
source "drivers/gpu/drm/panfrost/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/panthor/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/aspeed/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/mcde/Kconfig"
|
||||
|
|
@ -403,10 +439,6 @@ config DRM_HYPERV
|
|||
config DRM_EXPORT_FOR_TESTS
|
||||
bool
|
||||
|
||||
# Separate option because drm_panel_orientation_quirks.c is shared with fbdev
|
||||
config DRM_PANEL_ORIENTATION_QUIRKS
|
||||
tristate
|
||||
|
||||
config DRM_LIB_RANDOM
|
||||
bool
|
||||
default n
|
||||
|
|
@ -414,3 +446,22 @@ config DRM_LIB_RANDOM
|
|||
config DRM_PRIVACY_SCREEN
|
||||
bool
|
||||
default n
|
||||
|
||||
config DRM_WERROR
|
||||
bool "Compile the drm subsystem with warnings as errors"
|
||||
depends on DRM && EXPERT
|
||||
default n
|
||||
help
|
||||
A kernel build should not cause any compiler warnings, and this
|
||||
enables the '-Werror' flag to enforce that rule in the drm subsystem.
|
||||
|
||||
The drm subsystem enables more warnings than the kernel default, so
|
||||
this config option is disabled by default.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
endif
|
||||
|
||||
# Separate option because drm_panel_orientation_quirks.c is shared with fbdev
|
||||
config DRM_PANEL_ORIENTATION_QUIRKS
|
||||
tristate
|
||||
|
|
|
|||
|
|
@ -5,6 +5,34 @@
|
|||
|
||||
CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE
|
||||
|
||||
# Unconditionally enable W=1 warnings locally
|
||||
# --- begin copy-paste W=1 warnings from scripts/Makefile.extrawarn
|
||||
subdir-ccflags-y += -Wextra -Wunused -Wno-unused-parameter
|
||||
subdir-ccflags-y += $(call cc-option, -Wrestrict)
|
||||
subdir-ccflags-y += -Wmissing-format-attribute
|
||||
subdir-ccflags-y += -Wold-style-definition
|
||||
subdir-ccflags-y += -Wmissing-include-dirs
|
||||
subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable)
|
||||
subdir-ccflags-y += $(call cc-option, -Wunused-const-variable)
|
||||
subdir-ccflags-y += $(call cc-option, -Wpacked-not-aligned)
|
||||
subdir-ccflags-y += $(call cc-option, -Wformat-overflow)
|
||||
# FIXME: fix -Wformat-truncation warnings and uncomment
|
||||
#subdir-ccflags-y += $(call cc-option, -Wformat-truncation)
|
||||
subdir-ccflags-y += $(call cc-option, -Wstringop-truncation)
|
||||
# The following turn off the warnings enabled by -Wextra
|
||||
ifeq ($(findstring 2, $(KBUILD_EXTRA_WARN)),)
|
||||
subdir-ccflags-y += -Wno-missing-field-initializers
|
||||
subdir-ccflags-y += -Wno-type-limits
|
||||
subdir-ccflags-y += -Wno-shift-negative-value
|
||||
endif
|
||||
ifeq ($(findstring 3, $(KBUILD_EXTRA_WARN)),)
|
||||
subdir-ccflags-y += -Wno-sign-compare
|
||||
endif
|
||||
# --- end copy-paste
|
||||
|
||||
# Enable -Werror in CI and development
|
||||
subdir-ccflags-$(CONFIG_DRM_WERROR) += -Werror
|
||||
|
||||
drm-y := \
|
||||
drm_aperture.o \
|
||||
drm_atomic.o \
|
||||
|
|
@ -60,6 +88,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
|
|||
drm_privacy_screen.o \
|
||||
drm_privacy_screen_x86.o
|
||||
drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
|
||||
drm-$(CONFIG_DRM_PANIC) += drm_panic.o
|
||||
obj-$(CONFIG_DRM) += drm.o
|
||||
|
||||
obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
|
||||
|
|
@ -179,6 +208,7 @@ obj-$(CONFIG_DRM_XEN) += xen/
|
|||
obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
|
||||
obj-$(CONFIG_DRM_LIMA) += lima/
|
||||
obj-$(CONFIG_DRM_PANFROST) += panfrost/
|
||||
obj-$(CONFIG_DRM_PANTHOR) += panthor/
|
||||
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
|
||||
obj-$(CONFIG_DRM_MCDE) += mcde/
|
||||
obj-$(CONFIG_DRM_TIDSS) += tidss/
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \
|
|||
amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o \
|
||||
atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \
|
||||
atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
|
||||
amdgpu_dma_buf.o amdgpu_vm.o amdgpu_vm_pt.o amdgpu_ib.o amdgpu_pll.o \
|
||||
amdgpu_dma_buf.o amdgpu_vm.o amdgpu_vm_pt.o amdgpu_vm_tlb_fence.o \
|
||||
amdgpu_ib.o amdgpu_pll.o \
|
||||
amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \
|
||||
amdgpu_gtt_mgr.o amdgpu_preempt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o \
|
||||
amdgpu_atomfirmware.o amdgpu_vf_error.o amdgpu_sched.o \
|
||||
|
|
@ -80,7 +81,7 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \
|
|||
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
|
||||
amdgpu_fw_attestation.o amdgpu_securedisplay.o \
|
||||
amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \
|
||||
amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o
|
||||
amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o amdgpu_dev_coredump.o
|
||||
|
||||
amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
|
||||
|
||||
|
|
@ -247,7 +248,8 @@ amdgpu-y += \
|
|||
smuio_v11_0_6.o \
|
||||
smuio_v13_0.o \
|
||||
smuio_v13_0_3.o \
|
||||
smuio_v13_0_6.o
|
||||
smuio_v13_0_6.o \
|
||||
smuio_v14_0_2.o
|
||||
|
||||
# add reset block
|
||||
amdgpu-y += \
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ static int aldebaran_mode2_suspend_ip(struct amdgpu_device *adev)
|
|||
adev->ip_blocks[i].status.hw = false;
|
||||
}
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -139,6 +139,14 @@ enum amdgpu_ss {
|
|||
AMDGPU_SS_DRV_UNLOAD
|
||||
};
|
||||
|
||||
struct amdgpu_hwip_reg_entry {
|
||||
u32 hwip;
|
||||
u32 inst;
|
||||
u32 seg;
|
||||
u32 reg_offset;
|
||||
const char *reg_name;
|
||||
};
|
||||
|
||||
struct amdgpu_watchdog_timer {
|
||||
bool timeout_fatal_disable;
|
||||
uint32_t period; /* maxCycles = (1 << period), the number of cycles before a timeout */
|
||||
|
|
@ -494,6 +502,7 @@ struct amdgpu_wb {
|
|||
uint64_t gpu_addr;
|
||||
u32 num_wb; /* Number of wb slots actually reserved for amdgpu. */
|
||||
unsigned long used[DIV_ROUND_UP(AMDGPU_MAX_WB, BITS_PER_LONG)];
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb);
|
||||
|
|
@ -606,7 +615,7 @@ struct amdgpu_asic_funcs {
|
|||
/* PCIe replay counter */
|
||||
uint64_t (*get_pcie_replay_count)(struct amdgpu_device *adev);
|
||||
/* device supports BACO */
|
||||
bool (*supports_baco)(struct amdgpu_device *adev);
|
||||
int (*supports_baco)(struct amdgpu_device *adev);
|
||||
/* pre asic_init quirks */
|
||||
void (*pre_asic_init)(struct amdgpu_device *adev);
|
||||
/* enter/exit umd stable pstate */
|
||||
|
|
@ -1408,7 +1417,8 @@ bool amdgpu_device_supports_atpx(struct drm_device *dev);
|
|||
bool amdgpu_device_supports_px(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_boco(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_smart_shift(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_baco(struct drm_device *dev);
|
||||
int amdgpu_device_supports_baco(struct drm_device *dev);
|
||||
void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev);
|
||||
bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev);
|
||||
int amdgpu_device_baco_enter(struct drm_device *dev);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#define ACA_BANK_HWID(type, hwid, mcatype) [ACA_HWIP_TYPE_##type] = {hwid, mcatype}
|
||||
|
||||
typedef int bank_handler_t(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type, void *data);
|
||||
typedef int bank_handler_t(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type, void *data);
|
||||
|
||||
struct aca_banks {
|
||||
int nr_banks;
|
||||
|
|
@ -86,7 +86,7 @@ static void aca_banks_release(struct aca_banks *banks)
|
|||
}
|
||||
}
|
||||
|
||||
static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, enum aca_error_type type, u32 *count)
|
||||
static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, enum aca_smu_type type, u32 *count)
|
||||
{
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
|
||||
|
|
@ -116,20 +116,22 @@ static struct aca_regs_dump {
|
|||
{"CONTROL_MASK", ACA_REG_IDX_CTL_MASK},
|
||||
};
|
||||
|
||||
static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, struct aca_bank *bank)
|
||||
static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, struct aca_bank *bank,
|
||||
struct ras_query_context *qctx)
|
||||
{
|
||||
u64 event_id = qctx ? qctx->event_id : 0ULL;
|
||||
int i;
|
||||
|
||||
dev_info(adev->dev, HW_ERR "Accelerator Check Architecture events logged\n");
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n");
|
||||
/* plus 1 for output format, e.g: ACA[08/08]: xxxx */
|
||||
for (i = 0; i < ARRAY_SIZE(aca_regs); i++)
|
||||
dev_info(adev->dev, HW_ERR "ACA[%02d/%02d].%s=0x%016llx\n",
|
||||
idx + 1, total, aca_regs[i].name, bank->regs[aca_regs[i].reg_idx]);
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "ACA[%02d/%02d].%s=0x%016llx\n",
|
||||
idx + 1, total, aca_regs[i].name, bank->regs[aca_regs[i].reg_idx]);
|
||||
}
|
||||
|
||||
static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_error_type type,
|
||||
static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_smu_type type,
|
||||
int start, int count,
|
||||
struct aca_banks *banks)
|
||||
struct aca_banks *banks, struct ras_query_context *qctx)
|
||||
{
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
|
||||
|
|
@ -143,13 +145,12 @@ static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_erro
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
switch (type) {
|
||||
case ACA_ERROR_TYPE_UE:
|
||||
case ACA_SMU_TYPE_UE:
|
||||
max_count = smu_funcs->max_ue_bank_count;
|
||||
break;
|
||||
case ACA_ERROR_TYPE_CE:
|
||||
case ACA_SMU_TYPE_CE:
|
||||
max_count = smu_funcs->max_ce_bank_count;
|
||||
break;
|
||||
case ACA_ERROR_TYPE_DEFERRED:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -164,7 +165,9 @@ static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_erro
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
aca_smu_bank_dump(adev, i, count, &bank);
|
||||
bank.type = type;
|
||||
|
||||
aca_smu_bank_dump(adev, i, count, &bank, qctx);
|
||||
|
||||
ret = aca_banks_add_bank(banks, &bank);
|
||||
if (ret)
|
||||
|
|
@ -195,7 +198,7 @@ static bool aca_bank_hwip_is_matched(struct aca_bank *bank, enum aca_hwip_type t
|
|||
return hwip->hwid == hwid && hwip->mcatype == mcatype;
|
||||
}
|
||||
|
||||
static bool aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type)
|
||||
static bool aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type)
|
||||
{
|
||||
const struct aca_bank_ops *bank_ops = handle->bank_ops;
|
||||
|
||||
|
|
@ -273,59 +276,49 @@ static struct aca_bank_error *get_bank_error(struct aca_error *aerr, struct aca_
|
|||
return new_bank_error(aerr, info);
|
||||
}
|
||||
|
||||
static int aca_log_errors(struct aca_handle *handle, enum aca_error_type type,
|
||||
struct aca_bank_report *report)
|
||||
int aca_error_cache_log_bank_error(struct aca_handle *handle, struct aca_bank_info *info,
|
||||
enum aca_error_type type, u64 count)
|
||||
{
|
||||
struct aca_error_cache *error_cache = &handle->error_cache;
|
||||
struct aca_bank_error *bank_error;
|
||||
struct aca_error *aerr;
|
||||
|
||||
if (!handle || !report)
|
||||
if (!handle || !info || type >= ACA_ERROR_TYPE_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
if (!report->count[type])
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
aerr = &error_cache->errors[type];
|
||||
bank_error = get_bank_error(aerr, &report->info);
|
||||
bank_error = get_bank_error(aerr, info);
|
||||
if (!bank_error)
|
||||
return -ENOMEM;
|
||||
|
||||
bank_error->count[type] += report->count[type];
|
||||
bank_error->count += count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aca_generate_bank_report(struct aca_handle *handle, struct aca_bank *bank,
|
||||
enum aca_error_type type, struct aca_bank_report *report)
|
||||
static int aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type)
|
||||
{
|
||||
const struct aca_bank_ops *bank_ops = handle->bank_ops;
|
||||
|
||||
if (!bank || !report)
|
||||
if (!bank)
|
||||
return -EINVAL;
|
||||
|
||||
if (!bank_ops->aca_bank_generate_report)
|
||||
if (!bank_ops->aca_bank_parser)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memset(report, 0, sizeof(*report));
|
||||
return bank_ops->aca_bank_generate_report(handle, bank, type,
|
||||
report, handle->data);
|
||||
return bank_ops->aca_bank_parser(handle, bank, type,
|
||||
handle->data);
|
||||
}
|
||||
|
||||
static int handler_aca_log_bank_error(struct aca_handle *handle, struct aca_bank *bank,
|
||||
enum aca_error_type type, void *data)
|
||||
enum aca_smu_type type, void *data)
|
||||
{
|
||||
struct aca_bank_report report;
|
||||
int ret;
|
||||
|
||||
ret = aca_generate_bank_report(handle, bank, type, &report);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!report.count[type])
|
||||
return 0;
|
||||
|
||||
ret = aca_log_errors(handle, type, &report);
|
||||
ret = aca_bank_parser(handle, bank, type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -333,7 +326,7 @@ static int handler_aca_log_bank_error(struct aca_handle *handle, struct aca_bank
|
|||
}
|
||||
|
||||
static int aca_dispatch_bank(struct aca_handle_manager *mgr, struct aca_bank *bank,
|
||||
enum aca_error_type type, bank_handler_t handler, void *data)
|
||||
enum aca_smu_type type, bank_handler_t handler, void *data)
|
||||
{
|
||||
struct aca_handle *handle;
|
||||
int ret;
|
||||
|
|
@ -354,7 +347,7 @@ static int aca_dispatch_bank(struct aca_handle_manager *mgr, struct aca_bank *ba
|
|||
}
|
||||
|
||||
static int aca_dispatch_banks(struct aca_handle_manager *mgr, struct aca_banks *banks,
|
||||
enum aca_error_type type, bank_handler_t handler, void *data)
|
||||
enum aca_smu_type type, bank_handler_t handler, void *data)
|
||||
{
|
||||
struct aca_bank_node *node;
|
||||
struct aca_bank *bank;
|
||||
|
|
@ -378,8 +371,28 @@ static int aca_dispatch_banks(struct aca_handle_manager *mgr, struct aca_banks *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int aca_banks_update(struct amdgpu_device *adev, enum aca_error_type type,
|
||||
bank_handler_t handler, void *data)
|
||||
static bool aca_bank_should_update(struct amdgpu_device *adev, enum aca_smu_type type)
|
||||
{
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
bool ret = true;
|
||||
|
||||
/*
|
||||
* Because the UE Valid MCA count will only be cleared after reset,
|
||||
* in order to avoid repeated counting of the error count,
|
||||
* the aca bank is only updated once during the gpu recovery stage.
|
||||
*/
|
||||
if (type == ACA_SMU_TYPE_UE) {
|
||||
if (amdgpu_ras_intr_triggered())
|
||||
ret = atomic_cmpxchg(&aca->ue_update_flag, 0, 1) == 0;
|
||||
else
|
||||
atomic_set(&aca->ue_update_flag, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aca_banks_update(struct amdgpu_device *adev, enum aca_smu_type type,
|
||||
bank_handler_t handler, struct ras_query_context *qctx, void *data)
|
||||
{
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
struct aca_banks banks;
|
||||
|
|
@ -389,9 +402,8 @@ static int aca_banks_update(struct amdgpu_device *adev, enum aca_error_type type
|
|||
if (list_empty(&aca->mgr.list))
|
||||
return 0;
|
||||
|
||||
/* NOTE: pmfw is only support UE and CE */
|
||||
if (type == ACA_ERROR_TYPE_DEFERRED)
|
||||
type = ACA_ERROR_TYPE_CE;
|
||||
if (!aca_bank_should_update(adev, type))
|
||||
return 0;
|
||||
|
||||
ret = aca_smu_get_valid_aca_count(adev, type, &count);
|
||||
if (ret)
|
||||
|
|
@ -402,7 +414,7 @@ static int aca_banks_update(struct amdgpu_device *adev, enum aca_error_type type
|
|||
|
||||
aca_banks_init(&banks);
|
||||
|
||||
ret = aca_smu_get_valid_aca_banks(adev, type, 0, count, &banks);
|
||||
ret = aca_smu_get_valid_aca_banks(adev, type, 0, count, &banks, qctx);
|
||||
if (ret)
|
||||
goto err_release_banks;
|
||||
|
||||
|
|
@ -431,7 +443,7 @@ static int aca_log_aca_error_data(struct aca_bank_error *bank_error, enum aca_er
|
|||
if (type >= ACA_ERROR_TYPE_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
count = bank_error->count[type];
|
||||
count = bank_error->count;
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
|
|
@ -447,6 +459,8 @@ static int aca_log_aca_error_data(struct aca_bank_error *bank_error, enum aca_er
|
|||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, count);
|
||||
break;
|
||||
case ACA_ERROR_TYPE_DEFERRED:
|
||||
amdgpu_ras_error_statistic_de_count(err_data, &mcm_info, NULL, count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -477,12 +491,25 @@ out_unlock:
|
|||
}
|
||||
|
||||
static int __aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle, enum aca_error_type type,
|
||||
struct ras_err_data *err_data)
|
||||
struct ras_err_data *err_data, struct ras_query_context *qctx)
|
||||
{
|
||||
enum aca_smu_type smu_type;
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case ACA_ERROR_TYPE_UE:
|
||||
smu_type = ACA_SMU_TYPE_UE;
|
||||
break;
|
||||
case ACA_ERROR_TYPE_CE:
|
||||
case ACA_ERROR_TYPE_DEFERRED:
|
||||
smu_type = ACA_SMU_TYPE_CE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* udpate aca bank to aca source error_cache first */
|
||||
ret = aca_banks_update(adev, type, handler_aca_log_bank_error, NULL);
|
||||
ret = aca_banks_update(adev, smu_type, handler_aca_log_bank_error, qctx, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -498,10 +525,9 @@ static bool aca_handle_is_valid(struct aca_handle *handle)
|
|||
}
|
||||
|
||||
int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle,
|
||||
enum aca_error_type type, void *data)
|
||||
enum aca_error_type type, struct ras_err_data *err_data,
|
||||
struct ras_query_context *qctx)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)data;
|
||||
|
||||
if (!handle || !err_data)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -511,7 +537,7 @@ int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *han
|
|||
if (!(BIT(type) & handle->mask))
|
||||
return 0;
|
||||
|
||||
return __aca_get_error_data(adev, handle, type, err_data);
|
||||
return __aca_get_error_data(adev, handle, type, err_data, qctx);
|
||||
}
|
||||
|
||||
static void aca_error_init(struct aca_error *aerr, enum aca_error_type type)
|
||||
|
|
@ -668,6 +694,8 @@ int amdgpu_aca_init(struct amdgpu_device *adev)
|
|||
struct amdgpu_aca *aca = &adev->aca;
|
||||
int ret;
|
||||
|
||||
atomic_set(&aca->ue_update_flag, 0);
|
||||
|
||||
ret = aca_manager_init(&aca->mgr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -680,6 +708,8 @@ void amdgpu_aca_fini(struct amdgpu_device *adev)
|
|||
struct amdgpu_aca *aca = &adev->aca;
|
||||
|
||||
aca_manager_fini(&aca->mgr);
|
||||
|
||||
atomic_set(&aca->ue_update_flag, 0);
|
||||
}
|
||||
|
||||
int amdgpu_aca_reset(struct amdgpu_device *adev)
|
||||
|
|
@ -723,23 +753,13 @@ int aca_bank_info_decode(struct aca_bank *bank, struct aca_bank_info *info)
|
|||
|
||||
static int aca_bank_get_error_code(struct amdgpu_device *adev, struct aca_bank *bank)
|
||||
{
|
||||
int error_code;
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
|
||||
|
||||
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
|
||||
case IP_VERSION(13, 0, 6):
|
||||
if (!(adev->flags & AMD_IS_APU) && adev->pm.fw_version >= 0x00555600) {
|
||||
error_code = ACA_REG__SYND__ERRORINFORMATION(bank->regs[ACA_REG_IDX_SYND]);
|
||||
return error_code & 0xff;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!smu_funcs || !smu_funcs->parse_error_code)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* NOTE: the true error code is encoded in status.errorcode[0:7] */
|
||||
error_code = ACA_REG__STATUS__ERRORCODE(bank->regs[ACA_REG_IDX_STATUS]);
|
||||
|
||||
return error_code & 0xff;
|
||||
return smu_funcs->parse_error_code(adev, bank);
|
||||
}
|
||||
|
||||
int aca_bank_check_error_codes(struct amdgpu_device *adev, struct aca_bank *bank, int *err_codes, int size)
|
||||
|
|
@ -750,6 +770,9 @@ int aca_bank_check_error_codes(struct amdgpu_device *adev, struct aca_bank *bank
|
|||
return -EINVAL;
|
||||
|
||||
error_code = aca_bank_get_error_code(adev, bank);
|
||||
if (error_code < 0)
|
||||
return error_code;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (err_codes[i] == error_code)
|
||||
return 0;
|
||||
|
|
@ -784,7 +807,7 @@ static int amdgpu_aca_smu_debug_mode_set(void *data, u64 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_error_type type, int idx)
|
||||
static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_smu_type type, int idx)
|
||||
{
|
||||
struct aca_bank_info info;
|
||||
int i, ret;
|
||||
|
|
@ -793,7 +816,7 @@ static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_e
|
|||
if (ret)
|
||||
return;
|
||||
|
||||
seq_printf(m, "aca entry[%d].type: %s\n", idx, type == ACA_ERROR_TYPE_UE ? "UE" : "CE");
|
||||
seq_printf(m, "aca entry[%d].type: %s\n", idx, type == ACA_SMU_TYPE_UE ? "UE" : "CE");
|
||||
seq_printf(m, "aca entry[%d].info: socketid:%d aid:%d hwid:0x%03x mcatype:0x%04x\n",
|
||||
idx, info.socket_id, info.die_id, info.hwid, info.mcatype);
|
||||
|
||||
|
|
@ -807,7 +830,7 @@ struct aca_dump_context {
|
|||
};
|
||||
|
||||
static int handler_aca_bank_dump(struct aca_handle *handle, struct aca_bank *bank,
|
||||
enum aca_error_type type, void *data)
|
||||
enum aca_smu_type type, void *data)
|
||||
{
|
||||
struct aca_dump_context *ctx = (struct aca_dump_context *)data;
|
||||
|
||||
|
|
@ -816,7 +839,7 @@ static int handler_aca_bank_dump(struct aca_handle *handle, struct aca_bank *ban
|
|||
return handler_aca_log_bank_error(handle, bank, type, NULL);
|
||||
}
|
||||
|
||||
static int aca_dump_show(struct seq_file *m, enum aca_error_type type)
|
||||
static int aca_dump_show(struct seq_file *m, enum aca_smu_type type)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
|
||||
struct aca_dump_context context = {
|
||||
|
|
@ -824,12 +847,12 @@ static int aca_dump_show(struct seq_file *m, enum aca_error_type type)
|
|||
.idx = 0,
|
||||
};
|
||||
|
||||
return aca_banks_update(adev, type, handler_aca_bank_dump, (void *)&context);
|
||||
return aca_banks_update(adev, type, handler_aca_bank_dump, NULL, (void *)&context);
|
||||
}
|
||||
|
||||
static int aca_dump_ce_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
return aca_dump_show(m, ACA_ERROR_TYPE_CE);
|
||||
return aca_dump_show(m, ACA_SMU_TYPE_CE);
|
||||
}
|
||||
|
||||
static int aca_dump_ce_open(struct inode *inode, struct file *file)
|
||||
|
|
@ -847,7 +870,7 @@ static const struct file_operations aca_ce_dump_debug_fops = {
|
|||
|
||||
static int aca_dump_ue_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
return aca_dump_show(m, ACA_ERROR_TYPE_UE);
|
||||
return aca_dump_show(m, ACA_SMU_TYPE_UE);
|
||||
}
|
||||
|
||||
static int aca_dump_ue_open(struct inode *inode, struct file *file)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
#include <linux/list.h>
|
||||
|
||||
struct ras_err_data;
|
||||
struct ras_query_context;
|
||||
|
||||
#define ACA_MAX_REGS_COUNT (16)
|
||||
|
||||
#define ACA_REG_FIELD(x, h, l) (((x) & GENMASK_ULL(h, l)) >> l)
|
||||
|
|
@ -99,7 +102,14 @@ enum aca_error_type {
|
|||
ACA_ERROR_TYPE_COUNT
|
||||
};
|
||||
|
||||
enum aca_smu_type {
|
||||
ACA_SMU_TYPE_UE = 0,
|
||||
ACA_SMU_TYPE_CE,
|
||||
ACA_SMU_TYPE_COUNT,
|
||||
};
|
||||
|
||||
struct aca_bank {
|
||||
enum aca_smu_type type;
|
||||
u64 regs[ACA_MAX_REGS_COUNT];
|
||||
};
|
||||
|
||||
|
|
@ -115,15 +125,10 @@ struct aca_bank_info {
|
|||
int mcatype;
|
||||
};
|
||||
|
||||
struct aca_bank_report {
|
||||
struct aca_bank_info info;
|
||||
u64 count[ACA_ERROR_TYPE_COUNT];
|
||||
};
|
||||
|
||||
struct aca_bank_error {
|
||||
struct list_head node;
|
||||
struct aca_bank_info info;
|
||||
u64 count[ACA_ERROR_TYPE_COUNT];
|
||||
u64 count;
|
||||
};
|
||||
|
||||
struct aca_error {
|
||||
|
|
@ -157,9 +162,8 @@ struct aca_handle {
|
|||
};
|
||||
|
||||
struct aca_bank_ops {
|
||||
int (*aca_bank_generate_report)(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type,
|
||||
struct aca_bank_report *report, void *data);
|
||||
bool (*aca_bank_is_valid)(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type,
|
||||
int (*aca_bank_parser)(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type, void *data);
|
||||
bool (*aca_bank_is_valid)(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type,
|
||||
void *data);
|
||||
};
|
||||
|
||||
|
|
@ -167,13 +171,15 @@ struct aca_smu_funcs {
|
|||
int max_ue_bank_count;
|
||||
int max_ce_bank_count;
|
||||
int (*set_debug_mode)(struct amdgpu_device *adev, bool enable);
|
||||
int (*get_valid_aca_count)(struct amdgpu_device *adev, enum aca_error_type type, u32 *count);
|
||||
int (*get_valid_aca_bank)(struct amdgpu_device *adev, enum aca_error_type type, int idx, struct aca_bank *bank);
|
||||
int (*get_valid_aca_count)(struct amdgpu_device *adev, enum aca_smu_type type, u32 *count);
|
||||
int (*get_valid_aca_bank)(struct amdgpu_device *adev, enum aca_smu_type type, int idx, struct aca_bank *bank);
|
||||
int (*parse_error_code)(struct amdgpu_device *adev, struct aca_bank *bank);
|
||||
};
|
||||
|
||||
struct amdgpu_aca {
|
||||
struct aca_handle_manager mgr;
|
||||
const struct aca_smu_funcs *smu_funcs;
|
||||
atomic_t ue_update_flag;
|
||||
bool is_enabled;
|
||||
};
|
||||
|
||||
|
|
@ -196,7 +202,10 @@ int amdgpu_aca_add_handle(struct amdgpu_device *adev, struct aca_handle *handle,
|
|||
const char *name, const struct aca_info *aca_info, void *data);
|
||||
void amdgpu_aca_remove_handle(struct aca_handle *handle);
|
||||
int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle,
|
||||
enum aca_error_type type, void *data);
|
||||
enum aca_error_type type, struct ras_err_data *err_data,
|
||||
struct ras_query_context *qctx);
|
||||
int amdgpu_aca_smu_set_debug_mode(struct amdgpu_device *adev, bool en);
|
||||
void amdgpu_aca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root);
|
||||
int aca_error_cache_log_bank_error(struct aca_handle *handle, struct aca_bank_info *info,
|
||||
enum aca_error_type type, u64 count);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -637,6 +637,8 @@ static const struct amd_ip_funcs acp_ip_funcs = {
|
|||
.soft_reset = acp_soft_reset,
|
||||
.set_clockgating_state = acp_set_clockgating_state,
|
||||
.set_powergating_state = acp_set_powergating_state,
|
||||
.dump_ip_state = NULL,
|
||||
.print_ip_state = NULL,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version acp_ip_block = {
|
||||
|
|
|
|||
|
|
@ -747,10 +747,17 @@ bool amdgpu_amdkfd_is_fed(struct amdgpu_device *adev)
|
|||
return amdgpu_ras_get_fed_status(adev);
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, bool reset)
|
||||
void amdgpu_amdkfd_ras_pasid_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset)
|
||||
{
|
||||
amdgpu_umc_poison_handler(adev, block, reset);
|
||||
amdgpu_umc_pasid_poison_handler(adev, block, pasid, pasid_fn, data, reset);
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint32_t reset)
|
||||
{
|
||||
amdgpu_umc_pasid_poison_handler(adev, block, 0, NULL, NULL, reset);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
||||
|
|
@ -769,12 +776,20 @@ int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int hub_inst, int hub_type)
|
||||
{
|
||||
if (adev->gfx.ras && adev->gfx.ras->query_utcl2_poison_status)
|
||||
return adev->gfx.ras->query_utcl2_poison_status(adev);
|
||||
else
|
||||
return false;
|
||||
if (!hub_type) {
|
||||
if (adev->gfxhub.funcs->query_utcl2_poison_status)
|
||||
return adev->gfxhub.funcs->query_utcl2_poison_status(adev, hub_inst);
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
if (adev->mmhub.funcs->query_utcl2_poison_status)
|
||||
return adev->mmhub.funcs->query_utcl2_poison_status(adev, hub_inst);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev)
|
||||
|
|
|
|||
|
|
@ -336,12 +336,18 @@ void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev);
|
|||
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
|
||||
struct tile_config *config);
|
||||
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, bool reset);
|
||||
enum amdgpu_ras_block block, uint32_t reset);
|
||||
|
||||
void amdgpu_amdkfd_ras_pasid_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset);
|
||||
|
||||
bool amdgpu_amdkfd_is_fed(struct amdgpu_device *adev);
|
||||
bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem);
|
||||
void amdgpu_amdkfd_block_mmu_notifications(void *p);
|
||||
int amdgpu_amdkfd_criu_resume(void *p);
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev);
|
||||
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
int hub_inst, int hub_type);
|
||||
int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
||||
uint64_t size, u32 alloc_flag, int8_t xcp_id);
|
||||
void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev,
|
||||
|
|
|
|||
|
|
@ -881,6 +881,7 @@ uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
#define TCP_WATCH_STRIDE (mmTCP_WATCH1_ADDR_H - mmTCP_WATCH0_ADDR_H)
|
||||
#define SQ_WATCH_STRIDE (mmSQ_WATCH1_ADDR_H - mmSQ_WATCH0_ADDR_H)
|
||||
uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
|
||||
uint64_t watch_address,
|
||||
uint32_t watch_address_mask,
|
||||
|
|
@ -889,55 +890,93 @@ uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
|
|||
uint32_t debug_vmid,
|
||||
uint32_t inst)
|
||||
{
|
||||
/* SQ_WATCH?_ADDR_* and TCP_WATCH?_ADDR_* are programmed with the
|
||||
* same values.
|
||||
*/
|
||||
uint32_t watch_address_high;
|
||||
uint32_t watch_address_low;
|
||||
uint32_t watch_address_cntl;
|
||||
|
||||
watch_address_cntl = 0;
|
||||
uint32_t tcp_watch_address_cntl;
|
||||
uint32_t sq_watch_address_cntl;
|
||||
|
||||
watch_address_low = lower_32_bits(watch_address);
|
||||
watch_address_high = upper_32_bits(watch_address) & 0xffff;
|
||||
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
tcp_watch_address_cntl = 0;
|
||||
tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VMID,
|
||||
debug_vmid);
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MODE,
|
||||
watch_mode);
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
MASK,
|
||||
watch_address_mask >> 7);
|
||||
|
||||
sq_watch_address_cntl = 0;
|
||||
sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
|
||||
SQ_WATCH0_CNTL,
|
||||
VMID,
|
||||
debug_vmid);
|
||||
sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
|
||||
SQ_WATCH0_CNTL,
|
||||
MODE,
|
||||
watch_mode);
|
||||
sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
|
||||
SQ_WATCH0_CNTL,
|
||||
MASK,
|
||||
watch_address_mask >> 6);
|
||||
|
||||
/* Turning off this watch point until we set all the registers */
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VALID,
|
||||
0);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
tcp_watch_address_cntl);
|
||||
|
||||
sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
|
||||
SQ_WATCH0_CNTL,
|
||||
VALID,
|
||||
0);
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) +
|
||||
(watch_id * SQ_WATCH_STRIDE)),
|
||||
sq_watch_address_cntl);
|
||||
|
||||
/* Program {TCP,SQ}_WATCH?_ADDR* */
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_high);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_L) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_low);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_ADDR_H) +
|
||||
(watch_id * SQ_WATCH_STRIDE)),
|
||||
watch_address_high);
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_ADDR_L) +
|
||||
(watch_id * SQ_WATCH_STRIDE)),
|
||||
watch_address_low);
|
||||
|
||||
/* Enable the watch point */
|
||||
watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
|
||||
tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
|
||||
TCP_WATCH0_CNTL,
|
||||
VALID,
|
||||
1);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
|
||||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
tcp_watch_address_cntl);
|
||||
|
||||
sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
|
||||
SQ_WATCH0_CNTL,
|
||||
VALID,
|
||||
1);
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) +
|
||||
(watch_id * SQ_WATCH_STRIDE)),
|
||||
sq_watch_address_cntl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -953,8 +992,14 @@ uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev,
|
|||
(watch_id * TCP_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
|
||||
WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) +
|
||||
(watch_id * SQ_WATCH_STRIDE)),
|
||||
watch_address_cntl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#undef TCP_WATCH_STRIDE
|
||||
#undef SQ_WATCH_STRIDE
|
||||
|
||||
|
||||
/* kgd_gfx_v10_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ union firmware_info {
|
|||
struct atom_firmware_info_v3_2 v32;
|
||||
struct atom_firmware_info_v3_3 v33;
|
||||
struct atom_firmware_info_v3_4 v34;
|
||||
struct atom_firmware_info_v3_5 v35;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -872,6 +873,10 @@ int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev)
|
|||
fw_reserved_fb_size =
|
||||
(firmware_info->v34.fw_reserved_size_in_kb << 10);
|
||||
break;
|
||||
case 5:
|
||||
fw_reserved_fb_size =
|
||||
(firmware_info->v35.fw_reserved_size_in_kb << 10);
|
||||
break;
|
||||
default:
|
||||
fw_reserved_fb_size = 0;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
|
|||
for (i = 0; i < n; i++) {
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence,
|
||||
false, false, false);
|
||||
false, false, 0);
|
||||
if (r)
|
||||
goto exit_do_move;
|
||||
r = dma_fence_wait(fence, false);
|
||||
|
|
|
|||
|
|
@ -2065,12 +2065,13 @@ static ssize_t amdgpu_reset_dump_register_list_write(struct file *f,
|
|||
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
|
||||
char reg_offset[11];
|
||||
uint32_t *new = NULL, *tmp = NULL;
|
||||
int ret, i = 0, len = 0;
|
||||
unsigned int len = 0;
|
||||
int ret, i = 0;
|
||||
|
||||
do {
|
||||
memset(reg_offset, 0, 11);
|
||||
if (copy_from_user(reg_offset, buf + len,
|
||||
min(10, ((int)size-len)))) {
|
||||
min(10, (size-len)))) {
|
||||
ret = -EFAULT;
|
||||
goto error_free;
|
||||
}
|
||||
|
|
|
|||
360
drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
Normal file
360
drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright 2024 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <generated/utsrelease.h>
|
||||
#include <linux/devcoredump.h>
|
||||
#include "amdgpu_dev_coredump.h"
|
||||
#include "atom.h"
|
||||
|
||||
#ifndef CONFIG_DEV_COREDUMP
|
||||
void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
}
|
||||
#else
|
||||
|
||||
const char *hw_ip_names[MAX_HWIP] = {
|
||||
[GC_HWIP] = "GC",
|
||||
[HDP_HWIP] = "HDP",
|
||||
[SDMA0_HWIP] = "SDMA0",
|
||||
[SDMA1_HWIP] = "SDMA1",
|
||||
[SDMA2_HWIP] = "SDMA2",
|
||||
[SDMA3_HWIP] = "SDMA3",
|
||||
[SDMA4_HWIP] = "SDMA4",
|
||||
[SDMA5_HWIP] = "SDMA5",
|
||||
[SDMA6_HWIP] = "SDMA6",
|
||||
[SDMA7_HWIP] = "SDMA7",
|
||||
[LSDMA_HWIP] = "LSDMA",
|
||||
[MMHUB_HWIP] = "MMHUB",
|
||||
[ATHUB_HWIP] = "ATHUB",
|
||||
[NBIO_HWIP] = "NBIO",
|
||||
[MP0_HWIP] = "MP0",
|
||||
[MP1_HWIP] = "MP1",
|
||||
[UVD_HWIP] = "UVD/JPEG/VCN",
|
||||
[VCN1_HWIP] = "VCN1",
|
||||
[VCE_HWIP] = "VCE",
|
||||
[VPE_HWIP] = "VPE",
|
||||
[DF_HWIP] = "DF",
|
||||
[DCE_HWIP] = "DCE",
|
||||
[OSSSYS_HWIP] = "OSSSYS",
|
||||
[SMUIO_HWIP] = "SMUIO",
|
||||
[PWR_HWIP] = "PWR",
|
||||
[NBIF_HWIP] = "NBIF",
|
||||
[THM_HWIP] = "THM",
|
||||
[CLK_HWIP] = "CLK",
|
||||
[UMC_HWIP] = "UMC",
|
||||
[RSMU_HWIP] = "RSMU",
|
||||
[XGMI_HWIP] = "XGMI",
|
||||
[DCI_HWIP] = "DCI",
|
||||
[PCIE_HWIP] = "PCIE",
|
||||
};
|
||||
|
||||
static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
|
||||
struct drm_printer *p)
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t feature;
|
||||
uint8_t smu_program, smu_major, smu_minor, smu_debug;
|
||||
struct atom_context *ctx = adev->mode_info.atom_context;
|
||||
|
||||
drm_printf(p, "VCE feature version: %u, fw version: 0x%08x\n",
|
||||
adev->vce.fb_version, adev->vce.fw_version);
|
||||
drm_printf(p, "UVD feature version: %u, fw version: 0x%08x\n", 0,
|
||||
adev->uvd.fw_version);
|
||||
drm_printf(p, "GMC feature version: %u, fw version: 0x%08x\n", 0,
|
||||
adev->gmc.fw_version);
|
||||
drm_printf(p, "ME feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.me_feature_version, adev->gfx.me_fw_version);
|
||||
drm_printf(p, "PFP feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.pfp_feature_version, adev->gfx.pfp_fw_version);
|
||||
drm_printf(p, "CE feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.ce_feature_version, adev->gfx.ce_fw_version);
|
||||
drm_printf(p, "RLC feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.rlc_feature_version, adev->gfx.rlc_fw_version);
|
||||
|
||||
drm_printf(p, "RLC SRLC feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.rlc_srlc_feature_version,
|
||||
adev->gfx.rlc_srlc_fw_version);
|
||||
drm_printf(p, "RLC SRLG feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.rlc_srlg_feature_version,
|
||||
adev->gfx.rlc_srlg_fw_version);
|
||||
drm_printf(p, "RLC SRLS feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.rlc_srls_feature_version,
|
||||
adev->gfx.rlc_srls_fw_version);
|
||||
drm_printf(p, "RLCP feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.rlcp_ucode_feature_version,
|
||||
adev->gfx.rlcp_ucode_version);
|
||||
drm_printf(p, "RLCV feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.rlcv_ucode_feature_version,
|
||||
adev->gfx.rlcv_ucode_version);
|
||||
drm_printf(p, "MEC feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.mec_feature_version, adev->gfx.mec_fw_version);
|
||||
|
||||
if (adev->gfx.mec2_fw)
|
||||
drm_printf(p, "MEC2 feature version: %u, fw version: 0x%08x\n",
|
||||
adev->gfx.mec2_feature_version,
|
||||
adev->gfx.mec2_fw_version);
|
||||
|
||||
drm_printf(p, "IMU feature version: %u, fw version: 0x%08x\n", 0,
|
||||
adev->gfx.imu_fw_version);
|
||||
drm_printf(p, "PSP SOS feature version: %u, fw version: 0x%08x\n",
|
||||
adev->psp.sos.feature_version, adev->psp.sos.fw_version);
|
||||
drm_printf(p, "PSP ASD feature version: %u, fw version: 0x%08x\n",
|
||||
adev->psp.asd_context.bin_desc.feature_version,
|
||||
adev->psp.asd_context.bin_desc.fw_version);
|
||||
|
||||
drm_printf(p, "TA XGMI feature version: 0x%08x, fw version: 0x%08x\n",
|
||||
adev->psp.xgmi_context.context.bin_desc.feature_version,
|
||||
adev->psp.xgmi_context.context.bin_desc.fw_version);
|
||||
drm_printf(p, "TA RAS feature version: 0x%08x, fw version: 0x%08x\n",
|
||||
adev->psp.ras_context.context.bin_desc.feature_version,
|
||||
adev->psp.ras_context.context.bin_desc.fw_version);
|
||||
drm_printf(p, "TA HDCP feature version: 0x%08x, fw version: 0x%08x\n",
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version,
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version);
|
||||
drm_printf(p, "TA DTM feature version: 0x%08x, fw version: 0x%08x\n",
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version,
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version);
|
||||
drm_printf(p, "TA RAP feature version: 0x%08x, fw version: 0x%08x\n",
|
||||
adev->psp.rap_context.context.bin_desc.feature_version,
|
||||
adev->psp.rap_context.context.bin_desc.fw_version);
|
||||
drm_printf(p,
|
||||
"TA SECURE DISPLAY feature version: 0x%08x, fw version: 0x%08x\n",
|
||||
adev->psp.securedisplay_context.context.bin_desc.feature_version,
|
||||
adev->psp.securedisplay_context.context.bin_desc.fw_version);
|
||||
|
||||
/* SMC firmware */
|
||||
version = adev->pm.fw_version;
|
||||
|
||||
smu_program = (version >> 24) & 0xff;
|
||||
smu_major = (version >> 16) & 0xff;
|
||||
smu_minor = (version >> 8) & 0xff;
|
||||
smu_debug = (version >> 0) & 0xff;
|
||||
drm_printf(p,
|
||||
"SMC feature version: %u, program: %d, fw version: 0x%08x (%d.%d.%d)\n",
|
||||
0, smu_program, version, smu_major, smu_minor, smu_debug);
|
||||
|
||||
/* SDMA firmware */
|
||||
for (int i = 0; i < adev->sdma.num_instances; i++) {
|
||||
drm_printf(p,
|
||||
"SDMA%d feature version: %u, firmware version: 0x%08x\n",
|
||||
i, adev->sdma.instance[i].feature_version,
|
||||
adev->sdma.instance[i].fw_version);
|
||||
}
|
||||
|
||||
drm_printf(p, "VCN feature version: %u, fw version: 0x%08x\n", 0,
|
||||
adev->vcn.fw_version);
|
||||
drm_printf(p, "DMCU feature version: %u, fw version: 0x%08x\n", 0,
|
||||
adev->dm.dmcu_fw_version);
|
||||
drm_printf(p, "DMCUB feature version: %u, fw version: 0x%08x\n", 0,
|
||||
adev->dm.dmcub_fw_version);
|
||||
drm_printf(p, "PSP TOC feature version: %u, fw version: 0x%08x\n",
|
||||
adev->psp.toc.feature_version, adev->psp.toc.fw_version);
|
||||
|
||||
version = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK;
|
||||
feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK) >>
|
||||
AMDGPU_MES_FEAT_VERSION_SHIFT;
|
||||
drm_printf(p, "MES_KIQ feature version: %u, fw version: 0x%08x\n",
|
||||
feature, version);
|
||||
|
||||
version = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK;
|
||||
feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK) >>
|
||||
AMDGPU_MES_FEAT_VERSION_SHIFT;
|
||||
drm_printf(p, "MES feature version: %u, fw version: 0x%08x\n", feature,
|
||||
version);
|
||||
|
||||
drm_printf(p, "VPE feature version: %u, fw version: 0x%08x\n",
|
||||
adev->vpe.feature_version, adev->vpe.fw_version);
|
||||
|
||||
drm_printf(p, "\nVBIOS Information\n");
|
||||
drm_printf(p, "vbios name : %s\n", ctx->name);
|
||||
drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
|
||||
drm_printf(p, "vbios version : %d\n", ctx->version);
|
||||
drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
|
||||
drm_printf(p, "vbios date : %s\n", ctx->date);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
||||
void *data, size_t datalen)
|
||||
{
|
||||
struct drm_printer p;
|
||||
struct amdgpu_coredump_info *coredump = data;
|
||||
struct drm_print_iterator iter;
|
||||
struct amdgpu_vm_fault_info *fault_info;
|
||||
int i, ver;
|
||||
|
||||
iter.data = buffer;
|
||||
iter.offset = 0;
|
||||
iter.start = offset;
|
||||
iter.remain = count;
|
||||
|
||||
p = drm_coredump_printer(&iter);
|
||||
|
||||
drm_printf(&p, "**** AMDGPU Device Coredump ****\n");
|
||||
drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
|
||||
drm_printf(&p, "kernel: " UTS_RELEASE "\n");
|
||||
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
|
||||
drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec,
|
||||
coredump->reset_time.tv_nsec);
|
||||
|
||||
if (coredump->reset_task_info.pid)
|
||||
drm_printf(&p, "process_name: %s PID: %d\n",
|
||||
coredump->reset_task_info.process_name,
|
||||
coredump->reset_task_info.pid);
|
||||
|
||||
/* GPU IP's information of the SOC */
|
||||
drm_printf(&p, "\nIP Information\n");
|
||||
drm_printf(&p, "SOC Family: %d\n", coredump->adev->family);
|
||||
drm_printf(&p, "SOC Revision id: %d\n", coredump->adev->rev_id);
|
||||
drm_printf(&p, "SOC External Revision id: %d\n", coredump->adev->external_rev_id);
|
||||
|
||||
for (int i = 1; i < MAX_HWIP; i++) {
|
||||
for (int j = 0; j < HWIP_MAX_INSTANCE; j++) {
|
||||
ver = coredump->adev->ip_versions[i][j];
|
||||
if (ver)
|
||||
drm_printf(&p, "HWIP: %s[%d][%d]: v%d.%d.%d.%d.%d\n",
|
||||
hw_ip_names[i], i, j,
|
||||
IP_VERSION_MAJ(ver),
|
||||
IP_VERSION_MIN(ver),
|
||||
IP_VERSION_REV(ver),
|
||||
IP_VERSION_VARIANT(ver),
|
||||
IP_VERSION_SUBREV(ver));
|
||||
}
|
||||
}
|
||||
|
||||
/* IP firmware information */
|
||||
drm_printf(&p, "\nIP Firmwares\n");
|
||||
amdgpu_devcoredump_fw_info(coredump->adev, &p);
|
||||
|
||||
if (coredump->ring) {
|
||||
drm_printf(&p, "\nRing timed out details\n");
|
||||
drm_printf(&p, "IP Type: %d Ring Name: %s\n",
|
||||
coredump->ring->funcs->type,
|
||||
coredump->ring->name);
|
||||
}
|
||||
|
||||
/* Add page fault information */
|
||||
fault_info = &coredump->adev->vm_manager.fault_info;
|
||||
drm_printf(&p, "\n[%s] Page fault observed\n",
|
||||
fault_info->vmhub ? "mmhub" : "gfxhub");
|
||||
drm_printf(&p, "Faulty page starting at address: 0x%016llx\n", fault_info->addr);
|
||||
drm_printf(&p, "Protection fault status register: 0x%x\n\n", fault_info->status);
|
||||
|
||||
/* dump the ip state for each ip */
|
||||
drm_printf(&p, "IP Dump\n");
|
||||
for (int i = 0; i < coredump->adev->num_ip_blocks; i++) {
|
||||
if (coredump->adev->ip_blocks[i].version->funcs->print_ip_state) {
|
||||
drm_printf(&p, "IP: %s\n",
|
||||
coredump->adev->ip_blocks[i]
|
||||
.version->funcs->name);
|
||||
coredump->adev->ip_blocks[i]
|
||||
.version->funcs->print_ip_state(
|
||||
(void *)coredump->adev, &p);
|
||||
drm_printf(&p, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Add ring buffer information */
|
||||
drm_printf(&p, "Ring buffer information\n");
|
||||
for (int i = 0; i < coredump->adev->num_rings; i++) {
|
||||
int j = 0;
|
||||
struct amdgpu_ring *ring = coredump->adev->rings[i];
|
||||
|
||||
drm_printf(&p, "ring name: %s\n", ring->name);
|
||||
drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
|
||||
amdgpu_ring_get_rptr(ring),
|
||||
amdgpu_ring_get_wptr(ring),
|
||||
ring->buf_mask);
|
||||
drm_printf(&p, "Ring size in dwords: %d\n",
|
||||
ring->ring_size / 4);
|
||||
drm_printf(&p, "Ring contents\n");
|
||||
drm_printf(&p, "Offset \t Value\n");
|
||||
|
||||
while (j < ring->ring_size) {
|
||||
drm_printf(&p, "0x%x \t 0x%x\n", j, ring->ring[j / 4]);
|
||||
j += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (coredump->reset_vram_lost)
|
||||
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
|
||||
if (coredump->adev->reset_info.num_regs) {
|
||||
drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n");
|
||||
|
||||
for (i = 0; i < coredump->adev->reset_info.num_regs; i++)
|
||||
drm_printf(&p, "0x%08x: 0x%08x\n",
|
||||
coredump->adev->reset_info.reset_dump_reg_list[i],
|
||||
coredump->adev->reset_info.reset_dump_reg_value[i]);
|
||||
}
|
||||
|
||||
return count - iter.remain;
|
||||
}
|
||||
|
||||
static void amdgpu_devcoredump_free(void *data)
|
||||
{
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_coredump_info *coredump;
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct amdgpu_job *job = reset_context->job;
|
||||
struct drm_sched_job *s_job;
|
||||
|
||||
coredump = kzalloc(sizeof(*coredump), GFP_NOWAIT);
|
||||
|
||||
if (!coredump) {
|
||||
DRM_ERROR("%s: failed to allocate memory for coredump\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
coredump->reset_vram_lost = vram_lost;
|
||||
|
||||
if (reset_context->job && reset_context->job->vm) {
|
||||
struct amdgpu_task_info *ti;
|
||||
struct amdgpu_vm *vm = reset_context->job->vm;
|
||||
|
||||
ti = amdgpu_vm_get_task_info_vm(vm);
|
||||
if (ti) {
|
||||
coredump->reset_task_info = *ti;
|
||||
amdgpu_vm_put_task_info(ti);
|
||||
}
|
||||
}
|
||||
|
||||
if (job) {
|
||||
s_job = &job->base;
|
||||
coredump->ring = to_amdgpu_ring(s_job->sched);
|
||||
}
|
||||
|
||||
coredump->adev = adev;
|
||||
|
||||
ktime_get_ts64(&coredump->reset_time);
|
||||
|
||||
dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT,
|
||||
amdgpu_devcoredump_read, amdgpu_devcoredump_free);
|
||||
}
|
||||
#endif
|
||||
47
drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
Normal file
47
drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2024 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_DEV_COREDUMP_H__
|
||||
#define __AMDGPU_DEV_COREDUMP_H__
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#ifdef CONFIG_DEV_COREDUMP
|
||||
|
||||
#define AMDGPU_COREDUMP_VERSION "1"
|
||||
|
||||
struct amdgpu_coredump_info {
|
||||
struct amdgpu_device *adev;
|
||||
struct amdgpu_task_info reset_task_info;
|
||||
struct timespec64 reset_time;
|
||||
bool reset_vram_lost;
|
||||
struct amdgpu_ring *ring;
|
||||
};
|
||||
#endif
|
||||
|
||||
void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
|
||||
#endif
|
||||
|
|
@ -74,6 +74,7 @@
|
|||
#include "amdgpu_fru_eeprom.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_virt.h"
|
||||
#include "amdgpu_dev_coredump.h"
|
||||
|
||||
#include <linux/suspend.h>
|
||||
#include <drm/task_barrier.h>
|
||||
|
|
@ -143,6 +144,8 @@ const char *amdgpu_asic_name[] = {
|
|||
"LAST",
|
||||
};
|
||||
|
||||
static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* DOC: pcie_replay_count
|
||||
*
|
||||
|
|
@ -335,16 +338,93 @@ bool amdgpu_device_supports_boco(struct drm_device *dev)
|
|||
*
|
||||
* @dev: drm_device pointer
|
||||
*
|
||||
* Returns true if the device supporte BACO,
|
||||
* otherwise return false.
|
||||
* Return:
|
||||
* 1 if the device supporte BACO;
|
||||
* 3 if the device support MACO (only works if BACO is supported)
|
||||
* otherwise return 0.
|
||||
*/
|
||||
bool amdgpu_device_supports_baco(struct drm_device *dev)
|
||||
int amdgpu_device_supports_baco(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
return amdgpu_asic_supports_baco(adev);
|
||||
}
|
||||
|
||||
void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int bamaco_support;
|
||||
|
||||
dev = adev_to_drm(adev);
|
||||
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_NONE;
|
||||
bamaco_support = amdgpu_device_supports_baco(dev);
|
||||
|
||||
switch (amdgpu_runtime_pm) {
|
||||
case 2:
|
||||
if (bamaco_support & MACO_SUPPORT) {
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BAMACO;
|
||||
dev_info(adev->dev, "Forcing BAMACO for runtime pm\n");
|
||||
} else if (bamaco_support == BACO_SUPPORT) {
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
dev_info(adev->dev, "Requested mode BAMACO not available,fallback to use BACO\n");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (bamaco_support & BACO_SUPPORT) {
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
dev_info(adev->dev, "Forcing BACO for runtime pm\n");
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
case -2:
|
||||
if (amdgpu_device_supports_px(dev)) { /* enable PX as runtime mode */
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_PX;
|
||||
dev_info(adev->dev, "Using ATPX for runtime pm\n");
|
||||
} else if (amdgpu_device_supports_boco(dev)) { /* enable boco as runtime mode */
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO;
|
||||
dev_info(adev->dev, "Using BOCO for runtime pm\n");
|
||||
} else {
|
||||
if (!bamaco_support)
|
||||
goto no_runtime_pm;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
/* BACO are not supported on vega20 and arctrus */
|
||||
break;
|
||||
case CHIP_VEGA10:
|
||||
/* enable BACO as runpm mode if noretry=0 */
|
||||
if (!adev->gmc.noretry)
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
break;
|
||||
default:
|
||||
/* enable BACO as runpm mode on CI+ */
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) {
|
||||
if (bamaco_support & MACO_SUPPORT) {
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BAMACO;
|
||||
dev_info(adev->dev, "Using BAMACO for runtime pm\n");
|
||||
} else {
|
||||
dev_info(adev->dev, "Using BACO for runtime pm\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
dev_info(adev->dev, "runtime pm is manually disabled\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
no_runtime_pm:
|
||||
if (adev->pm.rpm_mode == AMDGPU_RUNPM_NONE)
|
||||
dev_info(adev->dev, "Runtime PM not available\n");
|
||||
}
|
||||
/**
|
||||
* amdgpu_device_supports_smart_shift - Is the device dGPU with
|
||||
* smart shift support
|
||||
|
|
@ -1402,13 +1482,17 @@ static int amdgpu_device_wb_init(struct amdgpu_device *adev)
|
|||
*/
|
||||
int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
|
||||
{
|
||||
unsigned long offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
|
||||
unsigned long flags, offset;
|
||||
|
||||
spin_lock_irqsave(&adev->wb.lock, flags);
|
||||
offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
|
||||
if (offset < adev->wb.num_wb) {
|
||||
__set_bit(offset, adev->wb.used);
|
||||
spin_unlock_irqrestore(&adev->wb.lock, flags);
|
||||
*wb = offset << 3; /* convert to dw offset */
|
||||
return 0;
|
||||
} else {
|
||||
spin_unlock_irqrestore(&adev->wb.lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1423,9 +1507,13 @@ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
|
|||
*/
|
||||
void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
wb >>= 3;
|
||||
spin_lock_irqsave(&adev->wb.lock, flags);
|
||||
if (wb < adev->wb.num_wb)
|
||||
__clear_bit(wb, adev->wb.used);
|
||||
spin_unlock_irqrestore(&adev->wb.lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1455,7 +1543,7 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
|
|||
|
||||
/* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */
|
||||
if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR))
|
||||
DRM_WARN("System can't access extended configuration space,please check!!\n");
|
||||
DRM_WARN("System can't access extended configuration space, please check!!\n");
|
||||
|
||||
/* skip if the bios has already enabled large BAR */
|
||||
if (adev->gmc.real_vram_size &&
|
||||
|
|
@ -3981,6 +4069,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
spin_lock_init(&adev->se_cac_idx_lock);
|
||||
spin_lock_init(&adev->audio_endpt_idx_lock);
|
||||
spin_lock_init(&adev->mm_stats.lock);
|
||||
spin_lock_init(&adev->wb.lock);
|
||||
|
||||
INIT_LIST_HEAD(&adev->shadow_list);
|
||||
mutex_init(&adev->shadow_list_lock);
|
||||
|
|
@ -4069,6 +4158,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
/* Enable TMZ based on IP_VERSION */
|
||||
amdgpu_gmc_tmz_set(adev);
|
||||
|
||||
if (amdgpu_sriov_vf(adev) &&
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
|
||||
/* VF MMIO access (except mailbox range) from CPU
|
||||
* will be blocked during sriov runtime
|
||||
*/
|
||||
adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT;
|
||||
|
||||
amdgpu_gmc_noretry_set(adev);
|
||||
/* Need to get xgmi info early to decide the reset behavior*/
|
||||
if (adev->gmc.xgmi.supported) {
|
||||
|
|
@ -4974,12 +5070,15 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||
retry:
|
||||
amdgpu_amdkfd_pre_reset(adev);
|
||||
|
||||
amdgpu_device_stop_pending_resets(adev);
|
||||
|
||||
if (from_hypervisor)
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
else
|
||||
r = amdgpu_virt_reset_gpu(adev);
|
||||
if (r)
|
||||
return r;
|
||||
amdgpu_ras_set_fed(adev, false);
|
||||
amdgpu_irq_gpu_reset_resume_helper(adev);
|
||||
|
||||
/* some sw clean up VF needs to do before recover */
|
||||
|
|
@ -5263,11 +5362,21 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
|||
struct amdgpu_device *tmp_adev = NULL;
|
||||
bool need_full_reset, skip_hw_reset, vram_lost = false;
|
||||
int r = 0;
|
||||
uint32_t i;
|
||||
|
||||
/* Try reset handler method first */
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
amdgpu_reset_reg_dumps(tmp_adev);
|
||||
|
||||
if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) {
|
||||
amdgpu_reset_reg_dumps(tmp_adev);
|
||||
|
||||
/* Trigger ip dump before we reset the asic */
|
||||
for (i = 0; i < tmp_adev->num_ip_blocks; i++)
|
||||
if (tmp_adev->ip_blocks[i].version->funcs->dump_ip_state)
|
||||
tmp_adev->ip_blocks[i].version->funcs
|
||||
->dump_ip_state((void *)tmp_adev);
|
||||
}
|
||||
|
||||
reset_context->reset_device_list = device_list_handle;
|
||||
r = amdgpu_reset_perform_reset(tmp_adev, reset_context);
|
||||
|
|
@ -5340,7 +5449,8 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
|||
|
||||
vram_lost = amdgpu_device_check_vram_lost(tmp_adev);
|
||||
|
||||
amdgpu_coredump(tmp_adev, vram_lost, reset_context);
|
||||
if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags))
|
||||
amdgpu_coredump(tmp_adev, vram_lost, reset_context);
|
||||
|
||||
if (vram_lost) {
|
||||
DRM_INFO("VRAM is lost due to GPU reset!\n");
|
||||
|
|
@ -5538,6 +5648,23 @@ static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev)
|
|||
|
||||
}
|
||||
|
||||
static int amdgpu_device_health_check(struct list_head *device_list_handle)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev;
|
||||
int ret = 0;
|
||||
u32 status;
|
||||
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
pci_read_config_dword(tmp_adev->pdev, PCI_COMMAND, &status);
|
||||
if (PCI_POSSIBLE_ERROR(status)) {
|
||||
dev_err(tmp_adev->dev, "device lost from bus!");
|
||||
ret = -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_gpu_recover - reset the asic and recover scheduler
|
||||
*
|
||||
|
|
@ -5609,6 +5736,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
device_list_handle = &device_list;
|
||||
}
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
r = amdgpu_device_health_check(device_list_handle);
|
||||
if (r)
|
||||
goto end_reset;
|
||||
}
|
||||
|
||||
/* We need to lock reset domain only once both for XGMI and single device */
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
|
|
@ -5691,11 +5824,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
|||
tmp_adev->asic_reset_res = r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop all pending non scheduler resets. Scheduler resets
|
||||
* were already dropped during drm_sched_stop
|
||||
*/
|
||||
amdgpu_device_stop_pending_resets(tmp_adev);
|
||||
if (!amdgpu_sriov_vf(tmp_adev))
|
||||
/*
|
||||
* Drop all pending non scheduler resets. Scheduler resets
|
||||
* were already dropped during drm_sched_stop
|
||||
*/
|
||||
amdgpu_device_stop_pending_resets(tmp_adev);
|
||||
}
|
||||
|
||||
/* Actual ASIC resets if needed.*/
|
||||
|
|
@ -5774,6 +5908,7 @@ skip_sched_resume:
|
|||
reset_list);
|
||||
amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
|
||||
|
||||
end_reset:
|
||||
if (hive) {
|
||||
mutex_unlock(&hive->hive_lock);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@
|
|||
#include "smuio_v13_0.h"
|
||||
#include "smuio_v13_0_3.h"
|
||||
#include "smuio_v13_0_6.h"
|
||||
#include "smuio_v14_0_2.h"
|
||||
#include "vcn_v5_0_0.h"
|
||||
#include "jpeg_v5_0_0.h"
|
||||
|
||||
|
|
@ -245,6 +246,9 @@ static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
#define IP_DISCOVERY_V2 2
|
||||
#define IP_DISCOVERY_V4 4
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
|
||||
uint8_t *binary)
|
||||
{
|
||||
|
|
@ -259,14 +263,14 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
|
|||
* wait for this to complete. Once the C2PMSG is updated, we can
|
||||
* continue.
|
||||
*/
|
||||
if (dev_is_removable(&adev->pdev->dev)) {
|
||||
for (i = 0; i < 1000; i++) {
|
||||
msg = RREG32(mmMP0_SMN_C2PMSG_33);
|
||||
if (msg & 0x80000000)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
msg = RREG32(mmMP0_SMN_C2PMSG_33);
|
||||
if (msg & 0x80000000)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
|
||||
vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||
|
||||
if (vram_size) {
|
||||
|
|
@ -1897,6 +1901,8 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
|
|||
break;
|
||||
case IP_VERSION(14, 0, 0):
|
||||
case IP_VERSION(14, 0, 1):
|
||||
case IP_VERSION(14, 0, 2):
|
||||
case IP_VERSION(14, 0, 3):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2678,6 +2684,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(14, 0, 1):
|
||||
adev->smuio.funcs = &smuio_v13_0_6_funcs;
|
||||
break;
|
||||
case IP_VERSION(14, 0, 2):
|
||||
adev->smuio.funcs = &smuio_v14_0_2_funcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -925,7 +925,7 @@ module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444);
|
|||
* GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)
|
||||
*/
|
||||
MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco/bamaco)");
|
||||
module_param_named(reset_method, amdgpu_reset_method, int, 0444);
|
||||
module_param_named(reset_method, amdgpu_reset_method, int, 0644);
|
||||
|
||||
/**
|
||||
* DOC: bad_page_threshold (int) Bad page threshold is specifies the
|
||||
|
|
@ -2481,6 +2481,7 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
|
|||
|
||||
/* Use a common context, just need to make sure full reset is done */
|
||||
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
|
||||
set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
|
||||
r = amdgpu_do_asic_reset(&device_list, &reset_context);
|
||||
|
||||
if (r) {
|
||||
|
|
@ -2744,7 +2745,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
|
|||
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
|
||||
} else if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO) {
|
||||
/* nothing to do */
|
||||
} else if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) {
|
||||
} else if ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) ||
|
||||
(adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)) {
|
||||
amdgpu_device_baco_enter(drm_dev);
|
||||
}
|
||||
|
||||
|
|
@ -2784,7 +2786,8 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
|
|||
* PCI core handles it for _PR3.
|
||||
*/
|
||||
pci_set_master(pdev);
|
||||
} else if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) {
|
||||
} else if ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) ||
|
||||
(adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)) {
|
||||
amdgpu_device_baco_exit(drm_dev);
|
||||
}
|
||||
ret = amdgpu_device_resume(drm_dev, false);
|
||||
|
|
|
|||
|
|
@ -1206,7 +1206,8 @@ void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev,
|
|||
fw_size = le32_to_cpu(cp_hdr_v2_0->data_size_bytes);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
dev_err(adev->dev, "Invalid ucode id %u\n", ucode_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
|
|
|
|||
|
|
@ -259,7 +259,6 @@ struct amdgpu_cu_info {
|
|||
struct amdgpu_gfx_ras {
|
||||
struct amdgpu_ras_block_object ras_block;
|
||||
void (*enable_watchdog_timer)(struct amdgpu_device *adev);
|
||||
bool (*query_utcl2_poison_status)(struct amdgpu_device *adev);
|
||||
int (*rlc_gc_fed_irq)(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
|
|
@ -434,6 +433,10 @@ struct amdgpu_gfx {
|
|||
uint32_t num_xcc_per_xcp;
|
||||
struct mutex partition_mutex;
|
||||
bool mcbp; /* mid command buffer preemption */
|
||||
|
||||
/* IP reg dump */
|
||||
uint32_t *ip_dump;
|
||||
uint32_t reg_count;
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras_reg_entry {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ struct amdgpu_gfxhub_funcs {
|
|||
void (*mode2_save_regs)(struct amdgpu_device *adev);
|
||||
void (*mode2_restore_regs)(struct amdgpu_device *adev);
|
||||
void (*halt)(struct amdgpu_device *adev);
|
||||
bool (*query_utcl2_poison_status)(struct amdgpu_device *adev,
|
||||
int xcc_id);
|
||||
};
|
||||
|
||||
struct amdgpu_gfxhub {
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ amdgpu_i2c_lookup(struct amdgpu_device *adev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus,
|
||||
static int amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 *val)
|
||||
|
|
@ -304,16 +304,18 @@ static void amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus,
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) {
|
||||
*val = in_buf[0];
|
||||
DRM_DEBUG("val = 0x%02x\n", *val);
|
||||
} else {
|
||||
DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n",
|
||||
addr, *val);
|
||||
if (i2c_transfer(&i2c_bus->adapter, msgs, 2) != 2) {
|
||||
DRM_DEBUG("i2c 0x%02x read failed\n", addr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*val = in_buf[0];
|
||||
DRM_DEBUG("val = 0x%02x\n", *val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus,
|
||||
static int amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus,
|
||||
u8 slave_addr,
|
||||
u8 addr,
|
||||
u8 val)
|
||||
|
|
@ -329,9 +331,12 @@ static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus,
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = val;
|
||||
|
||||
if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1)
|
||||
DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n",
|
||||
addr, val);
|
||||
if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1) {
|
||||
DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n", addr, val);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ddc router switching */
|
||||
|
|
@ -346,16 +351,18 @@ amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connecto
|
|||
if (!amdgpu_connector->router_bus)
|
||||
return;
|
||||
|
||||
amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
amdgpu_connector->router.i2c_addr,
|
||||
0x3, &val);
|
||||
0x3, &val))
|
||||
return;
|
||||
val &= ~amdgpu_connector->router.ddc_mux_control_pin;
|
||||
amdgpu_i2c_put_byte(amdgpu_connector->router_bus,
|
||||
amdgpu_connector->router.i2c_addr,
|
||||
0x3, val);
|
||||
amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
amdgpu_connector->router.i2c_addr,
|
||||
0x1, &val);
|
||||
0x1, &val))
|
||||
return;
|
||||
val &= ~amdgpu_connector->router.ddc_mux_control_pin;
|
||||
val |= amdgpu_connector->router.ddc_mux_state;
|
||||
amdgpu_i2c_put_byte(amdgpu_connector->router_bus,
|
||||
|
|
@ -375,16 +382,18 @@ amdgpu_i2c_router_select_cd_port(const struct amdgpu_connector *amdgpu_connector
|
|||
if (!amdgpu_connector->router_bus)
|
||||
return;
|
||||
|
||||
amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
amdgpu_connector->router.i2c_addr,
|
||||
0x3, &val);
|
||||
0x3, &val))
|
||||
return;
|
||||
val &= ~amdgpu_connector->router.cd_mux_control_pin;
|
||||
amdgpu_i2c_put_byte(amdgpu_connector->router_bus,
|
||||
amdgpu_connector->router.i2c_addr,
|
||||
0x3, val);
|
||||
amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus,
|
||||
amdgpu_connector->router.i2c_addr,
|
||||
0x1, &val);
|
||||
0x1, &val))
|
||||
return;
|
||||
val &= ~amdgpu_connector->router.cd_mux_control_pin;
|
||||
val |= amdgpu_connector->router.cd_mux_state;
|
||||
amdgpu_i2c_put_byte(amdgpu_connector->router_bus,
|
||||
|
|
|
|||
|
|
@ -445,6 +445,14 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
|||
|
||||
entry.ih = ih;
|
||||
entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
|
||||
|
||||
/*
|
||||
* timestamp is not supported on some legacy SOCs (cik, cz, iceland,
|
||||
* si and tonga), so initialize timestamp and timestamp_src to 0
|
||||
*/
|
||||
entry.timestamp = 0;
|
||||
entry.timestamp_src = 0;
|
||||
|
||||
amdgpu_ih_decode_iv(adev, &entry);
|
||||
|
||||
trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
|
||||
|
|
|
|||
|
|
@ -149,38 +149,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
|||
goto out;
|
||||
}
|
||||
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_NONE;
|
||||
if (amdgpu_device_supports_px(dev) &&
|
||||
(amdgpu_runtime_pm != 0)) { /* enable PX as runtime mode */
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_PX;
|
||||
dev_info(adev->dev, "Using ATPX for runtime pm\n");
|
||||
} else if (amdgpu_device_supports_boco(dev) &&
|
||||
(amdgpu_runtime_pm != 0)) { /* enable boco as runtime mode */
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO;
|
||||
dev_info(adev->dev, "Using BOCO for runtime pm\n");
|
||||
} else if (amdgpu_device_supports_baco(dev) &&
|
||||
(amdgpu_runtime_pm != 0)) {
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
/* enable BACO as runpm mode if runpm=1 */
|
||||
if (amdgpu_runtime_pm > 0)
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
break;
|
||||
case CHIP_VEGA10:
|
||||
/* enable BACO as runpm mode if noretry=0 */
|
||||
if (!adev->gmc.noretry)
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
break;
|
||||
default:
|
||||
/* enable BACO as runpm mode on CI+ */
|
||||
adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO)
|
||||
dev_info(adev->dev, "Using BACO for runtime pm\n");
|
||||
}
|
||||
amdgpu_device_detect_runtime_pm_mode(adev);
|
||||
|
||||
/* Call ACPI methods: require modeset init
|
||||
* but failure is not fatal
|
||||
|
|
|
|||
|
|
@ -210,22 +210,26 @@ int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry)
|
||||
static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry,
|
||||
struct ras_query_context *qctx)
|
||||
{
|
||||
dev_info(adev->dev, HW_ERR "Accelerator Check Architecture events logged\n");
|
||||
dev_info(adev->dev, HW_ERR "aca entry[%02d].STATUS=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_STATUS]);
|
||||
dev_info(adev->dev, HW_ERR "aca entry[%02d].ADDR=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_ADDR]);
|
||||
dev_info(adev->dev, HW_ERR "aca entry[%02d].MISC0=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_MISC0]);
|
||||
dev_info(adev->dev, HW_ERR "aca entry[%02d].IPID=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_IPID]);
|
||||
dev_info(adev->dev, HW_ERR "aca entry[%02d].SYND=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_SYND]);
|
||||
u64 event_id = qctx->event_id;
|
||||
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n");
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].STATUS=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_STATUS]);
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].ADDR=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_ADDR]);
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].MISC0=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_MISC0]);
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].IPID=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_IPID]);
|
||||
RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].SYND=0x%016llx\n",
|
||||
idx, entry->regs[MCA_REG_IDX_SYND]);
|
||||
}
|
||||
|
||||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data)
|
||||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
|
||||
struct ras_err_data *err_data, struct ras_query_context *qctx)
|
||||
{
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info;
|
||||
struct ras_err_addr err_addr = {0};
|
||||
|
|
@ -244,7 +248,7 @@ int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_blo
|
|||
list_for_each_entry(node, &mca_set.list, node) {
|
||||
entry = &node->entry;
|
||||
|
||||
amdgpu_mca_smu_mca_bank_dump(adev, i++, entry);
|
||||
amdgpu_mca_smu_mca_bank_dump(adev, i++, entry, qctx);
|
||||
|
||||
count = 0;
|
||||
ret = amdgpu_mca_smu_parse_mca_error_count(adev, blk, type, entry, &count);
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root
|
|||
void amdgpu_mca_bank_set_init(struct mca_bank_set *mca_set);
|
||||
int amdgpu_mca_bank_set_add_entry(struct mca_bank_set *mca_set, struct mca_bank_entry *entry);
|
||||
void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set);
|
||||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data);
|
||||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type,
|
||||
struct ras_err_data *err_data, struct ras_query_context *qctx);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,18 @@
|
|||
#define AMDGPU_MES_MAX_NUM_OF_QUEUES_PER_PROCESS 1024
|
||||
#define AMDGPU_ONE_DOORBELL_SIZE 8
|
||||
|
||||
signed long amdgpu_mes_fence_wait_polling(u64 *fence,
|
||||
u64 wait_seq,
|
||||
signed long timeout)
|
||||
{
|
||||
|
||||
while ((s64)(wait_seq - *fence) > 0 && timeout > 0) {
|
||||
udelay(2);
|
||||
timeout -= 2;
|
||||
}
|
||||
return timeout > 0 ? timeout : 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev)
|
||||
{
|
||||
return roundup(AMDGPU_ONE_DOORBELL_SIZE *
|
||||
|
|
@ -40,7 +52,6 @@ int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
static int amdgpu_mes_kernel_doorbell_get(struct amdgpu_device *adev,
|
||||
struct amdgpu_mes_process *process,
|
||||
int ip_type, uint64_t *doorbell_index)
|
||||
{
|
||||
unsigned int offset, found;
|
||||
|
|
@ -65,7 +76,6 @@ static int amdgpu_mes_kernel_doorbell_get(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
static void amdgpu_mes_kernel_doorbell_free(struct amdgpu_device *adev,
|
||||
struct amdgpu_mes_process *process,
|
||||
uint32_t doorbell_index)
|
||||
{
|
||||
unsigned int old, rel_index;
|
||||
|
|
@ -656,7 +666,7 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id,
|
|||
*queue_id = queue->queue_id = r;
|
||||
|
||||
/* allocate a doorbell index for the queue */
|
||||
r = amdgpu_mes_kernel_doorbell_get(adev, gang->process,
|
||||
r = amdgpu_mes_kernel_doorbell_get(adev,
|
||||
qprops->queue_type,
|
||||
&qprops->doorbell_off);
|
||||
if (r)
|
||||
|
|
@ -714,8 +724,7 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id,
|
|||
return 0;
|
||||
|
||||
clean_up_doorbell:
|
||||
amdgpu_mes_kernel_doorbell_free(adev, gang->process,
|
||||
qprops->doorbell_off);
|
||||
amdgpu_mes_kernel_doorbell_free(adev, qprops->doorbell_off);
|
||||
clean_up_queue_id:
|
||||
spin_lock_irqsave(&adev->mes.queue_id_lock, flags);
|
||||
idr_remove(&adev->mes.queue_id_idr, queue->queue_id);
|
||||
|
|
@ -769,8 +778,7 @@ int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id)
|
|||
queue_id);
|
||||
|
||||
list_del(&queue->list);
|
||||
amdgpu_mes_kernel_doorbell_free(adev, gang->process,
|
||||
queue->doorbell_off);
|
||||
amdgpu_mes_kernel_doorbell_free(adev, queue->doorbell_off);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
|
||||
amdgpu_mes_queue_free_mqd(queue);
|
||||
|
|
@ -778,6 +786,28 @@ int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring)
|
||||
{
|
||||
struct mes_map_legacy_queue_input queue_input;
|
||||
int r;
|
||||
|
||||
memset(&queue_input, 0, sizeof(queue_input));
|
||||
|
||||
queue_input.queue_type = ring->funcs->type;
|
||||
queue_input.doorbell_offset = ring->doorbell_index;
|
||||
queue_input.pipe_id = ring->pipe;
|
||||
queue_input.queue_id = ring->queue;
|
||||
queue_input.mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
|
||||
queue_input.wptr_addr = ring->wptr_gpu_addr;
|
||||
|
||||
r = adev->mes.funcs->map_legacy_queue(&adev->mes, &queue_input);
|
||||
if (r)
|
||||
DRM_ERROR("failed to map legacy queue\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring,
|
||||
enum amdgpu_unmap_queues_action action,
|
||||
|
|
@ -1475,7 +1505,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
|
|||
const struct mes_firmware_header_v1_0 *mes_hdr;
|
||||
struct amdgpu_firmware_info *info;
|
||||
char ucode_prefix[30];
|
||||
char fw_name[40];
|
||||
char fw_name[50];
|
||||
bool need_retry = false;
|
||||
int r;
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,12 @@ struct amdgpu_mes {
|
|||
|
||||
/* ip specific functions */
|
||||
const struct amdgpu_mes_funcs *funcs;
|
||||
|
||||
/* mes resource_1 bo*/
|
||||
struct amdgpu_bo *resource_1;
|
||||
uint64_t resource_1_gpu_addr;
|
||||
void *resource_1_addr;
|
||||
|
||||
};
|
||||
|
||||
struct amdgpu_mes_process {
|
||||
|
|
@ -242,6 +248,15 @@ struct mes_remove_queue_input {
|
|||
uint64_t gang_context_addr;
|
||||
};
|
||||
|
||||
struct mes_map_legacy_queue_input {
|
||||
uint32_t queue_type;
|
||||
uint32_t doorbell_offset;
|
||||
uint32_t pipe_id;
|
||||
uint32_t queue_id;
|
||||
uint64_t mqd_addr;
|
||||
uint64_t wptr_addr;
|
||||
};
|
||||
|
||||
struct mes_unmap_legacy_queue_input {
|
||||
enum amdgpu_unmap_queues_action action;
|
||||
uint32_t queue_type;
|
||||
|
|
@ -318,6 +333,9 @@ struct amdgpu_mes_funcs {
|
|||
int (*remove_hw_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_remove_queue_input *input);
|
||||
|
||||
int (*map_legacy_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_map_legacy_queue_input *input);
|
||||
|
||||
int (*unmap_legacy_queue)(struct amdgpu_mes *mes,
|
||||
struct mes_unmap_legacy_queue_input *input);
|
||||
|
||||
|
|
@ -334,6 +352,10 @@ struct amdgpu_mes_funcs {
|
|||
#define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev))
|
||||
#define amdgpu_mes_kiq_hw_fini(adev) (adev)->mes.kiq_hw_fini((adev))
|
||||
|
||||
signed long amdgpu_mes_fence_wait_polling(u64 *fence,
|
||||
u64 wait_seq,
|
||||
signed long timeout);
|
||||
|
||||
int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);
|
||||
|
||||
int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
|
||||
|
|
@ -357,6 +379,8 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id,
|
|||
int *queue_id);
|
||||
int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id);
|
||||
|
||||
int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring);
|
||||
int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring,
|
||||
enum amdgpu_unmap_queues_action action,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ struct amdgpu_mmhub_funcs {
|
|||
uint64_t page_table_base);
|
||||
void (*update_power_gating)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
bool (*query_utcl2_poison_status)(struct amdgpu_device *adev,
|
||||
int hub_inst);
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_vram_mgr.h"
|
||||
|
||||
/**
|
||||
* DOC: amdgpu_object
|
||||
|
|
@ -153,8 +154,10 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
|||
else
|
||||
places[c].flags |= TTM_PL_FLAG_TOPDOWN;
|
||||
|
||||
if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
|
||||
if (abo->tbo.type == ttm_bo_type_kernel &&
|
||||
flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
|
||||
places[c].flags |= TTM_PL_FLAG_CONTIGUOUS;
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +176,12 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
|
|||
abo->flags & AMDGPU_GEM_CREATE_PREEMPTIBLE ?
|
||||
AMDGPU_PL_PREEMPT : TTM_PL_TT;
|
||||
places[c].flags = 0;
|
||||
/*
|
||||
* When GTT is just an alternative to VRAM make sure that we
|
||||
* only use it as fallback and still try to fill up VRAM first.
|
||||
*/
|
||||
if (domain & abo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM)
|
||||
places[c].flags |= TTM_PL_FLAG_FALLBACK;
|
||||
c++;
|
||||
}
|
||||
|
||||
|
|
@ -595,8 +604,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
|||
if (!amdgpu_bo_support_uswc(bo->flags))
|
||||
bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
|
||||
if (adev->ras_enabled)
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
|
||||
bo->tbo.bdev = &adev->mman.bdev;
|
||||
if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
|
||||
|
|
@ -629,7 +637,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
|||
bo->tbo.resource->mem_type == TTM_PL_VRAM) {
|
||||
struct dma_fence *fence;
|
||||
|
||||
r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence, true);
|
||||
r = amdgpu_ttm_clear_buffer(bo, bo->tbo.base.resv, &fence);
|
||||
if (unlikely(r))
|
||||
goto fail_unreserve;
|
||||
|
||||
|
|
@ -759,7 +767,7 @@ int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, struct dma_fence **fence)
|
|||
|
||||
return amdgpu_copy_buffer(ring, shadow_addr, parent_addr,
|
||||
amdgpu_bo_size(shadow), NULL, fence,
|
||||
true, false, false);
|
||||
true, false, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -961,6 +969,10 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
|||
if (!bo->placements[i].lpfn ||
|
||||
(lpfn && lpfn < bo->placements[i].lpfn))
|
||||
bo->placements[i].lpfn = lpfn;
|
||||
|
||||
if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS &&
|
||||
bo->placements[i].mem_type == TTM_PL_VRAM)
|
||||
bo->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
|
||||
}
|
||||
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
|
|
@ -1366,8 +1378,9 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
|||
if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
|
||||
return;
|
||||
|
||||
r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence, true);
|
||||
r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true);
|
||||
if (!WARN_ON(r)) {
|
||||
amdgpu_vram_mgr_set_cleared(bo->resource);
|
||||
amdgpu_bo_fence(abo, fence, false);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1053,6 +1053,11 @@ static int psp_asd_initialize(struct psp_context *psp)
|
|||
if (amdgpu_sriov_vf(psp->adev) || !psp->asd_context.bin_desc.size_bytes)
|
||||
return 0;
|
||||
|
||||
/* bypass asd if display hardware is not available */
|
||||
if (!amdgpu_device_has_display_hardware(psp->adev) &&
|
||||
amdgpu_ip_version(psp->adev, MP0_HWIP, 0) >= IP_VERSION(13, 0, 10))
|
||||
return 0;
|
||||
|
||||
psp->asd_context.mem_context.shared_mc_addr = 0;
|
||||
psp->asd_context.mem_context.shared_mem_size = PSP_ASD_SHARED_MEM_SIZE;
|
||||
psp->asd_context.ta_load_type = GFX_CMD_ID_LOAD_ASD;
|
||||
|
|
@ -2260,6 +2265,15 @@ static int psp_hw_start(struct psp_context *psp)
|
|||
}
|
||||
}
|
||||
|
||||
if ((is_psp_fw_valid(psp->ipkeymgr_drv)) &&
|
||||
(psp->funcs->bootloader_load_ipkeymgr_drv != NULL)) {
|
||||
ret = psp_bootloader_load_ipkeymgr_drv(psp);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "PSP load ipkeymgr_drv failed!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((is_psp_fw_valid(psp->sos)) &&
|
||||
(psp->funcs->bootloader_load_sos != NULL)) {
|
||||
ret = psp_bootloader_load_sos(psp);
|
||||
|
|
@ -2617,7 +2631,8 @@ static int psp_load_p2s_table(struct psp_context *psp)
|
|||
struct amdgpu_firmware_info *ucode =
|
||||
&adev->firmware.ucode[AMDGPU_UCODE_ID_P2S_TABLE];
|
||||
|
||||
if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO))
|
||||
if (adev->in_runpm && ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) ||
|
||||
(adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)))
|
||||
return 0;
|
||||
|
||||
if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6)) {
|
||||
|
|
@ -2647,7 +2662,8 @@ static int psp_load_smu_fw(struct psp_context *psp)
|
|||
* Skip SMU FW reloading in case of using BACO for runpm only,
|
||||
* as SMU is always alive.
|
||||
*/
|
||||
if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO))
|
||||
if (adev->in_runpm && ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) ||
|
||||
(adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)))
|
||||
return 0;
|
||||
|
||||
if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
|
||||
|
|
@ -3273,6 +3289,12 @@ static int parse_sos_bin_descriptor(struct psp_context *psp,
|
|||
psp->ras_drv.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->ras_drv.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case PSP_FW_TYPE_PSP_IPKEYMGR_DRV:
|
||||
psp->ipkeymgr_drv.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->ipkeymgr_drv.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->ipkeymgr_drv.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->ipkeymgr_drv.start_addr = ucode_start_addr;
|
||||
break;
|
||||
default:
|
||||
dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -73,8 +73,10 @@ enum psp_bootloader_cmd {
|
|||
PSP_BL__LOAD_KEY_DATABASE = 0x80000,
|
||||
PSP_BL__LOAD_SOCDRV = 0xB0000,
|
||||
PSP_BL__LOAD_DBGDRV = 0xC0000,
|
||||
PSP_BL__LOAD_HADDRV = PSP_BL__LOAD_DBGDRV,
|
||||
PSP_BL__LOAD_INTFDRV = 0xD0000,
|
||||
PSP_BL__LOAD_RASDRV = 0xE0000,
|
||||
PSP_BL__LOAD_RASDRV = 0xE0000,
|
||||
PSP_BL__LOAD_IPKEYMGRDRV = 0xF0000,
|
||||
PSP_BL__DRAM_LONG_TRAIN = 0x100000,
|
||||
PSP_BL__DRAM_SHORT_TRAIN = 0x200000,
|
||||
PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000,
|
||||
|
|
@ -117,6 +119,7 @@ struct psp_funcs {
|
|||
int (*bootloader_load_intf_drv)(struct psp_context *psp);
|
||||
int (*bootloader_load_dbg_drv)(struct psp_context *psp);
|
||||
int (*bootloader_load_ras_drv)(struct psp_context *psp);
|
||||
int (*bootloader_load_ipkeymgr_drv)(struct psp_context *psp);
|
||||
int (*bootloader_load_sos)(struct psp_context *psp);
|
||||
int (*ring_create)(struct psp_context *psp,
|
||||
enum psp_ring_type ring_type);
|
||||
|
|
@ -336,6 +339,7 @@ struct psp_context {
|
|||
struct psp_bin_desc intf_drv;
|
||||
struct psp_bin_desc dbg_drv;
|
||||
struct psp_bin_desc ras_drv;
|
||||
struct psp_bin_desc ipkeymgr_drv;
|
||||
|
||||
/* tmr buffer */
|
||||
struct amdgpu_bo *tmr_bo;
|
||||
|
|
@ -424,6 +428,9 @@ struct amdgpu_psp_funcs {
|
|||
#define psp_bootloader_load_ras_drv(psp) \
|
||||
((psp)->funcs->bootloader_load_ras_drv ? \
|
||||
(psp)->funcs->bootloader_load_ras_drv((psp)) : 0)
|
||||
#define psp_bootloader_load_ipkeymgr_drv(psp) \
|
||||
((psp)->funcs->bootloader_load_ipkeymgr_drv ? \
|
||||
(psp)->funcs->bootloader_load_ipkeymgr_drv((psp)) : 0)
|
||||
#define psp_bootloader_load_sos(psp) \
|
||||
((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0)
|
||||
#define psp_smu_reload_quirk(psp) \
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ const char *get_ras_block_str(struct ras_common_if *ras_block)
|
|||
|
||||
#define MAX_UMC_POISON_POLLING_TIME_ASYNC 100 //ms
|
||||
|
||||
#define AMDGPU_RAS_RETIRE_PAGE_INTERVAL 100 //ms
|
||||
|
||||
enum amdgpu_ras_retire_page_reservation {
|
||||
AMDGPU_RAS_RETIRE_PAGE_RESERVED,
|
||||
AMDGPU_RAS_RETIRE_PAGE_PENDING,
|
||||
|
|
@ -1045,6 +1047,7 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d
|
|||
static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev,
|
||||
struct ras_manager *ras_mgr,
|
||||
struct ras_err_data *err_data,
|
||||
struct ras_query_context *qctx,
|
||||
const char *blk_name,
|
||||
bool is_ue,
|
||||
bool is_de)
|
||||
|
|
@ -1052,27 +1055,28 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev,
|
|||
struct amdgpu_smuio_mcm_config_info *mcm_info;
|
||||
struct ras_err_node *err_node;
|
||||
struct ras_err_info *err_info;
|
||||
u64 event_id = qctx->event_id;
|
||||
|
||||
if (is_ue) {
|
||||
for_each_ras_error(err_node, err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
mcm_info = &err_info->mcm_info;
|
||||
if (err_info->ue_count) {
|
||||
dev_info(adev->dev, "socket: %d, die: %d, "
|
||||
"%lld new uncorrectable hardware errors detected in %s block\n",
|
||||
mcm_info->socket_id,
|
||||
mcm_info->die_id,
|
||||
err_info->ue_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, "
|
||||
"%lld new uncorrectable hardware errors detected in %s block\n",
|
||||
mcm_info->socket_id,
|
||||
mcm_info->die_id,
|
||||
err_info->ue_count,
|
||||
blk_name);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_ras_error(err_node, &ras_mgr->err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
mcm_info = &err_info->mcm_info;
|
||||
dev_info(adev->dev, "socket: %d, die: %d, "
|
||||
"%lld uncorrectable hardware errors detected in total in %s block\n",
|
||||
mcm_info->socket_id, mcm_info->die_id, err_info->ue_count, blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, "
|
||||
"%lld uncorrectable hardware errors detected in total in %s block\n",
|
||||
mcm_info->socket_id, mcm_info->die_id, err_info->ue_count, blk_name);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -1081,44 +1085,44 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev,
|
|||
err_info = &err_node->err_info;
|
||||
mcm_info = &err_info->mcm_info;
|
||||
if (err_info->de_count) {
|
||||
dev_info(adev->dev, "socket: %d, die: %d, "
|
||||
"%lld new deferred hardware errors detected in %s block\n",
|
||||
mcm_info->socket_id,
|
||||
mcm_info->die_id,
|
||||
err_info->de_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, "
|
||||
"%lld new deferred hardware errors detected in %s block\n",
|
||||
mcm_info->socket_id,
|
||||
mcm_info->die_id,
|
||||
err_info->de_count,
|
||||
blk_name);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_ras_error(err_node, &ras_mgr->err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
mcm_info = &err_info->mcm_info;
|
||||
dev_info(adev->dev, "socket: %d, die: %d, "
|
||||
"%lld deferred hardware errors detected in total in %s block\n",
|
||||
mcm_info->socket_id, mcm_info->die_id,
|
||||
err_info->de_count, blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, "
|
||||
"%lld deferred hardware errors detected in total in %s block\n",
|
||||
mcm_info->socket_id, mcm_info->die_id,
|
||||
err_info->de_count, blk_name);
|
||||
}
|
||||
} else {
|
||||
for_each_ras_error(err_node, err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
mcm_info = &err_info->mcm_info;
|
||||
if (err_info->ce_count) {
|
||||
dev_info(adev->dev, "socket: %d, die: %d, "
|
||||
"%lld new correctable hardware errors detected in %s block\n",
|
||||
mcm_info->socket_id,
|
||||
mcm_info->die_id,
|
||||
err_info->ce_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, "
|
||||
"%lld new correctable hardware errors detected in %s block\n",
|
||||
mcm_info->socket_id,
|
||||
mcm_info->die_id,
|
||||
err_info->ce_count,
|
||||
blk_name);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_ras_error(err_node, &ras_mgr->err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
mcm_info = &err_info->mcm_info;
|
||||
dev_info(adev->dev, "socket: %d, die: %d, "
|
||||
"%lld correctable hardware errors detected in total in %s block\n",
|
||||
mcm_info->socket_id, mcm_info->die_id,
|
||||
err_info->ce_count, blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, "
|
||||
"%lld correctable hardware errors detected in total in %s block\n",
|
||||
mcm_info->socket_id, mcm_info->die_id,
|
||||
err_info->ce_count, blk_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1131,77 +1135,79 @@ static inline bool err_data_has_source_info(struct ras_err_data *data)
|
|||
|
||||
static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev,
|
||||
struct ras_query_if *query_if,
|
||||
struct ras_err_data *err_data)
|
||||
struct ras_err_data *err_data,
|
||||
struct ras_query_context *qctx)
|
||||
{
|
||||
struct ras_manager *ras_mgr = amdgpu_ras_find_obj(adev, &query_if->head);
|
||||
const char *blk_name = get_ras_block_str(&query_if->head);
|
||||
u64 event_id = qctx->event_id;
|
||||
|
||||
if (err_data->ce_count) {
|
||||
if (err_data_has_source_info(err_data)) {
|
||||
amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data,
|
||||
amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx,
|
||||
blk_name, false, false);
|
||||
} else if (!adev->aid_mask &&
|
||||
adev->smuio.funcs &&
|
||||
adev->smuio.funcs->get_socket_id &&
|
||||
adev->smuio.funcs->get_die_id) {
|
||||
dev_info(adev->dev, "socket: %d, die: %d "
|
||||
"%ld correctable hardware errors "
|
||||
"detected in %s block\n",
|
||||
adev->smuio.funcs->get_socket_id(adev),
|
||||
adev->smuio.funcs->get_die_id(adev),
|
||||
ras_mgr->err_data.ce_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d "
|
||||
"%ld correctable hardware errors "
|
||||
"detected in %s block\n",
|
||||
adev->smuio.funcs->get_socket_id(adev),
|
||||
adev->smuio.funcs->get_die_id(adev),
|
||||
ras_mgr->err_data.ce_count,
|
||||
blk_name);
|
||||
} else {
|
||||
dev_info(adev->dev, "%ld correctable hardware errors "
|
||||
"detected in %s block\n",
|
||||
ras_mgr->err_data.ce_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "%ld correctable hardware errors "
|
||||
"detected in %s block\n",
|
||||
ras_mgr->err_data.ce_count,
|
||||
blk_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (err_data->ue_count) {
|
||||
if (err_data_has_source_info(err_data)) {
|
||||
amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data,
|
||||
amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx,
|
||||
blk_name, true, false);
|
||||
} else if (!adev->aid_mask &&
|
||||
adev->smuio.funcs &&
|
||||
adev->smuio.funcs->get_socket_id &&
|
||||
adev->smuio.funcs->get_die_id) {
|
||||
dev_info(adev->dev, "socket: %d, die: %d "
|
||||
"%ld uncorrectable hardware errors "
|
||||
"detected in %s block\n",
|
||||
adev->smuio.funcs->get_socket_id(adev),
|
||||
adev->smuio.funcs->get_die_id(adev),
|
||||
ras_mgr->err_data.ue_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d "
|
||||
"%ld uncorrectable hardware errors "
|
||||
"detected in %s block\n",
|
||||
adev->smuio.funcs->get_socket_id(adev),
|
||||
adev->smuio.funcs->get_die_id(adev),
|
||||
ras_mgr->err_data.ue_count,
|
||||
blk_name);
|
||||
} else {
|
||||
dev_info(adev->dev, "%ld uncorrectable hardware errors "
|
||||
"detected in %s block\n",
|
||||
ras_mgr->err_data.ue_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "%ld uncorrectable hardware errors "
|
||||
"detected in %s block\n",
|
||||
ras_mgr->err_data.ue_count,
|
||||
blk_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (err_data->de_count) {
|
||||
if (err_data_has_source_info(err_data)) {
|
||||
amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data,
|
||||
amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx,
|
||||
blk_name, false, true);
|
||||
} else if (!adev->aid_mask &&
|
||||
adev->smuio.funcs &&
|
||||
adev->smuio.funcs->get_socket_id &&
|
||||
adev->smuio.funcs->get_die_id) {
|
||||
dev_info(adev->dev, "socket: %d, die: %d "
|
||||
"%ld deferred hardware errors "
|
||||
"detected in %s block\n",
|
||||
adev->smuio.funcs->get_socket_id(adev),
|
||||
adev->smuio.funcs->get_die_id(adev),
|
||||
ras_mgr->err_data.de_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d "
|
||||
"%ld deferred hardware errors "
|
||||
"detected in %s block\n",
|
||||
adev->smuio.funcs->get_socket_id(adev),
|
||||
adev->smuio.funcs->get_die_id(adev),
|
||||
ras_mgr->err_data.de_count,
|
||||
blk_name);
|
||||
} else {
|
||||
dev_info(adev->dev, "%ld deferred hardware errors "
|
||||
"detected in %s block\n",
|
||||
ras_mgr->err_data.de_count,
|
||||
blk_name);
|
||||
RAS_EVENT_LOG(adev, event_id, "%ld deferred hardware errors "
|
||||
"detected in %s block\n",
|
||||
ras_mgr->err_data.de_count,
|
||||
blk_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1244,6 +1250,10 @@ int amdgpu_ras_bind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
|||
{
|
||||
struct ras_manager *obj;
|
||||
|
||||
/* in resume phase, no need to create aca fs node */
|
||||
if (adev->in_suspend || amdgpu_in_reset(adev))
|
||||
return 0;
|
||||
|
||||
obj = get_ras_manager(adev, blk);
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
|
|
@ -1265,7 +1275,8 @@ int amdgpu_ras_unbind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk)
|
|||
}
|
||||
|
||||
static int amdgpu_aca_log_ras_error_data(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
|
||||
enum aca_error_type type, struct ras_err_data *err_data)
|
||||
enum aca_error_type type, struct ras_err_data *err_data,
|
||||
struct ras_query_context *qctx)
|
||||
{
|
||||
struct ras_manager *obj;
|
||||
|
||||
|
|
@ -1273,7 +1284,7 @@ static int amdgpu_aca_log_ras_error_data(struct amdgpu_device *adev, enum amdgpu
|
|||
if (!obj)
|
||||
return -EINVAL;
|
||||
|
||||
return amdgpu_aca_get_error_data(adev, &obj->aca_handle, type, err_data);
|
||||
return amdgpu_aca_get_error_data(adev, &obj->aca_handle, type, err_data, qctx);
|
||||
}
|
||||
|
||||
ssize_t amdgpu_ras_aca_sysfs_read(struct device *dev, struct device_attribute *attr,
|
||||
|
|
@ -1287,13 +1298,14 @@ ssize_t amdgpu_ras_aca_sysfs_read(struct device *dev, struct device_attribute *a
|
|||
if (amdgpu_ras_query_error_status(obj->adev, &info))
|
||||
return -EINVAL;
|
||||
|
||||
return sysfs_emit(buf, "%s: %lu\n%s: %lu\n", "ue", info.ue_count,
|
||||
"ce", info.ce_count);
|
||||
return sysfs_emit(buf, "%s: %lu\n%s: %lu\n%s: %lu\n", "ue", info.ue_count,
|
||||
"ce", info.ce_count, "de", info.ue_count);
|
||||
}
|
||||
|
||||
static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
|
||||
struct ras_query_if *info,
|
||||
struct ras_err_data *err_data,
|
||||
struct ras_query_context *qctx,
|
||||
unsigned int error_query_mode)
|
||||
{
|
||||
enum amdgpu_ras_block blk = info ? info->head.block : AMDGPU_RAS_BLOCK_COUNT;
|
||||
|
|
@ -1329,17 +1341,21 @@ static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
|
|||
}
|
||||
} else {
|
||||
if (amdgpu_aca_is_enabled(adev)) {
|
||||
ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_UE, err_data);
|
||||
ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_UE, err_data, qctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_CE, err_data);
|
||||
ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_CE, err_data, qctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_DEFERRED, err_data, qctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* FIXME: add code to check return value later */
|
||||
amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_UE, err_data);
|
||||
amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_CE, err_data);
|
||||
amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_UE, err_data, qctx);
|
||||
amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_CE, err_data, qctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1351,6 +1367,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i
|
|||
{
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
|
||||
struct ras_err_data err_data;
|
||||
struct ras_query_context qctx;
|
||||
unsigned int error_query_mode;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1364,8 +1381,12 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i
|
|||
if (!amdgpu_ras_get_error_query_mode(adev, &error_query_mode))
|
||||
return -EINVAL;
|
||||
|
||||
memset(&qctx, 0, sizeof(qctx));
|
||||
qctx.event_id = amdgpu_ras_acquire_event_id(adev, amdgpu_ras_intr_triggered() ?
|
||||
RAS_EVENT_TYPE_ISR : RAS_EVENT_TYPE_INVALID);
|
||||
ret = amdgpu_ras_query_error_status_helper(adev, info,
|
||||
&err_data,
|
||||
&qctx,
|
||||
error_query_mode);
|
||||
if (ret)
|
||||
goto out_fini_err_data;
|
||||
|
|
@ -1376,7 +1397,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i
|
|||
info->ce_count = obj->err_data.ce_count;
|
||||
info->de_count = obj->err_data.de_count;
|
||||
|
||||
amdgpu_ras_error_generate_report(adev, info, &err_data);
|
||||
amdgpu_ras_error_generate_report(adev, info, &err_data, &qctx);
|
||||
|
||||
out_fini_err_data:
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
|
|
@ -2041,7 +2062,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
|
|||
}
|
||||
}
|
||||
|
||||
amdgpu_umc_poison_handler(adev, obj->head.block, false);
|
||||
amdgpu_umc_poison_handler(adev, obj->head.block, 0);
|
||||
|
||||
if (block_obj->hw_ops && block_obj->hw_ops->handle_poison_consumption)
|
||||
poison_stat = block_obj->hw_ops->handle_poison_consumption(adev);
|
||||
|
|
@ -2061,6 +2082,17 @@ static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj
|
|||
{
|
||||
dev_info(obj->adev->dev,
|
||||
"Poison is created\n");
|
||||
|
||||
if (amdgpu_ip_version(obj->adev, UMC_HWIP, 0) >= IP_VERSION(12, 0, 0)) {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(obj->adev);
|
||||
|
||||
amdgpu_ras_put_poison_req(obj->adev,
|
||||
AMDGPU_RAS_BLOCK__UMC, 0, NULL, NULL, false);
|
||||
|
||||
atomic_inc(&con->page_retirement_req_cnt);
|
||||
|
||||
wake_up(&con->page_retirement_wq);
|
||||
}
|
||||
}
|
||||
|
||||
static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj,
|
||||
|
|
@ -2371,7 +2403,7 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev,
|
|||
.flags = AMDGPU_RAS_RETIRE_PAGE_RESERVED,
|
||||
};
|
||||
status = amdgpu_vram_mgr_query_page_status(&adev->mman.vram_mgr,
|
||||
data->bps[i].retired_page);
|
||||
data->bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT);
|
||||
if (status == -EBUSY)
|
||||
(*bps)[i].flags = AMDGPU_RAS_RETIRE_PAGE_PENDING;
|
||||
else if (status == -ENOENT)
|
||||
|
|
@ -2384,6 +2416,19 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_set_fed_all(struct amdgpu_device *adev,
|
||||
struct amdgpu_hive_info *hive, bool status)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev;
|
||||
|
||||
if (hive) {
|
||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
|
||||
amdgpu_ras_set_fed(tmp_adev, status);
|
||||
} else {
|
||||
amdgpu_ras_set_fed(adev, status);
|
||||
}
|
||||
}
|
||||
|
||||
static void amdgpu_ras_do_recovery(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_ras *ras =
|
||||
|
|
@ -2393,8 +2438,21 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
|
|||
struct list_head device_list, *device_list_handle = NULL;
|
||||
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
|
||||
|
||||
if (hive)
|
||||
if (hive) {
|
||||
atomic_set(&hive->ras_recovery, 1);
|
||||
|
||||
/* If any device which is part of the hive received RAS fatal
|
||||
* error interrupt, set fatal error status on all. This
|
||||
* condition will need a recovery, and flag will be cleared
|
||||
* as part of recovery.
|
||||
*/
|
||||
list_for_each_entry(remote_adev, &hive->device_list,
|
||||
gmc.xgmi.head)
|
||||
if (amdgpu_ras_get_fed_status(remote_adev)) {
|
||||
amdgpu_ras_set_fed_all(adev, hive, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ras->disable_ras_err_cnt_harvest) {
|
||||
|
||||
/* Build list of devices to query RAS related errors */
|
||||
|
|
@ -2439,18 +2497,6 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
|
|||
ras->gpu_reset_flags &= ~AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
|
||||
/* For any RAS error that needs a full reset to
|
||||
* recover, set the fatal error status
|
||||
*/
|
||||
if (hive) {
|
||||
list_for_each_entry(remote_adev,
|
||||
&hive->device_list,
|
||||
gmc.xgmi.head)
|
||||
amdgpu_ras_set_fed(remote_adev,
|
||||
true);
|
||||
} else {
|
||||
amdgpu_ras_set_fed(adev, true);
|
||||
}
|
||||
psp_fatal_error_recovery_quirk(&adev->psp);
|
||||
}
|
||||
}
|
||||
|
|
@ -2516,9 +2562,7 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
amdgpu_vram_mgr_reserve_range(&adev->mman.vram_mgr,
|
||||
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT,
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
amdgpu_ras_reserve_page(adev, bps[i].retired_page);
|
||||
|
||||
memcpy(&data->bps[data->count], &bps[i], sizeof(*data->bps));
|
||||
data->count++;
|
||||
|
|
@ -2674,10 +2718,167 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev,
|
|||
}
|
||||
}
|
||||
|
||||
int amdgpu_ras_put_poison_req(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ras_poison_msg poison_msg;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
memset(&poison_msg, 0, sizeof(poison_msg));
|
||||
poison_msg.block = block;
|
||||
poison_msg.pasid = pasid;
|
||||
poison_msg.reset = reset;
|
||||
poison_msg.pasid_fn = pasid_fn;
|
||||
poison_msg.data = data;
|
||||
|
||||
ret = kfifo_put(&con->poison_fifo, poison_msg);
|
||||
if (!ret) {
|
||||
dev_err(adev->dev, "Poison message fifo is full!\n");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ras_get_poison_req(struct amdgpu_device *adev,
|
||||
struct ras_poison_msg *poison_msg)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
return kfifo_get(&con->poison_fifo, poison_msg);
|
||||
}
|
||||
|
||||
static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log)
|
||||
{
|
||||
mutex_init(&ecc_log->lock);
|
||||
|
||||
/* Set any value as siphash key */
|
||||
memset(&ecc_log->ecc_key, 0xad, sizeof(ecc_log->ecc_key));
|
||||
|
||||
INIT_RADIX_TREE(&ecc_log->de_page_tree, GFP_KERNEL);
|
||||
ecc_log->de_updated = false;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log)
|
||||
{
|
||||
struct radix_tree_iter iter;
|
||||
void __rcu **slot;
|
||||
struct ras_ecc_err *ecc_err;
|
||||
|
||||
mutex_lock(&ecc_log->lock);
|
||||
radix_tree_for_each_slot(slot, &ecc_log->de_page_tree, &iter, 0) {
|
||||
ecc_err = radix_tree_deref_slot(slot);
|
||||
kfree(ecc_err->err_pages.pfn);
|
||||
kfree(ecc_err);
|
||||
radix_tree_iter_delete(&ecc_log->de_page_tree, &iter, slot);
|
||||
}
|
||||
mutex_unlock(&ecc_log->lock);
|
||||
|
||||
mutex_destroy(&ecc_log->lock);
|
||||
ecc_log->de_updated = false;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_do_page_retirement(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_ras *con = container_of(work, struct amdgpu_ras,
|
||||
page_retirement_dwork.work);
|
||||
struct amdgpu_device *adev = con->adev;
|
||||
struct ras_err_data err_data;
|
||||
|
||||
if (amdgpu_in_reset(adev) || atomic_read(&con->in_recovery))
|
||||
return;
|
||||
|
||||
amdgpu_ras_error_data_init(&err_data);
|
||||
|
||||
amdgpu_umc_handle_bad_pages(adev, &err_data);
|
||||
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
|
||||
mutex_lock(&con->umc_ecc_log.lock);
|
||||
if (radix_tree_tagged(&con->umc_ecc_log.de_page_tree,
|
||||
UMC_ECC_NEW_DETECTED_TAG))
|
||||
schedule_delayed_work(&con->page_retirement_dwork,
|
||||
msecs_to_jiffies(AMDGPU_RAS_RETIRE_PAGE_INTERVAL));
|
||||
mutex_unlock(&con->umc_ecc_log.lock);
|
||||
}
|
||||
|
||||
static int amdgpu_ras_query_ecc_status(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block ras_block, uint32_t timeout_ms)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ras_ecc_log_info *ecc_log;
|
||||
struct ras_query_if info;
|
||||
uint32_t timeout = timeout_ms;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.head.block = ras_block;
|
||||
|
||||
ecc_log = &ras->umc_ecc_log;
|
||||
ecc_log->de_updated = false;
|
||||
do {
|
||||
ret = amdgpu_ras_query_error_status(adev, &info);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to query ras error! ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (timeout && !ecc_log->de_updated) {
|
||||
msleep(1);
|
||||
timeout--;
|
||||
}
|
||||
} while (timeout && !ecc_log->de_updated);
|
||||
|
||||
if (timeout_ms && !timeout) {
|
||||
dev_warn(adev->dev, "Can't find deferred error\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev,
|
||||
uint32_t timeout)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_ras_query_ecc_status(adev, AMDGPU_RAS_BLOCK__UMC, timeout);
|
||||
if (!ret)
|
||||
schedule_delayed_work(&con->page_retirement_dwork, 0);
|
||||
}
|
||||
|
||||
static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
struct ras_poison_msg *poison_msg)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
uint32_t reset = poison_msg->reset;
|
||||
uint16_t pasid = poison_msg->pasid;
|
||||
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
|
||||
if (poison_msg->pasid_fn)
|
||||
poison_msg->pasid_fn(adev, pasid, poison_msg->data);
|
||||
|
||||
if (reset) {
|
||||
flush_delayed_work(&con->page_retirement_dwork);
|
||||
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ras_page_retirement_thread(void *param)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)param;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_poison_msg poison_msg;
|
||||
enum amdgpu_ras_block ras_block;
|
||||
bool poison_creation_is_handled = false;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
|
||||
|
|
@ -2688,13 +2889,34 @@ static int amdgpu_ras_page_retirement_thread(void *param)
|
|||
if (kthread_should_stop())
|
||||
break;
|
||||
|
||||
dev_info(adev->dev, "Start processing page retirement. request:%d\n",
|
||||
atomic_read(&con->page_retirement_req_cnt));
|
||||
|
||||
atomic_dec(&con->page_retirement_req_cnt);
|
||||
|
||||
amdgpu_umc_bad_page_polling_timeout(adev,
|
||||
false, MAX_UMC_POISON_POLLING_TIME_ASYNC);
|
||||
if (!amdgpu_ras_get_poison_req(adev, &poison_msg))
|
||||
continue;
|
||||
|
||||
ras_block = poison_msg.block;
|
||||
|
||||
dev_info(adev->dev, "Start processing ras block %s(%d)\n",
|
||||
ras_block_str(ras_block), ras_block);
|
||||
|
||||
if (ras_block == AMDGPU_RAS_BLOCK__UMC) {
|
||||
amdgpu_ras_poison_creation_handler(adev,
|
||||
MAX_UMC_POISON_POLLING_TIME_ASYNC);
|
||||
poison_creation_is_handled = true;
|
||||
} else {
|
||||
/* poison_creation_is_handled:
|
||||
* false: no poison creation interrupt, but it has poison
|
||||
* consumption interrupt.
|
||||
* true: It has poison creation interrupt at the beginning,
|
||||
* but it has no poison creation interrupt later.
|
||||
*/
|
||||
amdgpu_ras_poison_creation_handler(adev,
|
||||
poison_creation_is_handled ?
|
||||
0 : MAX_UMC_POISON_POLLING_TIME_ASYNC);
|
||||
|
||||
amdgpu_ras_poison_consumption_handler(adev, &poison_msg);
|
||||
poison_creation_is_handled = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2763,6 +2985,8 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
mutex_init(&con->page_rsv_lock);
|
||||
INIT_KFIFO(con->poison_fifo);
|
||||
mutex_init(&con->page_retirement_lock);
|
||||
init_waitqueue_head(&con->page_retirement_wq);
|
||||
atomic_set(&con->page_retirement_req_cnt, 0);
|
||||
|
|
@ -2773,6 +2997,8 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
|||
dev_warn(adev->dev, "Failed to create umc_page_retirement thread!!!\n");
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&con->page_retirement_dwork, amdgpu_ras_do_page_retirement);
|
||||
amdgpu_ras_ecc_log_init(&con->umc_ecc_log);
|
||||
#ifdef CONFIG_X86_MCE_AMD
|
||||
if ((adev->asic_type == CHIP_ALDEBARAN) &&
|
||||
(adev->gmc.xgmi.connected_to_cpu))
|
||||
|
|
@ -2813,8 +3039,14 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
|
|||
|
||||
atomic_set(&con->page_retirement_req_cnt, 0);
|
||||
|
||||
mutex_destroy(&con->page_rsv_lock);
|
||||
|
||||
cancel_work_sync(&con->recovery_work);
|
||||
|
||||
cancel_delayed_work_sync(&con->page_retirement_dwork);
|
||||
|
||||
amdgpu_ras_ecc_log_fini(&con->umc_ecc_log);
|
||||
|
||||
mutex_lock(&con->recovery_lock);
|
||||
con->eh_data = NULL;
|
||||
kfree(data->bps);
|
||||
|
|
@ -3036,6 +3268,35 @@ static int amdgpu_get_ras_schema(struct amdgpu_device *adev)
|
|||
AMDGPU_RAS_ERROR__PARITY;
|
||||
}
|
||||
|
||||
static void ras_event_mgr_init(struct ras_event_manager *mgr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mgr->seqnos); i++)
|
||||
atomic64_set(&mgr->seqnos[i], 0);
|
||||
}
|
||||
|
||||
static void amdgpu_ras_event_mgr_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
struct amdgpu_hive_info *hive;
|
||||
|
||||
if (!ras)
|
||||
return;
|
||||
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
ras->event_mgr = hive ? &hive->event_mgr : &ras->__event_mgr;
|
||||
|
||||
/* init event manager with node 0 on xgmi system */
|
||||
if (!amdgpu_in_reset(adev)) {
|
||||
if (!hive || adev->gmc.xgmi.node_id == 0)
|
||||
ras_event_mgr_init(ras->event_mgr);
|
||||
}
|
||||
|
||||
if (hive)
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
|
||||
int amdgpu_ras_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
|
@ -3356,6 +3617,8 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
amdgpu_ras_event_mgr_init(adev);
|
||||
|
||||
if (amdgpu_aca_is_enabled(adev)) {
|
||||
if (amdgpu_in_reset(adev))
|
||||
r = amdgpu_aca_reset(adev);
|
||||
|
|
@ -3472,14 +3735,39 @@ void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status)
|
|||
atomic_set(&ras->fed, !!status);
|
||||
}
|
||||
|
||||
bool amdgpu_ras_event_id_is_valid(struct amdgpu_device *adev, u64 id)
|
||||
{
|
||||
return !(id & BIT_ULL(63));
|
||||
}
|
||||
|
||||
u64 amdgpu_ras_acquire_event_id(struct amdgpu_device *adev, enum ras_event_type type)
|
||||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
u64 id;
|
||||
|
||||
switch (type) {
|
||||
case RAS_EVENT_TYPE_ISR:
|
||||
id = (u64)atomic64_read(&ras->event_mgr->seqnos[type]);
|
||||
break;
|
||||
case RAS_EVENT_TYPE_INVALID:
|
||||
default:
|
||||
id = BIT_ULL(63) | 0ULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev)
|
||||
{
|
||||
if (atomic_cmpxchg(&amdgpu_ras_in_intr, 0, 1) == 0) {
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
u64 event_id = (u64)atomic64_inc_return(&ras->event_mgr->seqnos[RAS_EVENT_TYPE_ISR]);
|
||||
|
||||
dev_info(adev->dev, "uncorrectable hardware error"
|
||||
"(ERREVENT_ATHUB_INTERRUPT) detected!\n");
|
||||
RAS_EVENT_LOG(adev, event_id, "uncorrectable hardware error"
|
||||
"(ERREVENT_ATHUB_INTERRUPT) detected!\n");
|
||||
|
||||
amdgpu_ras_set_fed(adev, true);
|
||||
ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
|
@ -3998,6 +4286,8 @@ void amdgpu_ras_add_mca_err_addr(struct ras_err_info *err_info, struct ras_err_a
|
|||
{
|
||||
struct ras_err_addr *mca_err_addr;
|
||||
|
||||
/* This function will be retired. */
|
||||
return;
|
||||
mca_err_addr = kzalloc(sizeof(*mca_err_addr), GFP_KERNEL);
|
||||
if (!mca_err_addr)
|
||||
return;
|
||||
|
|
@ -4195,3 +4485,19 @@ void amdgpu_ras_query_boot_status(struct amdgpu_device *adev, u32 num_instances)
|
|||
amdgpu_ras_boot_time_error_reporting(adev, i, boot_error);
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
|
||||
uint64_t start = pfn << AMDGPU_GPU_PAGE_SHIFT;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&con->page_rsv_lock);
|
||||
ret = amdgpu_vram_mgr_query_page_status(mgr, start);
|
||||
if (ret == -ENOENT)
|
||||
ret = amdgpu_vram_mgr_reserve_range(mgr, start, AMDGPU_GPU_PAGE_SIZE);
|
||||
mutex_unlock(&con->page_rsv_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/siphash.h>
|
||||
#include "ta_ras_if.h"
|
||||
#include "amdgpu_ras_eeprom.h"
|
||||
#include "amdgpu_smuio.h"
|
||||
|
|
@ -64,6 +67,14 @@ struct amdgpu_iv_entry;
|
|||
/* The high three bits indicates socketid */
|
||||
#define AMDGPU_RAS_GET_FEATURES(val) ((val) & ~AMDGPU_RAS_FEATURES_SOCKETID_MASK)
|
||||
|
||||
#define RAS_EVENT_LOG(_adev, _id, _fmt, ...) \
|
||||
do { \
|
||||
if (amdgpu_ras_event_id_is_valid((_adev), (_id))) \
|
||||
dev_info((_adev)->dev, "{%llu}" _fmt, (_id), ##__VA_ARGS__); \
|
||||
else \
|
||||
dev_info((_adev)->dev, _fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
enum amdgpu_ras_block {
|
||||
AMDGPU_RAS_BLOCK__UMC = 0,
|
||||
AMDGPU_RAS_BLOCK__SDMA,
|
||||
|
|
@ -419,6 +430,52 @@ struct umc_ecc_info {
|
|||
int record_ce_addr_supported;
|
||||
};
|
||||
|
||||
enum ras_event_type {
|
||||
RAS_EVENT_TYPE_INVALID = -1,
|
||||
RAS_EVENT_TYPE_ISR = 0,
|
||||
RAS_EVENT_TYPE_COUNT,
|
||||
};
|
||||
|
||||
struct ras_event_manager {
|
||||
atomic64_t seqnos[RAS_EVENT_TYPE_COUNT];
|
||||
};
|
||||
|
||||
struct ras_query_context {
|
||||
enum ras_event_type type;
|
||||
u64 event_id;
|
||||
};
|
||||
|
||||
typedef int (*pasid_notify)(struct amdgpu_device *adev,
|
||||
uint16_t pasid, void *data);
|
||||
|
||||
struct ras_poison_msg {
|
||||
enum amdgpu_ras_block block;
|
||||
uint16_t pasid;
|
||||
uint32_t reset;
|
||||
pasid_notify pasid_fn;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct ras_err_pages {
|
||||
uint32_t count;
|
||||
uint64_t *pfn;
|
||||
};
|
||||
|
||||
struct ras_ecc_err {
|
||||
u64 hash_index;
|
||||
uint64_t status;
|
||||
uint64_t ipid;
|
||||
uint64_t addr;
|
||||
struct ras_err_pages err_pages;
|
||||
};
|
||||
|
||||
struct ras_ecc_log_info {
|
||||
struct mutex lock;
|
||||
siphash_key_t ecc_key;
|
||||
struct radix_tree_root de_page_tree;
|
||||
bool de_updated;
|
||||
};
|
||||
|
||||
struct amdgpu_ras {
|
||||
/* ras infrastructure */
|
||||
/* for ras itself. */
|
||||
|
|
@ -477,8 +534,18 @@ struct amdgpu_ras {
|
|||
wait_queue_head_t page_retirement_wq;
|
||||
struct mutex page_retirement_lock;
|
||||
atomic_t page_retirement_req_cnt;
|
||||
struct mutex page_rsv_lock;
|
||||
DECLARE_KFIFO(poison_fifo, struct ras_poison_msg, 128);
|
||||
struct ras_ecc_log_info umc_ecc_log;
|
||||
struct delayed_work page_retirement_dwork;
|
||||
|
||||
/* Fatal error detected flag */
|
||||
atomic_t fed;
|
||||
|
||||
/* RAS event manager */
|
||||
struct ras_event_manager __event_mgr;
|
||||
struct ras_event_manager *event_mgr;
|
||||
|
||||
};
|
||||
|
||||
struct ras_fs_data {
|
||||
|
|
@ -512,6 +579,7 @@ struct ras_err_data {
|
|||
unsigned long de_count;
|
||||
unsigned long err_addr_cnt;
|
||||
struct eeprom_table_record *err_addr;
|
||||
unsigned long err_addr_len;
|
||||
u32 err_list_count;
|
||||
struct list_head err_node_list;
|
||||
};
|
||||
|
|
@ -879,4 +947,13 @@ void amdgpu_ras_del_mca_err_addr(struct ras_err_info *err_info,
|
|||
void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status);
|
||||
bool amdgpu_ras_get_fed_status(struct amdgpu_device *adev);
|
||||
|
||||
bool amdgpu_ras_event_id_is_valid(struct amdgpu_device *adev, u64 id);
|
||||
u64 amdgpu_ras_acquire_event_id(struct amdgpu_device *adev, enum ras_event_type type);
|
||||
|
||||
int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn);
|
||||
|
||||
int amdgpu_ras_put_poison_req(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -404,6 +404,22 @@ static int amdgpu_ras_eeprom_correct_header_tag(
|
|||
return res;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_set_eeprom_table_version(struct amdgpu_ras_eeprom_control *control)
|
||||
{
|
||||
struct amdgpu_device *adev = to_amdgpu_device(control);
|
||||
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
|
||||
|
||||
switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) {
|
||||
case IP_VERSION(8, 10, 0):
|
||||
case IP_VERSION(12, 0, 0):
|
||||
hdr->version = RAS_TABLE_VER_V2_1;
|
||||
return;
|
||||
default:
|
||||
hdr->version = RAS_TABLE_VER_V1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ras_eeprom_reset_table -- Reset the RAS EEPROM table
|
||||
* @control: pointer to control structure
|
||||
|
|
@ -423,11 +439,7 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
|
|||
mutex_lock(&control->ras_tbl_mutex);
|
||||
|
||||
hdr->header = RAS_TABLE_HDR_VAL;
|
||||
if (adev->umc.ras &&
|
||||
adev->umc.ras->set_eeprom_table_version)
|
||||
adev->umc.ras->set_eeprom_table_version(hdr);
|
||||
else
|
||||
hdr->version = RAS_TABLE_VER_V1;
|
||||
amdgpu_ras_set_eeprom_table_version(control);
|
||||
|
||||
if (hdr->version == RAS_TABLE_VER_V2_1) {
|
||||
hdr->first_rec_offset = RAS_RECORD_START_V2_1;
|
||||
|
|
|
|||
|
|
@ -164,4 +164,29 @@ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_res_cleared - check if blocks are cleared
|
||||
*
|
||||
* @cur: the cursor to extract the block
|
||||
*
|
||||
* Check if the @cur block is cleared
|
||||
*/
|
||||
static inline bool amdgpu_res_cleared(struct amdgpu_res_cursor *cur)
|
||||
{
|
||||
struct drm_buddy_block *block;
|
||||
|
||||
switch (cur->mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
block = cur->node;
|
||||
|
||||
if (!amdgpu_vram_mgr_is_cleared(block))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/devcoredump.h>
|
||||
#include <generated/utsrelease.h>
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
#include "aldebaran.h"
|
||||
#include "sienna_cichlid.h"
|
||||
|
|
@ -161,105 +158,3 @@ void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain)
|
|||
atomic_set(&reset_domain->in_gpu_reset, 0);
|
||||
up_write(&reset_domain->sem);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DEV_COREDUMP
|
||||
void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
}
|
||||
#else
|
||||
static ssize_t
|
||||
amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
||||
void *data, size_t datalen)
|
||||
{
|
||||
struct drm_printer p;
|
||||
struct amdgpu_coredump_info *coredump = data;
|
||||
struct drm_print_iterator iter;
|
||||
int i;
|
||||
|
||||
iter.data = buffer;
|
||||
iter.offset = 0;
|
||||
iter.start = offset;
|
||||
iter.remain = count;
|
||||
|
||||
p = drm_coredump_printer(&iter);
|
||||
|
||||
drm_printf(&p, "**** AMDGPU Device Coredump ****\n");
|
||||
drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
|
||||
drm_printf(&p, "kernel: " UTS_RELEASE "\n");
|
||||
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
|
||||
drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec,
|
||||
coredump->reset_time.tv_nsec);
|
||||
|
||||
if (coredump->reset_task_info.pid)
|
||||
drm_printf(&p, "process_name: %s PID: %d\n",
|
||||
coredump->reset_task_info.process_name,
|
||||
coredump->reset_task_info.pid);
|
||||
|
||||
if (coredump->ring) {
|
||||
drm_printf(&p, "\nRing timed out details\n");
|
||||
drm_printf(&p, "IP Type: %d Ring Name: %s\n",
|
||||
coredump->ring->funcs->type,
|
||||
coredump->ring->name);
|
||||
}
|
||||
|
||||
if (coredump->reset_vram_lost)
|
||||
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
|
||||
if (coredump->adev->reset_info.num_regs) {
|
||||
drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n");
|
||||
|
||||
for (i = 0; i < coredump->adev->reset_info.num_regs; i++)
|
||||
drm_printf(&p, "0x%08x: 0x%08x\n",
|
||||
coredump->adev->reset_info.reset_dump_reg_list[i],
|
||||
coredump->adev->reset_info.reset_dump_reg_value[i]);
|
||||
}
|
||||
|
||||
return count - iter.remain;
|
||||
}
|
||||
|
||||
static void amdgpu_devcoredump_free(void *data)
|
||||
{
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_coredump_info *coredump;
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct amdgpu_job *job = reset_context->job;
|
||||
struct drm_sched_job *s_job;
|
||||
|
||||
coredump = kzalloc(sizeof(*coredump), GFP_NOWAIT);
|
||||
|
||||
if (!coredump) {
|
||||
DRM_ERROR("%s: failed to allocate memory for coredump\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
coredump->reset_vram_lost = vram_lost;
|
||||
|
||||
if (reset_context->job && reset_context->job->vm) {
|
||||
struct amdgpu_task_info *ti;
|
||||
struct amdgpu_vm *vm = reset_context->job->vm;
|
||||
|
||||
ti = amdgpu_vm_get_task_info_vm(vm);
|
||||
if (ti) {
|
||||
coredump->reset_task_info = *ti;
|
||||
amdgpu_vm_put_task_info(ti);
|
||||
}
|
||||
}
|
||||
|
||||
if (job) {
|
||||
s_job = &job->base;
|
||||
coredump->ring = to_amdgpu_ring(s_job->sched);
|
||||
}
|
||||
|
||||
coredump->adev = adev;
|
||||
|
||||
ktime_get_ts64(&coredump->reset_time);
|
||||
|
||||
dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT,
|
||||
amdgpu_devcoredump_read, amdgpu_devcoredump_free);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ enum AMDGPU_RESET_FLAGS {
|
|||
|
||||
AMDGPU_NEED_FULL_RESET = 0,
|
||||
AMDGPU_SKIP_HW_RESET = 1,
|
||||
AMDGPU_SKIP_COREDUMP = 2,
|
||||
};
|
||||
|
||||
struct amdgpu_reset_context {
|
||||
|
|
@ -88,19 +89,6 @@ struct amdgpu_reset_domain {
|
|||
atomic_t reset_res;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEV_COREDUMP
|
||||
|
||||
#define AMDGPU_COREDUMP_VERSION "1"
|
||||
|
||||
struct amdgpu_coredump_info {
|
||||
struct amdgpu_device *adev;
|
||||
struct amdgpu_task_info reset_task_info;
|
||||
struct timespec64 reset_time;
|
||||
bool reset_vram_lost;
|
||||
struct amdgpu_ring *ring;
|
||||
};
|
||||
#endif
|
||||
|
||||
int amdgpu_reset_init(struct amdgpu_device *adev);
|
||||
int amdgpu_reset_fini(struct amdgpu_device *adev);
|
||||
|
||||
|
|
@ -141,9 +129,6 @@ void amdgpu_device_lock_reset_domain(struct amdgpu_reset_domain *reset_domain);
|
|||
|
||||
void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain);
|
||||
|
||||
void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost,
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
|
||||
#define for_each_handler(i, handler, reset_ctl) \
|
||||
for (i = 0; (i < AMDGPU_RESET_MAX_HANDLERS) && \
|
||||
(handler = (*reset_ctl->reset_handlers)[i]); \
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ struct amdgpu_buffer_funcs {
|
|||
uint64_t dst_offset,
|
||||
/* number of byte to transfer */
|
||||
uint32_t byte_count,
|
||||
bool tmz);
|
||||
uint32_t copy_flags);
|
||||
|
||||
/* maximum bytes in a single operation */
|
||||
uint32_t fill_max_bytes;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ struct amdgpu_smuio_funcs {
|
|||
u32 (*get_socket_id)(struct amdgpu_device *adev);
|
||||
enum amdgpu_pkg_type (*get_pkg_type)(struct amdgpu_device *adev);
|
||||
bool (*is_host_gpu_xgmi_supported)(struct amdgpu_device *adev);
|
||||
u64 (*get_gpu_clock_counter)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_smuio {
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
|
|||
dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo);
|
||||
dst_addr += window * AMDGPU_GTT_MAX_TRANSFER_SIZE * 8;
|
||||
amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr,
|
||||
dst_addr, num_bytes, false);
|
||||
dst_addr, num_bytes, 0);
|
||||
|
||||
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
|
||||
WARN_ON(job->ibs[0].length_dw > num_dw);
|
||||
|
|
@ -296,6 +296,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
|||
struct dma_fence *fence = NULL;
|
||||
int r = 0;
|
||||
|
||||
uint32_t copy_flags = 0;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled) {
|
||||
DRM_ERROR("Trying to move memory with ring turned off.\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -323,8 +325,11 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
|||
if (r)
|
||||
goto error;
|
||||
|
||||
r = amdgpu_copy_buffer(ring, from, to, cur_size,
|
||||
resv, &next, false, true, tmz);
|
||||
if (tmz)
|
||||
copy_flags |= AMDGPU_COPY_FLAGS_TMZ;
|
||||
|
||||
r = amdgpu_copy_buffer(ring, from, to, cur_size, resv,
|
||||
&next, false, true, copy_flags);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
|
|
@ -378,11 +383,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) {
|
||||
struct dma_fence *wipe_fence = NULL;
|
||||
|
||||
r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence,
|
||||
false);
|
||||
r = amdgpu_fill_buffer(abo, 0, NULL, &wipe_fence,
|
||||
false);
|
||||
if (r) {
|
||||
goto error;
|
||||
} else if (wipe_fence) {
|
||||
amdgpu_vram_mgr_set_cleared(bo->resource);
|
||||
dma_fence_put(fence);
|
||||
fence = wipe_fence;
|
||||
}
|
||||
|
|
@ -1492,7 +1498,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo,
|
|||
swap(src_addr, dst_addr);
|
||||
|
||||
amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr,
|
||||
PAGE_SIZE, false);
|
||||
PAGE_SIZE, 0);
|
||||
|
||||
amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]);
|
||||
WARN_ON(job->ibs[0].length_dw > num_dw);
|
||||
|
|
@ -2143,7 +2149,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
|||
uint64_t dst_offset, uint32_t byte_count,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence, bool direct_submit,
|
||||
bool vm_needs_flush, bool tmz)
|
||||
bool vm_needs_flush, uint32_t copy_flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned int num_loops, num_dw;
|
||||
|
|
@ -2169,8 +2175,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
|||
uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
|
||||
|
||||
amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_offset,
|
||||
dst_offset, cur_size_in_bytes, tmz);
|
||||
|
||||
dst_offset, cur_size_in_bytes, copy_flags);
|
||||
src_offset += cur_size_in_bytes;
|
||||
dst_offset += cur_size_in_bytes;
|
||||
byte_count -= cur_size_in_bytes;
|
||||
|
|
@ -2230,6 +2235,71 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_clear_buffer - clear memory buffers
|
||||
* @bo: amdgpu buffer object
|
||||
* @resv: reservation object
|
||||
* @fence: dma_fence associated with the operation
|
||||
*
|
||||
* Clear the memory buffer resource.
|
||||
*
|
||||
* Returns:
|
||||
* 0 for success or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
u64 addr;
|
||||
int r;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
if (!fence)
|
||||
return -EINVAL;
|
||||
|
||||
*fence = dma_fence_get_stub();
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
|
||||
|
||||
mutex_lock(&adev->mman.gtt_window_lock);
|
||||
while (cursor.remaining) {
|
||||
struct dma_fence *next = NULL;
|
||||
u64 size;
|
||||
|
||||
if (amdgpu_res_cleared(&cursor)) {
|
||||
amdgpu_res_next(&cursor, cursor.size);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Never clear more than 256MiB at once to avoid timeouts */
|
||||
size = min(cursor.size, 256ULL << 20);
|
||||
|
||||
r = amdgpu_ttm_map_buffer(&bo->tbo, bo->tbo.resource, &cursor,
|
||||
1, ring, false, &size, &addr);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = amdgpu_ttm_fill_mem(ring, 0, addr, size, resv,
|
||||
&next, true, true);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
dma_fence_put(*fence);
|
||||
*fence = next;
|
||||
|
||||
amdgpu_res_next(&cursor, size);
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&adev->mman.gtt_window_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
uint32_t src_data,
|
||||
struct dma_resv *resv,
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
#define AMDGPU_GTT_MAX_TRANSFER_SIZE 512
|
||||
#define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2
|
||||
|
||||
#define AMDGPU_POISON 0xd0bed0be
|
||||
|
||||
extern const struct attribute_group amdgpu_vram_mgr_attr_group;
|
||||
extern const struct attribute_group amdgpu_gtt_mgr_attr_group;
|
||||
|
||||
|
|
@ -111,6 +109,8 @@ struct amdgpu_copy_mem {
|
|||
unsigned long offset;
|
||||
};
|
||||
|
||||
#define AMDGPU_COPY_FLAGS_TMZ (1 << 0)
|
||||
|
||||
int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size);
|
||||
void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_preempt_mgr_init(struct amdgpu_device *adev);
|
||||
|
|
@ -151,13 +151,16 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
|||
uint64_t dst_offset, uint32_t byte_count,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence, bool direct_submit,
|
||||
bool vm_needs_flush, bool tmz);
|
||||
bool vm_needs_flush, uint32_t copy_flags);
|
||||
int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
||||
const struct amdgpu_copy_mem *src,
|
||||
const struct amdgpu_copy_mem *dst,
|
||||
uint64_t size, bool tmz,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **f);
|
||||
int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
||||
struct dma_resv *resv,
|
||||
struct dma_fence **fence);
|
||||
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
uint32_t src_data,
|
||||
struct dma_resv *resv,
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ enum psp_fw_type {
|
|||
PSP_FW_TYPE_PSP_INTF_DRV,
|
||||
PSP_FW_TYPE_PSP_DBG_DRV,
|
||||
PSP_FW_TYPE_PSP_RAS_DRV,
|
||||
PSP_FW_TYPE_PSP_IPKEYMGR_DRV,
|
||||
PSP_FW_TYPE_MAX_INDEX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,13 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/sort.h>
|
||||
#include "amdgpu.h"
|
||||
#include "umc_v6_7.h"
|
||||
#define MAX_UMC_POISON_POLLING_TIME_SYNC 20 //ms
|
||||
|
||||
#define MAX_UMC_HASH_STRING_SIZE 256
|
||||
|
||||
static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev,
|
||||
struct ras_err_data *err_data, uint64_t err_addr,
|
||||
uint32_t ch_inst, uint32_t umc_inst)
|
||||
|
|
@ -63,6 +66,8 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
|
|||
goto out_fini_err_data;
|
||||
}
|
||||
|
||||
err_data.err_addr_len = adev->umc.max_ras_err_cnt_per_query;
|
||||
|
||||
/*
|
||||
* Translate UMC channel address to Physical address
|
||||
*/
|
||||
|
|
@ -86,7 +91,7 @@ out_fini_err_data:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
||||
void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
|
|
@ -118,6 +123,8 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
|||
if(!err_data->err_addr)
|
||||
dev_warn(adev->dev, "Failed to alloc memory for "
|
||||
"umc error address record!\n");
|
||||
else
|
||||
err_data->err_addr_len = adev->umc.max_ras_err_cnt_per_query;
|
||||
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
|
|
@ -143,6 +150,8 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
|||
if(!err_data->err_addr)
|
||||
dev_warn(adev->dev, "Failed to alloc memory for "
|
||||
"umc error address record!\n");
|
||||
else
|
||||
err_data->err_addr_len = adev->umc.max_ras_err_cnt_per_query;
|
||||
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
|
|
@ -170,6 +179,7 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
kfree(err_data->err_addr);
|
||||
err_data->err_addr = NULL;
|
||||
|
||||
mutex_unlock(&con->page_retirement_lock);
|
||||
}
|
||||
|
|
@ -177,7 +187,7 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
|||
static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
struct amdgpu_iv_entry *entry,
|
||||
bool reset)
|
||||
uint32_t reset)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
|
@ -186,9 +196,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
|||
amdgpu_umc_handle_bad_pages(adev, ras_error_status);
|
||||
|
||||
if (err_data->ue_count && reset) {
|
||||
/* use mode-2 reset for poison consumption */
|
||||
if (!entry)
|
||||
con->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +204,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
||||
bool reset, uint32_t timeout_ms)
|
||||
uint32_t reset, uint32_t timeout_ms)
|
||||
{
|
||||
struct ras_err_data err_data;
|
||||
struct ras_common_if head = {
|
||||
|
|
@ -238,16 +246,16 @@ int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
|||
if (reset) {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
/* use mode-2 reset for poison consumption */
|
||||
con->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, bool reset)
|
||||
int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset)
|
||||
{
|
||||
int ret = AMDGPU_RAS_SUCCESS;
|
||||
|
||||
|
|
@ -285,16 +293,14 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
|||
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
} else {
|
||||
if (reset) {
|
||||
amdgpu_umc_bad_page_polling_timeout(adev,
|
||||
reset, MAX_UMC_POISON_POLLING_TIME_SYNC);
|
||||
} else {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
amdgpu_ras_put_poison_req(adev,
|
||||
block, pasid, pasid_fn, data, reset);
|
||||
|
||||
atomic_inc(&con->page_retirement_req_cnt);
|
||||
|
||||
wake_up(&con->page_retirement_wq);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
|
||||
|
|
@ -307,11 +313,19 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint32_t reset)
|
||||
{
|
||||
return amdgpu_umc_pasid_poison_handler(adev,
|
||||
block, 0, NULL, NULL, reset);
|
||||
}
|
||||
|
||||
int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
void *ras_error_status,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry, true);
|
||||
return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry,
|
||||
AMDGPU_RAS_GPU_RESET_MODE1_RESET);
|
||||
}
|
||||
|
||||
int amdgpu_umc_ras_sw_init(struct amdgpu_device *adev)
|
||||
|
|
@ -388,14 +402,20 @@ int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
||||
int amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
||||
uint64_t err_addr,
|
||||
uint64_t retired_page,
|
||||
uint32_t channel_index,
|
||||
uint32_t umc_inst)
|
||||
{
|
||||
struct eeprom_table_record *err_rec =
|
||||
&err_data->err_addr[err_data->err_addr_cnt];
|
||||
struct eeprom_table_record *err_rec;
|
||||
|
||||
if (!err_data ||
|
||||
!err_data->err_addr ||
|
||||
(err_data->err_addr_cnt >= err_data->err_addr_len))
|
||||
return -EINVAL;
|
||||
|
||||
err_rec = &err_data->err_addr[err_data->err_addr_cnt];
|
||||
|
||||
err_rec->address = err_addr;
|
||||
/* page frame address is saved */
|
||||
|
|
@ -407,6 +427,8 @@ void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
|||
err_rec->mcumc_id = umc_inst;
|
||||
|
||||
err_data->err_addr_cnt++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_umc_loop_channels(struct amdgpu_device *adev,
|
||||
|
|
@ -439,3 +461,76 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_umc_update_ecc_status(struct amdgpu_device *adev,
|
||||
uint64_t status, uint64_t ipid, uint64_t addr)
|
||||
{
|
||||
if (adev->umc.ras->update_ecc_status)
|
||||
return adev->umc.ras->update_ecc_status(adev,
|
||||
status, ipid, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_umc_uint64_cmp(const void *a, const void *b)
|
||||
{
|
||||
uint64_t *addr_a = (uint64_t *)a;
|
||||
uint64_t *addr_b = (uint64_t *)b;
|
||||
|
||||
if (*addr_a > *addr_b)
|
||||
return 1;
|
||||
else if (*addr_a < *addr_b)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use string hash to avoid logging the same bad pages repeatedly */
|
||||
int amdgpu_umc_build_pages_hash(struct amdgpu_device *adev,
|
||||
uint64_t *pfns, int len, uint64_t *val)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
char buf[MAX_UMC_HASH_STRING_SIZE] = {0};
|
||||
int offset = 0, i = 0;
|
||||
uint64_t hash_val;
|
||||
|
||||
if (!pfns || !len)
|
||||
return -EINVAL;
|
||||
|
||||
sort(pfns, len, sizeof(uint64_t), amdgpu_umc_uint64_cmp, NULL);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
offset += snprintf(&buf[offset], sizeof(buf) - offset, "%llx", pfns[i]);
|
||||
|
||||
hash_val = siphash(buf, offset, &con->umc_ecc_log.ecc_key);
|
||||
|
||||
*val = hash_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev,
|
||||
struct radix_tree_root *ecc_tree, struct ras_ecc_err *ecc_err)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_ecc_log_info *ecc_log;
|
||||
int ret;
|
||||
|
||||
ecc_log = &con->umc_ecc_log;
|
||||
|
||||
mutex_lock(&ecc_log->lock);
|
||||
ret = radix_tree_insert(ecc_tree, ecc_err->hash_index, ecc_err);
|
||||
if (!ret) {
|
||||
struct ras_err_pages *err_pages = &ecc_err->err_pages;
|
||||
int i;
|
||||
|
||||
/* Reserve memory */
|
||||
for (i = 0; i < err_pages->count; i++)
|
||||
amdgpu_ras_reserve_page(adev, err_pages->pfn[i]);
|
||||
|
||||
radix_tree_tag_set(ecc_tree,
|
||||
ecc_err->hash_index, UMC_ECC_NEW_DETECTED_TAG);
|
||||
}
|
||||
mutex_unlock(&ecc_log->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@
|
|||
#define LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) \
|
||||
LOOP_UMC_NODE_INST((node_inst)) LOOP_UMC_INST_AND_CH((umc_inst), (ch_inst))
|
||||
|
||||
/* Page retirement tag */
|
||||
#define UMC_ECC_NEW_DETECTED_TAG 0x1
|
||||
|
||||
typedef int (*umc_func)(struct amdgpu_device *adev, uint32_t node_inst,
|
||||
uint32_t umc_inst, uint32_t ch_inst, void *data);
|
||||
|
|
@ -66,8 +68,8 @@ struct amdgpu_umc_ras {
|
|||
void *ras_error_status);
|
||||
bool (*check_ecc_err_status)(struct amdgpu_device *adev,
|
||||
enum amdgpu_mca_error_type type, void *ras_error_status);
|
||||
/* support different eeprom table version for different asic */
|
||||
void (*set_eeprom_table_version)(struct amdgpu_ras_eeprom_table_header *hdr);
|
||||
int (*update_ecc_status)(struct amdgpu_device *adev,
|
||||
uint64_t status, uint64_t ipid, uint64_t addr);
|
||||
};
|
||||
|
||||
struct amdgpu_umc_funcs {
|
||||
|
|
@ -103,11 +105,14 @@ struct amdgpu_umc {
|
|||
int amdgpu_umc_ras_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, bool reset);
|
||||
enum amdgpu_ras_block block, uint32_t reset);
|
||||
int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset);
|
||||
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
||||
int amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
|
||||
uint64_t err_addr,
|
||||
uint64_t retired_page,
|
||||
uint32_t channel_index,
|
||||
|
|
@ -123,5 +128,15 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev,
|
|||
umc_func func, void *data);
|
||||
|
||||
int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
||||
bool reset, uint32_t timeout_ms);
|
||||
uint32_t reset, uint32_t timeout_ms);
|
||||
|
||||
int amdgpu_umc_update_ecc_status(struct amdgpu_device *adev,
|
||||
uint64_t status, uint64_t ipid, uint64_t addr);
|
||||
int amdgpu_umc_build_pages_hash(struct amdgpu_device *adev,
|
||||
uint64_t *pfns, int len, uint64_t *val);
|
||||
int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev,
|
||||
struct radix_tree_root *ecc_tree, struct ras_ecc_err *ecc_err);
|
||||
|
||||
void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -878,6 +878,8 @@ static const struct amd_ip_funcs umsch_mm_v4_0_ip_funcs = {
|
|||
.hw_fini = umsch_mm_hw_fini,
|
||||
.suspend = umsch_mm_suspend,
|
||||
.resume = umsch_mm_resume,
|
||||
.dump_ip_state = NULL,
|
||||
.print_ip_state = NULL,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version umsch_mm_v4_0_ip_block = {
|
||||
|
|
|
|||
|
|
@ -743,7 +743,8 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p,
|
|||
uint32_t created = 0;
|
||||
uint32_t allocated = 0;
|
||||
uint32_t tmp, handle = 0;
|
||||
uint32_t *size = &tmp;
|
||||
uint32_t dummy = 0xffffffff;
|
||||
uint32_t *size = &dummy;
|
||||
unsigned int idx;
|
||||
int i, r = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
|
|||
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
char ucode_prefix[30];
|
||||
char ucode_prefix[25];
|
||||
char fw_name[40];
|
||||
int r, i;
|
||||
|
||||
|
|
@ -185,7 +185,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
|||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
|
||||
|
||||
if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
|
||||
if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {
|
||||
fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));
|
||||
log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);
|
||||
} else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {
|
||||
fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));
|
||||
log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -454,6 +454,16 @@ struct amdgpu_vcn_rb_metadata {
|
|||
uint8_t pad[26];
|
||||
};
|
||||
|
||||
struct amdgpu_vcn5_fw_shared {
|
||||
uint32_t present_flag_0;
|
||||
uint8_t pad[12];
|
||||
struct amdgpu_fw_shared_unified_queue_struct sq;
|
||||
uint8_t pad1[8];
|
||||
struct amdgpu_fw_shared_fw_logging fw_log;
|
||||
struct amdgpu_fw_shared_rb_setup rb_setup;
|
||||
uint8_t pad2[4];
|
||||
};
|
||||
|
||||
#define VCN_BLOCK_ENCODE_DISABLE_MASK 0x80
|
||||
#define VCN_BLOCK_DECODE_DISABLE_MASK 0x40
|
||||
#define VCN_BLOCK_QUEUE_DISABLE_MASK 0xC0
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "vi.h"
|
||||
#include "soc15.h"
|
||||
#include "nv.h"
|
||||
|
|
@ -424,7 +425,7 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
|
|||
return -EINVAL;
|
||||
|
||||
if (pf2vf_info->size > 1024) {
|
||||
DRM_ERROR("invalid pf2vf message size\n");
|
||||
dev_err(adev->dev, "invalid pf2vf message size: 0x%x\n", pf2vf_info->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +436,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
|
|||
adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size,
|
||||
adev->virt.fw_reserve.checksum_key, checksum);
|
||||
if (checksum != checkval) {
|
||||
DRM_ERROR("invalid pf2vf message\n");
|
||||
dev_err(adev->dev,
|
||||
"invalid pf2vf message: header checksum=0x%x calculated checksum=0x%x\n",
|
||||
checksum, checkval);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -449,7 +452,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
|
|||
adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size,
|
||||
0, checksum);
|
||||
if (checksum != checkval) {
|
||||
DRM_ERROR("invalid pf2vf message\n");
|
||||
dev_err(adev->dev,
|
||||
"invalid pf2vf message: header checksum=0x%x calculated checksum=0x%x\n",
|
||||
checksum, checkval);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -485,7 +490,7 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
|
|||
((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("invalid pf2vf version\n");
|
||||
dev_err(adev->dev, "invalid pf2vf version: 0x%x\n", pf2vf_info->version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -571,6 +576,11 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
|
|||
vf2pf_info->decode_usage = 0;
|
||||
|
||||
vf2pf_info->dummy_page_addr = (uint64_t)adev->dummy_page_addr;
|
||||
vf2pf_info->mes_info_addr = (uint64_t)adev->mes.resource_1_gpu_addr;
|
||||
|
||||
if (adev->mes.resource_1) {
|
||||
vf2pf_info->mes_info_size = adev->mes.resource_1->tbo.base.size;
|
||||
}
|
||||
vf2pf_info->checksum =
|
||||
amd_sriov_msg_checksum(
|
||||
vf2pf_info, vf2pf_info->header.size, 0, 0);
|
||||
|
|
@ -584,8 +594,22 @@ static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work)
|
|||
int ret;
|
||||
|
||||
ret = amdgpu_virt_read_pf2vf_data(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->virt.vf2pf_update_retry_cnt++;
|
||||
if ((adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) &&
|
||||
amdgpu_sriov_runtime(adev) && !amdgpu_in_reset(adev)) {
|
||||
amdgpu_ras_set_fed(adev, true);
|
||||
if (amdgpu_reset_domain_schedule(adev->reset_domain,
|
||||
&adev->virt.flr_work))
|
||||
return;
|
||||
else
|
||||
dev_err(adev->dev, "Failed to queue work! at %s", __func__);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
adev->virt.vf2pf_update_retry_cnt = 0;
|
||||
amdgpu_virt_write_vf2pf_data(adev);
|
||||
|
||||
out:
|
||||
|
|
@ -606,6 +630,7 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
|
|||
adev->virt.fw_reserve.p_pf2vf = NULL;
|
||||
adev->virt.fw_reserve.p_vf2pf = NULL;
|
||||
adev->virt.vf2pf_update_interval_ms = 0;
|
||||
adev->virt.vf2pf_update_retry_cnt = 0;
|
||||
|
||||
if (adev->mman.fw_vram_usage_va && adev->mman.drv_vram_usage_va) {
|
||||
DRM_WARN("Currently fw_vram and drv_vram should not have values at the same time!");
|
||||
|
|
@ -705,12 +730,6 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev)
|
|||
adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)
|
||||
/* VF MMIO access (except mailbox range) from CPU
|
||||
* will be blocked during sriov runtime
|
||||
*/
|
||||
adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT;
|
||||
|
||||
/* we have the ability to check now */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
switch (adev->asic_type) {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@
|
|||
/* tonga/fiji use this offset */
|
||||
#define mmBIF_IOV_FUNC_IDENTIFIER 0x1503
|
||||
|
||||
#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 5
|
||||
|
||||
enum amdgpu_sriov_vf_mode {
|
||||
SRIOV_VF_MODE_BARE_METAL = 0,
|
||||
SRIOV_VF_MODE_ONE_VF,
|
||||
|
|
@ -130,6 +132,8 @@ enum AMDGIM_FEATURE_FLAG {
|
|||
AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6),
|
||||
/* VCN RB decouple */
|
||||
AMDGIM_FEATURE_VCN_RB_DECOUPLE = (1 << 7),
|
||||
/* MES info */
|
||||
AMDGIM_FEATURE_MES_INFO_ENABLE = (1 << 8),
|
||||
};
|
||||
|
||||
enum AMDGIM_REG_ACCESS_FLAG {
|
||||
|
|
@ -257,6 +261,7 @@ struct amdgpu_virt {
|
|||
/* vf2pf message */
|
||||
struct delayed_work vf2pf_work;
|
||||
uint32_t vf2pf_update_interval_ms;
|
||||
int vf2pf_update_retry_cnt;
|
||||
|
||||
/* multimedia bandwidth config */
|
||||
bool is_mm_bw_enabled;
|
||||
|
|
@ -332,6 +337,8 @@ static inline bool is_virtual_machine(void)
|
|||
((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT)
|
||||
#define amdgpu_sriov_is_vcn_rb_decouple(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_VCN_RB_DECOUPLE)
|
||||
#define amdgpu_sriov_is_mes_info_enable(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_MES_INFO_ENABLE)
|
||||
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
|
||||
|
|
|
|||
|
|
@ -658,6 +658,8 @@ static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
|
|||
.soft_reset = amdgpu_vkms_soft_reset,
|
||||
.set_clockgating_state = amdgpu_vkms_set_clockgating_state,
|
||||
.set_powergating_state = amdgpu_vkms_set_powergating_state,
|
||||
.dump_ip_state = NULL,
|
||||
.print_ip_state = NULL,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version amdgpu_vkms_ip_block = {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue