drm for 6.16-rc1

new drivers:
 - bring in the asahi uapi header standalone
 - nova-drm: stub driver
 
 rust dependencies (for nova-core):
 - auxiliary
   - bus abstractions
   - driver registration
   - sample driver
 - devres changes from driver-core
 - revocable changes
 
 core:
 - add Apple fourcc modifiers
 - add virtio capset definitions
 - extend EXPORT_SYNC_FILE for timeline syncobjs
 - convert to devm_platform_ioremap_resource
 - refactor shmem helper page pinning
 - DP powerup/down link helpers
 - remove disgusting turds
 - extended %p4cc in vsprintf.c to support fourcc prints
 - change vsprintf %p4cn to %p4chR, remove %p4cn
 - Add drm_file_err function
 - IN_FORMATS_ASYNC property
 - move sitronix from tiny to their own subdir
 
 rust:
 - add drm core infrastructure rust abstractions
   (device/driver, ioctl, file, gem)
 
 dma-buf:
 - adjust sg handling to not cache map on attach
 - allow setting dma-device for import
 - Add a helper to sort and deduplicate dma_fence arrays
 
 docs:
 - updated drm scheduler docs
 - fbdev todo update
 - fb rendering
 - actual brightness
 
 ttm:
 - fix delayed destroy resv object
 
 bridge:
 - add kunit tests
 - convert tc358775 to atomic
 - convert drivers to devm_drm_bridge_alloc
 - convert rk3066_hdmi to bridge driver
 
 scheduler:
 - add kunit tests
 
 panel:
 - refcount panels to improve lifetime handling
 - Powertip PH128800T004-ZZA01
 - NLT NL13676BC25-03F, Tianma TM070JDHG34-00
 - Himax HX8279/HX8279-D DDIC
 - Visionox G2647FB105
 - Sitronix ST7571
 - ZOTAC rotation quirk
 
 vkms:
 - allow attaching more displays
 
 i915:
 - xe3lpd display updates
 - vrr refactor
 - intel_display struct conversions
 - xe2hpd memory type identification
 - add link rate/count to i915_display_info
 - cleanup VGA plane handling
 - refactor HDCP GSC
 - fix SLPC wait boosting reference counting
 - add 20ms delay to engine reset
 - fix fence release on early probe errors
 
 xe:
 - SRIOV updates
 - BMG PCI ID update
 - support separate firmware for each GT
 - SVM fix, prelim SVM multi-device work
 - export fan speed
 - temp disable d3cold on BMG
 - backup VRAM in PM notifier instead of suspend/freeze
 - update xe_ttm_access_memory to use GPU for non-visible access
 - fix guc_info debugfs for VFs
 - use copy_from_user instead of __copy_from_user
 - append PCIe gen5 limitations to xe_firmware document
 
 amdgpu:
 - DSC cleanup
 - DC Scaling updates
 - Fused I2C-over-AUX updates
 - DMUB updates
 - Use drm_file_err in amdgpu
 - Enforce isolation updates
 - Use new dma_fence helpers
 - USERQ fixes
 - Documentation updates
 - SR-IOV updates
 - RAS updates
 - PSP 12 cleanups
 - GC 9.5 updates
 - SMU 13.x updates
 - VCN / JPEG SR-IOV updates
 
 amdkfd:
 - Update error messages for SDMA
 - Userptr updates
 - XNACK fixes
 
 radeon:
 - CIK doorbell cleanup
 
 nouveau:
 - add support for NVIDIA r570 GSP firmware
 - enable Hopper/Blackwell support
 
 nova-core:
 - fix task list
 - register definition infrastructure
 - move firmware into own rust module
 - register auxiliary device for nova-drm
 
 nova-drm:
 - initial driver skeleton
 
 msm:
 - GPU:
   - ACD (adaptive clock distribution) for X1-85
   - drop fictional address_space_size
   - improve GMU HFI response time out robustness
   - fix crash when throttling during boot
 - DPU:
   - use single CTL path for flushing on DPU 5.x+
   - improve SSPP allocation code for better sharing
   - Enabled SmartDMA on SM8150, SC8180X, SC8280XP, SM8550
   - Added SAR2130P support
   - Disabled DSC support on MSM8937, MSM8917, MSM8953, SDM660
 - DP:
   - switch to new audio helpers
   - better LTTPR handling
 - DSI:
   - Added support for SA8775P
   - Added SAR2130P support
 - HDMI:
   - Switched to use new helpers for ACR data
   - Fixed old standing issue of HPD not working in some cases
 
 amdxdna:
 - add dma-buf support
 - allow empty command submits
 
 renesas:
 - add dma-buf support
 - add zpos, alpha, blend support
 
 panthor:
 - fail properly for NO_MMAP bos
 - add SET_LABEL ioctl
 - debugfs BO dumping support
 
 imagination:
 - update DT bindings
 - support TI AM68 GPU
 
 hibmc:
 - improve interrupt handling and HPD support
 
 virtio:
 - add panic handler support
 
 rockchip:
 - add RK3588 support
 - add DP AUX bus panel support
 
 ivpu:
 - add heartbeat based hangcheck
 
 mediatek:
 - prepares support for MT8195/99 HDMIv2/DDCv2
 
 anx7625:
 - improve HPD
 
 tegra:
 - speed up firmware loading
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmg2aVAACgkQDHTzWXnE
 hr6DjhAApr2fZjugU3EmpsARdcIWgEd+X65R97ef7RlUGqBKm2joSwZGOhH0oBsG
 9WyO92Qzu6XMe8OibKqY4D2hir9UPz5v+uEWe3q9CzZGbNyAwyVRjVkaKpnI9upv
 1dmHFI7HgPu6qbz6RfPIfgALBLXvVXMaQ4+ZgN/cLtZFa+OLAV5ByqWsRPPXZFb0
 F/pQGQ4ursglfA+LH3SVPfnTN53lu93IlM5/Os9OQQGj+44w94zQ6DCm7CY1AugH
 n+RM/0Yv7WaoF1ByeOtq4FcrmLRrd+ozsvITbRZqhOx7zS/mhP8LRzAwgKWOYzSh
 puKunyQiSdHR7FSqSi8uyY3YumcLWNa/17LMKoTf+KqweJbKGE7RVBuFBn6WUdPb
 AYHZrSB4USAeyahdrrsU+q7ltu5urs5ckpbXsRurMiaUz/BLim1PIm3N5FDLPY7B
 PD1n1FcMUv3CmJT5Y+aNIQgmf1/dETESRTSAgSoOo3gNp6jdRCYqSuWIBsppibWT
 26+tyz0/FGhE50QviHzg0Sv+jd/g93fN6snNlV8wNFMviq3bC69Toa+y3qJ5e7UC
 /42R7nCWdkCZJfr6E67rOaahe9TDV/LXLqPErwptOkdK8sMchaIgF+deybgTtTi/
 zGRBfjLvb5ocYBmPbeGX4mtXNRpyZ3o9I0QUyGUO4zMwFXmFwn0=
 =jpVr
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2025-05-28' of https://gitlab.freedesktop.org/drm/kernel

Pull drm updates from Dave Airlie:
 "As part of building up nova-core/nova-drm pieces we've brought in some
  rust abstractions through this tree, aux bus being the main one, with
  devres changes also in the driver-core tree. Along with the drm core
  abstractions and enough nova-core/nova-drm to use them. This is still
  all stub work under construction, to build the nova driver upstream.

  The other big NVIDIA related one is nouveau adds support for
  Hopper/Blackwell GPUs, this required a new GSP firmware update to
  570.144, and a bunch of rework in order to support multiple fw
  interfaces.

  There is also the introduction of an asahi uapi header file as a
  precursor to getting the real driver in later, but to unblock
  userspace mesa packages while the driver is trapped behind rust
  enablement.

  Otherwise it's the usual mixture of stuff all over, amdgpu, i915/xe,
  and msm being the main ones, and some changes to vsprintf.

  new drivers:
   - bring in the asahi uapi header standalone
   - nova-drm: stub driver

  rust dependencies (for nova-core):
   - auxiliary
       - bus abstractions
       - driver registration
       - sample driver
   - devres changes from driver-core
   - revocable changes

  core:
   - add Apple fourcc modifiers
   - add virtio capset definitions
   - extend EXPORT_SYNC_FILE for timeline syncobjs
   - convert to devm_platform_ioremap_resource
   - refactor shmem helper page pinning
   - DP powerup/down link helpers
   - extended %p4cc in vsprintf.c to support fourcc prints
   - change vsprintf %p4cn to %p4chR, remove %p4cn
   - Add drm_file_err function
   - IN_FORMATS_ASYNC property
   - move sitronix from tiny to their own subdir

  rust:
   - add drm core infrastructure rust abstractions
     (device/driver, ioctl, file, gem)

  dma-buf:
   - adjust sg handling to not cache map on attach
   - allow setting dma-device for import
   - Add a helper to sort and deduplicate dma_fence arrays

  docs:
   - updated drm scheduler docs
   - fbdev todo update
   - fb rendering
   - actual brightness

  ttm:
   - fix delayed destroy resv object

  bridge:
   - add kunit tests
   - convert tc358775 to atomic
   - convert drivers to devm_drm_bridge_alloc
   - convert rk3066_hdmi to bridge driver

  scheduler:
   - add kunit tests

  panel:
   - refcount panels to improve lifetime handling
   - Powertip PH128800T004-ZZA01
   - NLT NL13676BC25-03F, Tianma TM070JDHG34-00
   - Himax HX8279/HX8279-D DDIC
   - Visionox G2647FB105
   - Sitronix ST7571
   - ZOTAC rotation quirk

  vkms:
   - allow attaching more displays

  i915:
   - xe3lpd display updates
   - vrr refactor
   - intel_display struct conversions
   - xe2hpd memory type identification
   - add link rate/count to i915_display_info
   - cleanup VGA plane handling
   - refactor HDCP GSC
   - fix SLPC wait boosting reference counting
   - add 20ms delay to engine reset
   - fix fence release on early probe errors

  xe:
   - SRIOV updates
   - BMG PCI ID update
   - support separate firmware for each GT
   - SVM fix, prelim SVM multi-device work
   - export fan speed
   - temp disable d3cold on BMG
   - backup VRAM in PM notifier instead of suspend/freeze
   - update xe_ttm_access_memory to use GPU for non-visible access
   - fix guc_info debugfs for VFs
   - use copy_from_user instead of __copy_from_user
   - append PCIe gen5 limitations to xe_firmware document

  amdgpu:
   - DSC cleanup
   - DC Scaling updates
   - Fused I2C-over-AUX updates
   - DMUB updates
   - Use drm_file_err in amdgpu
   - Enforce isolation updates
   - Use new dma_fence helpers
   - USERQ fixes
   - Documentation updates
   - SR-IOV updates
   - RAS updates
   - PSP 12 cleanups
   - GC 9.5 updates
   - SMU 13.x updates
   - VCN / JPEG SR-IOV updates

  amdkfd:
   - Update error messages for SDMA
   - Userptr updates
   - XNACK fixes

  radeon:
   - CIK doorbell cleanup

  nouveau:
   - add support for NVIDIA r570 GSP firmware
   - enable Hopper/Blackwell support

  nova-core:
   - fix task list
   - register definition infrastructure
   - move firmware into own rust module
   - register auxiliary device for nova-drm

  nova-drm:
   - initial driver skeleton

  msm:
   - GPU:
       - ACD (adaptive clock distribution) for X1-85
       - drop fictional address_space_size
       - improve GMU HFI response time out robustness
       - fix crash when throttling during boot
   - DPU:
       - use single CTL path for flushing on DPU 5.x+
       - improve SSPP allocation code for better sharing
       - Enabled SmartDMA on SM8150, SC8180X, SC8280XP, SM8550
       - Added SAR2130P support
       - Disabled DSC support on MSM8937, MSM8917, MSM8953, SDM660
   - DP:
       - switch to new audio helpers
       - better LTTPR handling
   - DSI:
       - Added support for SA8775P
       - Added SAR2130P support
   - HDMI:
       - Switched to use new helpers for ACR data
       - Fixed old standing issue of HPD not working in some cases

  amdxdna:
   - add dma-buf support
   - allow empty command submits

  renesas:
   - add dma-buf support
   - add zpos, alpha, blend support

  panthor:
   - fail properly for NO_MMAP bos
   - add SET_LABEL ioctl
   - debugfs BO dumping support

  imagination:
   - update DT bindings
   - support TI AM68 GPU

  hibmc:
   - improve interrupt handling and HPD support

  virtio:
   - add panic handler support

  rockchip:
   - add RK3588 support
   - add DP AUX bus panel support

  ivpu:
   - add heartbeat based hangcheck

  mediatek:
   - prepares support for MT8195/99 HDMIv2/DDCv2

  anx7625:
   - improve HPD

  tegra:
   - speed up firmware loading

* tag 'drm-next-2025-05-28' of https://gitlab.freedesktop.org/drm/kernel: (1627 commits)
  drm/nouveau/tegra: Fix error pointer vs NULL return in nvkm_device_tegra_resource_addr()
  drm/xe: Default auto_link_downgrade status to false
  drm/xe/guc: Make creation of SLPC debugfs files conditional
  drm/i915/display: Add check for alloc_ordered_workqueue() and alloc_workqueue()
  drm/i915/dp_mst: Work around Thunderbolt sink disconnect after SINK_COUNT_ESI read
  drm/i915/ptl: Use everywhere the correct DDI port clock select mask
  drm/nouveau/kms: add support for GB20x
  drm/dp: add option to disable zero sized address only transactions.
  drm/nouveau: add support for GB20x
  drm/nouveau/gsp: add hal for fifo.chan.doorbell_handle
  drm/nouveau: add support for GB10x
  drm/nouveau/gf100-: track chan progress with non-WFI semaphore release
  drm/nouveau/nv50-: separate CHANNEL_GPFIFO handling out from CHANNEL_DMA
  drm/nouveau: add helper functions for allocating pinned/cpu-mapped bos
  drm/nouveau: add support for GH100
  drm/nouveau: improve handling of 64-bit BARs
  drm/nouveau/gv100-: switch to volta semaphore methods
  drm/nouveau/gsp: support deeper page tables in COPY_SERVER_RESERVED_PDES
  drm/nouveau/gsp: init client VMMs with NV0080_CTRL_DMA_SET_PAGE_DIRECTORY
  drm/nouveau/gsp: fetch level shift and PDE from BAR2 VMM
  ...
This commit is contained in:
Linus Torvalds 2025-05-28 09:46:39 -07:00
commit b08494a8f7
1726 changed files with 71517 additions and 36307 deletions

View file

@ -722,6 +722,13 @@ ForEachMacros:
- 'v4l2_m2m_for_each_src_buf'
- 'v4l2_m2m_for_each_src_buf_safe'
- 'virtio_device_for_each_vq'
- 'vkms_config_for_each_connector'
- 'vkms_config_for_each_crtc'
- 'vkms_config_for_each_encoder'
- 'vkms_config_for_each_plane'
- 'vkms_config_connector_for_each_possible_encoder'
- 'vkms_config_encoder_for_each_possible_crtc'
- 'vkms_config_plane_for_each_possible_crtc'
- 'while_for_each_ftrace_op'
- 'workloads__for_each'
- 'xa_for_each'

View file

@ -26,7 +26,12 @@ Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Show the actual brightness by querying the hardware.
Show the actual brightness by querying the hardware. Due
to implementation differences in hardware this may not
match the value in 'brightness'. For example some hardware
may treat blanking differently or have custom power saving
features. Userspace should generally use the values in
'brightness' to make decisions.
Users: HAL
What: /sys/class/backlight/<backlight>/max_brightness

View file

@ -124,3 +124,27 @@ Contact: intel-xe@lists.freedesktop.org
Description: RO. VRAM temperature in millidegree Celsius.
Only supported for particular Intel Xe graphics platforms.
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan1_input
Date: March 2025
KernelVersion: 6.16
Contact: intel-xe@lists.freedesktop.org
Description: RO. Fan 1 speed in RPM.
Only supported for particular Intel Xe graphics platforms.
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan2_input
Date: March 2025
KernelVersion: 6.16
Contact: intel-xe@lists.freedesktop.org
Description: RO. Fan 2 speed in RPM.
Only supported for particular Intel Xe graphics platforms.
What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan3_input
Date: March 2025
KernelVersion: 6.16
Contact: intel-xe@lists.freedesktop.org
Description: RO. Fan 3 speed in RPM.
Only supported for particular Intel Xe graphics platforms.

View file

@ -647,6 +647,38 @@ Examples::
%p4cc Y10 little-endian (0x20303159)
%p4cc NV12 big-endian (0xb231564e)
Generic FourCC code
-------------------
::
%p4c[h[R]lb] gP00 (0x67503030)
Print a generic FourCC code, as both ASCII characters and its numerical
value as hexadecimal.
The generic FourCC code is always printed in the big-endian format,
the most significant byte first. This is the opposite of V4L/DRM FourCCs.
The additional ``h``, ``hR``, ``l``, and ``b`` specifiers define what
endianness is used to load the stored bytes. The data might be interpreted
using the host, reversed host byte order, little-endian, or big-endian.
Passed by reference.
Examples for a little-endian machine, given &(u32)0x67503030::
%p4ch gP00 (0x67503030)
%p4chR 00Pg (0x30305067)
%p4cl gP00 (0x67503030)
%p4cb 00Pg (0x30305067)
Examples for a big-endian machine, given &(u32)0x67503030::
%p4ch gP00 (0x67503030)
%p4chR 00Pg (0x30305067)
%p4cl 00Pg (0x30305067)
%p4cb gP00 (0x67503030)
Rust
----

View file

@ -0,0 +1,41 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek HDMI MT8195 series HDMI Display Data Channel (DDC)
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
- CK Hu <ck.hu@mediatek.com>
properties:
compatible:
oneOf:
- const: mediatek,mt8195-hdmi-ddc
- items:
- const: mediatek,mt8188-hdmi-ddc
- const: mediatek,mt8195-hdmi-ddc
clocks:
maxItems: 1
power-domains:
maxItems: 1
required:
- compatible
- clocks
additionalProperties: false
examples:
- |
hdmi {
hdmi_ddc: i2c {
compatible = "mediatek,mt8195-hdmi-ddc";
clocks = <&clk26m>;
};
};
...

View file

@ -0,0 +1,151 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/mediatek/mediatek,mt8195-hdmi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8195 series HDMI-TX Encoder
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
- CK Hu <ck.hu@mediatek.com>
description:
The MediaTek HDMI-TX v2 encoder can generate HDMI format data based on
the HDMI Specification 2.0b.
properties:
compatible:
enum:
- mediatek,mt8188-hdmi-tx
- mediatek,mt8195-hdmi-tx
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: HDMI Peripheral Bus (APB) clock
- description: HDCP and HDMI_TOP clock
- description: HDCP, HDMI_TOP and HDMI Audio reference clock
- description: VPP HDMI Split clock
clock-names:
items:
- const: bus
- const: hdcp
- const: hdcp24m
- const: hdmi-split
i2c:
type: object
$ref: /schemas/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml
unevaluatedProperties: false
description: HDMI DDC I2C controller
phys:
maxItems: 1
description: PHY providing clocking TMDS and pixel to controller
phy-names:
items:
- const: hdmi
power-domains:
maxItems: 1
'#sound-dai-cells':
const: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description:
Input port, usually connected to the output port of a DPI
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
Output port that must be connected either to the input port of
a HDMI connector node containing a ddc-i2c-bus, or to the input
port of an attached bridge chip, such as a SlimPort transmitter.
required:
- port@0
- port@1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- power-domains
- phys
- phy-names
- ports
allOf:
- $ref: /schemas/sound/dai-common.yaml#
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8195-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/mt8195-power.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
hdmi@1c300000 {
compatible = "mediatek,mt8195-hdmi-tx";
reg = <0 0x1c300000 0 0x1000>;
clocks = <&topckgen CLK_TOP_HDMI_APB>,
<&topckgen CLK_TOP_HDCP>,
<&topckgen CLK_TOP_HDCP_24M>,
<&vppsys1 CLK_VPP1_VPP_SPLIT_HDMI>;
clock-names = "bus", "hdcp", "hdcp24m", "hdmi-split";
interrupts = <GIC_SPI 677 IRQ_TYPE_LEVEL_HIGH 0>;
phys = <&hdmi_phy>;
phy-names = "hdmi";
power-domains = <&spm MT8195_POWER_DOMAIN_HDMI_TX>;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
#sound-dai-cells = <1>;
hdmitx_ddc: i2c {
compatible = "mediatek,mt8195-hdmi-ddc";
clocks = <&clk26m>;
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hdmi_in: endpoint {
remote-endpoint = <&dpi1_out>;
};
};
port@1 {
reg = <1>;
hdmi_out: endpoint {
remote-endpoint = <&hdmi_connector_in>;
};
};
};
};
};

View file

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

View file

@ -23,6 +23,8 @@ properties:
- qcom,msm8996-dsi-ctrl
- qcom,msm8998-dsi-ctrl
- qcom,qcm2290-dsi-ctrl
- qcom,sa8775p-dsi-ctrl
- qcom,sar2130p-dsi-ctrl
- qcom,sc7180-dsi-ctrl
- qcom,sc7280-dsi-ctrl
- qcom,sdm660-dsi-ctrl
@ -314,6 +316,8 @@ allOf:
contains:
enum:
- qcom,msm8998-dsi-ctrl
- qcom,sa8775p-dsi-ctrl
- qcom,sar2130p-dsi-ctrl
- qcom,sc7180-dsi-ctrl
- qcom,sc7280-dsi-ctrl
- qcom,sdm845-dsi-ctrl

View file

@ -17,6 +17,8 @@ properties:
enum:
- qcom,dsi-phy-7nm
- qcom,dsi-phy-7nm-8150
- qcom,sa8775p-dsi-phy-5nm
- qcom,sar2130p-dsi-phy-5nm
- qcom,sc7280-dsi-phy-7nm
- qcom,sm6375-dsi-phy-7nm
- qcom,sm8350-dsi-phy-5nm

View file

@ -66,21 +66,6 @@ properties:
maxItems: 1
description: hpd pin
qcom,hdmi-tx-mux-en-gpios:
maxItems: 1
deprecated: true
description: HDMI mux enable pin
qcom,hdmi-tx-mux-sel-gpios:
maxItems: 1
deprecated: true
description: HDMI mux select pin
qcom,hdmi-tx-mux-lpm-gpios:
maxItems: 1
deprecated: true
description: HDMI mux lpm pin
'#sound-dai-cells':
const: 1
@ -89,12 +74,12 @@ properties:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
$ref: /schemas/graph.yaml#/properties/port
description: |
Input endpoints of the controller.
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
$ref: /schemas/graph.yaml#/properties/port
description: |
Output endpoints of the controller.

View file

@ -18,9 +18,10 @@ properties:
clocks:
minItems: 6
maxItems: 6
maxItems: 8
clock-names:
minItems: 6
items:
- const: core_clk
- const: iface_clk
@ -28,6 +29,12 @@ properties:
- const: lut_clk
- const: hdmi_clk
- const: tv_clk
- const: lcdc_clk
- const: pxo
description: XO used to drive the internal LVDS PLL
'#clock-cells':
const: 0
reg:
maxItems: 1

View file

@ -84,6 +84,18 @@ properties:
items:
- description: MDSS_CORE reset
interconnects:
minItems: 1
items:
- description: Interconnect path from mdp0 (or a single mdp) port to the data bus
- description: Interconnect path from CPU to the reg bus
interconnect-names:
minItems: 1
items:
- const: mdp0-mem
- const: cpu-cfg
required:
- compatible
- reg

View file

