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:
Linus Torvalds 2024-05-15 09:43:42 -07:00
commit db5d28c0bf
1373 changed files with 77527 additions and 55665 deletions

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,6 +29,7 @@ properties:
- qcom,sm8650-dp
- items:
- enum:
- qcom,sm6350-dp
- qcom,sm8150-dp
- qcom,sm8250-dp
- qcom,sm8450-dp

View File

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

View File

@ -19,6 +19,7 @@ properties:
- ampire,am8001280g
- bananapi,lhr050h41
- feixin,k101-im2byl02
- startek,kd050hdfia020
- tdo,tl050hdv35
- wanchanglong,w552946aba
- const: ilitek,ili9881c

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,6 +23,8 @@ properties:
reg: true
backlight: true
width-mm: true
height-mm: true
vddio-supply:
description: VDDIO 1.8V supply

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

@ -15,4 +15,5 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
ras
thermal
driver-misc
debugging
amdgpu-glossary

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,8 @@
#ifndef __M68K_PGTABLE_H
#define __M68K_PGTABLE_H
#include <asm/page.h>
#ifdef __uClinux__
#include <asm/pgtable_no.h>
#else

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 += \

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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