@ -52,12 +52,23 @@ patternProperties:
items:
- const: qcom,sa8775p-dp
"^dsi@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
compatible:
contains:
const: qcom,sa8775p-dsi-ctrl
"^phy@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
compatible:
const: qcom,sa8775p-edp-phy
contains:
enum:
- qcom,sa8775p-dsi-phy-5nm
- qcom,sa8775p-edp-phy
required:
- compatible
@ -139,6 +150,20 @@ examples:
remote-endpoint = <&mdss0_dp0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf1_out: endpoint {
remote-endpoint = <&mdss0_dsi0_in>;
};
};
port@2 {
reg = <2>;
dpu_intf2_out: endpoint {
remote-endpoint = <&mdss0_dsi1_in>;
};
};
};
mdss0_mdp_opp_table: opp-table {
@ -186,6 +211,160 @@ examples:
vdda-pll-supply = <&vreg_l4a>;
};
dsi@ae94000 {
compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl";
reg = <0x0ae94000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <4>;
clocks = <&dispc_byte_clk>,
<&dispcc_intf_clk>,
<&dispcc_pclk>,
<&dispcc_esc_clk>,
<&dispcc_ahb_clk>,
<&gcc_bus_clk>;
clock-names = "byte",
"byte_intf",
"pixel",
"core",
"iface",
"bus";
assigned-clocks = <&dispcc_byte_clk>,
<&dispcc_pclk>;
assigned-clock-parents = <&mdss0_dsi0_phy 0>, <&mdss0_dsi0_phy 1>;
phys = <&mdss0_dsi0_phy>;
operating-points-v2 = <&dsi0_opp_table>;
power-domains = <&rpmhpd SA8775P_MMCX>;
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mdss0_dsi0_in: endpoint {
remote-endpoint = <&dpu_intf1_out>;
};
};
port@1 {
reg = <1>;
mdss0_dsi0_out: endpoint { };
};
};
dsi0_opp_table: opp-table {
compatible = "operating-points-v2";
opp-358000000 {
opp-hz = /bits/ 64 <358000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
};
};
mdss0_dsi0_phy: phy@ae94400 {
compatible = "qcom,sa8775p-dsi-phy-5nm";
reg = <0x0ae94400 0x200>,
<0x0ae94600 0x280>,
<0x0ae94900 0x27c>;
reg-names = "dsi_phy",
"dsi_phy_lane",
"dsi_pll";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc_iface_clk>,
<&rpmhcc_ref_clk>;
clock-names = "iface", "ref";
vdds-supply = <&vreg_dsi_supply>;
};
dsi@ae96000 {
compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl";
reg = <0x0ae96000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <4>;
clocks = <&dispc_byte_clk>,
<&dispcc_intf_clk>,
<&dispcc_pclk>,
<&dispcc_esc_clk>,
<&dispcc_ahb_clk>,
<&gcc_bus_clk>;
clock-names = "byte",
"byte_intf",
"pixel",
"core",
"iface",
"bus";
assigned-clocks = <&dispcc_byte_clk>,
<&dispcc_pclk>;
assigned-clock-parents = <&mdss0_dsi1_phy 0>, <&mdss0_dsi1_phy 1>;
phys = <&mdss0_dsi1_phy>;
operating-points-v2 = <&dsi1_opp_table>;
power-domains = <&rpmhpd SA8775P_MMCX>;
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mdss0_dsi1_in: endpoint {
remote-endpoint = <&dpu_intf2_out>;
};
};
port@1 {
reg = <1>;
mdss0_dsi1_out: endpoint { };
};
};
dsi1_opp_table: opp-table {
compatible = "operating-points-v2";
opp-358000000 {
opp-hz = /bits/ 64 <358000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
};
};
mdss0_dsi1_phy: phy@ae96400 {
compatible = "qcom,sa8775p-dsi-phy-5nm";
reg = <0x0ae96400 0x200>,
<0x0ae96600 0x280>,
<0x0ae96900 0x27c>;
reg-names = "dsi_phy",
"dsi_phy_lane",
"dsi_pll";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc_iface_clk>,
<&rpmhcc_ref_clk>;
clock-names = "iface", "ref";
vdds-supply = <&vreg_dsi_supply>;
};
displayport-controller@af54000 {
compatible = "qcom,sa8775p-dp";

View file

@ -0,0 +1,439 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/msm/qcom,sar2130p-mdss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SAR2130P Display MDSS
maintainers:
- Dmitry Baryshkov <lumag@kernel.org>
description:
SAR2310P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
DPU display controller, DSI and DP interfaces etc.
$ref: /schemas/display/msm/mdss-common.yaml#
properties:
compatible:
const: qcom,sar2130p-mdss
clocks:
items:
- description: Display MDSS AHB
- description: Display AHB
- description: Display hf AXI
- description: Display core
iommus:
maxItems: 1
interconnects:
items:
- description: Interconnect path from mdp0 port to the data bus
- description: Interconnect path from CPU to the reg bus
interconnect-names:
items:
- const: mdp0-mem
- const: cpu-cfg
patternProperties:
"^display-controller@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
compatible:
const: qcom,sar2130p-dpu
"^displayport-controller@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
compatible:
contains:
const: qcom,sar2130p-dp
"^dsi@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
compatible:
contains:
const: qcom,sar2130p-dsi-ctrl
"^phy@[0-9a-f]+$":
type: object
additionalProperties: true
properties:
compatible:
const: qcom,sar2130p-dsi-phy-5nm
required:
- compatible
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom,rpmhpd.h>
#include <dt-bindings/phy/phy-qcom-qmp.h>
display-subsystem@ae00000 {
compatible = "qcom,sar2130p-mdss";
reg = <0x0ae00000 0x1000>;
reg-names = "mdss";
interconnects = <&mmss_noc_master_mdp &mc_virt_slave_ebi1>,
<&gem_noc_master_appss_proc &config_noc_slave_display_cfg>;
interconnect-names = "mdp0-mem", "cpu-cfg";
resets = <&dispcc_disp_cc_mdss_core_bcr>;
power-domains = <&dispcc_mdss_gdsc>;
clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
<&gcc_gcc_disp_ahb_clk>,
<&gcc_gcc_disp_hf_axi_clk>,
<&dispcc_disp_cc_mdss_mdp_clk>;
clock-names = "iface", "bus", "nrt_bus", "core";
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
iommus = <&apps_smmu 0x1c00 0x2>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
display-controller@ae01000 {
compatible = "qcom,sar2130p-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp", "vbif";
clocks = <&gcc_gcc_disp_ahb_clk>,
<&gcc_gcc_disp_hf_axi_clk>,
<&dispcc_disp_cc_mdss_ahb_clk>,
<&dispcc_disp_cc_mdss_mdp_lut_clk>,
<&dispcc_disp_cc_mdss_mdp_clk>,
<&dispcc_disp_cc_mdss_vsync_clk>;
clock-names = "bus",
"nrt_bus",
"iface",
"lut",
"core",
"vsync";
assigned-clocks = <&dispcc_disp_cc_mdss_vsync_clk>;
assigned-clock-rates = <19200000>;
operating-points-v2 = <&mdp_opp_table>;
power-domains = <&rpmhpd RPMHPD_MMCX>;
interrupt-parent = <&mdss>;
interrupts = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf0_out: endpoint {
remote-endpoint = <&mdss_dp0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf1_out: endpoint {
remote-endpoint = <&mdss_dsi0_in>;
};
};
port@2 {
reg = <2>;
dpu_intf2_out: endpoint {
remote-endpoint = <&mdss_dsi1_in>;
};
};
};
mdp_opp_table: opp-table {
compatible = "operating-points-v2";
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
opp-325000000 {
opp-hz = /bits/ 64 <325000000>;
required-opps = <&rpmhpd_opp_svs>;
};
opp-375000000 {
opp-hz = /bits/ 64 <375000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
opp-514000000 {
opp-hz = /bits/ 64 <514000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};
displayport-controller@ae90000 {
compatible = "qcom,sar2130p-dp",
"qcom,sm8350-dp";
reg = <0xae90000 0x200>,
<0xae90200 0x200>,
<0xae90400 0xc00>,
<0xae91000 0x400>,
<0xae91400 0x400>;
interrupt-parent = <&mdss>;
interrupts = <12>;
clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
<&dispcc_disp_cc_mdss_dptx0_aux_clk>,
<&dispcc_disp_cc_mdss_dptx0_link_clk>,
<&dispcc_disp_cc_mdss_dptx0_link_intf_clk>,
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk>;
clock-names = "core_iface",
"core_aux",
"ctrl_link",
"ctrl_link_iface",
"stream_pixel";
assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>,
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>;
assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>,
<&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>;
phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
phy-names = "dp";
#sound-dai-cells = <0>;
operating-points-v2 = <&dp_opp_table>;
power-domains = <&rpmhpd RPMHPD_MMCX>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mdss_dp0_in: endpoint {
remote-endpoint = <&dpu_intf0_out>;
};
};
port@1 {
reg = <1>;
mdss_dp0_out: endpoint {
remote-endpoint = <&usb_dp_qmpphy_dp_in>;
};
};
};
dp_opp_table: opp-table {
compatible = "operating-points-v2";
opp-162000000 {
opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs_d1>;
};
opp-270000000 {
opp-hz = /bits/ 64 <270000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
opp-540000000 {
opp-hz = /bits/ 64 <540000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
opp-810000000 {
opp-hz = /bits/ 64 <810000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};
dsi@ae94000 {
compatible = "qcom,sar2130p-dsi-ctrl",
"qcom,mdss-dsi-ctrl";
reg = <0x0ae94000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <4>;
clocks = <&dispcc_disp_cc_mdss_byte0_clk>,
<&dispcc_disp_cc_mdss_byte0_intf_clk>,
<&dispcc_disp_cc_mdss_pclk0_clk>,
<&dispcc_disp_cc_mdss_esc0_clk>,
<&dispcc_disp_cc_mdss_ahb_clk>,
<&gcc_gcc_disp_hf_axi_clk>;
clock-names = "byte",
"byte_intf",
"pixel",
"core",
"iface",
"bus";
assigned-clocks = <&dispcc_disp_cc_mdss_byte0_clk_src>,
<&dispcc_disp_cc_mdss_pclk0_clk_src>;
assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>;
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd RPMHPD_MMCX>;
phys = <&mdss_dsi0_phy>;
phy-names = "dsi";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mdss_dsi0_in: endpoint {
remote-endpoint = <&dpu_intf1_out>;
};
};
port@1 {
reg = <1>;
mdss_dsi0_out: endpoint {
};
};
};
dsi_opp_table: opp-table {
compatible = "operating-points-v2";
opp-187500000 {
opp-hz = /bits/ 64 <187500000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
required-opps = <&rpmhpd_opp_svs>;
};
opp-358000000 {
opp-hz = /bits/ 64 <358000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
};
};
mdss_dsi0_phy: phy@ae94400 {
compatible = "qcom,sar2130p-dsi-phy-5nm";
reg = <0x0ae95000 0x200>,
<0x0ae95200 0x280>,
<0x0ae95500 0x400>;
reg-names = "dsi_phy",
"dsi_phy_lane",
"dsi_pll";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
<&rpmhcc_rpmh_cxo_clk>;
clock-names = "iface", "ref";
};
dsi@ae96000 {
compatible = "qcom,sar2130p-dsi-ctrl",
"qcom,mdss-dsi-ctrl";
reg = <0x0ae96000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <5>;
clocks = <&dispcc_disp_cc_mdss_byte1_clk>,
<&dispcc_disp_cc_mdss_byte1_intf_clk>,
<&dispcc_disp_cc_mdss_pclk1_clk>,
<&dispcc_disp_cc_mdss_esc1_clk>,
<&dispcc_disp_cc_mdss_ahb_clk>,
<&gcc_gcc_disp_hf_axi_clk>;
clock-names = "byte",
"byte_intf",
"pixel",
"core",
"iface",
"bus";
assigned-clocks = <&dispcc_disp_cc_mdss_byte1_clk_src>,
<&dispcc_disp_cc_mdss_pclk1_clk_src>;
assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>;
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd RPMHPD_MMCX>;
phys = <&mdss_dsi1_phy>;
phy-names = "dsi";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mdss_dsi1_in: endpoint {
remote-endpoint = <&dpu_intf2_out>;
};
};
port@1 {
reg = <1>;
mdss_dsi1_out: endpoint {
};
};
};
};
mdss_dsi1_phy: phy@ae97000 {
compatible = "qcom,sar2130p-dsi-phy-5nm";
reg = <0x0ae97000 0x200>,
<0x0ae97200 0x280>,
<0x0ae97500 0x400>;
reg-names = "dsi_phy",
"dsi_phy_lane",
"dsi_pll";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc_disp_cc_mdss_ahb_clk>,
<&rpmhcc_rpmh_cxo_clk>;
clock-names = "iface", "ref";
};
};
...

View file

@ -17,6 +17,7 @@ $ref: /schemas/display/msm/dpu-common.yaml#
properties:
compatible:
enum:
- qcom,sar2130p-dpu
- qcom,sc7280-dpu
- qcom,sc8280xp-dpu
- qcom,sm8350-dpu

View file

@ -38,12 +38,16 @@ properties:
maxItems: 1
interconnects:
maxItems: 2
items:
- description: Interconnect path from the MDP0 port to the data bus
- description: Interconnect path from the MDP1 port to the data bus
- description: Interconnect path from the CPU to the reg bus
interconnect-names:
items:
- const: mdp0-mem
- const: mdp1-mem
- const: cpu-cfg
patternProperties:
"^display-controller@[0-9a-f]+$":
@ -88,6 +92,7 @@ examples:
#include <dt-bindings/clock/qcom,gcc-sm8350.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interconnect/qcom,sm8350.h>
#include <dt-bindings/power/qcom,rpmhpd.h>
@ -97,8 +102,10 @@ examples:
reg-names = "mdss";
interconnects = <&mmss_noc MASTER_MDP0 0 &mc_virt SLAVE_EBI1 0>,
<&mmss_noc MASTER_MDP1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "mdp0-mem", "mdp1-mem";
<&mmss_noc MASTER_MDP1 0 &mc_virt SLAVE_EBI1 0>,
<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
&config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>;
interconnect-names = "mdp0-mem", "mdp1-mem", "cpu-cfg";
power-domains = <&dispcc MDSS_GDSC>;
resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;

View file

@ -0,0 +1,65 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/boe,td4320.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: BOE TD4320 MIPI-DSI panels
maintainers:
- Barnabas Czeman <barnabas.czeman@mainlining.org>
description:
BOE TD4320 6.3" 1080x2340 panel found in Xiaomi Redmi Note 7 smartphone.
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
items:
- const: boe,td4320
reg:
maxItems: 1
iovcc-supply:
description: I/O voltage rail
vsn-supply:
description: Negative source voltage rail
vsp-supply:
description: Positive source voltage rail
required:
- compatible
- reg
- reset-gpios
- port
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "boe,td4320";
reg = <0>;
backlight = <&backlight>;
reset-gpios = <&tlmm 45 GPIO_ACTIVE_LOW>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
};
};
...

View file

@ -0,0 +1,75 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/himax,hx8279.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Himax HX8279/HX8279-D based MIPI-DSI panels
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
description:
The Himax HX8279 is a 1803 channel outputs source driver with MIPI
TCON, which generates the horizontal and vertical control timing to
the source and gate drivers.
This DriverIC is most suitable for 1200x1920, 1080x1920, 1200x1600,
and 600x1024 panels and outputs full RGB888 over two or four lanes,
single or dual, MIPI-DSI video interface.
allOf:
- $ref: panel-common-dual.yaml#
properties:
compatible:
items:
- enum:
- aoly,sl101pm1794fog-v15
- startek,kd070fhfid078
- const: himax,hx8279
reg:
maxItems: 1
iovcc-supply:
description: I/O voltage supply
vdd-supply:
description: Panel power supply
required:
- compatible
- reg
- backlight
- reset-gpios
- iovcc-supply
- vdd-supply
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "startek,kd070fhfid078", "himax,hx8279";
reg = <0>;
backlight = <&backlight>;
enable-gpios = <&pio 25 GPIO_ACTIVE_HIGH>;
reset-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
iovcc-supply = <&vreg_lcm_vio>;
vdd-supply = <&vreg_lcm_vdd>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
};
};
...

View file

@ -23,6 +23,7 @@ properties:
maxItems: 1
backlight: true
port: true
reset-gpios: true
iovcc-supply:
description: regulator that supplies the iovcc voltage

View file

@ -22,6 +22,7 @@ properties:
maxItems: 1
backlight: true
port: true
reset-gpios: true
iovcc-supply:
description: regulator that supplies the iovcc voltage

View file

@ -0,0 +1,69 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/novatek,nt37801.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Novatek NT37801 AMOLED DSI Panel
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description:
Naming is inconclusive and different sources claim this is either Novatek
NT37801 or NT37810 AMOLED DSI Panel.
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: novatek,nt37801
reg:
maxItems: 1
description: DSI virtual channel
vci-supply: true
vdd-supply: true
vddio-supply: true
port: true
reset-gpios: true
required:
- compatible
- reg
- vci-supply
- vdd-supply
- vddio-supply
- port
- reset-gpios
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "novatek,nt37801";
reg = <0>;
vci-supply = <&vreg_l13b_3p0>;
vdd-supply = <&vreg_l11b_1p2>;
vddio-supply = <&vreg_l12b_1p8>;
reset-gpios = <&tlmm 98 GPIO_ACTIVE_LOW>;
port {
endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
...

View file

@ -226,6 +226,8 @@ properties:
- netron-dy,e231732
# Newhaven Display International 480 x 272 TFT LCD panel
- newhaven,nhd-4.3-480272ef-atxl
# NLT Technologies, Ltd. 15.6" WXGA (1366×768) LVDS TFT LCD panel
- nlt,nl13676bc25-03f
# New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
- nvd,9128
# OKAYA Electric America, Inc. RS800480T-7X0GP 7" WVGA LCD panel
@ -246,6 +248,8 @@ properties:
- osddisplays,osd070t1718-19ts
# One Stop Displays OSD101T2045-53TS 10.1" 1920x1200 panel
- osddisplays,osd101t2045-53ts
# POWERTIP PH128800T004-ZZA01 10.1" WXGA TFT LCD panel
- powertip,ph128800t004-zza01
# POWERTIP PH128800T006-ZHC01 10.1" WXGA TFT LCD panel
- powertip,ph128800t006-zhc01
# POWERTIP PH800480T013-IDF2 7.0" WVGA TFT LCD panel
@ -284,6 +288,8 @@ properties:
- startek,kd070wvfpa
# Team Source Display Technology TST043015CMHX 4.3" WQVGA TFT LCD panel
- team-source-display,tst043015cmhx
# Tianma Micro-electronics P0700WXF1MBAA 7.0" WXGA (1280x800) LVDS TFT LCD panel
- tianma,p0700wxf1mbaa
# Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel
- tianma,tm070jdhg30
# Tianma Micro-electronics TM070JDHG34-00 7.0" WXGA (1280x800) LVDS TFT LCD panel

View file

@ -19,6 +19,8 @@ properties:
- const: samsung,atna33xc20
- items:
- enum:
# Samsung 14" WQXGA+ (2880×1800 pixels) eDP AMOLED panel
- samsung,atna40yk20
# Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel
- samsung,atna45af01
# Samsung 14.5" 3K (2944x1840 pixels) eDP AMOLED panel

View file

@ -0,0 +1,97 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/truly,nt35597-2K-display.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Truly NT35597 DSI 2K display
maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
description: |
Truly NT35597 DSI 2K display is used on the Qualcomm SDM845 MTP board.
allOf:
- $ref: panel-common-dual.yaml#
properties:
compatible:
const: truly,nt35597-2K-display
reg:
maxItems: 1
vdda-supply:
description: regulator that provides the supply voltage Power IC supply
vdispp-supply:
description: regulator that provides the supply voltage for positive LCD bias
vdispn-supply:
description: regulator that provides the supply voltage for negative LCD bias
reset-gpios: true
mode-gpios:
description:
Gpio for choosing the mode of the display for single DSI or Dual DSI.
This should be low for dual DSI and high for single DSI mode.
ports:
required:
- port@0
- port@1
required:
- compatible
- reg
- vdda-supply
- reset-gpios
- mode-gpios
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "truly,nt35597-2K-display";
reg = <0>;
vdda-supply = <&pm8998_l14>;
vdispp-supply = <&lab_regulator>;
vdispn-supply = <&ibb_regulator>;
reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
mode-gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
port@1 {
reg = <1>;
panel1_in: endpoint {
remote-endpoint = <&dsi1_out>;
};
};
};
};
};
...

View file

@ -0,0 +1,79 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/visionox,g2647fb105.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Visionox G2647FB105 6.47" 1080x2340 MIPI-DSI Panel
maintainers:
- Alexander Baransky <sanyapilot496@gmail.com>
description:
The Visionox G2647FB105 is a 6.47 inch 1080x2340 MIPI-DSI CMD mode OLED panel.
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: visionox,g2647fb105
reg:
maxItems: 1
vdd3p3-supply:
description: 3.3V source voltage rail
vddio-supply:
description: I/O source voltage rail
vsn-supply:
description: Negative source voltage rail
vsp-supply:
description: Positive source voltage rail
reset-gpios: true
port: true
required:
- compatible
- reg
- vdd3p3-supply
- vddio-supply
- vsn-supply
- vsp-supply
- reset-gpios
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "visionox,g2647fb105";
reg = <0>;
vdd3p3-supply = <&vreg_l7c_3p0>;
vddio-supply = <&vreg_l13a_1p8>;
vsn-supply = <&vreg_ibb>;
vsp-supply = <&vreg_lab>;
reset-gpios = <&pm6150l_gpios 9 GPIO_ACTIVE_LOW>;
port {
panel_in: endpoint {
remote-endpoint = <&mdss_dsi0_out>;
};
};
};
};
...

View file

@ -15,6 +15,7 @@ properties:
enum:
- rockchip,rk3288-dp
- rockchip,rk3399-edp
- rockchip,rk3588-edp
clocks:
minItems: 2
@ -31,16 +32,23 @@ properties:
maxItems: 1
resets:
maxItems: 1
minItems: 1
maxItems: 2
reset-names:
const: dp
minItems: 1
items:
- const: dp
- const: apb
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description:
This SoC makes use of GRF regs.
aux-bus:
$ref: /schemas/display/dp-aux-bus.yaml#
required:
- compatible
- clocks
@ -52,6 +60,19 @@ required:
allOf:
- $ref: /schemas/display/bridge/analogix,dp.yaml#
- if:
properties:
compatible:
contains:
enum:
- rockchip,rk3588-edp
then:
properties:
resets:
minItems: 2
reset-names:
minItems: 2
unevaluatedProperties: false
examples:

View file

@ -23,13 +23,11 @@ properties:
maxItems: 1
clocks:
minItems: 1
items:
- description: The HDMI controller main clock
- description: The HDMI PHY reference clock
clock-names:
minItems: 1
items:
- const: pclk
- const: ref
@ -58,6 +56,12 @@ properties:
- port@0
- port@1
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to GRF used for control the polarity of hsync/vsync of rk3036
HDMI.
required:
- compatible
- reg
@ -77,6 +81,8 @@ allOf:
const: rockchip,rk3036-inno-hdmi
then:
required:
- rockchip,grf
properties:
power-domains: false
@ -87,11 +93,6 @@ allOf:
const: rockchip,rk3128-inno-hdmi
then:
properties:
clocks:
minItems: 2
clock-names:
minItems: 2
required:
- power-domains
@ -106,10 +107,11 @@ examples:
compatible = "rockchip,rk3036-inno-hdmi";
reg = <0x20034000 0x4000>;
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_HDMI>;
clock-names = "pclk";
clocks = <&cru PCLK_HDMI>, <&cru SCLK_LCDC>;
clock-names = "pclk", "ref";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_ctl>;
rockchip,grf = <&grf>;
#sound-dai-cells = <0>;
ports {

View file

@ -73,12 +73,6 @@ properties:
port:
$ref: /schemas/graph.yaml#/properties/port
assigned-clocks:
maxItems: 2
assigned-clock-rates:
maxItems: 2
iommus:
maxItems: 1

View file

@ -0,0 +1,73 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/sitronix,st7571.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sitronix ST7571 Display Controller
maintainers:
- Marcus Folkesson <marcus.folkesson@gmail.com>
description:
Sitronix ST7571 is a driver and controller for 4-level gray
scale and monochrome dot matrix LCD panels.
allOf:
- $ref: panel/panel-common.yaml#
properties:
compatible:
const: sitronix,st7571
reg:
maxItems: 1
sitronix,grayscale:
type: boolean
description:
Display supports 4-level grayscale.
reset-gpios: true
width-mm: true
height-mm: true
panel-timing: true
required:
- compatible
- reg
- reset-gpios
- width-mm
- height-mm
- panel-timing
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
display@3f {
compatible = "sitronix,st7571";
reg = <0x3f>;
reset-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
width-mm = <37>;
height-mm = <27>;
panel-timing {
hactive = <128>;
vactive = <96>;
hback-porch = <0>;
vback-porch = <0>;
clock-frequency = <0>;
hfront-porch = <0>;
hsync-len = <0>;
vfront-porch = <0>;
vsync-len = <0>;
};
};
};

View file

@ -1,59 +0,0 @@
Truly model NT35597 DSI display driver
The Truly NT35597 is a generic display driver, currently only configured
for use in the 2K display on the Qualcomm SDM845 MTP board.
Required properties:
- compatible: should be "truly,nt35597-2K-display"
- vdda-supply: phandle of the regulator that provides the supply voltage
Power IC supply
- vdispp-supply: phandle of the regulator that provides the supply voltage
for positive LCD bias
- vdispn-supply: phandle of the regulator that provides the supply voltage
for negative LCD bias
- reset-gpios: phandle of gpio for reset line
This should be 8mA, gpio can be configured using mux, pinctrl, pinctrl-names
(active low)
- mode-gpios: phandle of the gpio for choosing the mode of the display
for single DSI or Dual DSI
This should be low for dual DSI and high for single DSI mode
- ports: This device has two video ports driven by two DSIs. Their connections
are modeled using the OF graph bindings specified in
Documentation/devicetree/bindings/graph.txt.
- port@0: DSI input port driven by master DSI
- port@1: DSI input port driven by secondary DSI
Example:
dsi@ae94000 {
panel@0 {
compatible = "truly,nt35597-2K-display";
reg = <0>;
vdda-supply = <&pm8998_l14>;
vdispp-supply = <&lab_regulator>;
vdispn-supply = <&ibb_regulator>;
pinctrl-names = "default", "suspend";
pinctrl-0 = <&dpu_dsi_active>;
pinctrl-1 = <&dpu_dsi_suspend>;
reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
mode-gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
port@1 {
reg = <1>;
panel1_in: endpoint {
remote-endpoint = <&dsi1_out>;
};
};
};
};
};

View file

@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom V3D GPU
maintainers:
- Eric Anholt <eric@anholt.net>
- Maíra Canal <mcanal@igalia.com>
- Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
properties:
@ -22,20 +22,12 @@ properties:
- brcm,7278-v3d
reg:
items:
- description: hub register (required)
- description: core0 register (required)
- description: GCA cache controller register (if GCA controller present)
- description: bridge register (if no external reset controller)
minItems: 2
maxItems: 4
reg-names:
items:
- const: hub
- const: core0
- enum: [ bridge, gca ]
- enum: [ bridge, gca ]
minItems: 2
maxItems: 4
interrupts:
items:
@ -58,6 +50,76 @@ required:
- reg-names
- interrupts
allOf:
- if:
properties:
compatible:
contains:
const: brcm,2711-v3d
then:
properties:
reg:
items:
- description: hub register
- description: core0 register
reg-names:
items:
- const: hub
- const: core0
- if:
properties:
compatible:
contains:
const: brcm,2712-v3d
then:
properties:
reg:
items:
- description: hub register
- description: core0 register
- description: SMS state manager register
reg-names:
items:
- const: hub
- const: core0
- const: sms
- if:
properties:
compatible:
contains:
const: brcm,7268-v3d
then:
properties:
reg:
items:
- description: hub register
- description: core0 register
- description: GCA cache controller register
- description: bridge register
reg-names:
items:
- const: hub
- const: core0
- const: gca
- const: bridge
- if:
properties:
compatible:
contains:
const: brcm,7278-v3d
then:
properties:
reg:
items:
- description: hub register
- description: core0 register
- description: bridge register
reg-names:
items:
- const: hub
- const: core0
- const: bridge
additionalProperties: false
examples:
@ -66,9 +128,9 @@ examples:
compatible = "brcm,7268-v3d";
reg = <0xf1200000 0x4000>,
<0xf1208000 0x4000>,
<0xf1204000 0x100>,
<0xf1204100 0x100>;
reg-names = "hub", "core0", "bridge", "gca";
<0xf1204100 0x100>,
<0xf1204000 0x100>;
reg-names = "hub", "core0", "gca", "bridge";
interrupts = <0 78 4>,
<0 77 4>;
};

View file

@ -12,10 +12,28 @@ maintainers:
properties:
compatible:
items:
- enum:
- ti,am62-gpu
- const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
oneOf:
- items:
- enum:
- ti,am62-gpu
- const: img,img-axe-1-16m
# This deprecated element must be kept around to allow old kernels to
# work with newer dts.
- const: img,img-axe
- const: img,img-rogue
- items:
- enum:
- ti,j721s2-gpu
- const: img,img-bxs-4-64
- const: img,img-rogue
# This legacy combination of compatible strings was introduced early on
# before the more specific GPU identifiers were used.
- items:
- enum:
- ti,am62-gpu
- const: img,img-axe
deprecated: true
reg:
maxItems: 1
@ -35,6 +53,18 @@ properties:
maxItems: 1
power-domains:
minItems: 1
maxItems: 2
power-domain-names:
items:
- const: a
- const: b
minItems: 1
dma-coherent: true
resets:
maxItems: 1
required:
@ -47,11 +77,49 @@ required:
additionalProperties: false
allOf:
# Constraints added alongside the new compatible strings that would otherwise
# create an ABI break.
- if:
properties:
compatible:
contains:
const: ti,am62-gpu
const: img,img-rogue
then:
required:
- power-domains
- power-domain-names
- if:
properties:
compatible:
contains:
const: img,img-axe-1-16m
then:
properties:
power-domains:
maxItems: 1
power-domain-names:
maxItems: 1
- if:
properties:
compatible:
contains:
const: img,img-bxs-4-64
then:
properties:
power-domains:
minItems: 2
power-domain-names:
minItems: 2
- if:
properties:
compatible:
contains:
enum:
- ti,am62-gpu
- ti,j721s2-gpu
then:
properties:
clocks:
@ -64,10 +132,12 @@ examples:
#include <dt-bindings/soc/ti,sci_pm_domain.h>
gpu@fd00000 {
compatible = "ti,am62-gpu", "img,img-axe";
compatible = "ti,am62-gpu", "img,img-axe-1-16m", "img,img-axe",
"img,img-rogue";
reg = <0x0fd00000 0x20000>;
clocks = <&k3_clks 187 0>;
clock-names = "core";
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
power-domain-names = "a";
};

View file

@ -0,0 +1,96 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/opp/opp-v2-qcom-adreno.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Adreno compatible OPP supply
description:
Adreno GPUs present in Qualcomm's Snapdragon chipsets uses an OPP specific
ACD related information tailored for the specific chipset. This binding
provides the information needed to describe such a hardware value.
maintainers:
- Rob Clark <robdclark@gmail.com>
allOf:
- $ref: opp-v2-base.yaml#
properties:
compatible:
contains:
const: operating-points-v2-adreno
patternProperties:
'^opp-[0-9]+$':
type: object
additionalProperties: false
properties:
opp-hz: true
opp-level: true
opp-peak-kBps: true
opp-supported-hw: true
qcom,opp-acd-level:
description: |
A positive value representing the ACD (Adaptive Clock Distribution,
a fancy name for clk throttling during voltage droop) level associated
with this OPP node. This value is shared to a co-processor inside GPU
(called Graphics Management Unit a.k.a GMU) during wake up. It may not
be present for some OPPs and GMU will disable ACD while transitioning
to that OPP. This value encodes a voltage threshold, delay cycles &
calibration margins which are identified by characterization of the
SoC. So, it doesn't have any unit. This data is passed to GMU firmware
via 'HFI_H2F_MSG_ACD' packet.
$ref: /schemas/types.yaml#/definitions/uint32
required:
- opp-hz
- opp-level
required:
- compatible
additionalProperties: false
examples:
- |
#include <dt-bindings/power/qcom-rpmpd.h>
gpu_opp_table: opp-table {
compatible = "operating-points-v2-adreno", "operating-points-v2";
opp-687000000 {
opp-hz = /bits/ 64 <687000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
opp-peak-kBps = <8171875>;
qcom,opp-acd-level = <0x882e5ffd>;
};
opp-550000000 {
opp-hz = /bits/ 64 <550000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
opp-peak-kBps = <6074219>;
qcom,opp-acd-level = <0xc0285ffd>;
};
opp-390000000 {
opp-hz = /bits/ 64 <390000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
opp-peak-kBps = <3000000>;
qcom,opp-acd-level = <0xc0285ffd>;
};
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS_D1>;
opp-peak-kBps = <2136719>;
/* Intentionally left out qcom,opp-acd-level property here */
};
};

View file

@ -129,6 +129,8 @@ patternProperties:
description: Andes Technology Corporation
"^anvo,.*":
description: Anvo-Systems Dresden GmbH
"^aoly,.*":
description: Shenzhen Aoly Technology Co., Ltd.
"^aosong,.*":
description: Guangzhou Aosong Electronic Co., Ltd.
"^apm,.*":

View file

@ -0,0 +1,23 @@
=================================================
AMD Hardware Components Information per Product
=================================================
On this page, you can find the AMD product name and which component version is
part of it.
Accelerated Processing Units (APU) Info
---------------------------------------
.. csv-table::
:header-rows: 1
:widths: 3, 2, 2, 1, 1, 1, 1
:file: ./apu-asic-info-table.csv
Discrete GPU Info
-----------------
.. csv-table::
:header-rows: 1
:widths: 3, 2, 2, 1, 1, 1
:file: ./dgpu-asic-info-table.csv

View file

@ -12,18 +12,39 @@ we have a dedicated glossary for Display Core at
The number of CUs that are active on the system. The number of active
CUs may be less than SE * SH * CU depending on the board configuration.
BACO
Bus Alive, Chip Off
BOCO
Bus Off, Chip Off
CE
Constant Engine
CIK
Sea Islands
CB
Color Buffer
CP
Command Processor
CPLIB
Content Protection Library
CS
Command Submission
CSB
Clear State Indirect Buffer
CU
Compute Unit
DB
Depth Buffer
DFS
Digital Frequency Synthesizer
@ -33,6 +54,9 @@ we have a dedicated glossary for Display Core at
EOP
End Of Pipe/Pipeline
FLR
Function Level Reset
GART
Graphics Address Remapping Table. This is the name we use for the GPUVM
page table used by the GPU kernel driver. It remaps system resources
@ -45,6 +69,12 @@ we have a dedicated glossary for Display Core at
GC
Graphics and Compute
GDS
Global Data Share
GE
Geometry Engine
GMC
Graphic Memory Controller
@ -80,6 +110,9 @@ we have a dedicated glossary for Display Core at
KCQ
Kernel Compute Queue
KFD
Kernel Fusion Driver
KGQ
Kernel Graphics Queue
@ -89,6 +122,9 @@ we have a dedicated glossary for Display Core at
MC
Memory Controller
MCBP
Mid Command Buffer Preemption
ME
MicroEngine (Graphics)
@ -104,6 +140,9 @@ we have a dedicated glossary for Display Core at
MQD
Memory Queue Descriptor
PA
Primitive Assembler / Physical Address
PFP
Pre-Fetch Parser (Graphics)
@ -113,24 +152,39 @@ we have a dedicated glossary for Display Core at
PSP
Platform Security Processor
RB
Render Backends. Some people called it ROPs.
RLC
RunList Controller. This name is a remnant of past ages and doesn't have
much meaning today. It's a group of general-purpose helper engines for
the GFX block. It's involved in GFX power management and SR-IOV, among
other things.
SC
Scan Converter
SDMA
System DMA
SE
Shader Engine
SGPR
Scalar General-Purpose Registers
SH
SHader array
SI
Southern Islands
SMU/SMC
System Management Unit / System Management Controller
SPI (AMDGPU)
Shader Processor Input
SRLC
Save/Restore List Control
@ -143,12 +197,21 @@ we have a dedicated glossary for Display Core at
SS
Spread Spectrum
SX
Shader Export
TA
Trusted Application
TC
Texture Cache
TOC
Table of Contents
UMSCH
User Mode Scheduler
UVD
Unified Video Decoder
@ -158,5 +221,17 @@ we have a dedicated glossary for Display Core at
VCN
Video Codec Next
VGPR
Vector General-Purpose Registers
VMID
Virtual Memory ID
VPE
Video Processing Engine
XCC
Accelerator Core Complex
XCP
Accelerator Core Partition

View file

@ -13,3 +13,5 @@ Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0
Ryzen AI 350 series, Krackan Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4
Ryzen AI Max 300 series, Strix Halo, 3.5.1, 11.5.1, 4.0.6, 6.1.1, 14.0.1

1 Product Name Code Reference DCN/DCE version GC version VCE/UVD/VCN version SDMA version MP0 version
13 Ryzen 7x40 series Phoenix 3.1.4 11.0.1 / 11.0.4 4.0.2 6.0.1 13.0.4 / 13.0.11
14 Ryzen 8x40 series Hawk Point 3.1.4 11.0.1 / 11.0.4 4.0.2 6.0.1 13.0.4 / 13.0.11
15 Ryzen AI 300 series Strix Point 3.5.0 11.5.0 4.0.5 6.1.0 14.0.0
16 Ryzen AI 350 series Krackan Point 3.5.0 11.5.2 4.0.5 6.1.2 14.0.4
17 Ryzen AI Max 300 series Strix Halo 3.5.1 11.5.1 4.0.6 6.1.1 14.0.1

View file

@ -0,0 +1,210 @@
==============
AMDGPU DebugFS
==============
The amdgpu driver provides a number of debugfs files to aid in debugging
issues in the driver. These are usually found in
/sys/kernel/debug/dri/<num>.
DebugFS Files
=============
amdgpu_benchmark
----------------
Run benchmarks using the DMA engine the driver uses for GPU memory paging.
Write a number to the file to run the test. The results are written to the
kernel log. VRAM is on device memory (dGPUs) or carve out (APUs) and GTT
(Graphics Translation Tables) is system memory that is accessible by the GPU.
The following tests are available:
- 1: simple test, VRAM to GTT and GTT to VRAM
- 2: simple test, VRAM to VRAM
- 3: GTT to VRAM, buffer size sweep, powers of 2
- 4: VRAM to GTT, buffer size sweep, powers of 2
- 5: VRAM to VRAM, buffer size sweep, powers of 2
- 6: GTT to VRAM, buffer size sweep, common display sizes
- 7: VRAM to GTT, buffer size sweep, common display sizes
- 8: VRAM to VRAM, buffer size sweep, common display sizes
amdgpu_test_ib
--------------
Read this file to run simple IB (Indirect Buffer) tests on all kernel managed
rings. IBs are command buffers usually generated by userspace applications
which are submitted to the kernel for execution on an particular GPU engine.
This just runs the simple IB tests included in the kernel. These tests
are engine specific and verify that IB submission works.
amdgpu_discovery
----------------
Provides raw access to the IP discovery binary provided by the GPU. Read this
file to access the raw binary. This is useful for verifying the contents of
the IP discovery table. It is chip specific.
amdgpu_vbios
------------
Provides raw access to the ROM binary image from the GPU. Read this file to
access the raw binary. This is useful for verifying the contents of the
video BIOS ROM. It is board specific.
amdgpu_evict_gtt
----------------
Evict all buffers from the GTT memory pool. Read this file to evict all
buffers from this pool.
amdgpu_evict_vram
-----------------
Evict all buffers from the VRAM memory pool. Read this file to evict all
buffers from this pool.
amdgpu_gpu_recover
------------------
Trigger a GPU reset. Read this file to trigger reset the entire GPU.
All work currently running on the GPU will be lost.
amdgpu_ring_<name>
------------------
Provides read access to the kernel managed ring buffers for each ring <name>.
These are useful for debugging problems on a particular ring. The ring buffer
is how the CPU sends commands to the GPU. The CPU writes commands into the
buffer and then asks the GPU engine to process it. This is the raw binary
contents of the ring buffer. Use a tool like UMR to decode the rings into human
readable form.
amdgpu_mqd_<name>
-----------------
Provides read access to the kernel managed MQD (Memory Queue Descriptor) for
ring <name> managed by the kernel driver. MQDs define the features of the ring
and are used to store the ring's state when it is not connected to hardware.
The driver writes the requested ring features and metadata (GPU addresses of
the ring itself and associated buffers) to the MQD and the firmware uses the MQD
to populate the hardware when the ring is mapped to a hardware slot. Only
available on engines which use MQDs. This provides access to the raw MQD
binary.
amdgpu_error_<name>
-------------------
Provides an interface to set an error code on the dma fences associated with
ring <name>. The error code specified is propogated to all fences associated
with the ring. Use this to inject a fence error into a ring.
amdgpu_pm_info
--------------
Provides human readable information about the power management features
and state of the GPU. This includes current GFX clock, Memory clock,
voltages, average SoC power, temperature, GFX load, Memory load, SMU
feature mask, VCN power state, clock and power gating features.
amdgpu_firmware_info
--------------------
Lists the firmware versions for all firmwares used by the GPU. Only
entries with a non-0 version are valid. If the version is 0, the firmware
is not valid for the GPU.
amdgpu_fence_info
-----------------
Shows the last signalled and emitted fence sequence numbers for each
kernel driver managed ring. Fences are associated with submissions
to the engine. Emitted fences have been submitted to the ring
and signalled fences have been signalled by the GPU. Rings with a
larger emitted fence value have outstanding work that is still being
processed by the engine that owns that ring. When the emitted and
signalled fence values are equal, the ring is idle.
amdgpu_gem_info
---------------
Lists all of the PIDs using the GPU and the GPU buffers that they have
allocated. This lists the buffer size, pool (VRAM, GTT, etc.), and buffer
attributes (CPU access required, CPU cache attributes, etc.).
amdgpu_vm_info
--------------
Lists all of the PIDs using the GPU and the GPU buffers that they have
allocated as well as the status of those buffers relative to that process'
GPU virtual address space (e.g., evicted, idle, invalidated, etc.).
amdgpu_sa_info
--------------
Prints out all of the suballocations (sa) by the suballocation manager in the
kernel driver. Prints the GPU address, size, and fence info associated
with each suballocation. The suballocations are used internally within
the kernel driver for various things.
amdgpu_<pool>_mm
----------------
Prints TTM information about the memory pool <pool>.
amdgpu_vram
-----------
Provides direct access to VRAM. Used by tools like UMR to inspect
objects in VRAM.
amdgpu_iomem
------------
Provides direct access to GTT memory. Used by tools like UMR to inspect
GTT memory.
amdgpu_regs_*
-------------
Provides direct access to various register aperatures on the GPU. Used
by tools like UMR to access GPU registers.
amdgpu_regs2
------------
Provides an IOCTL interface used by UMR for interacting with GPU registers.
amdgpu_sensors
--------------
Provides an interface to query GPU power metrics (temperature, average
power, etc.). Used by tools like UMR to query GPU power metrics.
amdgpu_gca_config
-----------------
Provides an interface to query GPU details (Graphics/Compute Array config,
PCI config, GPU family, etc.). Used by tools like UMR to query GPU details.
amdgpu_wave
-----------
Used to query GFX/compute wave information from the hardware. Used by tools
like UMR to query GFX/compute wave information.
amdgpu_gpr
----------
Used to query GFX/compute GPR (General Purpose Register) information from the
hardware. Used by tools like UMR to query GPRs when debugging shaders.
amdgpu_gprwave
--------------
Provides an IOCTL interface used by UMR for interacting with shader waves.
amdgpu_fw_attestation
---------------------
Provides an interface for reading back firmware attestation records.

View file

@ -2,6 +2,13 @@
GPU Debugging
===============
General Debugging Options
=========================
The DebugFS section provides documentation on a number files to aid in debugging
issues on the GPU.
GPUVM Debugging
===============

View file

@ -154,7 +154,7 @@ of the display parameters, but the userspace might also cause this issue. One
way to identify the source of the problem is to take a screenshot or make a
desktop video capture when the problem happens; after checking the
screenshot/video recording, if you don't see any of the artifacts, it means
that the issue is likely on the the driver side. If you can still see the
that the issue is likely on the driver side. If you can still see the
problem in the data collected, it is an issue that probably happened during
rendering, and the display code just got the framebuffer already corrupted.

View file

@ -67,36 +67,66 @@ GC (Graphics and Compute)
This is the graphics and compute engine, i.e., the block that
encompasses the 3D pipeline and and shader blocks. This is by far the
largest block on the GPU. The 3D pipeline has tons of sub-blocks. In
addition to that, it also contains the CP microcontrollers (ME, PFP,
CE, MEC) and the RLC microcontroller. It's exposed to userspace for
user mode drivers (OpenGL, Vulkan, OpenCL, etc.)
addition to that, it also contains the CP microcontrollers (ME, PFP, CE,
MEC) and the RLC microcontroller. It's exposed to userspace for user mode
drivers (OpenGL, Vulkan, OpenCL, etc.). More details in :ref:`Graphics (GFX)
and Compute <amdgpu-gc>`.
VCN (Video Core Next)
This is the multi-media engine. It handles video and image encode and
decode. It's exposed to userspace for user mode drivers (VA-API,
OpenMAX, etc.)
Graphics and Compute Microcontrollers
-------------------------------------
.. _pipes-and-queues-description:
CP (Command Processor)
The name for the hardware block that encompasses the front end of the
GFX/Compute pipeline. Consists mainly of a bunch of microcontrollers
(PFP, ME, CE, MEC). The firmware that runs on these microcontrollers
provides the driver interface to interact with the GFX/Compute engine.
GFX, Compute, and SDMA Overall Behavior
=======================================
MEC (MicroEngine Compute)
This is the microcontroller that controls the compute queues on the
GFX/compute engine.
.. note:: For simplicity, whenever the term block is used in this section, it
means GFX, Compute, and SDMA.
MES (MicroEngine Scheduler)
This is a new engine for managing queues. This is currently unused.
GFX, Compute and SDMA share a similar form of operation that can be abstracted
to facilitate understanding of the behavior of these blocks. See the figure
below illustrating the common components of these blocks:
RLC (RunList Controller)
This is another microcontroller in the GFX/Compute engine. It handles
power management related functionality within the GFX/Compute engine.
The name is a vestige of old hardware where it was originally added
and doesn't really have much relation to what the engine does now.
.. kernel-figure:: pipe_and_queue_abstraction.svg
In the central part of this figure, you can see two hardware elements, one called
**Pipes** and another called **Queues**; it is important to highlight that Queues
must be associated with a Pipe and vice-versa. Every specific hardware IP may have
a different number of Pipes and, in turn, a different number of Queues; for
example, GFX 11 has two Pipes and two Queues per Pipe for the GFX front end.
Pipe is the hardware that processes the instructions available in the Queues;
in other words, it is a thread executing the operations inserted in the Queue.
One crucial characteristic of Pipes is that they can only execute one Queue at
a time; no matter if the hardware has multiple Queues in the Pipe, it only runs
one Queue per Pipe.
Pipes have the mechanics of swapping between queues at the hardware level.
Nonetheless, they only make use of Queues that are considered mapped. Pipes can
switch between queues based on any of the following inputs:
1. Command Stream;
2. Packet by Packet;
3. Other hardware requests the change (e.g., MES).
Queues within Pipes are defined by the Hardware Queue Descriptors (HQD).
Associated with the HQD concept, we have the Memory Queue Descriptor (MQD),
which is responsible for storing information about the state of each of the
available Queues in the memory. The state of a Queue contains information such
as the GPU virtual address of the queue itself, save areas, doorbell, etc. The
MQD also stores the HQD registers, which are vital for activating or
deactivating a given Queue. The scheduling firmware (e.g., MES) is responsible
for loading HQDs from MQDs and vice versa.
The Queue-switching process can also happen with the firmware requesting the
preemption or unmapping of a Queue. The firmware waits for the HQD_ACTIVE bit
to change to low before saving the state into the MQD. To make a different
Queue become active, the firmware copies the MQD state into the HQD registers
and loads any additional state. Finally, it sets the HQD_ACTIVE bit to high to
indicate that the queue is active. The Pipe will then execute work from active
Queues.
Driver Structure
================
@ -110,7 +140,8 @@ Some useful constructs:
KIQ (Kernel Interface Queue)
This is a control queue used by the kernel driver to manage other gfx
and compute queues on the GFX/compute engine. You can use it to
map/unmap additional queues, etc.
map/unmap additional queues, etc. This is replaced by MES on
GFX 11 and newer hardware.
IB (Indirect Buffer)
A command buffer for a particular engine. Rather than writing

View file

@ -50,23 +50,6 @@ board_info
.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
:doc: board_info
Accelerated Processing Units (APU) Info
---------------------------------------
.. csv-table::
:header-rows: 1
:widths: 3, 2, 2, 1, 1, 1, 1
:file: ./apu-asic-info-table.csv
Discrete GPU Info
-----------------
.. csv-table::
:header-rows: 1
:widths: 3, 2, 2, 1, 1, 1
:file: ./dgpu-asic-info-table.csv
GPU Memory Usage Information
============================

View file

@ -0,0 +1,52 @@
.. _amdgpu-gc:
========================================
drm/amdgpu - Graphics and Compute (GC)
========================================
The relationship between the CPU and GPU can be described as the
producer-consumer problem, where the CPU fills out a buffer with operations
(producer) to be executed by the GPU (consumer). The requested operations in
the buffer are called Command Packets, which can be summarized as a compressed
way of transmitting command information to the graphics controller.
The component that acts as the front end between the CPU and the GPU is called
the Command Processor (CP). This component is responsible for providing greater
flexibility to the GC since CP makes it possible to program various aspects of
the GPU pipeline. CP also coordinates the communication between the CPU and GPU
via a mechanism named **Ring Buffers**, where the CPU appends information to
the buffer while the GPU removes operations. It is relevant to highlight that a
CPU can add a pointer to the Ring Buffer that points to another region of
memory outside the Ring Buffer, and CP can handle it; this mechanism is called
**Indirect Buffer (IB)**. CP receives and parses the Command Streams (CS), and
writes the operations to the correct hardware blocks.
Graphics (GFX) and Compute Microcontrollers
-------------------------------------------
GC is a large block, and as a result, it has multiple firmware associated with
it. Some of them are:
CP (Command Processor)
The name for the hardware block that encompasses the front end of the
GFX/Compute pipeline. Consists mainly of a bunch of microcontrollers
(PFP, ME, CE, MEC). The firmware that runs on these microcontrollers
provides the driver interface to interact with the GFX/Compute engine.
MEC (MicroEngine Compute)
This is the microcontroller that controls the compute queues on the
GFX/compute engine.
MES (MicroEngine Scheduler)
This is the engine for managing queues. For more details check
:ref:`MicroEngine Scheduler (MES) <amdgpu-mes>`.
RLC (RunList Controller)
This is another microcontroller in the GFX/Compute engine. It handles
power management related functionality within the GFX/Compute engine.
The name is a vestige of old hardware where it was originally added
and doesn't really have much relation to what the engine does now.
.. toctree::
mes.rst

View file

@ -0,0 +1,38 @@
.. _amdgpu-mes:
=============================
MicroEngine Scheduler (MES)
=============================
.. note::
Queue and ring buffer are used as a synonymous.
.. note::
This section assumes that you are familiar with the concept of Pipes, Queues, and GC.
If not, check :ref:`GFX, Compute, and SDMA Overall Behavior<pipes-and-queues-description>`
and :ref:`drm/amdgpu - Graphics and Compute (GC) <amdgpu-gc>`.
Every GFX has a pipe component with one or more hardware queues. Pipes can
switch between queues depending on certain conditions, and one of the
components that can request a queue switch to a pipe is the MicroEngine
Scheduler (MES). Whenever the driver is initialized, it creates one MQD per
hardware queue, and then the MQDs are handed to the MES firmware for mapping
to:
1. Kernel Queues (legacy): This queue is statically mapped to HQDs and never
preempted. Even though this is a legacy feature, it is the current default, and
most existing hardware supports it. When an application submits work to the
kernel driver, it submits all of the application command buffers to the kernel
queues. The CS IOCTL takes the command buffer from the applications and
schedules them on the kernel queue.
2. User Queues: These queues are dynamically mapped to the HQDs. Regarding the
utilization of User Queues, the userspace application will create its user
queues and submit work directly to its user queues with no need to IOCTL for
each submission and no need to share a single kernel queue.
In terms of User Queues, MES can dynamically map them to the HQD. If there are
more MQDs than HQDs, the MES firmware will preempt other user queues to make
sure each queues get a time slice; in other words, MES is a microcontroller
that handles the mapping and unmapping of MQDs into HQDs, as well as the
priorities and oversubscription of MQDs.

View file

@ -7,8 +7,10 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
.. toctree::
module-parameters
driver-core
amd-hardware-list-info
module-parameters
gc/index
display/index
flashing
xgmi
@ -16,5 +18,6 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
thermal
driver-misc
debugging
debugfs
process-isolation
amdgpu-glossary

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 61 KiB

View file

@ -115,6 +115,10 @@ created (eg. https://gitlab.freedesktop.org/janedoe/linux/-/pipelines)
5. The various jobs will be run and when the pipeline is finished, all jobs
should be green unless a regression has been found.
6. Warnings in the pipeline indicate that lockdep
(see Documentation/locking/lockdep-design.rst) issues have been detected
during the tests.
How to update test expectations
===============================

View file

@ -27,3 +27,8 @@ drm/xe uAPI
===========
.. kernel-doc:: include/uapi/drm/xe_drm.h
drm/asahi uAPI
================
.. kernel-doc:: include/uapi/drm/asahi_drm.h

View file

@ -233,6 +233,21 @@ Panel Self Refresh Helper Reference
.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c
:export:
HDMI Atomic State Helpers
=========================
Overview
--------
.. kernel-doc:: drivers/gpu/drm/display/drm_hdmi_state_helper.c
:doc: hdmi helpers
Functions Reference
-------------------
.. kernel-doc:: drivers/gpu/drm/display/drm_hdmi_state_helper.c
:export:
HDCP Helper Functions Reference
===============================

View file

@ -27,3 +27,6 @@ GSP Support
.. kernel-doc:: drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
:doc: GSP message queue element
.. kernel-doc:: drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
:doc: GSP message handling policy

View file

@ -102,7 +102,13 @@ Usage:
let boot0 = Boot0::read(&bar);
pr_info!("Revision: {}\n", boot0.revision());
Note: a work-in-progress implementation currently resides in
`drivers/gpu/nova-core/regs/macros.rs` and is used in nova-core. It would be
nice to improve it (possibly using proc macros) and move it to the `kernel`
crate so it can be used by other components as well.
| Complexity: Advanced
| Contact: Alexandre Courbot
Delay / Sleep abstractions
--------------------------
@ -190,16 +196,6 @@ Rust abstraction for debugfs APIs.
| Reference: Export GSP log buffers
| Complexity: Intermediate
Vec extensions
--------------
Implement ``Vec::truncate`` and ``Vec::resize``.
Currently this is used for some experimental code to parse the vBIOS.
| Reference vBIOS support
| Complexity: Beginner
GPU (general)
=============

View file

@ -441,14 +441,15 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>
Level: Intermediate
Request memory regions in all drivers
-------------------------------------
Request memory regions in all fbdev drivers
--------------------------------------------
Go through all drivers and add code to request the memory regions that the
driver uses. This requires adding calls to request_mem_region(),
Old/ancient fbdev drivers do not request their memory properly.
Go through these drivers and add code to request the memory regions
that the driver uses. This requires adding calls to request_mem_region(),
pci_request_region() or similar functions. Use helpers for managed cleanup
where possible.
where possible. Problematic areas include hardware that has exclusive ranges
like VGA. VGA16fb does not request the range as it is expected.
Drivers are pretty bad at doing this and there used to be conflicts among
DRM and fbdev drivers. Still, it's the correct thing to do.

View file

@ -11,9 +11,9 @@ Section 7, Legacy Devices.
The Resource Access Control (RAC) module inside the X server [0] existed for
the legacy VGA arbitration task (besides other bus management tasks) when more
than one legacy device co-exists on the same machine. But the problem happens
than one legacy device co-exist on the same machine. But the problem happens
when these devices are trying to be accessed by different userspace clients
(e.g. two server in parallel). Their address assignments conflict. Moreover,
(e.g. two servers in parallel). Their address assignments conflict. Moreover,
ideally, being a userspace application, it is not the role of the X server to
control bus resources. Therefore an arbitration scheme outside of the X server
is needed to control the sharing of these resources. This document introduces
@ -106,7 +106,7 @@ In-kernel interface
libpciaccess
------------
To use the vga arbiter char device it was implemented an API inside the
To use the vga arbiter char device, an API was implemented inside the
libpciaccess library. One field was added to struct pci_device (each device
on the system)::

View file

@ -25,3 +25,4 @@ DG2, etc is provided to prototype the driver.
xe_debugging
xe_devcoredump
xe-drm-usage-stats.rst
xe_configfs

View file

@ -0,0 +1,10 @@
.. SPDX-License-Identifier: GPL-2.0+
.. _xe_configfs:
============
Xe Configfs
============
.. kernel-doc:: drivers/gpu/drm/xe/xe_configfs.c
:doc: Xe Configfs

View file

@ -31,6 +31,12 @@ GuC Power Conservation (PC)
.. kernel-doc:: drivers/gpu/drm/xe/xe_guc_pc.c
:doc: GuC Power Conservation (PC)
PCIe Gen5 Limitations
=====================
.. kernel-doc:: drivers/gpu/drm/xe/xe_device_sysfs.c
:doc: PCIe Gen5 Limitations
Internal API
============

View file

@ -12,3 +12,10 @@ Internal API
.. kernel-doc:: drivers/gpu/drm/xe/xe_pcode.c
:internal:
==================
Boot Survivability
==================
.. kernel-doc:: drivers/gpu/drm/xe/xe_survivability_mode.c
:doc: Xe Boot Survivability

View file

@ -2341,6 +2341,7 @@ F: drivers/watchdog/apple_wdt.c
F: include/dt-bindings/interrupt-controller/apple-aic.h
F: include/dt-bindings/pinctrl/apple.h
F: include/linux/soc/apple/*
F: include/uapi/drm/asahi_drm.h
ARM/ARTPEC MACHINE SUPPORT
M: Jesper Nilsson <jesper.nilsson@axis.com>
@ -3916,6 +3917,9 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
F: Documentation/driver-api/auxiliary_bus.rst
F: drivers/base/auxiliary.c
F: include/linux/auxiliary_bus.h
F: rust/helpers/auxiliary.c
F: rust/kernel/auxiliary.rs
F: samples/rust/rust_driver_auxiliary.rs
AUXILIARY DISPLAY DRIVERS
M: Andy Shevchenko <andy@kernel.org>
@ -7432,8 +7436,7 @@ M: Javier Martinez Canillas <javierm@redhat.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: drivers/gpu/drm/tiny/ofdrm.c
F: drivers/gpu/drm/tiny/simpledrm.c
F: drivers/gpu/drm/sysfb/
F: drivers/video/aperture.c
F: drivers/video/nomodeset.c
F: include/linux/aperture.h
@ -7574,6 +7577,7 @@ 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: Documentation/devicetree/bindings/opp/opp-v2-qcom-adreno.yaml
F: drivers/gpu/drm/msm/adreno/
F: drivers/gpu/drm/msm/msm_gpu.*
F: drivers/gpu/drm/msm/msm_gpu_devfreq.*
@ -7627,6 +7631,12 @@ 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
DRM DRIVER FOR NOVATEK NT37801 PANELS
M: Krzysztof Kozlowski <krzk@kernel.org>
S: Maintained
F: Documentation/devicetree/bindings/display/panel/novatek,nt37801.yaml
F: drivers/gpu/drm/panel/panel-novatek-nt37801.c
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
M: Lyude Paul <lyude@redhat.com>
M: Danilo Krummrich <dakr@kernel.org>
@ -7653,6 +7663,18 @@ T: git https://gitlab.freedesktop.org/drm/nova.git nova-next
F: Documentation/gpu/nova/
F: drivers/gpu/nova-core/
DRM DRIVER FOR NVIDIA GPUS [RUST]
M: Danilo Krummrich <dakr@kernel.org>
L: nouveau@lists.freedesktop.org
S: Supported
Q: https://patchwork.freedesktop.org/project/nouveau/
B: https://gitlab.freedesktop.org/drm/nova/-/issues
C: irc://irc.oftc.net/nouveau
T: git https://gitlab.freedesktop.org/drm/nova.git nova-next
F: Documentation/gpu/nova/
F: drivers/gpu/drm/nova/
F: include/uapi/drm/nova_drm.h
DRM DRIVER FOR OLIMEX LCD-OLINUXINO PANELS
M: Stefan Mavrodiev <stefan@olimex.com>
S: Maintained
@ -7742,7 +7764,13 @@ M: David Lechner <david@lechnology.com>
S: Maintained
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
F: drivers/gpu/drm/sitronix/st7586.c
DRM DRIVER FOR SITRONIX ST7571 PANELS
M: Marcus Folkesson <marcus.folkesson@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/display/sitronix,st7571.yaml
F: drivers/gpu/drm/sitronix/st7571-i2c.c
DRM DRIVER FOR SITRONIX ST7701 PANELS
M: Jagan Teki <jagan@amarulasolutions.com>
@ -7763,7 +7791,7 @@ M: David Lechner <david@lechnology.com>
S: Maintained
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
F: drivers/gpu/drm/sitronix/st7735r.c
DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
M: Javier Martinez Canillas <javierm@redhat.com>
@ -7860,6 +7888,7 @@ F: Documentation/devicetree/bindings/display/
F: Documentation/devicetree/bindings/gpu/
F: Documentation/gpu/
F: drivers/gpu/
F: rust/kernel/drm/
F: include/drm/
F: include/linux/vga*
F: include/uapi/drm/
@ -7876,6 +7905,7 @@ F: Documentation/devicetree/bindings/gpu/
F: Documentation/gpu/
F: drivers/gpu/drm/
F: drivers/gpu/vga/
F: rust/kernel/drm/
F: include/drm/drm
F: include/linux/vga*
F: include/uapi/drm/
@ -7915,8 +7945,8 @@ F: drivers/gpu/drm/ci/xfails/meson*
F: drivers/gpu/drm/meson/
DRM DRIVERS FOR ATMEL HLCDC
M: Sam Ravnborg <sam@ravnborg.org>
M: Boris Brezillon <bbrezillon@kernel.org>
M: Manikandan Muralidharan <manikandan.m@microchip.com>
M: Dharma Balasubiramani <dharma.b@microchip.com>
L: dri-devel@lists.freedesktop.org
S: Supported
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
@ -8244,7 +8274,8 @@ F: drivers/gpu/drm/ttm/
F: include/drm/ttm/
DRM AUTOMATED TESTING
M: Helen Koike <helen.koike@collabora.com>
M: Helen Koike <helen.fornazier@gmail.com>
M: Vignesh Raman <vignesh.raman@collabora.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
@ -12004,13 +12035,10 @@ F: drivers/gpio/gpio-tangier.c
F: drivers/gpio/gpio-tangier.h
INTEL GVT-g DRIVERS (Intel GPU Virtualization)
M: Zhenyu Wang <zhenyuw.linux@gmail.com>
M: Zhi Wang <zhi.wang.linux@gmail.com>
L: intel-gvt-dev@lists.freedesktop.org
L: intel-gfx@lists.freedesktop.org
S: Supported
R: Zhenyu Wang <zhenyuw.linux@gmail.com>
R: Zhi Wang <zhi.wang.linux@gmail.com>
S: Odd Fixes
W: https://github.com/intel/gvt-linux/wiki
T: git https://github.com/intel/gvt-linux.git
F: drivers/gpu/drm/i915/gvt/
INTEL HID EVENT DRIVER
@ -25940,6 +25968,7 @@ F: include/uapi/linux/virtio_gpio.h
VIRTIO GPU DRIVER
M: David Airlie <airlied@redhat.com>
M: Gerd Hoffmann <kraxel@redhat.com>
M: Dmitry Osipenko <dmitry.osipenko@collabora.com>
R: Gurchetan Singh <gurchetansingh@chromium.org>
R: Chia-I Wu <olvaffe@gmail.com>
L: dri-devel@lists.freedesktop.org

View file

@ -3752,60 +3752,83 @@
};
gpu_opp_table: opp-table {
compatible = "operating-points-v2";
compatible = "operating-points-v2-adreno", "operating-points-v2";
opp-1250000000 {
opp-hz = /bits/ 64 <1250000000>;
opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L3>;
opp-peak-kBps = <16500000>;
qcom,opp-acd-level = <0xa82a5ffd>;
};
opp-1175000000 {
opp-hz = /bits/ 64 <1175000000>;
opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L2>;
opp-peak-kBps = <14398438>;
qcom,opp-acd-level = <0xa82a5ffd>;
};
opp-1100000000 {
opp-hz = /bits/ 64 <1100000000>;
opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
opp-peak-kBps = <16500000>;
opp-peak-kBps = <14398438>;
qcom,opp-acd-level = <0xa82a5ffd>;
};
opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
opp-peak-kBps = <14398438>;
qcom,opp-acd-level = <0xa82b5ffd>;
};
opp-925000000 {
opp-hz = /bits/ 64 <925000000>;
opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
opp-peak-kBps = <14398438>;
qcom,opp-acd-level = <0xa82b5ffd>;
};
opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
opp-peak-kBps = <12449219>;
qcom,opp-acd-level = <0xa82c5ffd>;
};
opp-744000000 {
opp-hz = /bits/ 64 <744000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L2>;
opp-peak-kBps = <10687500>;
qcom,opp-acd-level = <0x882e5ffd>;
};
opp-687000000 {
opp-hz = /bits/ 64 <687000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
opp-peak-kBps = <8171875>;
qcom,opp-acd-level = <0x882e5ffd>;
};
opp-550000000 {
opp-hz = /bits/ 64 <550000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
opp-peak-kBps = <6074219>;
qcom,opp-acd-level = <0xc0285ffd>;
};
opp-390000000 {
opp-hz = /bits/ 64 <390000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
opp-peak-kBps = <3000000>;
qcom,opp-acd-level = <0xc0285ffd>;
};
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS_D1>;
opp-peak-kBps = <2136719>;
qcom,opp-acd-level = <0xc02b5ffd>;
};
};
};

View file

@ -1,3 +1,2 @@
- Add import and export BO support
- Add debugfs support
- Add debug BO support

View file

@ -758,27 +758,42 @@ int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *bu
static int aie2_populate_range(struct amdxdna_gem_obj *abo)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
struct mm_struct *mm = abo->mem.notifier.mm;
struct hmm_range range = { 0 };
struct amdxdna_umap *mapp;
unsigned long timeout;
struct mm_struct *mm;
bool found;
int ret;
XDNA_INFO_ONCE(xdna, "populate memory range %llx size %lx",
abo->mem.userptr, abo->mem.size);
range.notifier = &abo->mem.notifier;
range.start = abo->mem.userptr;
range.end = abo->mem.userptr + abo->mem.size;
range.hmm_pfns = abo->mem.pfns;
range.default_flags = HMM_PFN_REQ_FAULT;
if (!mmget_not_zero(mm))
return -EFAULT;
timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
again:
range.notifier_seq = mmu_interval_read_begin(&abo->mem.notifier);
found = false;
down_write(&xdna->notifier_lock);
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
if (mapp->invalid) {
found = true;
break;
}
}
if (!found) {
abo->mem.map_invalid = false;
up_write(&xdna->notifier_lock);
return 0;
}
kref_get(&mapp->refcnt);
up_write(&xdna->notifier_lock);
XDNA_DBG(xdna, "populate memory range %lx %lx",
mapp->vma->vm_start, mapp->vma->vm_end);
mm = mapp->notifier.mm;
if (!mmget_not_zero(mm)) {
amdxdna_umap_put(mapp);
return -EFAULT;
}
mapp->range.notifier_seq = mmu_interval_read_begin(&mapp->notifier);
mmap_read_lock(mm);
ret = hmm_range_fault(&range);
ret = hmm_range_fault(&mapp->range);
mmap_read_unlock(mm);
if (ret) {
if (time_after(jiffies, timeout)) {
@ -786,21 +801,27 @@ again:
goto put_mm;
}
if (ret == -EBUSY)
if (ret == -EBUSY) {
amdxdna_umap_put(mapp);
goto again;
}
goto put_mm;
}
down_read(&xdna->notifier_lock);
if (mmu_interval_read_retry(&abo->mem.notifier, range.notifier_seq)) {
up_read(&xdna->notifier_lock);
down_write(&xdna->notifier_lock);
if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) {
up_write(&xdna->notifier_lock);
amdxdna_umap_put(mapp);
goto again;
}
abo->mem.map_invalid = false;
up_read(&xdna->notifier_lock);
mapp->invalid = false;
up_write(&xdna->notifier_lock);
amdxdna_umap_put(mapp);
goto again;
put_mm:
amdxdna_umap_put(mapp);
mmput(mm);
return ret;
}
@ -908,10 +929,6 @@ void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo,
struct drm_gem_object *gobj = to_gobj(abo);
long ret;
down_write(&xdna->notifier_lock);
abo->mem.map_invalid = true;
mmu_interval_set_seq(&abo->mem.notifier, cur_seq);
up_write(&xdna->notifier_lock);
ret = dma_resv_wait_timeout(gobj->resv, DMA_RESV_USAGE_BOOKKEEP,
true, MAX_SCHEDULE_TIMEOUT);
if (!ret || ret == -ERESTARTSYS)

View file

@ -525,7 +525,7 @@ aie2_cmdlist_fill_one_slot_cf(void *cmd_buf, u32 offset,
if (!payload)
return -EINVAL;
if (!slot_cf_has_space(offset, payload_len))
if (!slot_has_space(*buf, offset, payload_len))
return -ENOSPC;
buf->cu_idx = cu_idx;
@ -558,7 +558,7 @@ aie2_cmdlist_fill_one_slot_dpu(void *cmd_buf, u32 offset,
if (payload_len < sizeof(*sn) || arg_sz > MAX_DPU_ARGS_SIZE)
return -EINVAL;
if (!slot_dpu_has_space(offset, arg_sz))
if (!slot_has_space(*buf, offset, arg_sz))
return -ENOSPC;
buf->inst_buf_addr = sn->buffer;
@ -569,7 +569,7 @@ aie2_cmdlist_fill_one_slot_dpu(void *cmd_buf, u32 offset,
memcpy(buf->args, sn->prop_args, arg_sz);
/* Accurate buf size to hint firmware to do necessary copy */
*size += sizeof(*buf) + arg_sz;
*size = sizeof(*buf) + arg_sz;
return 0;
}

View file

@ -319,18 +319,16 @@ struct async_event_msg_resp {
} __packed;
#define MAX_CHAIN_CMDBUF_SIZE SZ_4K
#define slot_cf_has_space(offset, payload_size) \
(MAX_CHAIN_CMDBUF_SIZE - ((offset) + (payload_size)) > \
offsetof(struct cmd_chain_slot_execbuf_cf, args[0]))
#define slot_has_space(slot, offset, payload_size) \
(MAX_CHAIN_CMDBUF_SIZE >= (offset) + (payload_size) + \
sizeof(typeof(slot)))
struct cmd_chain_slot_execbuf_cf {
__u32 cu_idx;
__u32 arg_cnt;
__u32 args[] __counted_by(arg_cnt);
};
#define slot_dpu_has_space(offset, payload_size) \
(MAX_CHAIN_CMDBUF_SIZE - ((offset) + (payload_size)) > \
offsetof(struct cmd_chain_slot_dpu, args[0]))
struct cmd_chain_slot_dpu {
__u64 inst_buf_addr;
__u32 inst_size;

View file

@ -496,11 +496,11 @@ static int amdxdna_drm_submit_execbuf(struct amdxdna_client *client,
struct amdxdna_drm_exec_cmd *args)
{
struct amdxdna_dev *xdna = client->xdna;
u32 *arg_bo_hdls;
u32 *arg_bo_hdls = NULL;
u32 cmd_bo_hdl;
int ret;
if (!args->arg_count || args->arg_count > MAX_ARG_COUNT) {
if (args->arg_count > MAX_ARG_COUNT) {
XDNA_ERR(xdna, "Invalid arg bo count %d", args->arg_count);
return -EINVAL;
}
@ -512,14 +512,16 @@ static int amdxdna_drm_submit_execbuf(struct amdxdna_client *client,
}
cmd_bo_hdl = (u32)args->cmd_handles;
arg_bo_hdls = kcalloc(args->arg_count, sizeof(u32), GFP_KERNEL);
if (!arg_bo_hdls)
return -ENOMEM;
ret = copy_from_user(arg_bo_hdls, u64_to_user_ptr(args->args),
args->arg_count * sizeof(u32));
if (ret) {
ret = -EFAULT;
goto free_cmd_bo_hdls;
if (args->arg_count) {
arg_bo_hdls = kcalloc(args->arg_count, sizeof(u32), GFP_KERNEL);
if (!arg_bo_hdls)
return -ENOMEM;
ret = copy_from_user(arg_bo_hdls, u64_to_user_ptr(args->args),
args->arg_count * sizeof(u32));
if (ret) {
ret = -EFAULT;
goto free_cmd_bo_hdls;
}
}
ret = amdxdna_cmd_submit(client, cmd_bo_hdl, arg_bo_hdls,

View file

@ -9,7 +9,10 @@
#include <drm/drm_gem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/gpu_scheduler.h>
#include <linux/dma-buf.h>
#include <linux/dma-direct.h>
#include <linux/iosys-map.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include "amdxdna_ctx.h"
@ -18,6 +21,8 @@
#define XDNA_MAX_CMD_BO_SIZE SZ_32K
MODULE_IMPORT_NS("DMA_BUF");
static int
amdxdna_gem_insert_node_locked(struct amdxdna_gem_obj *abo, bool use_vmap)
{
@ -55,6 +60,306 @@ amdxdna_gem_insert_node_locked(struct amdxdna_gem_obj *abo, bool use_vmap)
return 0;
}
static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
const struct mmu_notifier_range *range,
unsigned long cur_seq)
{
struct amdxdna_umap *mapp = container_of(mni, struct amdxdna_umap, notifier);
struct amdxdna_gem_obj *abo = mapp->abo;
struct amdxdna_dev *xdna;
xdna = to_xdna_dev(to_gobj(abo)->dev);
XDNA_DBG(xdna, "Invalidating range 0x%lx, 0x%lx, type %d",
mapp->vma->vm_start, mapp->vma->vm_end, abo->type);
if (!mmu_notifier_range_blockable(range))
return false;
down_write(&xdna->notifier_lock);
abo->mem.map_invalid = true;
mapp->invalid = true;
mmu_interval_set_seq(&mapp->notifier, cur_seq);
up_write(&xdna->notifier_lock);
xdna->dev_info->ops->hmm_invalidate(abo, cur_seq);
if (range->event == MMU_NOTIFY_UNMAP) {
down_write(&xdna->notifier_lock);
if (!mapp->unmapped) {
queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
mapp->unmapped = true;
}
up_write(&xdna->notifier_lock);
}
return true;
}
static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = {
.invalidate = amdxdna_hmm_invalidate,
};
static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
struct vm_area_struct *vma)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
struct amdxdna_umap *mapp;
down_read(&xdna->notifier_lock);
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
if (!vma || mapp->vma == vma) {
if (!mapp->unmapped) {
queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
mapp->unmapped = true;
}
if (vma)
break;
}
}
up_read(&xdna->notifier_lock);
}
static void amdxdna_umap_release(struct kref *ref)
{
struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
struct vm_area_struct *vma = mapp->vma;
struct amdxdna_dev *xdna;
mmu_interval_notifier_remove(&mapp->notifier);
if (is_import_bo(mapp->abo) && vma->vm_file && vma->vm_file->f_mapping)
mapping_clear_unevictable(vma->vm_file->f_mapping);
xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
down_write(&xdna->notifier_lock);
list_del(&mapp->node);
up_write(&xdna->notifier_lock);
kvfree(mapp->range.hmm_pfns);
kfree(mapp);
}
void amdxdna_umap_put(struct amdxdna_umap *mapp)
{
kref_put(&mapp->refcnt, amdxdna_umap_release);
}
static void amdxdna_hmm_unreg_work(struct work_struct *work)
{
struct amdxdna_umap *mapp = container_of(work, struct amdxdna_umap,
hmm_unreg_work);
amdxdna_umap_put(mapp);
}
static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
struct vm_area_struct *vma)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
unsigned long len = vma->vm_end - vma->vm_start;
unsigned long addr = vma->vm_start;
struct amdxdna_umap *mapp;
u32 nr_pages;
int ret;
if (!xdna->dev_info->ops->hmm_invalidate)
return 0;
mapp = kzalloc(sizeof(*mapp), GFP_KERNEL);
if (!mapp)
return -ENOMEM;
nr_pages = (PAGE_ALIGN(addr + len) - (addr & PAGE_MASK)) >> PAGE_SHIFT;
mapp->range.hmm_pfns = kvcalloc(nr_pages, sizeof(*mapp->range.hmm_pfns),
GFP_KERNEL);
if (!mapp->range.hmm_pfns) {
ret = -ENOMEM;
goto free_map;
}
ret = mmu_interval_notifier_insert_locked(&mapp->notifier,
current->mm,
addr,
len,
&amdxdna_hmm_ops);
if (ret) {
XDNA_ERR(xdna, "Insert mmu notifier failed, ret %d", ret);
goto free_pfns;
}
mapp->range.notifier = &mapp->notifier;
mapp->range.start = vma->vm_start;
mapp->range.end = vma->vm_end;
mapp->range.default_flags = HMM_PFN_REQ_FAULT;
mapp->vma = vma;
mapp->abo = abo;
kref_init(&mapp->refcnt);
if (abo->mem.userptr == AMDXDNA_INVALID_ADDR)
abo->mem.userptr = addr;
INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
mapping_set_unevictable(vma->vm_file->f_mapping);
down_write(&xdna->notifier_lock);
list_add_tail(&mapp->node, &abo->mem.umap_list);
up_write(&xdna->notifier_lock);
return 0;
free_pfns:
kvfree(mapp->range.hmm_pfns);
free_map:
kfree(mapp);
return ret;
}
static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
struct vm_area_struct *vma)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
unsigned long num_pages = vma_pages(vma);
unsigned long offset = 0;
int ret;
if (!is_import_bo(abo)) {
ret = drm_gem_shmem_mmap(&abo->base, vma);
if (ret) {
XDNA_ERR(xdna, "Failed shmem mmap %d", ret);
return ret;
}
/* The buffer is based on memory pages. Fix the flag. */
vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages,
&num_pages);
if (ret) {
XDNA_ERR(xdna, "Failed insert pages %d", ret);
vma->vm_ops->close(vma);
return ret;
}
return 0;
}
vma->vm_private_data = NULL;
vma->vm_ops = NULL;
ret = dma_buf_mmap(to_gobj(abo)->dma_buf, vma, 0);
if (ret) {
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
return ret;
}
do {
vm_fault_t fault_ret;
fault_ret = handle_mm_fault(vma, vma->vm_start + offset,
FAULT_FLAG_WRITE, NULL);
if (fault_ret & VM_FAULT_ERROR) {
vma->vm_ops->close(vma);
XDNA_ERR(xdna, "Fault in page failed");
return -EFAULT;
}
offset += PAGE_SIZE;
} while (--num_pages);
/* Drop the reference drm_gem_mmap_obj() acquired.*/
drm_gem_object_put(to_gobj(abo));
return 0;
}
static int amdxdna_gem_obj_mmap(struct drm_gem_object *gobj,
struct vm_area_struct *vma)
{
struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev);
struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
int ret;
ret = amdxdna_hmm_register(abo, vma);
if (ret)
return ret;
ret = amdxdna_insert_pages(abo, vma);
if (ret) {
XDNA_ERR(xdna, "Failed insert pages, ret %d", ret);
goto hmm_unreg;
}
XDNA_DBG(xdna, "BO map_offset 0x%llx type %d userptr 0x%lx size 0x%lx",
drm_vma_node_offset_addr(&gobj->vma_node), abo->type,
vma->vm_start, gobj->size);
return 0;
hmm_unreg:
amdxdna_hmm_unregister(abo, vma);
return ret;
}
static int amdxdna_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
{
struct drm_gem_object *gobj = dma_buf->priv;
struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
unsigned long num_pages = vma_pages(vma);
int ret;
vma->vm_ops = &drm_gem_shmem_vm_ops;
vma->vm_private_data = gobj;
drm_gem_object_get(gobj);
ret = drm_gem_shmem_mmap(&abo->base, vma);
if (ret)
goto put_obj;
/* The buffer is based on memory pages. Fix the flag. */
vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages,
&num_pages);
if (ret)
goto close_vma;
return 0;
close_vma:
vma->vm_ops->close(vma);
put_obj:
drm_gem_object_put(gobj);
return ret;
}
static const struct dma_buf_ops amdxdna_dmabuf_ops = {
.attach = drm_gem_map_attach,
.detach = drm_gem_map_detach,
.map_dma_buf = drm_gem_map_dma_buf,
.unmap_dma_buf = drm_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.mmap = amdxdna_gem_dmabuf_mmap,
.vmap = drm_gem_dmabuf_vmap,
.vunmap = drm_gem_dmabuf_vunmap,
};
static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags)
{
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
exp_info.ops = &amdxdna_dmabuf_ops;
exp_info.size = gobj->size;
exp_info.flags = flags;
exp_info.priv = gobj;
exp_info.resv = gobj->resv;
return drm_gem_dmabuf_export(gobj->dev, &exp_info);
}
static void amdxdna_imported_obj_free(struct amdxdna_gem_obj *abo)
{
dma_buf_unmap_attachment_unlocked(abo->attach, abo->base.sgt, DMA_BIDIRECTIONAL);
dma_buf_detach(abo->dma_buf, abo->attach);
dma_buf_put(abo->dma_buf);
drm_gem_object_release(to_gobj(abo));
kfree(abo);
}
static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
{
struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev);
@ -62,6 +367,10 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
struct iosys_map map = IOSYS_MAP_INIT_VADDR(abo->mem.kva);
XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, abo->mem.dev_addr);
amdxdna_hmm_unregister(abo, NULL);
flush_workqueue(xdna->notifier_wq);
if (abo->pinned)
amdxdna_gem_unpin(abo);
@ -81,8 +390,14 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
if (abo->type == AMDXDNA_BO_DEV_HEAP)
drm_mm_takedown(&abo->mm);
drm_gem_vunmap_unlocked(gobj, &map);
drm_gem_vunmap(gobj, &map);
mutex_destroy(&abo->lock);
if (is_import_bo(abo)) {
amdxdna_imported_obj_free(abo);
return;
}
drm_gem_shmem_free(&abo->base);
}
@ -90,127 +405,6 @@ static const struct drm_gem_object_funcs amdxdna_gem_dev_obj_funcs = {
.free = amdxdna_gem_obj_free,
};
static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
const struct mmu_notifier_range *range,
unsigned long cur_seq)
{
struct amdxdna_gem_obj *abo = container_of(mni, struct amdxdna_gem_obj,
mem.notifier);
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
XDNA_DBG(xdna, "Invalid range 0x%llx, 0x%lx, type %d",
abo->mem.userptr, abo->mem.size, abo->type);
if (!mmu_notifier_range_blockable(range))
return false;
xdna->dev_info->ops->hmm_invalidate(abo, cur_seq);
return true;
}
static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = {
.invalidate = amdxdna_hmm_invalidate,
};
static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
if (!xdna->dev_info->ops->hmm_invalidate)
return;
mmu_interval_notifier_remove(&abo->mem.notifier);
kvfree(abo->mem.pfns);
abo->mem.pfns = NULL;
}
static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo, unsigned long addr,
size_t len)
{
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
u32 nr_pages;
int ret;
if (!xdna->dev_info->ops->hmm_invalidate)
return 0;
if (abo->mem.pfns)
return -EEXIST;
nr_pages = (PAGE_ALIGN(addr + len) - (addr & PAGE_MASK)) >> PAGE_SHIFT;
abo->mem.pfns = kvcalloc(nr_pages, sizeof(*abo->mem.pfns),
GFP_KERNEL);
if (!abo->mem.pfns)
return -ENOMEM;
ret = mmu_interval_notifier_insert_locked(&abo->mem.notifier,
current->mm,
addr,
len,
&amdxdna_hmm_ops);
if (ret) {
XDNA_ERR(xdna, "Insert mmu notifier failed, ret %d", ret);
kvfree(abo->mem.pfns);
}
abo->mem.userptr = addr;
return ret;
}
static int amdxdna_gem_obj_mmap(struct drm_gem_object *gobj,
struct vm_area_struct *vma)
{
struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
unsigned long num_pages;
int ret;
ret = amdxdna_hmm_register(abo, vma->vm_start, gobj->size);
if (ret)
return ret;
ret = drm_gem_shmem_mmap(&abo->base, vma);
if (ret)
goto hmm_unreg;
num_pages = gobj->size >> PAGE_SHIFT;
/* Try to insert the pages */
vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages, &num_pages);
if (ret)
XDNA_ERR(abo->client->xdna, "Failed insert pages, ret %d", ret);
return 0;
hmm_unreg:
amdxdna_hmm_unregister(abo);
return ret;
}
static vm_fault_t amdxdna_gem_vm_fault(struct vm_fault *vmf)
{
return drm_gem_shmem_vm_ops.fault(vmf);
}
static void amdxdna_gem_vm_open(struct vm_area_struct *vma)
{
drm_gem_shmem_vm_ops.open(vma);
}
static void amdxdna_gem_vm_close(struct vm_area_struct *vma)
{
struct drm_gem_object *gobj = vma->vm_private_data;
amdxdna_hmm_unregister(to_xdna_obj(gobj));
drm_gem_shmem_vm_ops.close(vma);
}
static const struct vm_operations_struct amdxdna_gem_vm_ops = {
.fault = amdxdna_gem_vm_fault,
.open = amdxdna_gem_vm_open,
.close = amdxdna_gem_vm_close,
};
static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
.free = amdxdna_gem_obj_free,
.print_info = drm_gem_shmem_object_print_info,
@ -220,7 +414,8 @@ static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
.vmap = drm_gem_shmem_object_vmap,
.vunmap = drm_gem_shmem_object_vunmap,
.mmap = amdxdna_gem_obj_mmap,
.vm_ops = &amdxdna_gem_vm_ops,
.vm_ops = &drm_gem_shmem_vm_ops,
.export = amdxdna_gem_prime_export,
};
static struct amdxdna_gem_obj *
@ -239,6 +434,7 @@ amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
abo->mem.userptr = AMDXDNA_INVALID_ADDR;
abo->mem.dev_addr = AMDXDNA_INVALID_ADDR;
abo->mem.size = size;
INIT_LIST_HEAD(&abo->mem.umap_list);
return abo;
}
@ -258,6 +454,51 @@ amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
return to_gobj(abo);
}
struct drm_gem_object *
amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
{
struct dma_buf_attachment *attach;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
struct sg_table *sgt;
int ret;
get_dma_buf(dma_buf);
attach = dma_buf_attach(dma_buf, dev->dev);
if (IS_ERR(attach)) {
ret = PTR_ERR(attach);
goto put_buf;
}
sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
}
gobj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt);
if (IS_ERR(gobj)) {
ret = PTR_ERR(gobj);
goto fail_unmap;
}
abo = to_xdna_obj(gobj);
abo->attach = attach;
abo->dma_buf = dma_buf;
return gobj;
fail_unmap:
dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
fail_detach:
dma_buf_detach(dma_buf, attach);
put_buf:
dma_buf_put(dma_buf);
return ERR_PTR(ret);
}
static struct amdxdna_gem_obj *
amdxdna_drm_alloc_shmem(struct drm_device *dev,
struct amdxdna_drm_create_bo *args,
@ -417,7 +658,7 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
abo->type = AMDXDNA_BO_CMD;
abo->client = filp->driver_priv;
ret = drm_gem_vmap_unlocked(to_gobj(abo), &map);
ret = drm_gem_vmap(to_gobj(abo), &map);
if (ret) {
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
goto release_obj;
@ -483,6 +724,9 @@ int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo)
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
int ret;
if (is_import_bo(abo))
return 0;
switch (abo->type) {
case AMDXDNA_BO_SHMEM:
case AMDXDNA_BO_DEV_HEAP:
@ -515,6 +759,9 @@ int amdxdna_gem_pin(struct amdxdna_gem_obj *abo)
void amdxdna_gem_unpin(struct amdxdna_gem_obj *abo)
{
if (is_import_bo(abo))
return;
if (abo->type == AMDXDNA_BO_DEV)
abo = abo->dev_heap;
@ -606,7 +853,9 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
goto put_obj;
}
if (abo->type == AMDXDNA_BO_DEV)
if (is_import_bo(abo))
drm_clflush_sg(abo->base.sgt);
else if (abo->type == AMDXDNA_BO_DEV)
drm_clflush_pages(abo->mem.pages, abo->mem.nr_pages);
else
drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT);

View file

@ -6,6 +6,20 @@
#ifndef _AMDXDNA_GEM_H_
#define _AMDXDNA_GEM_H_
#include <linux/hmm.h>
struct amdxdna_umap {
struct vm_area_struct *vma;
struct mmu_interval_notifier notifier;
struct hmm_range range;
struct work_struct hmm_unreg_work;
struct amdxdna_gem_obj *abo;
struct list_head node;
struct kref refcnt;
bool invalid;
bool unmapped;
};
struct amdxdna_mem {
u64 userptr;
void *kva;
@ -13,8 +27,7 @@ struct amdxdna_mem {
size_t size;
struct page **pages;
u32 nr_pages;
struct mmu_interval_notifier notifier;
unsigned long *pfns;
struct list_head umap_list;
bool map_invalid;
};
@ -31,9 +44,12 @@ struct amdxdna_gem_obj {
struct amdxdna_gem_obj *dev_heap; /* For AMDXDNA_BO_DEV */
struct drm_mm_node mm_node; /* For AMDXDNA_BO_DEV */
u32 assigned_hwctx;
struct dma_buf *dma_buf;
struct dma_buf_attachment *attach;
};
#define to_gobj(obj) (&(obj)->base.base)
#define is_import_bo(obj) ((obj)->attach)
static inline struct amdxdna_gem_obj *to_xdna_obj(struct drm_gem_object *gobj)
{
@ -47,8 +63,12 @@ static inline void amdxdna_gem_put_obj(struct amdxdna_gem_obj *abo)
drm_gem_object_put(to_gobj(abo));
}
void amdxdna_umap_put(struct amdxdna_umap *mapp);
struct drm_gem_object *
amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size);
struct drm_gem_object *
amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf);
struct amdxdna_gem_obj *
amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
struct amdxdna_drm_create_bo *args,

View file

@ -226,6 +226,7 @@ const struct drm_driver amdxdna_drm_drv = {
.num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),
.gem_create_object = amdxdna_gem_create_object_cb,
.gem_prime_import = amdxdna_gem_prime_import,
};
static const struct amdxdna_dev_info *
@ -266,12 +267,16 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
fs_reclaim_release(GFP_KERNEL);
}
xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", 0);
if (!xdna->notifier_wq)
return -ENOMEM;
mutex_lock(&xdna->dev_lock);
ret = xdna->dev_info->ops->init(xdna);
mutex_unlock(&xdna->dev_lock);
if (ret) {
XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);
return ret;
goto destroy_notifier_wq;
}
ret = amdxdna_sysfs_init(xdna);
@ -301,6 +306,8 @@ failed_dev_fini:
mutex_lock(&xdna->dev_lock);
xdna->dev_info->ops->fini(xdna);
mutex_unlock(&xdna->dev_lock);
destroy_notifier_wq:
destroy_workqueue(xdna->notifier_wq);
return ret;
}
@ -310,6 +317,8 @@ static void amdxdna_remove(struct pci_dev *pdev)
struct device *dev = &pdev->dev;
struct amdxdna_client *client;
destroy_workqueue(xdna->notifier_wq);
pm_runtime_get_noresume(dev);
pm_runtime_forbid(dev);

View file

@ -6,6 +6,7 @@
#ifndef _AMDXDNA_PCI_DRV_H_
#define _AMDXDNA_PCI_DRV_H_
#include <linux/workqueue.h>
#include <linux/xarray.h>
#define XDNA_INFO(xdna, fmt, args...) drm_info(&(xdna)->ddev, fmt, ##args)
@ -98,6 +99,7 @@ struct amdxdna_dev {
struct list_head client_list;
struct amdxdna_fw_ver fw_ver;
struct rw_semaphore notifier_lock; /* for mmu notifier*/
struct workqueue_struct *notifier_wq;
};
/*

View file

@ -374,6 +374,9 @@ int ivpu_boot(struct ivpu_device *vdev)
{
int ret;
drm_WARN_ON(&vdev->drm, atomic_read(&vdev->job_timeout_counter));
drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa));
/* Update boot params located at first 4KB of FW memory */
ivpu_fw_boot_params_setup(vdev, ivpu_bo_vaddr(vdev->fw->mem));
@ -573,6 +576,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID;
vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID;
atomic64_set(&vdev->unique_id_counter, 0);
atomic_set(&vdev->job_timeout_counter, 0);
xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1);
xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1);

View file

@ -154,6 +154,7 @@ struct ivpu_device {
struct mutex submitted_jobs_lock; /* Protects submitted_jobs */
struct xarray submitted_jobs_xa;
struct ivpu_ipc_consumer job_done_consumer;
atomic_t job_timeout_counter;
atomic64_t unique_id_counter;

View file

@ -39,6 +39,7 @@ struct ivpu_fw_info {
u64 read_only_addr;
u32 read_only_size;
u32 sched_mode;
u64 last_heartbeat;
};
int ivpu_fw_init(struct ivpu_device *vdev);

View file

@ -30,7 +30,7 @@ static inline void ivpu_dbg_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, con
"%6s: bo %8p vpu_addr %9llx size %8zu ctx %d has_pages %d dma_mapped %d mmu_mapped %d wc %d imported %d\n",
action, bo, bo->vpu_addr, ivpu_bo_size(bo), bo->ctx ? bo->ctx->id : 0,
(bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc,
(bool)bo->base.base.import_attach);
(bool)drm_gem_is_imported(&bo->base.base));
}
/*
@ -122,7 +122,7 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo)
bo->ctx = NULL;
}
if (bo->base.base.import_attach)
if (drm_gem_is_imported(&bo->base.base))
return;
dma_resv_lock(bo->base.base.resv, NULL);
@ -282,7 +282,7 @@ static void ivpu_gem_bo_free(struct drm_gem_object *obj)
ivpu_bo_unbind_locked(bo);
mutex_destroy(&bo->lock);
drm_WARN_ON(obj->dev, bo->base.pages_use_count > 1);
drm_WARN_ON(obj->dev, refcount_read(&bo->base.pages_use_count) > 1);
drm_gem_shmem_free(&bo->base);
}
@ -362,7 +362,7 @@ ivpu_bo_create(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
if (flags & DRM_IVPU_BO_MAPPABLE) {
dma_resv_lock(bo->base.base.resv, NULL);
ret = drm_gem_shmem_vmap(&bo->base, &map);
ret = drm_gem_shmem_vmap_locked(&bo->base, &map);
dma_resv_unlock(bo->base.base.resv);
if (ret)
@ -387,7 +387,7 @@ void ivpu_bo_free(struct ivpu_bo *bo)
if (bo->flags & DRM_IVPU_BO_MAPPABLE) {
dma_resv_lock(bo->base.base.resv, NULL);
drm_gem_shmem_vunmap(&bo->base, &map);
drm_gem_shmem_vunmap_locked(&bo->base, &map);
dma_resv_unlock(bo->base.base.resv);
}
@ -461,7 +461,7 @@ static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p)
if (bo->mmu_mapped)
drm_printf(p, " mmu_mapped");
if (bo->base.base.import_attach)
if (drm_gem_is_imported(&bo->base.base))
drm_printf(p, " imported");
drm_printf(p, "\n");

View file

@ -34,6 +34,7 @@ module_param_named(tdr_timeout_ms, ivpu_tdr_timeout_ms, ulong, 0644);
MODULE_PARM_DESC(tdr_timeout_ms, "Timeout for device hang detection, in milliseconds, 0 - default");
#define PM_RESCHEDULE_LIMIT 5
#define PM_TDR_HEARTBEAT_LIMIT 30
static void ivpu_pm_prepare_cold_boot(struct ivpu_device *vdev)
{
@ -44,6 +45,7 @@ static void ivpu_pm_prepare_cold_boot(struct ivpu_device *vdev)
ivpu_fw_log_reset(vdev);
ivpu_fw_load(vdev);
fw->entry_point = fw->cold_boot_entry_point;
fw->last_heartbeat = 0;
}
static void ivpu_pm_prepare_warm_boot(struct ivpu_device *vdev)
@ -189,7 +191,24 @@ static void ivpu_job_timeout_work(struct work_struct *work)
{
struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, job_timeout_work.work);
struct ivpu_device *vdev = pm->vdev;
u64 heartbeat;
if (ivpu_jsm_get_heartbeat(vdev, 0, &heartbeat) || heartbeat <= vdev->fw->last_heartbeat) {
ivpu_err(vdev, "Job timeout detected, heartbeat not progressed\n");
goto recovery;
}
if (atomic_fetch_inc(&vdev->job_timeout_counter) > PM_TDR_HEARTBEAT_LIMIT) {
ivpu_err(vdev, "Job timeout detected, heartbeat limit exceeded\n");
goto recovery;
}
vdev->fw->last_heartbeat = heartbeat;
ivpu_start_job_timeout_detection(vdev);
return;
recovery:
atomic_set(&vdev->job_timeout_counter, 0);
ivpu_pm_trigger_recovery(vdev, "TDR");
}
@ -204,6 +223,7 @@ void ivpu_start_job_timeout_detection(struct ivpu_device *vdev)
void ivpu_stop_job_timeout_detection(struct ivpu_device *vdev)
{
cancel_delayed_work_sync(&vdev->pm->job_timeout_work);
atomic_set(&vdev->job_timeout_counter, 0);
}
int ivpu_pm_suspend_cb(struct device *dev)

View file

@ -609,7 +609,7 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc
struct scatterlist *sg;
int ret = 0;
if (obj->import_attach)
if (drm_gem_is_imported(obj))
return -EINVAL;
for (sg = bo->sgt->sgl; sg; sg = sg_next(sg)) {
@ -630,7 +630,7 @@ static void qaic_free_object(struct drm_gem_object *obj)
{
struct qaic_bo *bo = to_qaic_bo(obj);
if (obj->import_attach) {
if (drm_gem_is_imported(obj)) {
/* DMABUF/PRIME Path */
drm_prime_gem_destroy(obj, NULL);
} else {
@ -870,7 +870,7 @@ static int qaic_prepare_bo(struct qaic_device *qdev, struct qaic_bo *bo,
{
int ret;
if (bo->base.import_attach)
if (drm_gem_is_imported(&bo->base))
ret = qaic_prepare_import_bo(bo, hdr);
else
ret = qaic_prepare_export_bo(qdev, bo, hdr);
@ -894,7 +894,7 @@ static void qaic_unprepare_export_bo(struct qaic_device *qdev, struct qaic_bo *b
static void qaic_unprepare_bo(struct qaic_device *qdev, struct qaic_bo *bo)
{
if (bo->base.import_attach)
if (drm_gem_is_imported(&bo->base))
qaic_unprepare_import_bo(bo);
else
qaic_unprepare_export_bo(qdev, bo);

View file

@ -240,7 +240,6 @@ static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_d
mhi_unprepare:
mhi_unprepare_from_transfer(mhi_dev);
destroy_workqueue:
flush_workqueue(qdev->bootlog_wq);
destroy_workqueue(qdev->bootlog_wq);
out:
return ret;
@ -253,7 +252,6 @@ static void qaic_bootlog_mhi_remove(struct mhi_device *mhi_dev)
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;
}

View file

@ -53,6 +53,7 @@ struct intel_gtt_driver {
* of the mmio register file, that's done in the generic code. */
void (*cleanup)(void);
void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags);
dma_addr_t (*read_entry)(unsigned int entry, bool *is_present, bool *is_local);
/* Flags is a more or less chipset specific opaque value.
* For chipsets that need to support old ums (non-gem) code, this
* needs to be identical to the various supported agp memory types! */
@ -336,6 +337,19 @@ static void i810_write_entry(dma_addr_t addr, unsigned int entry,
writel_relaxed(addr | pte_flags, intel_private.gtt + entry);
}
static dma_addr_t i810_read_entry(unsigned int entry,
bool *is_present, bool *is_local)
{
u32 val;
val = readl(intel_private.gtt + entry);
*is_present = val & I810_PTE_VALID;
*is_local = val & I810_PTE_LOCAL;
return val & ~0xfff;
}
static resource_size_t intel_gtt_stolen_size(void)
{
u16 gmch_ctrl;
@ -741,6 +755,19 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry,
writel_relaxed(addr | pte_flags, intel_private.gtt + entry);
}
static dma_addr_t i830_read_entry(unsigned int entry,
bool *is_present, bool *is_local)
{
u32 val;
val = readl(intel_private.gtt + entry);
*is_present = val & I810_PTE_VALID;
*is_local = false;
return val & ~0xfff;
}
bool intel_gmch_enable_gtt(void)
{
u8 __iomem *reg;
@ -878,6 +905,13 @@ void intel_gmch_gtt_insert_sg_entries(struct sg_table *st,
}
EXPORT_SYMBOL(intel_gmch_gtt_insert_sg_entries);
dma_addr_t intel_gmch_gtt_read_entry(unsigned int pg,
bool *is_present, bool *is_local)
{
return intel_private.driver->read_entry(pg, is_present, is_local);
}
EXPORT_SYMBOL(intel_gmch_gtt_read_entry);
#if IS_ENABLED(CONFIG_AGP_INTEL)
static void intel_gmch_gtt_insert_pages(unsigned int first_entry,
unsigned int num_entries,
@ -1126,6 +1160,19 @@ static void i965_write_entry(dma_addr_t addr,
writel_relaxed(addr | pte_flags, intel_private.gtt + entry);
}
static dma_addr_t i965_read_entry(unsigned int entry,
bool *is_present, bool *is_local)
{
u64 val;
val = readl(intel_private.gtt + entry);
*is_present = val & I810_PTE_VALID;
*is_local = false;
return ((val & 0xf0) << 28) | (val & ~0xfff);
}
static int i9xx_setup(void)
{
phys_addr_t reg_addr;
@ -1187,6 +1234,7 @@ static const struct intel_gtt_driver i81x_gtt_driver = {
.cleanup = i810_cleanup,
.check_flags = i830_check_flags,
.write_entry = i810_write_entry,
.read_entry = i810_read_entry,
};
static const struct intel_gtt_driver i8xx_gtt_driver = {
.gen = 2,
@ -1194,6 +1242,7 @@ static const struct intel_gtt_driver i8xx_gtt_driver = {
.setup = i830_setup,
.cleanup = i830_cleanup,
.write_entry = i830_write_entry,
.read_entry = i830_read_entry,
.dma_mask_size = 32,
.check_flags = i830_check_flags,
.chipset_flush = i830_chipset_flush,
@ -1205,6 +1254,7 @@ static const struct intel_gtt_driver i915_gtt_driver = {
.cleanup = i9xx_cleanup,
/* i945 is the last gpu to need phys mem (for overlay and cursors). */
.write_entry = i830_write_entry,
.read_entry = i830_read_entry,
.dma_mask_size = 32,
.check_flags = i830_check_flags,
.chipset_flush = i9xx_chipset_flush,
@ -1215,6 +1265,7 @@ static const struct intel_gtt_driver g33_gtt_driver = {
.setup = i9xx_setup,
.cleanup = i9xx_cleanup,
.write_entry = i965_write_entry,
.read_entry = i965_read_entry,
.dma_mask_size = 36,
.check_flags = i830_check_flags,
.chipset_flush = i9xx_chipset_flush,
@ -1225,6 +1276,7 @@ static const struct intel_gtt_driver pineview_gtt_driver = {
.setup = i9xx_setup,
.cleanup = i9xx_cleanup,
.write_entry = i965_write_entry,
.read_entry = i965_read_entry,
.dma_mask_size = 36,
.check_flags = i830_check_flags,
.chipset_flush = i9xx_chipset_flush,
@ -1235,6 +1287,7 @@ static const struct intel_gtt_driver i965_gtt_driver = {
.setup = i9xx_setup,
.cleanup = i9xx_cleanup,
.write_entry = i965_write_entry,
.read_entry = i965_read_entry,
.dma_mask_size = 36,
.check_flags = i830_check_flags,
.chipset_flush = i9xx_chipset_flush,
@ -1244,6 +1297,7 @@ static const struct intel_gtt_driver g4x_gtt_driver = {
.setup = i9xx_setup,
.cleanup = i9xx_cleanup,
.write_entry = i965_write_entry,
.read_entry = i965_read_entry,
.dma_mask_size = 36,
.check_flags = i830_check_flags,
.chipset_flush = i9xx_chipset_flush,
@ -1254,6 +1308,7 @@ static const struct intel_gtt_driver ironlake_gtt_driver = {
.setup = i9xx_setup,
.cleanup = i9xx_cleanup,
.write_entry = i965_write_entry,
.read_entry = i965_read_entry,
.dma_mask_size = 36,
.check_flags = i830_check_flags,
.chipset_flush = i9xx_chipset_flush,

View file

@ -636,10 +636,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
|| !exp_info->ops->release))
return ERR_PTR(-EINVAL);
if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
(exp_info->ops->pin || exp_info->ops->unpin)))
return ERR_PTR(-EINVAL);
if (WARN_ON(!exp_info->ops->pin != !exp_info->ops->unpin))
return ERR_PTR(-EINVAL);
@ -782,7 +778,7 @@ static void mangle_sg_table(struct sg_table *sg_table)
/* To catch abuse of the underlying struct page by importers mix
* up the bits, but take care to preserve the low SG_ bits to
* not corrupt the sgt. The mixing is undone in __unmap_dma_buf
* not corrupt the sgt. The mixing is undone on unmap
* before passing the sgt back to the exporter.
*/
for_each_sgtable_sg(sg_table, sg, i)
@ -790,29 +786,19 @@ static void mangle_sg_table(struct sg_table *sg_table)
#endif
}
static struct sg_table *__map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
static inline bool
dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
{
struct sg_table *sg_table;
signed long ret;
return !!attach->importer_ops;
}
sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
if (IS_ERR_OR_NULL(sg_table))
return sg_table;
if (!dma_buf_attachment_is_dynamic(attach)) {
ret = dma_resv_wait_timeout(attach->dmabuf->resv,
DMA_RESV_USAGE_KERNEL, true,
MAX_SCHEDULE_TIMEOUT);
if (ret < 0) {
attach->dmabuf->ops->unmap_dma_buf(attach, sg_table,
direction);
return ERR_PTR(ret);
}
}
mangle_sg_table(sg_table);
return sg_table;
static bool
dma_buf_pin_on_map(struct dma_buf_attachment *attach)
{
return attach->dmabuf->ops->pin &&
(!dma_buf_attachment_is_dynamic(attach) ||
!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY));
}
/**
@ -935,48 +921,11 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
list_add(&attach->node, &dmabuf->attachments);
dma_resv_unlock(dmabuf->resv);
/* When either the importer or the exporter can't handle dynamic
* mappings we cache the mapping here to avoid issues with the
* reservation object lock.
*/
if (dma_buf_attachment_is_dynamic(attach) !=
dma_buf_is_dynamic(dmabuf)) {
struct sg_table *sgt;
dma_resv_lock(attach->dmabuf->resv, NULL);
if (dma_buf_is_dynamic(attach->dmabuf)) {
ret = dmabuf->ops->pin(attach);
if (ret)
goto err_unlock;
}
sgt = __map_dma_buf(attach, DMA_BIDIRECTIONAL);
if (!sgt)
sgt = ERR_PTR(-ENOMEM);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto err_unpin;
}
dma_resv_unlock(attach->dmabuf->resv);
attach->sgt = sgt;
attach->dir = DMA_BIDIRECTIONAL;
}
return attach;
err_attach:
kfree(attach);
return ERR_PTR(ret);
err_unpin:
if (dma_buf_is_dynamic(attach->dmabuf))
dmabuf->ops->unpin(attach);
err_unlock:
dma_resv_unlock(attach->dmabuf->resv);
dma_buf_detach(dmabuf, attach);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_NS_GPL(dma_buf_dynamic_attach, "DMA_BUF");
@ -995,16 +944,6 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
}
EXPORT_SYMBOL_NS_GPL(dma_buf_attach, "DMA_BUF");
static void __unmap_dma_buf(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
enum dma_data_direction direction)
{
/* uses XOR, hence this unmangles */
mangle_sg_table(sg_table);
attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
}
/**
* dma_buf_detach - Remove the given attachment from dmabuf's attachments list
* @dmabuf: [in] buffer to detach from.
@ -1020,16 +959,7 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
return;
dma_resv_lock(dmabuf->resv, NULL);
if (attach->sgt) {
__unmap_dma_buf(attach, attach->sgt, attach->dir);
if (dma_buf_is_dynamic(attach->dmabuf))
dmabuf->ops->unpin(attach);
}
list_del(&attach->node);
dma_resv_unlock(dmabuf->resv);
if (dmabuf->ops->detach)
@ -1058,7 +988,7 @@ int dma_buf_pin(struct dma_buf_attachment *attach)
struct dma_buf *dmabuf = attach->dmabuf;
int ret = 0;
WARN_ON(!dma_buf_attachment_is_dynamic(attach));
WARN_ON(!attach->importer_ops);
dma_resv_assert_held(dmabuf->resv);
@ -1081,7 +1011,7 @@ void dma_buf_unpin(struct dma_buf_attachment *attach)
{
struct dma_buf *dmabuf = attach->dmabuf;
WARN_ON(!dma_buf_attachment_is_dynamic(attach));
WARN_ON(!attach->importer_ops);
dma_resv_assert_held(dmabuf->resv);
@ -1115,7 +1045,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
{
struct sg_table *sg_table;
int r;
signed long ret;
might_sleep();
@ -1124,41 +1054,37 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
dma_resv_assert_held(attach->dmabuf->resv);
if (attach->sgt) {
if (dma_buf_pin_on_map(attach)) {
ret = attach->dmabuf->ops->pin(attach);
/*
* Two mappings with different directions for the same
* attachment are not allowed.
* Catch exporters making buffers inaccessible even when
* attachments preventing that exist.
*/
if (attach->dir != direction &&
attach->dir != DMA_BIDIRECTIONAL)
return ERR_PTR(-EBUSY);
return attach->sgt;
WARN_ON_ONCE(ret == EBUSY);
if (ret)
return ERR_PTR(ret);
}
if (dma_buf_is_dynamic(attach->dmabuf)) {
if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
r = attach->dmabuf->ops->pin(attach);
if (r)
return ERR_PTR(r);
}
}
sg_table = __map_dma_buf(attach, direction);
sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
if (!sg_table)
sg_table = ERR_PTR(-ENOMEM);
if (IS_ERR(sg_table))
goto error_unpin;
if (IS_ERR(sg_table) && dma_buf_is_dynamic(attach->dmabuf) &&
!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY))
attach->dmabuf->ops->unpin(attach);
if (!IS_ERR(sg_table) && attach->dmabuf->ops->cache_sgt_mapping) {
attach->sgt = sg_table;
attach->dir = direction;
/*
* Importers with static attachments don't wait for fences.
*/
if (!dma_buf_attachment_is_dynamic(attach)) {
ret = dma_resv_wait_timeout(attach->dmabuf->resv,
DMA_RESV_USAGE_KERNEL, true,
MAX_SCHEDULE_TIMEOUT);
if (ret < 0)
goto error_unmap;
}
mangle_sg_table(sg_table);
#ifdef CONFIG_DMA_API_DEBUG
if (!IS_ERR(sg_table)) {
{
struct scatterlist *sg;
u64 addr;
int len;
@ -1175,6 +1101,16 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
}
#endif /* CONFIG_DMA_API_DEBUG */
return sg_table;
error_unmap:
attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
sg_table = ERR_PTR(ret);
error_unpin:
if (dma_buf_pin_on_map(attach))
attach->dmabuf->ops->unpin(attach);
return sg_table;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, "DMA_BUF");
@ -1227,14 +1163,11 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
dma_resv_assert_held(attach->dmabuf->resv);
if (attach->sgt == sg_table)
return;
mangle_sg_table(sg_table);
attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
__unmap_dma_buf(attach, sg_table, direction);
if (dma_buf_is_dynamic(attach->dmabuf) &&
!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY))
dma_buf_unpin(attach);
if (dma_buf_pin_on_map(attach))
attach->dmabuf->ops->unpin(attach);
}
EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, "DMA_BUF");

View file

@ -79,6 +79,41 @@ static int fence_cmp(const void *_a, const void *_b)
return 0;
}
/**
* dma_fence_dedup_array - Sort and deduplicate an array of dma_fence pointers
* @fences: Array of dma_fence pointers to be deduplicated
* @num_fences: Number of entries in the @fences array
*
* Sorts the input array by context, then removes duplicate
* fences with the same context, keeping only the most recent one.
*
* The array is modified in-place and unreferenced duplicate fences are released
* via dma_fence_put(). The function returns the new number of fences after
* deduplication.
*
* Return: Number of unique fences remaining in the array.
*/
int dma_fence_dedup_array(struct dma_fence **fences, int num_fences)
{
int i, j;
sort(fences, num_fences, sizeof(*fences), fence_cmp, NULL);
/*
* Only keep the most recent fence for each context.
*/
j = 0;
for (i = 1; i < num_fences; i++) {
if (fences[i]->context == fences[j]->context)
dma_fence_put(fences[i]);
else
fences[++j] = fences[i];
}
return ++j;
}
EXPORT_SYMBOL_GPL(dma_fence_dedup_array);
/* Implementation for the dma_fence_merge() marco, don't use directly */
struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence **fences,
@ -87,7 +122,7 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence *tmp, *unsignaled = NULL, **array;
struct dma_fence_array *result;
ktime_t timestamp;
int i, j, count;
int i, count;
count = 0;
timestamp = ns_to_ktime(0);
@ -141,19 +176,7 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
if (count == 0 || count == 1)
goto return_fastpath;
sort(array, count, sizeof(*array), fence_cmp, NULL);
/*
* Only keep the most recent fence for each context.
*/
j = 0;
for (i = 1; i < count; i++) {
if (array[i]->context == array[j]->context)
dma_fence_put(array[i]);
else
array[++j] = array[i];
}
count = ++j;
count = dma_fence_dedup_array(array, count);
if (count > 1) {
result = dma_fence_array_create(count, array,

View file

@ -21,8 +21,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
static struct dma_heap *sys_heap;
struct system_heap_buffer {
struct dma_heap *heap;
struct list_head attachments;
@ -424,6 +422,7 @@ static const struct dma_heap_ops system_heap_ops = {
static int __init system_heap_create(void)
{
struct dma_heap_export_info exp_info;
struct dma_heap *sys_heap;
exp_info.name = "system";
exp_info.ops = &system_heap_ops;

View file

@ -173,20 +173,6 @@ static bool timeline_fence_signaled(struct dma_fence *fence)
return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops);
}
static void timeline_fence_value_str(struct dma_fence *fence,
char *str, int size)
{
snprintf(str, size, "%lld", fence->seqno);
}
static void timeline_fence_timeline_value_str(struct dma_fence *fence,
char *str, int size)
{
struct sync_timeline *parent = dma_fence_parent(fence);
snprintf(str, size, "%d", parent->value);
}
static void timeline_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
{
struct sync_pt *pt = dma_fence_to_sync_pt(fence);
@ -208,8 +194,6 @@ static const struct dma_fence_ops timeline_fence_ops = {
.get_timeline_name = timeline_fence_get_timeline_name,
.signaled = timeline_fence_signaled,
.release = timeline_fence_release,
.fence_value_str = timeline_fence_value_str,
.timeline_value_str = timeline_fence_timeline_value_str,
.set_deadline = timeline_fence_set_deadline,
};

View file

@ -12,8 +12,6 @@ static struct dentry *dbgfs;
static LIST_HEAD(sync_timeline_list_head);
static DEFINE_SPINLOCK(sync_timeline_list_lock);
static LIST_HEAD(sync_file_list_head);
static DEFINE_SPINLOCK(sync_file_list_lock);
void sync_timeline_debug_add(struct sync_timeline *obj)
{
@ -33,24 +31,6 @@ void sync_timeline_debug_remove(struct sync_timeline *obj)
spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
}
void sync_file_debug_add(struct sync_file *sync_file)
{
unsigned long flags;
spin_lock_irqsave(&sync_file_list_lock, flags);
list_add_tail(&sync_file->sync_file_list, &sync_file_list_head);
spin_unlock_irqrestore(&sync_file_list_lock, flags);
}
void sync_file_debug_remove(struct sync_file *sync_file)
{
unsigned long flags;
spin_lock_irqsave(&sync_file_list_lock, flags);
list_del(&sync_file->sync_file_list);
spin_unlock_irqrestore(&sync_file_list_lock, flags);
}
static const char *sync_status_str(int status)
{
if (status < 0)
@ -82,25 +62,8 @@ static void sync_print_fence(struct seq_file *s,
seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
}
if (fence->ops->timeline_value_str &&
fence->ops->fence_value_str) {
char value[64];
bool success;
fence->ops->fence_value_str(fence, value, sizeof(value));
success = strlen(value);
if (success) {
seq_printf(s, ": %s", value);
fence->ops->timeline_value_str(fence, value,
sizeof(value));
if (strlen(value))
seq_printf(s, " / %s", value);
}
}
seq_printf(s, ": %lld", fence->seqno);
seq_printf(s, " / %d", parent->value);
seq_putc(s, '\n');
}
@ -118,26 +81,6 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
spin_unlock(&obj->lock);
}
static void sync_print_sync_file(struct seq_file *s,
struct sync_file *sync_file)
{
char buf[128];
int i;
seq_printf(s, "[%p] %s: %s\n", sync_file,
sync_file_get_name(sync_file, buf, sizeof(buf)),
sync_status_str(dma_fence_get_status(sync_file->fence)));
if (dma_fence_is_array(sync_file->fence)) {
struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
for (i = 0; i < array->num_fences; ++i)
sync_print_fence(s, array->fences[i], true);
} else {
sync_print_fence(s, sync_file->fence, true);
}
}
static int sync_info_debugfs_show(struct seq_file *s, void *unused)
{
struct list_head *pos;
@ -157,15 +100,6 @@ static int sync_info_debugfs_show(struct seq_file *s, void *unused)
seq_puts(s, "fences:\n--------------\n");
spin_lock_irq(&sync_file_list_lock);
list_for_each(pos, &sync_file_list_head) {
struct sync_file *sync_file =
container_of(pos, struct sync_file, sync_file_list);
sync_print_sync_file(s, sync_file);
seq_putc(s, '\n');
}
spin_unlock_irq(&sync_file_list_lock);
return 0;
}

View file

@ -68,7 +68,5 @@ extern const struct file_operations sw_sync_debugfs_fops;
void sync_timeline_debug_add(struct sync_timeline *obj);
void sync_timeline_debug_remove(struct sync_timeline *obj);
void sync_file_debug_add(struct sync_file *fence);
void sync_file_debug_remove(struct sync_file *fence);
#endif /* _LINUX_SYNC_H */

View file

@ -285,7 +285,6 @@ static int end_cpu_udmabuf(struct dma_buf *buf,
}
static const struct dma_buf_ops udmabuf_ops = {
.cache_sgt_mapping = true,
.map_dma_buf = map_udmabuf,
.unmap_dma_buf = unmap_udmabuf,
.release = release_udmabuf,

View file

@ -558,6 +558,7 @@ int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
__weak __alias(__efi_mem_desc_lookup);
EXPORT_SYMBOL_GPL(efi_mem_desc_lookup);
/*
* Calculate the highest address of an efi memory descriptor.

View file

@ -35,36 +35,7 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI)
return false;
/*
* The meaning of depth and bpp for direct-color formats is
* inconsistent:
*
* - DRM format info specifies depth as the number of color
* bits; including alpha, but not including filler bits.
* - Linux' EFI platform code computes lfb_depth from the
* individual color channels, including the reserved bits.
* - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later
* versions use 15.
* - On the kernel command line, 'bpp' of 32 is usually
* XRGB8888 including the filler bits, but 15 is XRGB1555
* not including the filler bit.
*
* It's not easily possible to fix this in struct screen_info,
* as this could break UAPI. The best solution is to compute
* bits_per_pixel from the color bits, reserved bits and
* reported lfb_depth, whichever is highest. In the loop below,
* ignore simplefb formats with alpha bits, as EFI and VESA
* don't specify alpha channels.
*/
if (si->lfb_depth > 8) {
bits_per_pixel = max(max3(si->red_size + si->red_pos,
si->green_size + si->green_pos,
si->blue_size + si->blue_pos),
si->rsvd_size + si->rsvd_pos);
bits_per_pixel = max_t(u32, bits_per_pixel, si->lfb_depth);
} else {
bits_per_pixel = si->lfb_depth;
}
bits_per_pixel = __screen_info_lfb_bits_per_pixel(si);
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
const struct simplefb_format *f = &formats[i];

View file

@ -26,6 +26,11 @@ menuconfig DRM
details. You should also select and configure AGP
(/dev/agpgart) support if it is available for your platform.
menu "DRM debugging options"
depends on DRM
source "drivers/gpu/drm/Kconfig.debug"
endmenu
if DRM
config DRM_MIPI_DBI
@ -37,65 +42,6 @@ config DRM_MIPI_DSI
bool
depends on DRM
config DRM_DEBUG_MM
bool "Insert extra checks and debug info into the DRM range managers"
default n
depends on DRM
depends on STACKTRACE_SUPPORT
select STACKDEPOT
help
Enable allocation tracking of memory manager and leak detection on
shutdown.
Recommended for driver developers only.
If in doubt, say "N".
config DRM_USE_DYNAMIC_DEBUG
bool "use dynamic debug to implement drm.debug"
default n
depends on BROKEN
depends on DRM
depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
depends on JUMP_LABEL
help
Use dynamic-debug to avoid drm_debug_enabled() runtime overheads.
Due to callsite counts in DRM drivers (~4k in amdgpu) and 56
bytes per callsite, the .data costs can be substantial, and
are therefore configurable.
config DRM_KUNIT_TEST_HELPERS
tristate
depends on DRM && KUNIT
select DRM_KMS_HELPER
help
KUnit Helpers for KMS drivers.
config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
depends on DRM && KUNIT && MMU
select DRM_BUDDY
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDMI_STATE_HELPER
select DRM_DISPLAY_HELPER
select DRM_EXEC
select DRM_EXPORT_FOR_TESTS if m
select DRM_GEM_SHMEM_HELPER
select DRM_KUNIT_TEST_HELPERS
select DRM_LIB_RANDOM
select PRIME_NUMBERS
default KUNIT_ALL_TESTS
help
This builds unit tests for DRM. This option is not useful for
distributions or general kernels, but only for kernel
developers working on DRM and associated drivers.
For more information on KUnit and unit tests in general,
please refer to the KUnit documentation in
Documentation/dev-tools/kunit/.
If in doubt, say "N".
config DRM_KMS_HELPER
tristate
depends on DRM
@ -247,23 +193,6 @@ config DRM_TTM
GPU memory types. Will be enabled automatically if a device driver
uses it.
config DRM_TTM_KUNIT_TEST
tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
default n
depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
select DRM_TTM
select DRM_BUDDY
select DRM_EXPORT_FOR_TESTS if m
select DRM_KUNIT_TEST_HELPERS
default KUNIT_ALL_TESTS
help
Enables unit tests for TTM, a GPU memory manager subsystem used
to manage memory buffers. This option is mostly useful for kernel
developers. It depends on (UML || COMPILE_TEST) since no other driver
which uses TTM can be loaded while running the tests.
If in doubt, say "N".
config DRM_EXEC
tristate
depends on DRM
@ -335,6 +264,8 @@ config DRM_SCHED
tristate
depends on DRM
source "drivers/gpu/drm/sysfb/Kconfig"
source "drivers/gpu/drm/arm/Kconfig"
source "drivers/gpu/drm/radeon/Kconfig"
@ -343,6 +274,8 @@ source "drivers/gpu/drm/amd/amdgpu/Kconfig"
source "drivers/gpu/drm/nouveau/Kconfig"
source "drivers/gpu/drm/nova/Kconfig"
source "drivers/gpu/drm/i915/Kconfig"
source "drivers/gpu/drm/xe/Kconfig"
@ -454,6 +387,8 @@ source "drivers/gpu/drm/xlnx/Kconfig"
source "drivers/gpu/drm/gud/Kconfig"
source "drivers/gpu/drm/sitronix/Kconfig"
source "drivers/gpu/drm/solomon/Kconfig"
source "drivers/gpu/drm/sprd/Kconfig"
@ -474,9 +409,6 @@ config DRM_HYPERV
If M is selected the module will be called hyperv_drm.
config DRM_EXPORT_FOR_TESTS
bool
# Separate option as not all DRM drivers use it
config DRM_PANEL_BACKLIGHT_QUIRKS
tristate
@ -489,31 +421,6 @@ config DRM_PRIVACY_SCREEN
bool
default n
config DRM_WERROR
bool "Compile the drm subsystem with warnings as errors"
depends on DRM && EXPERT
depends on !WERROR
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.
config DRM_HEADER_TEST
bool "Ensure DRM headers are self-contained and pass kernel-doc"
depends on DRM && EXPERT && BROKEN
default n
help
Ensure the DRM subsystem headers both under drivers/gpu/drm and
include/drm compile, are self-contained, have header guards, and have
no kernel-doc warnings.
If in doubt, say N.
endif
# Separate option because drm_panel_orientation_quirks.c is shared with fbdev

View file

@ -0,0 +1,116 @@
config DRM_USE_DYNAMIC_DEBUG
bool "use dynamic debug to implement drm.debug"
default n
depends on BROKEN
depends on DRM
depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
depends on JUMP_LABEL
help
Use dynamic-debug to avoid drm_debug_enabled() runtime overheads.
Due to callsite counts in DRM drivers (~4k in amdgpu) and 56
bytes per callsite, the .data costs can be substantial, and
are therefore configurable.
config DRM_WERROR
bool "Compile the drm subsystem with warnings as errors"
depends on DRM && EXPERT
depends on !WERROR
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.
config DRM_HEADER_TEST
bool "Ensure DRM headers are self-contained and pass kernel-doc"
depends on DRM && EXPERT && BROKEN
default n
help
Ensure the DRM subsystem headers both under drivers/gpu/drm and
include/drm compile, are self-contained, have header guards, and have
no kernel-doc warnings.
If in doubt, say N.
config DRM_DEBUG_MM
bool "Insert extra checks and debug info into the DRM range managers"
default n
depends on DRM
depends on STACKTRACE_SUPPORT
select STACKDEPOT
help
Enable allocation tracking of memory manager and leak detection on
shutdown.
Recommended for driver developers only.
If in doubt, say "N".
config DRM_KUNIT_TEST_HELPERS
tristate
depends on DRM && KUNIT
select DRM_KMS_HELPER
help
KUnit Helpers for KMS drivers.
config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
depends on DRM && KUNIT && MMU
select DRM_BRIDGE_CONNECTOR
select DRM_BUDDY
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDMI_STATE_HELPER
select DRM_DISPLAY_HELPER
select DRM_EXEC
select DRM_EXPORT_FOR_TESTS if m
select DRM_GEM_SHMEM_HELPER
select DRM_KUNIT_TEST_HELPERS
select DRM_LIB_RANDOM
select PRIME_NUMBERS
default KUNIT_ALL_TESTS
help
This builds unit tests for DRM. This option is not useful for
distributions or general kernels, but only for kernel
developers working on DRM and associated drivers.
For more information on KUnit and unit tests in general,
please refer to the KUnit documentation in
Documentation/dev-tools/kunit/.
If in doubt, say "N".
config DRM_TTM_KUNIT_TEST
tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
default n
depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST)
select DRM_TTM
select DRM_BUDDY
select DRM_EXPORT_FOR_TESTS if m
select DRM_KUNIT_TEST_HELPERS
default KUNIT_ALL_TESTS
help
Enables unit tests for TTM, a GPU memory manager subsystem used
to manage memory buffers. This option is mostly useful for kernel
developers. It depends on (UML || COMPILE_TEST) since no other driver
which uses TTM can be loaded while running the tests.
If in doubt, say "N".
config DRM_SCHED_KUNIT_TEST
tristate "KUnit tests for the DRM scheduler" if !KUNIT_ALL_TESTS
select DRM_SCHED
depends on DRM && KUNIT
default KUNIT_ALL_TESTS
help
Choose this option to build unit tests for the DRM scheduler.
Recommended for driver developers only.
If in doubt, say "N".
config DRM_EXPORT_FOR_TESTS
bool

View file

@ -134,6 +134,7 @@ obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
drm_kms_helper-y := \
drm_atomic_helper.o \
drm_atomic_state_helper.o \
drm_bridge_helper.o \
drm_crtc_helper.o \
drm_damage_helper.o \
drm_flip_work.o \
@ -176,6 +177,7 @@ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
obj-$(CONFIG_DRM_VGEM) += vgem/
obj-$(CONFIG_DRM_VKMS) += vkms/
obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
obj-$(CONFIG_DRM_NOVA) += nova/
obj-$(CONFIG_DRM_EXYNOS) +=exynos/
obj-$(CONFIG_DRM_ROCKCHIP) +=rockchip/
obj-$(CONFIG_DRM_GMA500) += gma500/
@ -204,6 +206,7 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
obj-y += hisilicon/
obj-y += mxsfb/
obj-y += sysfb/
obj-y += tiny/
obj-$(CONFIG_DRM_PL111) += pl111/
obj-$(CONFIG_DRM_TVE200) += tve200/
@ -219,6 +222,7 @@ obj-$(CONFIG_DRM_TIDSS) += tidss/
obj-y += xlnx/
obj-y += gud/
obj-$(CONFIG_DRM_HYPERV) += hyperv/
obj-y += sitronix/
obj-y += solomon/
obj-$(CONFIG_DRM_SPRD) += sprd/
obj-$(CONFIG_DRM_LOONGSON) += loongson/

View file

@ -212,12 +212,13 @@ static const struct mipi_dsi_host_ops adp_dsi_host_ops = {
};
static int adp_dsi_bridge_attach(struct drm_bridge *bridge,
struct drm_encoder *encoder,
enum drm_bridge_attach_flags flags)
{
struct adp_mipi_drv_private *adp =
container_of(bridge, struct adp_mipi_drv_private, bridge);
return drm_bridge_attach(bridge->encoder, adp->next_bridge, bridge, flags);
return drm_bridge_attach(encoder, adp->next_bridge, bridge, flags);
}
static const struct drm_bridge_funcs adp_dsi_bridge_funcs = {

View file

@ -66,7 +66,7 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.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_dev_coredump.o \
amdgpu_cper.o
amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o
amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
@ -174,7 +174,10 @@ amdgpu-y += \
amdgpu-y += \
amdgpu_mes.o \
mes_v11_0.o \
mes_v12_0.o
mes_v12_0.o \
# add GFX userqueue support
amdgpu-y += mes_userqueue.o
# add UVD block
amdgpu-y += \
@ -253,6 +256,8 @@ amdgpu-y += \
# add amdkfd interfaces
amdgpu-y += amdgpu_amdkfd.o
# add gfx usermode queue
amdgpu-y += amdgpu_userq.o
ifneq ($(CONFIG_HSA_AMD),)
AMDKFD_PATH := ../amdkfd

View file

@ -113,6 +113,8 @@
#include "amdgpu_xcp.h"
#include "amdgpu_seq64.h"
#include "amdgpu_reg_state.h"
#include "amdgpu_userq.h"
#include "amdgpu_eviction_fence.h"
#if defined(CONFIG_DRM_AMD_ISP)
#include "amdgpu_isp.h"
#endif
@ -228,7 +230,7 @@ extern int amdgpu_force_asic_type;
extern int amdgpu_smartshift_bias;
extern int amdgpu_use_xgmi_p2p;
extern int amdgpu_mtype_local;
extern bool enforce_isolation;
extern int amdgpu_enforce_isolation;
#ifdef CONFIG_HSA_AMD
extern int sched_policy;
extern bool debug_evictions;
@ -266,8 +268,10 @@ extern int amdgpu_umsch_mm_fwlog;
extern int amdgpu_user_partt_mode;
extern int amdgpu_agp;
extern int amdgpu_rebar;
extern int amdgpu_wbrf;
extern int amdgpu_user_queue;
#define AMDGPU_VM_MAX_NUM_CTX 4096
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
@ -488,7 +492,6 @@ struct amdgpu_flip_work {
bool async;
};
/*
* file private structure
*/
@ -501,6 +504,11 @@ struct amdgpu_fpriv {
struct mutex bo_list_lock;
struct idr bo_list_handles;
struct amdgpu_ctx_mgr ctx_mgr;
struct amdgpu_userq_mgr userq_mgr;
/* Eviction fence infra */
struct amdgpu_eviction_fence_mgr evf_mgr;
/** GPU partition selection */
uint32_t xcp_id;
};
@ -512,12 +520,62 @@ int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
*/
#define AMDGPU_MAX_WB 1024 /* Reserve at most 1024 WB slots for amdgpu-owned rings. */
/**
* amdgpu_wb - This struct is used for small GPU memory allocation.
*
* This struct is used to allocate a small amount of GPU memory that can be
* used to shadow certain states into the memory. This is especially useful for
* providing easy CPU access to some states without requiring register access
* (e.g., if some block is power gated, reading register may be problematic).
*
* Note: the term writeback was initially used because many of the amdgpu
* components had some level of writeback memory, and this struct initially
* described those components.
*/
struct amdgpu_wb {
/**
* @wb_obj:
*
* Buffer Object used for the writeback memory.
*/
struct amdgpu_bo *wb_obj;
/**
* @wb:
*
* Pointer to the first writeback slot. In terms of CPU address
* this value can be accessed directly by using the offset as an index.
* For the GPU address, it is necessary to use gpu_addr and the offset.
*/
volatile uint32_t *wb;
/**
* @gpu_addr:
*
* Writeback base address in the GPU.
*/
uint64_t gpu_addr;
u32 num_wb; /* Number of wb slots actually reserved for amdgpu. */
/**
* @num_wb:
*
* Number of writeback slots reserved for amdgpu.
*/
u32 num_wb;
/**
* @used:
*
* Track the writeback slot already used.
*/
unsigned long used[DIV_ROUND_UP(AMDGPU_MAX_WB, BITS_PER_LONG)];
/**
* @lock:
*
* Protects read and write of the used field array.
*/
spinlock_t lock;
};
@ -551,6 +609,7 @@ struct amdgpu_allowed_register_entry {
* are reset depends on the ASIC. Notably doesn't reset IPs
* shared with the CPU on APUs or the memory controllers (so
* VRAM is not lost). Not available on all ASICs.
* @AMD_RESET_LINK: Triggers SW-UP link reset on other GPUs
* @AMD_RESET_BACO: BACO (Bus Alive, Chip Off) method powers off and on the card
* but without powering off the PCI bus. Suitable only for
* discrete GPUs.
@ -568,6 +627,7 @@ enum amd_reset_method {
AMD_RESET_METHOD_MODE0,
AMD_RESET_METHOD_MODE1,
AMD_RESET_METHOD_MODE2,
AMD_RESET_METHOD_LINK,
AMD_RESET_METHOD_BACO,
AMD_RESET_METHOD_PCI,
AMD_RESET_METHOD_ON_INIT,
@ -821,6 +881,11 @@ struct amdgpu_mqd_prop {
uint32_t hqd_queue_priority;
bool allow_tunneling;
bool hqd_active;
uint64_t shadow_addr;
uint64_t gds_bkup_addr;
uint64_t csa_addr;
uint64_t fence_address;
bool tmz_queue;
};
struct amdgpu_mqd {
@ -829,6 +894,12 @@ struct amdgpu_mqd {
struct amdgpu_mqd_prop *p);
};
struct amdgpu_pcie_reset_ctx {
bool in_link_reset;
bool occurs_dpc;
bool audio_suspended;
};
/*
* Custom Init levels could be defined for different situations where a full
* initialization of all hardware blocks are not expected. Sample cases are
@ -853,6 +924,14 @@ struct amdgpu_init_level {
struct amdgpu_reset_domain;
struct amdgpu_fru_info;
enum amdgpu_enforce_isolation_mode {
AMDGPU_ENFORCE_ISOLATION_DISABLE = 0,
AMDGPU_ENFORCE_ISOLATION_ENABLE = 1,
AMDGPU_ENFORCE_ISOLATION_ENABLE_LEGACY = 2,
AMDGPU_ENFORCE_ISOLATION_NO_CLEANER_SHADER = 3,
};
/*
* Non-zero (true) if the GPU has VRAM. Zero (false) otherwise.
*/
@ -1081,6 +1160,13 @@ struct amdgpu_device {
bool enable_uni_mes;
struct amdgpu_mes mes;
struct amdgpu_mqd mqds[AMDGPU_HW_IP_NUM];
const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
/* xarray used to retrieve the user queue fence driver reference
* in the EOP interrupt handler to signal the particular user
* queue fence.
*/
struct xarray userq_xa;
/* df */
struct amdgpu_df df;
@ -1160,6 +1246,8 @@ struct amdgpu_device {
struct pci_saved_state *pci_state;
pci_channel_state_t pci_channel_state;
struct amdgpu_pcie_reset_ctx pcie_reset_ctx;
/* Track auto wait count on s_barrier settings */
bool barrier_has_auto_waitcnt;
@ -1193,10 +1281,11 @@ struct amdgpu_device {
bool debug_enable_ras_aca;
bool debug_exp_resets;
bool debug_disable_gpu_ring_reset;
bool debug_vm_userptr;
/* Protection for the following isolation structure */
struct mutex enforce_isolation_mutex;
bool enforce_isolation[MAX_XCP];
enum amdgpu_enforce_isolation_mode enforce_isolation[MAX_XCP];
struct amdgpu_isolation {
void *owner;
struct dma_fence *spearhead;
@ -1210,6 +1299,10 @@ struct amdgpu_device {
* in KFD: VRAM or GTT.
*/
bool apu_prefer_gtt;
struct list_head userq_mgr_list;
struct mutex userq_mutex;
bool userq_halt_for_enforce_isolation;
};
static inline uint32_t amdgpu_ip_version(const struct amdgpu_device *adev,
@ -1464,6 +1557,7 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
const u32 array_size);
int amdgpu_device_mode1_reset(struct amdgpu_device *adev);
int amdgpu_device_link_reset(struct amdgpu_device *adev);
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);

View file

@ -120,6 +120,9 @@ static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, st
for (i = 0; i < ARRAY_SIZE(aca_regs); i++)
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]);
if (ACA_REG__STATUS__SCRUB(bank->regs[ACA_REG_IDX_STATUS]))
RAS_EVENT_LOG(adev, event_id, HW_ERR "hardware error logged by the scrubber\n");
}
static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_smu_type type,

View file

@ -2559,6 +2559,18 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
if (ret != -EFAULT)
return ret;
/* If applications unmap memory before destroying the userptr
* from the KFD, trigger a segmentation fault in VM debug mode.
*/
if (amdgpu_ttm_adev(bo->tbo.bdev)->debug_vm_userptr) {
pr_err("Pid %d unmapped memory before destroying userptr at GPU addr 0x%llx\n",
pid_nr(process_info->pid), mem->va);
// Send GPU VM fault to user space
kfd_signal_vm_fault_event_with_userptr(kfd_lookup_process_by_pid(process_info->pid),
mem->va);
}
ret = 0;
}

View file

@ -281,6 +281,9 @@ static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,
case ATOM_DGPU_VRAM_TYPE_GDDR6:
vram_type = AMDGPU_VRAM_TYPE_GDDR6;
break;
case ATOM_DGPU_VRAM_TYPE_HBM3E:
vram_type = AMDGPU_VRAM_TYPE_HBM3E;
break;
default:
vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
break;

View file

@ -252,83 +252,22 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
if (!adev->pm.fw) {
switch (adev->asic_type) {
case CHIP_TAHITI:
strcpy(fw_name, "radeon/tahiti_smc.bin");
break;
case CHIP_PITCAIRN:
if ((adev->pdev->revision == 0x81) &&
((adev->pdev->device == 0x6810) ||
(adev->pdev->device == 0x6811))) {
info->is_kicker = true;
strcpy(fw_name, "radeon/pitcairn_k_smc.bin");
} else {
strcpy(fw_name, "radeon/pitcairn_smc.bin");
}
break;
case CHIP_VERDE:
if (((adev->pdev->device == 0x6820) &&
((adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0x83))) ||
((adev->pdev->device == 0x6821) &&
((adev->pdev->revision == 0x83) ||
(adev->pdev->revision == 0x87))) ||
((adev->pdev->revision == 0x87) &&
((adev->pdev->device == 0x6823) ||
(adev->pdev->device == 0x682b)))) {
info->is_kicker = true;
strcpy(fw_name, "radeon/verde_k_smc.bin");
} else {
strcpy(fw_name, "radeon/verde_smc.bin");
}
break;
case CHIP_OLAND:
if (((adev->pdev->revision == 0x81) &&
((adev->pdev->device == 0x6600) ||
(adev->pdev->device == 0x6604) ||
(adev->pdev->device == 0x6605) ||
(adev->pdev->device == 0x6610))) ||
((adev->pdev->revision == 0x83) &&
(adev->pdev->device == 0x6610))) {
info->is_kicker = true;
strcpy(fw_name, "radeon/oland_k_smc.bin");
} else {
strcpy(fw_name, "radeon/oland_smc.bin");
}
break;
case CHIP_HAINAN:
if (((adev->pdev->revision == 0x81) &&
(adev->pdev->device == 0x6660)) ||
((adev->pdev->revision == 0x83) &&
((adev->pdev->device == 0x6660) ||
(adev->pdev->device == 0x6663) ||
(adev->pdev->device == 0x6665) ||
(adev->pdev->device == 0x6667)))) {
info->is_kicker = true;
strcpy(fw_name, "radeon/hainan_k_smc.bin");
} else if ((adev->pdev->revision == 0xc3) &&
(adev->pdev->device == 0x6665)) {
info->is_kicker = true;
strcpy(fw_name, "radeon/banks_k_2_smc.bin");
} else {
strcpy(fw_name, "radeon/hainan_smc.bin");
}
break;
case CHIP_BONAIRE:
if ((adev->pdev->revision == 0x80) ||
(adev->pdev->revision == 0x81) ||
(adev->pdev->device == 0x665f)) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/bonaire_k_smc.bin");
strscpy(fw_name, "amdgpu/bonaire_k_smc.bin");
} else {
strcpy(fw_name, "amdgpu/bonaire_smc.bin");
strscpy(fw_name, "amdgpu/bonaire_smc.bin");
}
break;
case CHIP_HAWAII:
if (adev->pdev->revision == 0x80) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/hawaii_k_smc.bin");
strscpy(fw_name, "amdgpu/hawaii_k_smc.bin");
} else {
strcpy(fw_name, "amdgpu/hawaii_smc.bin");
strscpy(fw_name, "amdgpu/hawaii_smc.bin");
}
break;
case CHIP_TOPAZ:
@ -338,76 +277,76 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/topaz_k_smc.bin");
strscpy(fw_name, "amdgpu/topaz_k_smc.bin");
} else
strcpy(fw_name, "amdgpu/topaz_smc.bin");
strscpy(fw_name, "amdgpu/topaz_smc.bin");
break;
case CHIP_TONGA:
if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/tonga_k_smc.bin");
strscpy(fw_name, "amdgpu/tonga_k_smc.bin");
} else
strcpy(fw_name, "amdgpu/tonga_smc.bin");
strscpy(fw_name, "amdgpu/tonga_smc.bin");
break;
case CHIP_FIJI:
strcpy(fw_name, "amdgpu/fiji_smc.bin");
strscpy(fw_name, "amdgpu/fiji_smc.bin");
break;
case CHIP_POLARIS11:
if (type == CGS_UCODE_ID_SMU) {
if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
strscpy(fw_name, "amdgpu/polaris11_k_smc.bin");
} else if (ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
strscpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
} else {
strcpy(fw_name, "amdgpu/polaris11_smc.bin");
strscpy(fw_name, "amdgpu/polaris11_smc.bin");
}
} else if (type == CGS_UCODE_ID_SMU_SK) {
strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
strscpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
}
break;
case CHIP_POLARIS10:
if (type == CGS_UCODE_ID_SMU) {
if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
strscpy(fw_name, "amdgpu/polaris10_k_smc.bin");
} else if (ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
strscpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
} else {
strcpy(fw_name, "amdgpu/polaris10_smc.bin");
strscpy(fw_name, "amdgpu/polaris10_smc.bin");
}
} else if (type == CGS_UCODE_ID_SMU_SK) {
strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
strscpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
}
break;
case CHIP_POLARIS12:
if (ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) {
info->is_kicker = true;
strcpy(fw_name, "amdgpu/polaris12_k_smc.bin");
strscpy(fw_name, "amdgpu/polaris12_k_smc.bin");
} else {
strcpy(fw_name, "amdgpu/polaris12_smc.bin");
strscpy(fw_name, "amdgpu/polaris12_smc.bin");
}
break;
case CHIP_VEGAM:
strcpy(fw_name, "amdgpu/vegam_smc.bin");
strscpy(fw_name, "amdgpu/vegam_smc.bin");
break;
case CHIP_VEGA10:
if ((adev->pdev->device == 0x687f) &&
((adev->pdev->revision == 0xc0) ||
(adev->pdev->revision == 0xc1) ||
(adev->pdev->revision == 0xc3)))
strcpy(fw_name, "amdgpu/vega10_acg_smc.bin");
strscpy(fw_name, "amdgpu/vega10_acg_smc.bin");
else
strcpy(fw_name, "amdgpu/vega10_smc.bin");
strscpy(fw_name, "amdgpu/vega10_smc.bin");
break;
case CHIP_VEGA12:
strcpy(fw_name, "amdgpu/vega12_smc.bin");
strscpy(fw_name, "amdgpu/vega12_smc.bin");
break;
case CHIP_VEGA20:
strcpy(fw_name, "amdgpu/vega20_smc.bin");
strscpy(fw_name, "amdgpu/vega20_smc.bin");
break;
default:
DRM_ERROR("SMC firmware not supported\n");

View file

@ -549,7 +549,7 @@ int amdgpu_cper_init(struct amdgpu_device *adev)
{
int r;
if (!amdgpu_aca_is_enabled(adev))
if (!amdgpu_aca_is_enabled(adev) && !amdgpu_sriov_ras_cper_en(adev))
return 0;
r = amdgpu_cper_ring_init(adev);
@ -568,7 +568,7 @@ int amdgpu_cper_init(struct amdgpu_device *adev)
int amdgpu_cper_fini(struct amdgpu_device *adev)
{
if (!amdgpu_aca_is_enabled(adev))
if (!amdgpu_aca_is_enabled(adev) && !amdgpu_sriov_ras_cper_en(adev))
return 0;
adev->cper.enabled = false;

View file

@ -296,7 +296,25 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
num_ibs[i], &p->jobs[i]);
if (ret)
goto free_all_kdata;
p->jobs[i]->enforce_isolation = p->adev->enforce_isolation[fpriv->xcp_id];
switch (p->adev->enforce_isolation[fpriv->xcp_id]) {
case AMDGPU_ENFORCE_ISOLATION_DISABLE:
default:
p->jobs[i]->enforce_isolation = false;
p->jobs[i]->run_cleaner_shader = false;
break;
case AMDGPU_ENFORCE_ISOLATION_ENABLE:
p->jobs[i]->enforce_isolation = true;
p->jobs[i]->run_cleaner_shader = true;
break;
case AMDGPU_ENFORCE_ISOLATION_ENABLE_LEGACY:
p->jobs[i]->enforce_isolation = true;
p->jobs[i]->run_cleaner_shader = false;
break;
case AMDGPU_ENFORCE_ISOLATION_NO_CLEANER_SHADER:
p->jobs[i]->enforce_isolation = true;
p->jobs[i]->run_cleaner_shader = false;
break;
}
}
p->gang_leader = p->jobs[p->gang_leader_idx];
@ -349,6 +367,10 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p,
ring = amdgpu_job_ring(job);
ib = &job->ibs[job->num_ibs++];
/* submissions to kernel queues are disabled */
if (ring->no_user_submission)
return -EINVAL;
/* MM engine doesn't support user fences */
if (p->uf_bo && ring->funcs->no_user_fence)
return -EINVAL;

View file

@ -2105,6 +2105,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
amdgpu_rap_debugfs_init(adev);
amdgpu_securedisplay_debugfs_init(adev);
amdgpu_fw_attestation_debugfs_init(adev);
amdgpu_psp_debugfs_init(adev);
debugfs_create_file("amdgpu_evict_vram", 0400, root, adev,
&amdgpu_evict_vram_fops);

View file

@ -85,6 +85,7 @@
#if IS_ENABLED(CONFIG_X86)
#include <asm/intel-family.h>
#include <asm/cpu_device_id.h>
#endif
MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
@ -1680,6 +1681,9 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
if (amdgpu_sriov_vf(adev))
return 0;
if (!amdgpu_rebar)
return 0;
/* resizing on Dell G5 SE platforms causes problems with runtime pm */
if ((amdgpu_runtime_pm != 0) &&
adev->pdev->vendor == PCI_VENDOR_ID_ATI &&
@ -1870,6 +1874,35 @@ static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device
return true;
}
static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
{
#if IS_ENABLED(CONFIG_X86)
struct cpuinfo_x86 *c = &cpu_data(0);
if (!(amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 0) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 1)))
return false;
if (c->x86 == 6 &&
adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5) {
switch (c->x86_model) {
case VFM_MODEL(INTEL_ALDERLAKE):
case VFM_MODEL(INTEL_ALDERLAKE_L):
case VFM_MODEL(INTEL_RAPTORLAKE):
case VFM_MODEL(INTEL_RAPTORLAKE_P):
case VFM_MODEL(INTEL_RAPTORLAKE_S):
return true;
default:
return false;
}
} else {
return false;
}
#else
return false;
#endif
}
/**
* amdgpu_device_should_use_aspm - check if the device should program ASPM
*
@ -1894,7 +1927,7 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
}
if (adev->flags & AMD_IS_APU)
return false;
if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK))
if (amdgpu_device_aspm_support_quirk(adev))
return false;
return pcie_aspm_enabled(adev->pdev);
}
@ -2112,8 +2145,31 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
for (i = 0; i < MAX_XCP; i++)
adev->enforce_isolation[i] = !!enforce_isolation;
for (i = 0; i < MAX_XCP; i++) {
switch (amdgpu_enforce_isolation) {
case -1:
case 0:
default:
/* disable */
adev->enforce_isolation[i] = AMDGPU_ENFORCE_ISOLATION_DISABLE;
break;
case 1:
/* enable */
adev->enforce_isolation[i] =
AMDGPU_ENFORCE_ISOLATION_ENABLE;
break;
case 2:
/* enable legacy mode */
adev->enforce_isolation[i] =
AMDGPU_ENFORCE_ISOLATION_ENABLE_LEGACY;
break;
case 3:
/* enable only process isolation without submitting cleaner shader */
adev->enforce_isolation[i] =
AMDGPU_ENFORCE_ISOLATION_NO_CLEANER_SHADER;
break;
}
}
return 0;
}
@ -2689,6 +2745,13 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
break;
}
/* Check for IP version 9.4.3 with A0 hardware */
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) &&
!amdgpu_device_get_rev_id(adev)) {
dev_err(adev->dev, "Unsupported A0 hardware\n");
return -ENODEV; /* device unsupported - no device error */
}
if (amdgpu_has_atpx() &&
(amdgpu_is_atpx_hybrid() ||
amdgpu_has_atpx_dgpu_power_cntl()) &&
@ -2701,7 +2764,6 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
}
adev->pm.pp_feature = amdgpu_pp_feature_mask;
if (amdgpu_sriov_vf(adev) || sched_policy == KFD_SCHED_POLICY_NO_HWS)
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
@ -3172,6 +3234,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
* always assumed to be lost.
*/
switch (amdgpu_asic_reset_method(adev)) {
case AMD_RESET_METHOD_LINK:
case AMD_RESET_METHOD_BACO:
case AMD_RESET_METHOD_MODE1:
return true;
@ -3455,6 +3518,7 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
amdgpu_amdkfd_suspend(adev, false);
amdgpu_userq_suspend(adev);
/* Workaround for ASICs need to disable SMC first */
amdgpu_device_smu_fini_early(adev);
@ -4307,9 +4371,10 @@ int amdgpu_device_init(struct amdgpu_device *adev,
amdgpu_sync_create(&adev->isolation[i].active);
amdgpu_sync_create(&adev->isolation[i].prev);
}
mutex_init(&adev->gfx.kfd_sch_mutex);
mutex_init(&adev->gfx.userq_sch_mutex);
mutex_init(&adev->gfx.workload_profile_mutex);
mutex_init(&adev->vcn.workload_profile_mutex);
mutex_init(&adev->userq_mutex);
amdgpu_device_init_apu_flags(adev);
@ -4329,12 +4394,16 @@ int amdgpu_device_init(struct amdgpu_device *adev,
spin_lock_init(&adev->virt.rlcg_reg_lock);
spin_lock_init(&adev->wb.lock);
xa_init_flags(&adev->userq_xa, XA_FLAGS_LOCK_IRQ);
INIT_LIST_HEAD(&adev->reset_list);
INIT_LIST_HEAD(&adev->ras_list);
INIT_LIST_HEAD(&adev->pm.od_kobj_list);
INIT_LIST_HEAD(&adev->userq_mgr_list);
INIT_DELAYED_WORK(&adev->delayed_init_work,
amdgpu_device_delayed_init_work_handler);
INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
@ -5003,8 +5072,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients)
amdgpu_device_ip_suspend_phase1(adev);
if (!adev->in_s0ix)
if (!adev->in_s0ix) {
amdgpu_amdkfd_suspend(adev, adev->in_runpm);
amdgpu_userq_suspend(adev);
}
r = amdgpu_device_evict_resources(adev);
if (r)
@ -5071,6 +5142,10 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
if (r)
goto exit;
r = amdgpu_userq_resume(adev);
if (r)
goto exit;
}
r = amdgpu_device_ip_late_init(adev);
@ -5119,9 +5194,6 @@ exit:
}
adev->in_suspend = false;
if (adev->enable_mes)
amdgpu_mes_self_test(adev);
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))
DRM_WARN("smart shift update failed\n");
@ -5502,6 +5574,29 @@ mode1_reset_failed:
return ret;
}
int amdgpu_device_link_reset(struct amdgpu_device *adev)
{
int ret = 0;
dev_info(adev->dev, "GPU link reset\n");
if (!adev->pcie_reset_ctx.occurs_dpc)
ret = amdgpu_dpm_link_reset(adev);
if (ret)
goto link_reset_failed;
ret = amdgpu_psp_wait_for_bootloader(adev);
if (ret)
goto link_reset_failed;
return 0;
link_reset_failed:
dev_err(adev->dev, "GPU link reset failed\n");
return ret;
}
int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
struct amdgpu_reset_context *reset_context)
{
@ -5806,6 +5901,7 @@ static void amdgpu_device_set_mp1_state(struct amdgpu_device *adev)
switch (amdgpu_asic_reset_method(adev)) {
case AMD_RESET_METHOD_MODE1:
case AMD_RESET_METHOD_LINK:
adev->mp1_state = PP_MP1_STATE_SHUTDOWN;
break;
case AMD_RESET_METHOD_MODE2:
@ -5922,94 +6018,42 @@ static int amdgpu_device_health_check(struct list_head *device_list_handle)
return ret;
}
/**
* amdgpu_device_gpu_recover - reset the asic and recover scheduler
*
* @adev: amdgpu_device pointer
* @job: which job trigger hang
* @reset_context: amdgpu reset context pointer
*
* Attempt to reset the GPU if it has hung (all asics).
* Attempt to do soft-reset or full-reset and reinitialize Asic
* Returns 0 for success or an error on failure.
*/
int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
static int amdgpu_device_halt_activities(struct amdgpu_device *adev,
struct amdgpu_job *job,
struct amdgpu_reset_context *reset_context)
struct amdgpu_reset_context *reset_context,
struct list_head *device_list,
struct amdgpu_hive_info *hive,
bool need_emergency_restart)
{
struct list_head device_list, *device_list_handle = NULL;
bool job_signaled = false;
struct amdgpu_hive_info *hive = NULL;
struct list_head *device_list_handle = NULL;
struct amdgpu_device *tmp_adev = NULL;
int i, r = 0;
bool need_emergency_restart = false;
bool audio_suspended = false;
int retry_limit = AMDGPU_MAX_RETRY_LIMIT;
/*
* If it reaches here because of hang/timeout and a RAS error is
* detected at the same time, let RAS recovery take care of it.
*/
if (amdgpu_ras_is_err_state(adev, AMDGPU_RAS_BLOCK__ANY) &&
!amdgpu_sriov_vf(adev) &&
reset_context->src != AMDGPU_RESET_SRC_RAS) {
dev_dbg(adev->dev,
"Gpu recovery from source: %d yielding to RAS error recovery handling",
reset_context->src);
return 0;
}
/*
* Special case: RAS triggered and full reset isn't supported
*/
need_emergency_restart = amdgpu_ras_need_emergency_restart(adev);
/*
* Flush RAM to disk so that after reboot
* the user can read log and see why the system rebooted.
*/
if (need_emergency_restart && amdgpu_ras_get_context(adev) &&
amdgpu_ras_get_context(adev)->reboot) {
DRM_WARN("Emergency reboot.");
ksys_sync_helper();
emergency_restart();
}
dev_info(adev->dev, "GPU %s begin!\n",
need_emergency_restart ? "jobs stop":"reset");
if (!amdgpu_sriov_vf(adev))
hive = amdgpu_get_xgmi_hive(adev);
if (hive)
mutex_lock(&hive->hive_lock);
reset_context->job = job;
reset_context->hive = hive;
/*
* Build list of devices to reset.
* In case we are in XGMI hive mode, resort the device list
* to put adev in the 1st position.
*/
INIT_LIST_HEAD(&device_list);
if (!amdgpu_sriov_vf(adev) && (adev->gmc.xgmi.num_physical_nodes > 1) && hive) {
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
list_add_tail(&tmp_adev->reset_list, &device_list);
list_add_tail(&tmp_adev->reset_list, device_list);
if (adev->shutdown)
tmp_adev->shutdown = true;
if (adev->pcie_reset_ctx.occurs_dpc)
tmp_adev->pcie_reset_ctx.in_link_reset = true;
}
if (!list_is_first(&adev->reset_list, &device_list))
list_rotate_to_front(&adev->reset_list, &device_list);
device_list_handle = &device_list;
if (!list_is_first(&adev->reset_list, device_list))
list_rotate_to_front(&adev->reset_list, device_list);
device_list_handle = device_list;
} else {
list_add_tail(&adev->reset_list, &device_list);
device_list_handle = &device_list;
list_add_tail(&adev->reset_list, device_list);
device_list_handle = device_list;
}
if (!amdgpu_sriov_vf(adev)) {
if (!amdgpu_sriov_vf(adev) && (!adev->pcie_reset_ctx.occurs_dpc)) {
r = amdgpu_device_health_check(device_list_handle);
if (r)
goto end_reset;
return r;
}
/* We need to lock reset domain only once both for XGMI and single device */
@ -6033,7 +6077,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
* some audio codec errors.
*/
if (!amdgpu_device_suspend_display_audio(tmp_adev))
audio_suspended = true;
tmp_adev->pcie_reset_ctx.audio_suspended = true;
amdgpu_ras_set_error_query_ready(tmp_adev, false);
@ -6051,6 +6095,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
/* disable ras on ALL IPs */
if (!need_emergency_restart &&
(!adev->pcie_reset_ctx.occurs_dpc) &&
amdgpu_device_ip_need_full_reset(tmp_adev))
amdgpu_ras_suspend(tmp_adev);
@ -6068,24 +6113,24 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
atomic_inc(&tmp_adev->gpu_reset_counter);
}
if (need_emergency_restart)
goto skip_sched_resume;
return r;
}
/*
* Must check guilty signal here since after this point all old
* HW fences are force signaled.
*
* job->base holds a reference to parent fence
*/
if (job && dma_fence_is_signaled(&job->hw_fence)) {
job_signaled = true;
dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
goto skip_hw_reset;
}
static int amdgpu_device_asic_reset(struct amdgpu_device *adev,
struct list_head *device_list,
struct amdgpu_reset_context *reset_context)
{
struct amdgpu_device *tmp_adev = NULL;
int retry_limit = AMDGPU_MAX_RETRY_LIMIT;
int r = 0;
retry: /* Rest of adevs pre asic reset from XGMI hive. */
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
list_for_each_entry(tmp_adev, device_list, reset_list) {
if (adev->pcie_reset_ctx.occurs_dpc)
tmp_adev->no_hw_access = true;
r = amdgpu_device_pre_asic_reset(tmp_adev, reset_context);
if (adev->pcie_reset_ctx.occurs_dpc)
tmp_adev->no_hw_access = false;
/*TODO Should we stop ?*/
if (r) {
dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ",
@ -6097,6 +6142,11 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
/* Actual ASIC resets if needed.*/
/* Host driver will handle XGMI hive reset for SRIOV */
if (amdgpu_sriov_vf(adev)) {
/* Bail out of reset early */
if (amdgpu_ras_is_rma(adev))
return -ENODEV;
if (amdgpu_ras_get_fed_status(adev) || amdgpu_virt_rcvd_ras_interrupt(adev)) {
dev_dbg(adev->dev, "Detected RAS error, wait for FLR completion\n");
amdgpu_ras_set_fed(adev, true);
@ -6111,12 +6161,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
if (r)
adev->asic_reset_res = r;
} else {
r = amdgpu_do_asic_reset(device_list_handle, reset_context);
r = amdgpu_do_asic_reset(device_list, reset_context);
if (r && r == -EAGAIN)
goto retry;
}
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
list_for_each_entry(tmp_adev, device_list, reset_list) {
/*
* Drop any pending non scheduler resets queued before reset is done.
* Any reset scheduled after this point would be valid. Scheduler resets
@ -6126,10 +6176,18 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
amdgpu_device_stop_pending_resets(tmp_adev);
}
skip_hw_reset:
return r;
}
static int amdgpu_device_sched_resume(struct list_head *device_list,
struct amdgpu_reset_context *reset_context,
bool job_signaled)
{
struct amdgpu_device *tmp_adev = NULL;
int i, r = 0;
/* Post ASIC reset for all devs .*/
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
list_for_each_entry(tmp_adev, device_list, reset_list) {
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = tmp_adev->rings[i];
@ -6165,8 +6223,16 @@ skip_hw_reset:
}
}
skip_sched_resume:
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
return r;
}
static void amdgpu_device_gpu_resume(struct amdgpu_device *adev,
struct list_head *device_list,
bool need_emergency_restart)
{
struct amdgpu_device *tmp_adev = NULL;
list_for_each_entry(tmp_adev, device_list, reset_list) {
/* unlock kfd: SRIOV would do it separately */
if (!need_emergency_restart && !amdgpu_sriov_vf(tmp_adev))
amdgpu_amdkfd_post_reset(tmp_adev);
@ -6177,18 +6243,114 @@ skip_sched_resume:
if (!adev->kfd.init_complete)
amdgpu_amdkfd_device_init(adev);
if (audio_suspended)
if (tmp_adev->pcie_reset_ctx.audio_suspended)
amdgpu_device_resume_display_audio(tmp_adev);
amdgpu_device_unset_mp1_state(tmp_adev);
amdgpu_ras_set_error_query_ready(tmp_adev, true);
}
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
tmp_adev = list_first_entry(device_list, struct amdgpu_device,
reset_list);
amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
}
/**
* amdgpu_device_gpu_recover - reset the asic and recover scheduler
*
* @adev: amdgpu_device pointer
* @job: which job trigger hang
* @reset_context: amdgpu reset context pointer
*
* Attempt to reset the GPU if it has hung (all asics).
* Attempt to do soft-reset or full-reset and reinitialize Asic
* Returns 0 for success or an error on failure.
*/
int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
struct amdgpu_job *job,
struct amdgpu_reset_context *reset_context)
{
struct list_head device_list;
bool job_signaled = false;
struct amdgpu_hive_info *hive = NULL;
int r = 0;
bool need_emergency_restart = false;
/*
* If it reaches here because of hang/timeout and a RAS error is
* detected at the same time, let RAS recovery take care of it.
*/
if (amdgpu_ras_is_err_state(adev, AMDGPU_RAS_BLOCK__ANY) &&
!amdgpu_sriov_vf(adev) &&
reset_context->src != AMDGPU_RESET_SRC_RAS) {
dev_dbg(adev->dev,
"Gpu recovery from source: %d yielding to RAS error recovery handling",
reset_context->src);
return 0;
}
/*
* Special case: RAS triggered and full reset isn't supported
*/
need_emergency_restart = amdgpu_ras_need_emergency_restart(adev);
/*
* Flush RAM to disk so that after reboot
* the user can read log and see why the system rebooted.
*/
if (need_emergency_restart && amdgpu_ras_get_context(adev) &&
amdgpu_ras_get_context(adev)->reboot) {
DRM_WARN("Emergency reboot.");
ksys_sync_helper();
emergency_restart();
}
dev_info(adev->dev, "GPU %s begin!\n",
need_emergency_restart ? "jobs stop":"reset");
if (!amdgpu_sriov_vf(adev))
hive = amdgpu_get_xgmi_hive(adev);
if (hive)
mutex_lock(&hive->hive_lock);
reset_context->job = job;
reset_context->hive = hive;
INIT_LIST_HEAD(&device_list);
r = amdgpu_device_halt_activities(adev, job, reset_context, &device_list,
hive, need_emergency_restart);
if (r)
goto end_reset;
if (need_emergency_restart)
goto skip_sched_resume;
/*
* Must check guilty signal here since after this point all old
* HW fences are force signaled.
*
* job->base holds a reference to parent fence
*/
if (job && dma_fence_is_signaled(&job->hw_fence)) {
job_signaled = true;
dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
goto skip_hw_reset;
}
r = amdgpu_device_asic_reset(adev, &device_list, reset_context);
if (r)
goto end_reset;
skip_hw_reset:
r = amdgpu_device_sched_resume(&device_list, reset_context, job_signaled);
if (r)
goto end_reset;
skip_sched_resume:
amdgpu_device_gpu_resume(adev, &device_list, need_emergency_restart);
end_reset:
if (hive) {
mutex_unlock(&hive->hive_lock);
@ -6572,12 +6734,15 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
int i;
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
struct amdgpu_reset_context reset_context;
struct list_head device_list;
int r = 0;
DRM_INFO("PCI error: detected callback, state(%d)!!\n", state);
dev_info(adev->dev, "PCI error: detected callback!!\n");
if (adev->gmc.xgmi.num_physical_nodes > 1) {
DRM_WARN("No support for XGMI hive yet...");
if (!amdgpu_dpm_is_link_reset_supported(adev)) {
dev_warn(adev->dev, "No support for XGMI hive yet...\n");
return PCI_ERS_RESULT_DISCONNECT;
}
@ -6585,32 +6750,30 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
switch (state) {
case pci_channel_io_normal:
dev_info(adev->dev, "pci_channel_io_normal: state(%d)!!\n", state);
return PCI_ERS_RESULT_CAN_RECOVER;
/* Fatal error, prepare for slot reset */
case pci_channel_io_frozen:
/*
* Locking adev->reset_domain->sem will prevent any external access
* to GPU during PCI error recovery
*/
amdgpu_device_lock_reset_domain(adev->reset_domain);
amdgpu_device_set_mp1_state(adev);
/* Fatal error, prepare for slot reset */
dev_info(adev->dev, "pci_channel_io_frozen: state(%d)!!\n", state);
/*
* Block any work scheduling as we do for regular GPU reset
* for the duration of the recovery
*/
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
if (hive)
mutex_lock(&hive->hive_lock);
adev->pcie_reset_ctx.occurs_dpc = true;
memset(&reset_context, 0, sizeof(reset_context));
INIT_LIST_HEAD(&device_list);
if (!amdgpu_ring_sched_ready(ring))
continue;
drm_sched_stop(&ring->sched, NULL);
r = amdgpu_device_halt_activities(adev, NULL, &reset_context, &device_list,
hive, false);
if (hive) {
mutex_unlock(&hive->hive_lock);
amdgpu_put_xgmi_hive(hive);
}
atomic_inc(&adev->gpu_reset_counter);
if (r)
return PCI_ERS_RESULT_DISCONNECT;
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
/* Permanent error, prepare for device removal */
dev_info(adev->dev, "pci_channel_io_perm_failure: state(%d)!!\n", state);
return PCI_ERS_RESULT_DISCONNECT;
}
@ -6623,8 +6786,10 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
*/
pci_ers_result_t amdgpu_pci_mmio_enabled(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
DRM_INFO("PCI error: mmio enabled callback!!\n");
dev_info(adev->dev, "PCI error: mmio enabled callback!!\n");
/* TODO - dump whatever for debugging purposes */
@ -6648,10 +6813,12 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
int r, i;
struct amdgpu_reset_context reset_context;
u32 memsize;
struct amdgpu_device *tmp_adev;
struct amdgpu_hive_info *hive;
struct list_head device_list;
int r = 0, i;
u32 memsize;
/* PCI error slot reset should be skipped During RAS recovery */
if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
@ -6659,15 +6826,12 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
amdgpu_ras_in_recovery(adev))
return PCI_ERS_RESULT_RECOVERED;
DRM_INFO("PCI error: slot reset callback!!\n");
dev_info(adev->dev, "PCI error: slot reset callback!!\n");
memset(&reset_context, 0, sizeof(reset_context));
INIT_LIST_HEAD(&device_list);
list_add_tail(&adev->reset_list, &device_list);
/* wait for asic to come out of reset */
msleep(500);
msleep(700);
/* Restore PCI confspace */
amdgpu_device_load_pci_state(pdev);
@ -6688,26 +6852,40 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
reset_context.method = AMD_RESET_METHOD_NONE;
reset_context.reset_req_dev = adev;
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
INIT_LIST_HEAD(&device_list);
adev->no_hw_access = true;
r = amdgpu_device_pre_asic_reset(adev, &reset_context);
adev->no_hw_access = false;
if (r)
goto out;
r = amdgpu_do_asic_reset(&device_list, &reset_context);
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
mutex_lock(&hive->hive_lock);
reset_context.hive = hive;
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
tmp_adev->pcie_reset_ctx.in_link_reset = true;
list_add_tail(&tmp_adev->reset_list, &device_list);
}
} else {
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
list_add_tail(&adev->reset_list, &device_list);
}
r = amdgpu_device_asic_reset(adev, &device_list, &reset_context);
out:
if (!r) {
if (amdgpu_device_cache_pci_state(adev->pdev))
pci_restore_state(adev->pdev);
DRM_INFO("PCIe error recovery succeeded\n");
dev_info(adev->dev, "PCIe error recovery succeeded\n");
} else {
DRM_ERROR("PCIe error recovery failed, err:%d", r);
amdgpu_device_unset_mp1_state(adev);
amdgpu_device_unlock_reset_domain(adev->reset_domain);
dev_err(adev->dev, "PCIe error recovery failed, err:%d\n", r);
if (hive) {
list_for_each_entry(tmp_adev, &device_list, reset_list)
amdgpu_device_unset_mp1_state(tmp_adev);
amdgpu_device_unlock_reset_domain(adev->reset_domain);
}
}
if (hive) {
mutex_unlock(&hive->hive_lock);
amdgpu_put_xgmi_hive(hive);
}
return r ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
@ -6724,26 +6902,36 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
int i;
struct list_head device_list;
struct amdgpu_hive_info *hive = NULL;
struct amdgpu_device *tmp_adev = NULL;
DRM_INFO("PCI error: resume callback!!\n");
dev_info(adev->dev, "PCI error: resume callback!!\n");
/* Only continue execution for the case of pci_channel_io_frozen */
if (adev->pci_channel_state != pci_channel_io_frozen)
return;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
INIT_LIST_HEAD(&device_list);
if (!amdgpu_ring_sched_ready(ring))
continue;
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
mutex_lock(&hive->hive_lock);
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
tmp_adev->pcie_reset_ctx.in_link_reset = false;
list_add_tail(&tmp_adev->reset_list, &device_list);
}
} else
list_add_tail(&adev->reset_list, &device_list);
drm_sched_start(&ring->sched, 0);
amdgpu_device_sched_resume(&device_list, NULL, NULL);
amdgpu_device_gpu_resume(adev, &device_list, false);
adev->pcie_reset_ctx.occurs_dpc = false;
if (hive) {
mutex_unlock(&hive->hive_lock);
amdgpu_put_xgmi_hive(hive);
}
amdgpu_device_unset_mp1_state(adev);
amdgpu_device_unlock_reset_domain(adev->reset_domain);
}
bool amdgpu_device_cache_pci_state(struct pci_dev *pdev)

View file

@ -51,6 +51,8 @@
#include "amdgpu_reset.h"
#include "amdgpu_sched.h"
#include "amdgpu_xgmi.h"
#include "amdgpu_userq.h"
#include "amdgpu_userq_fence.h"
#include "../amdxcp/amdgpu_xcp_drv.h"
/*
@ -123,9 +125,10 @@
* - 3.61.0 - Contains fix for RV/PCO compute queues
* - 3.62.0 - Add AMDGPU_IDS_FLAGS_MODE_PF, AMDGPU_IDS_FLAGS_MODE_VF & AMDGPU_IDS_FLAGS_MODE_PT
* - 3.63.0 - GFX12 display DCC supports 256B max compressed block size
* - 3.64.0 - Userq IP support query
*/
#define KMS_DRIVER_MAJOR 3
#define KMS_DRIVER_MINOR 63
#define KMS_DRIVER_MINOR 64
#define KMS_DRIVER_PATCHLEVEL 0
/*
@ -140,6 +143,7 @@ enum AMDGPU_DEBUG_MASK {
AMDGPU_DEBUG_ENABLE_EXP_RESETS = BIT(5),
AMDGPU_DEBUG_DISABLE_GPU_RING_RESET = BIT(6),
AMDGPU_DEBUG_SMU_POOL = BIT(7),
AMDGPU_DEBUG_VM_USERPTR = BIT(8),
};
unsigned int amdgpu_vram_limit = UINT_MAX;
@ -176,7 +180,7 @@ uint amdgpu_pg_mask = 0xffffffff;
uint amdgpu_sdma_phase_quantum = 32;
char *amdgpu_disable_cu;
char *amdgpu_virtual_display;
bool enforce_isolation;
int amdgpu_enforce_isolation = -1;
int amdgpu_modeset = -1;
/* Specifies the default granularity for SVM, used in buffer
@ -238,6 +242,8 @@ int amdgpu_agp = -1; /* auto */
int amdgpu_wbrf = -1;
int amdgpu_damage_clips = -1; /* auto */
int amdgpu_umsch_mm_fwlog;
int amdgpu_rebar = -1; /* auto */
int amdgpu_user_queue = -1;
DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
"DRM_UT_CORE",
@ -1033,11 +1039,13 @@ module_param_named(user_partt_mode, amdgpu_user_partt_mode, uint, 0444);
/**
* DOC: enforce_isolation (bool)
* enforce process isolation between graphics and compute via using the same reserved vmid.
* DOC: enforce_isolation (int)
* enforce process isolation between graphics and compute.
* (-1 = auto, 0 = disable, 1 = enable, 2 = enable legacy mode, 3 = enable without cleaner shader)
*/
module_param(enforce_isolation, bool, 0444);
MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between graphics and compute . enforce_isolation = on");
module_param_named(enforce_isolation, amdgpu_enforce_isolation, int, 0444);
MODULE_PARM_DESC(enforce_isolation,
"enforce process isolation between graphics and compute. (-1 = auto, 0 = disable, 1 = enable, 2 = enable legacy mode, 3 = enable without cleaner shader)");
/**
* DOC: modeset (int)
@ -1096,6 +1104,28 @@ MODULE_PARM_DESC(wbrf,
"Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 = auto(default)");
module_param_named(wbrf, amdgpu_wbrf, int, 0444);
/**
* DOC: rebar (int)
* Allow BAR resizing. Disable this to prevent the driver from attempting
* to resize the BAR if the GPU supports it and there is available MMIO space.
* Note that this just prevents the driver from resizing the BAR. The BIOS
* may have already resized the BAR at boot time.
*/
MODULE_PARM_DESC(rebar, "Resizable BAR (-1 = auto (default), 0 = disable, 1 = enable)");
module_param_named(rebar, amdgpu_rebar, int, 0444);
/**
* DOC: user_queue (int)
* Enable user queues on systems that support user queues. Possible values:
*
* - -1 = auto (ASIC specific default)
* - 0 = user queues disabled
* - 1 = user queues enabled and kernel queues enabled (if supported)
* - 2 = user queues enabled and kernel queues disabled
*/
MODULE_PARM_DESC(user_queue, "Enable user queues (-1 = auto (default), 0 = disable, 1 = enable, 2 = enable UQs and disable KQs)");
module_param_named(user_queue, amdgpu_user_queue, int, 0444);
/* These devices are not supported by amdgpu.
* They are supported by the mach64, r128, radeon drivers
*/
@ -2244,6 +2274,10 @@ static void amdgpu_init_debug_options(struct amdgpu_device *adev)
pr_info("debug: use vram for smu pool\n");
adev->pm.smu_debug_mask |= SMU_DEBUG_POOL_USE_VRAM;
}
if (amdgpu_debug_mask & AMDGPU_DEBUG_VM_USERPTR) {
pr_info("debug: VM mode debug for userptr is enabled\n");
adev->debug_vm_userptr = true;
}
}
static unsigned long amdgpu_fix_asic_type(struct pci_dev *pdev, unsigned long flags)
@ -2700,6 +2734,29 @@ static int amdgpu_runtime_idle_check_display(struct device *dev)
return 0;
}
static int amdgpu_runtime_idle_check_userq(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
struct amdgpu_usermode_queue *queue;
struct amdgpu_userq_mgr *uqm, *tmp;
int queue_id;
int ret = 0;
mutex_lock(&adev->userq_mutex);
list_for_each_entry_safe(uqm, tmp, &adev->userq_mgr_list, list) {
idr_for_each_entry(&uqm->userq_idr, queue, queue_id) {
ret = -EBUSY;
goto done;
}
}
done:
mutex_unlock(&adev->userq_mutex);
return ret;
}
static int amdgpu_pmops_runtime_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@ -2713,6 +2770,9 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
}
ret = amdgpu_runtime_idle_check_display(dev);
if (ret)
return ret;
ret = amdgpu_runtime_idle_check_userq(dev);
if (ret)
return ret;
@ -2836,12 +2896,30 @@ static int amdgpu_pmops_runtime_idle(struct device *dev)
}
ret = amdgpu_runtime_idle_check_display(dev);
if (ret)
goto done;
ret = amdgpu_runtime_idle_check_userq(dev);
done:
pm_runtime_mark_last_busy(dev);
pm_runtime_autosuspend(dev);
return ret;
}
static int amdgpu_drm_release(struct inode *inode, struct file *filp)
{
struct drm_file *file_priv = filp->private_data;
struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
if (fpriv) {
fpriv->evf_mgr.fd_closing = true;
amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
amdgpu_eviction_fence_destroy(&fpriv->evf_mgr);
}
return drm_release(inode, filp);
}
long amdgpu_drm_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
@ -2893,7 +2971,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.flush = amdgpu_flush,
.release = drm_release,
.release = amdgpu_drm_release,
.unlocked_ioctl = amdgpu_drm_ioctl,
.mmap = drm_gem_mmap,
.poll = drm_poll,
@ -2940,6 +3018,9 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_USERQ, amdgpu_userq_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_SIGNAL, amdgpu_userq_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_WAIT, amdgpu_userq_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
};
static const struct drm_driver amdgpu_kms_driver = {
@ -3030,6 +3111,10 @@ static int __init amdgpu_init(void)
if (r)
goto error_fence;
r = amdgpu_userq_fence_slab_init();
if (r)
goto error_fence;
DRM_INFO("amdgpu kernel modesetting enabled.\n");
amdgpu_register_atpx_handler();
amdgpu_acpi_detect();
@ -3061,6 +3146,7 @@ static void __exit amdgpu_exit(void)
amdgpu_acpi_release();
amdgpu_sync_fini();
amdgpu_fence_slab_fini();
amdgpu_userq_fence_slab_fini();
mmu_notifier_synchronize();
amdgpu_xcp_drv_release();
}

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