summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-05-15 12:10:39 +1000
committerDave Airlie <airlied@redhat.com>2026-05-15 12:14:25 +1000
commit15342d4aebcb4c02c37a62c9222ac5056eab6faf (patch)
tree0d2d34c1e860c86bfc652621b34d5ce20c9ec795
parente53bf933163f88eb31762052e63c5bec50c35afb (diff)
parent4c26e162947f91aa78ba57dd4fddd38fc80e7d60 (diff)
Merge tag 'drm-misc-next-2026-05-14' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v7.2-rc1: UAPI Changes: - Update fourcc descriptions of BG(R) floating formats. - Add deferred mapping support to virtio. Cross-subsystem Changes: - Update lontium lt9211 bindings. Core Changes: - Bugfixes and cleanups to pagemap, dp/mst. - Add lockdep annotations to gpu buddy manager. - Updates to drm/dp for PR + VRR. - Improve documentation's table of contents. - Bump fpfn and lpfn in ttm to 64-bits. Driver Changes: - Assorted bugfixes, cleanups and updates to panthor, nouveau, qaic, hisilicon. - Add support for CMN N116BCN-EA1, CMN N140HCA-EEK, IVO M140NWFQ R5, IVO R140NWFW R0, BOE NT140*, BOE NV133FHM-N4F, AUO B140*, AUO B133HAN06.6 and AUO B116XTN02.3 eDP panels. - More implementation of AIE4 in amdxdna. - Update panels to use refcounts instead of devm_kzalloc to make drm_panel_init static. - Add support for the RCade Display Adapter to gud. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patch.msgid.link/98788814-e462-4950-bb2a-ea493c30d0c0@linux.intel.com
-rw-r--r--Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml43
-rw-r--r--Documentation/gpu/driver-uapi.rst2
-rw-r--r--Documentation/gpu/drm-internals.rst2
-rw-r--r--Documentation/gpu/drm-kms-helpers.rst2
-rw-r--r--Documentation/gpu/drm-kms.rst2
-rw-r--r--Documentation/gpu/drm-mm.rst2
-rw-r--r--Documentation/gpu/drm-ras.rst2
-rw-r--r--Documentation/gpu/drm-uapi.rst4
-rw-r--r--Documentation/gpu/drm-usage-stats.rst2
-rw-r--r--Documentation/gpu/index.rst1
-rw-r--r--Documentation/gpu/introduction.rst2
-rw-r--r--Documentation/gpu/rfc/index.rst26
-rw-r--r--drivers/accel/amdxdna/Makefile1
-rw-r--r--drivers/accel/amdxdna/aie.c48
-rw-r--r--drivers/accel/amdxdna/aie.h9
-rw-r--r--drivers/accel/amdxdna/aie2_ctx.c4
-rw-r--r--drivers/accel/amdxdna/aie2_error.c7
-rw-r--r--drivers/accel/amdxdna/aie2_message.c65
-rw-r--r--drivers/accel/amdxdna/aie2_pci.c54
-rw-r--r--drivers/accel/amdxdna/aie2_pci.h36
-rw-r--r--drivers/accel/amdxdna/aie4_ctx.c333
-rw-r--r--drivers/accel/amdxdna/aie4_host_queue.h24
-rw-r--r--drivers/accel/amdxdna/aie4_message.c56
-rw-r--r--drivers/accel/amdxdna/aie4_msg_priv.h98
-rw-r--r--drivers/accel/amdxdna/aie4_pci.c310
-rw-r--r--drivers/accel/amdxdna/aie4_pci.h38
-rw-r--r--drivers/accel/amdxdna/amdxdna_ctx.c40
-rw-r--r--drivers/accel/amdxdna/amdxdna_ctx.h7
-rw-r--r--drivers/accel/amdxdna/amdxdna_gem.c5
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.c25
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.h4
-rw-r--r--drivers/accel/amdxdna/npu3_regs.c25
-rw-r--r--drivers/accel/qaic/qaic.h4
-rw-r--r--drivers/accel/qaic/qaic_drv.c8
-rw-r--r--drivers/gpu/buddy.c11
-rw-r--r--drivers/gpu/drm/display/drm_dp_helper.c71
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c9
-rw-r--r--drivers/gpu/drm/drm_buddy.c1
-rw-r--r--drivers/gpu/drm/drm_gpusvm.c5
-rw-r--r--drivers/gpu/drm/drm_pagemap.c5
-rw-r--r--drivers/gpu/drm/drm_panel.c7
-rw-r--r--drivers/gpu/drm/gud/gud_drv.c1
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h1
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h1
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c2
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c80
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c35
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c14
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h1
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c75
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/crc.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c3
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c16
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c10
-rw-r--r--drivers/gpu/drm/panel/panel-lxd-m9189a.c11
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt37700f.c11
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0.c14
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c11
-rw-r--r--drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c12
-rw-r--r--drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c14
-rw-r--r--drivers/gpu/drm/panel/panel-truly-nt35597.c10
-rw-r--r--drivers/gpu/drm/panel/panel-visionox-g2647fb105.c13
-rw-r--r--drivers/gpu/drm/panthor/panthor_mmu.c16
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ioctl.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vram.c30
-rw-r--r--drivers/gpu/drm/xe/xe_ttm_vram_mgr.c1
-rw-r--r--include/drm/display/drm_dp.h20
-rw-r--r--include/drm/display/drm_dp_helper.h1
-rw-r--r--include/drm/drm_panel.h4
-rw-r--r--include/drm/ttm/ttm_placement.h4
-rw-r--r--include/linux/gpu_buddy.h41
-rw-r--r--include/uapi/drm/amdxdna_accel.h24
-rw-r--r--include/uapi/drm/drm_fourcc.h6
-rw-r--r--include/uapi/drm/virtgpu_drm.h4
77 files changed, 1458 insertions, 439 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml
index 9a6e9b25d14a..7cfe92a8bcd7 100644
--- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml
@@ -36,18 +36,56 @@ properties:
properties:
port@0:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
description:
Primary MIPI DSI port-1 for MIPI input or
LVDS port-1 for LVDS input or DPI input.
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description: array of physical DSI data lane indexes.
+ minItems: 1
+ items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ required:
+ - data-lanes
+
port@1:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
description:
Additional MIPI port-2 for MIPI input or LVDS port-2
for LVDS input. Used in combination with primary
port-1 to drive higher resolution displays
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description: array of physical DSI data lane indexes.
+ minItems: 1
+ items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ required:
+ - data-lanes
+
port@2:
$ref: /schemas/graph.yaml#/properties/port
description:
@@ -99,6 +137,7 @@ examples:
reg = <0>;
endpoint {
+ data-lanes = <1 2 3 4>;
remote-endpoint = <&dsi0_out>;
};
};
diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst
index 1f15a8ca1265..627fc68c7a21 100644
--- a/Documentation/gpu/driver-uapi.rst
+++ b/Documentation/gpu/driver-uapi.rst
@@ -2,6 +2,8 @@
DRM Driver uAPI
===============
+.. contents::
+
drm/i915 uAPI
=============
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index 94f93fd3b8a0..a3ce25a36f1d 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -18,6 +18,8 @@ event handling, memory management, output management, framebuffer
management, command submission & fencing, suspend/resume support, and
DMA services.
+.. contents::
+
Driver Initialization
=====================
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index b4a9e5ae81f6..80453dda33b8 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -33,6 +33,8 @@ There are a few areas these helpers can grouped into:
pipeline: Planes, handling rectangles for visibility checking and scissoring,
flip queues and assorted bits.
+.. contents::
+
Modeset Helper Reference for Common Vtables
===========================================
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index fbe0583eb84c..d22817fdf9aa 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -15,6 +15,8 @@ be setup by initializing the following fields.
- struct drm_mode_config_funcs \*funcs;
Mode setting functions.
+.. contents::
+
Overview
========
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index 32fb506db05b..2dea94f77d52 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -25,6 +25,8 @@ share it. GEM has simpler initialization and execution requirements than
TTM, but has no video RAM management capabilities and is thus limited to
UMA devices.
+.. contents::
+
The Translation Table Manager (TTM)
===================================
diff --git a/Documentation/gpu/drm-ras.rst b/Documentation/gpu/drm-ras.rst
index 4636e68f5678..83c21853b74b 100644
--- a/Documentation/gpu/drm-ras.rst
+++ b/Documentation/gpu/drm-ras.rst
@@ -24,6 +24,8 @@ Key Goals:
nodes for different IP blocks, sub-blocks, or other logical subdivisions
as applicable.
+.. contents::
+
Nodes
=====
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 32206ce62931..2c2f939322fb 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -16,6 +16,8 @@ management, and output management.
Cover generic ioctls and sysfs layout here. We only need high-level
info, since man pages should cover the rest.
+.. contents::
+
libdrm Device Lookup
====================
@@ -765,4 +767,4 @@ Stable uAPI events
From ``drivers/gpu/drm/scheduler/gpu_scheduler_trace.h``
.. kernel-doc:: drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
- :doc: uAPI trace events \ No newline at end of file
+ :doc: uAPI trace events
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index 24d3012ca7a6..70b7cfcc194f 100644
--- a/Documentation/gpu/drm-usage-stats.rst
+++ b/Documentation/gpu/drm-usage-stats.rst
@@ -16,6 +16,8 @@ output is split between common and driver specific parts. Having said that,
wherever possible effort should still be made to standardise as much as
possible.
+.. contents::
+
File format specification
=========================
diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
index 5d708a106b3f..65bf3b26e4f4 100644
--- a/Documentation/gpu/index.rst
+++ b/Documentation/gpu/index.rst
@@ -3,6 +3,7 @@ GPU Driver Developer's Guide
============================
.. toctree::
+ :maxdepth: 2
introduction
drm-internals
diff --git a/Documentation/gpu/introduction.rst b/Documentation/gpu/introduction.rst
index d8f519693fc2..64074ac22d9b 100644
--- a/Documentation/gpu/introduction.rst
+++ b/Documentation/gpu/introduction.rst
@@ -16,6 +16,8 @@ found in current kernels.
[Insert diagram of typical DRM stack here]
+.. contents::
+
Style Guidelines
================
diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.rst
index ef19b0ba2a3e..26a7ebe6fb44 100644
--- a/Documentation/gpu/rfc/index.rst
+++ b/Documentation/gpu/rfc/index.rst
@@ -18,23 +18,9 @@ host such documentation:
.. toctree::
- gpusvm.rst
-
-.. toctree::
-
- i915_gem_lmem.rst
-
-.. toctree::
-
- i915_scheduler.rst
-
-.. toctree::
-
- i915_small_bar.rst
-
-.. toctree::
-
- i915_vm_bind.rst
-
-.. toctree::
- color_pipeline.rst \ No newline at end of file
+ gpusvm
+ i915_gem_lmem
+ i915_scheduler
+ i915_small_bar
+ i915_vm_bind
+ color_pipeline
diff --git a/drivers/accel/amdxdna/Makefile b/drivers/accel/amdxdna/Makefile
index d7720c8c8a98..05cce0a38692 100644
--- a/drivers/accel/amdxdna/Makefile
+++ b/drivers/accel/amdxdna/Makefile
@@ -10,6 +10,7 @@ amdxdna-y := \
aie2_pci.o \
aie2_pm.o \
aie2_solver.o \
+ aie4_ctx.o \
aie4_message.o \
aie4_pci.o \
amdxdna_cbuf.o \
diff --git a/drivers/accel/amdxdna/aie.c b/drivers/accel/amdxdna/aie.c
index 66849ba9026a..dd6f36f222c7 100644
--- a/drivers/accel/amdxdna/aie.c
+++ b/drivers/accel/amdxdna/aie.c
@@ -117,3 +117,51 @@ void amdxdna_vbnv_init(struct amdxdna_dev *xdna)
amdxdna_update_vbnv(xdna, info->rev_vbnv_tbl, rev);
}
+
+int amdxdna_get_metadata(struct aie_device *aie,
+ struct amdxdna_client *client,
+ struct amdxdna_drm_get_info *args)
+{
+ int ret = 0;
+ u32 buf_sz;
+
+ buf_sz = min(args->buffer_size, sizeof(aie->metadata));
+ if (copy_to_user(u64_to_user_ptr(args->buffer), &aie->metadata, buf_sz))
+ ret = -EFAULT;
+
+ return ret;
+}
+
+void *amdxdna_alloc_msg_buffer(struct amdxdna_dev *xdna, u32 *size,
+ dma_addr_t *dma_addr)
+{
+ void *vaddr;
+ int order;
+
+ *size = max_t(u32, *size, SZ_8K);
+ order = get_order(*size);
+ if (order > MAX_PAGE_ORDER)
+ return ERR_PTR(-EINVAL);
+ *size = PAGE_SIZE << order;
+
+ if (amdxdna_iova_on(xdna))
+ return amdxdna_iommu_alloc(xdna, *size, dma_addr);
+
+ vaddr = dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr,
+ DMA_FROM_DEVICE, GFP_KERNEL);
+ if (!vaddr)
+ return ERR_PTR(-ENOMEM);
+
+ return vaddr;
+}
+
+void amdxdna_free_msg_buffer(struct amdxdna_dev *xdna, size_t size,
+ void *cpu_addr, dma_addr_t dma_addr)
+{
+ if (amdxdna_iova_on(xdna)) {
+ amdxdna_iommu_free(xdna, size, cpu_addr, dma_addr);
+ return;
+ }
+
+ dma_free_noncoherent(xdna->ddev.dev, size, cpu_addr, dma_addr, DMA_FROM_DEVICE);
+}
diff --git a/drivers/accel/amdxdna/aie.h b/drivers/accel/amdxdna/aie.h
index 7a68b114f235..0483d582b7f8 100644
--- a/drivers/accel/amdxdna/aie.h
+++ b/drivers/accel/amdxdna/aie.h
@@ -5,6 +5,7 @@
#ifndef _AIE_H_
#define _AIE_H_
+#include <drm/amdxdna_accel.h>
#include "amdxdna_pci_drv.h"
#include "amdxdna_mailbox.h"
@@ -26,6 +27,8 @@ struct aie_device {
struct psp_device *psp_hdl;
struct smu_device *smu_hdl;
+
+ struct amdxdna_drm_query_aie_metadata metadata;
};
#define DECLARE_AIE_MSG(name, op) \
@@ -94,6 +97,12 @@ void aie_destroy_chann(struct aie_device *aie, struct mailbox_channel **chann);
int aie_send_mgmt_msg_wait(struct aie_device *aie, struct xdna_mailbox_msg *msg);
int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor);
void amdxdna_vbnv_init(struct amdxdna_dev *xdna);
+int amdxdna_get_metadata(struct aie_device *aie, struct amdxdna_client *client,
+ struct amdxdna_drm_get_info *args);
+void *amdxdna_alloc_msg_buffer(struct amdxdna_dev *xdna, u32 *size,
+ dma_addr_t *dma_addr);
+void amdxdna_free_msg_buffer(struct amdxdna_dev *xdna, size_t size,
+ void *cpu_addr, dma_addr_t dma_addr);
/* aie_psp.c */
struct psp_device *aiem_psp_create(struct drm_device *ddev, struct psp_config *conf);
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 139825ac8515..7d6094aefb6f 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -489,12 +489,12 @@ static int aie2_hwctx_col_list(struct amdxdna_hwctx *hwctx)
}
ndev = xdna->dev_handle;
- if (unlikely(!ndev->metadata.core.row_count)) {
+ if (unlikely(!ndev->aie.metadata.core.row_count)) {
XDNA_WARN(xdna, "Core tile row count is zero");
return -EINVAL;
}
- hwctx->num_col = hwctx->num_tiles / ndev->metadata.core.row_count;
+ hwctx->num_col = hwctx->num_tiles / ndev->aie.metadata.core.row_count;
if (!hwctx->num_col || hwctx->num_col > ndev->total_col) {
XDNA_ERR(xdna, "Invalid num_col %d", hwctx->num_col);
return -EINVAL;
diff --git a/drivers/accel/amdxdna/aie2_error.c b/drivers/accel/amdxdna/aie2_error.c
index 70007b4363cd..babdac0157ab 100644
--- a/drivers/accel/amdxdna/aie2_error.c
+++ b/drivers/accel/amdxdna/aie2_error.c
@@ -11,6 +11,7 @@
#include <linux/kthread.h>
#include <linux/kernel.h>
+#include "aie.h"
#include "aie2_msg_priv.h"
#include "aie2_pci.h"
#include "amdxdna_error.h"
@@ -338,7 +339,7 @@ void aie2_error_async_events_free(struct amdxdna_dev_hdl *ndev)
destroy_workqueue(events->wq);
mutex_lock(&xdna->dev_lock);
- aie2_free_msg_buffer(ndev, events->size, events->buf, events->addr);
+ amdxdna_free_msg_buffer(xdna, events->size, events->buf, events->addr);
kfree(events);
}
@@ -354,7 +355,7 @@ int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev)
if (!events)
return -ENOMEM;
- events->buf = aie2_alloc_msg_buffer(ndev, &total_size, &events->addr);
+ events->buf = amdxdna_alloc_msg_buffer(xdna, &total_size, &events->addr);
if (IS_ERR(events->buf)) {
ret = PTR_ERR(events->buf);
goto free_events;
@@ -394,7 +395,7 @@ int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev)
free_wq:
destroy_workqueue(events->wq);
free_buf:
- aie2_free_msg_buffer(ndev, events->size, events->buf, events->addr);
+ amdxdna_free_msg_buffer(xdna, events->size, events->buf, events->addr);
free_events:
kfree(events);
return ret;
diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c
index 6e98af7b74db..1504295a21e4 100644
--- a/drivers/accel/amdxdna/aie2_message.c
+++ b/drivers/accel/amdxdna/aie2_message.c
@@ -27,43 +27,6 @@
#define EXEC_MSG_OPS(xdna) ((xdna)->dev_handle->exec_msg_ops)
-void *aie2_alloc_msg_buffer(struct amdxdna_dev_hdl *ndev, u32 *size,
- dma_addr_t *dma_addr)
-{
- struct amdxdna_dev *xdna = ndev->aie.xdna;
- void *vaddr;
- int order;
-
- *size = max(*size, SZ_8K);
- order = get_order(*size);
- if (order > MAX_PAGE_ORDER)
- return ERR_PTR(-EINVAL);
- *size = PAGE_SIZE << order;
-
- if (amdxdna_iova_on(xdna))
- return amdxdna_iommu_alloc(xdna, *size, dma_addr);
-
- vaddr = dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr,
- DMA_FROM_DEVICE, GFP_KERNEL);
- if (!vaddr)
- return ERR_PTR(-ENOMEM);
-
- return vaddr;
-}
-
-void aie2_free_msg_buffer(struct amdxdna_dev_hdl *ndev, size_t size,
- void *cpu_addr, dma_addr_t dma_addr)
-{
- struct amdxdna_dev *xdna = ndev->aie.xdna;
-
- if (amdxdna_iova_on(xdna)) {
- amdxdna_iommu_free(xdna, size, cpu_addr, dma_addr);
- return;
- }
-
- dma_free_noncoherent(xdna->ddev.dev, size, cpu_addr, dma_addr, DMA_FROM_DEVICE);
-}
-
int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev)
{
DECLARE_AIE_MSG(suspend, MSG_OP_SUSPEND);
@@ -127,7 +90,8 @@ int aie2_assign_mgmt_pasid(struct amdxdna_dev_hdl *ndev, u16 pasid)
return aie_send_mgmt_msg_wait(&ndev->aie, &msg);
}
-int aie2_query_aie_version(struct amdxdna_dev_hdl *ndev, struct aie_version *version)
+int aie2_query_aie_version(struct amdxdna_dev_hdl *ndev,
+ struct amdxdna_drm_query_aie_version *version)
{
DECLARE_AIE_MSG(aie_version_info, MSG_OP_QUERY_AIE_VERSION);
struct amdxdna_dev *xdna = ndev->aie.xdna;
@@ -146,7 +110,8 @@ int aie2_query_aie_version(struct amdxdna_dev_hdl *ndev, struct aie_version *ver
return 0;
}
-int aie2_query_aie_metadata(struct amdxdna_dev_hdl *ndev, struct aie_metadata *metadata)
+int aie2_query_aie_metadata(struct amdxdna_dev_hdl *ndev,
+ struct amdxdna_drm_query_aie_metadata *metadata)
{
DECLARE_AIE_MSG(aie_tile_info, MSG_OP_QUERY_AIE_TILE_INFO);
int ret;
@@ -155,7 +120,7 @@ int aie2_query_aie_metadata(struct amdxdna_dev_hdl *ndev, struct aie_metadata *m
if (ret)
return ret;
- metadata->size = resp.info.size;
+ metadata->col_size = resp.info.size;
metadata->cols = resp.info.cols;
metadata->rows = resp.info.rows;
@@ -375,8 +340,8 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
u8 *buff_addr;
int ret;
- buf_sz = ndev->metadata.cols * ndev->metadata.size;
- buff_addr = aie2_alloc_msg_buffer(ndev, &buf_sz, &dma_addr);
+ buf_sz = ndev->aie.metadata.cols * ndev->aie.metadata.col_size;
+ buff_addr = amdxdna_alloc_msg_buffer(xdna, &buf_sz, &dma_addr);
if (IS_ERR(buff_addr))
return PTR_ERR(buff_addr);
@@ -390,7 +355,7 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
req.num_cols = hweight32(aie_bitmap);
req.aie_bitmap = aie_bitmap;
- drm_clflush_virt_range(buff_addr, size); /* device can access */
+ drm_clflush_virt_range(buff_addr, req.dump_buff_size); /* device can access */
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret) {
XDNA_ERR(xdna, "Error during NPU query, status %d", ret);
@@ -415,7 +380,7 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
*cols_filled = aie_bitmap;
fail:
- aie2_free_msg_buffer(ndev, buf_sz, buff_addr, dma_addr);
+ amdxdna_free_msg_buffer(xdna, buf_sz, buff_addr, dma_addr);
return ret;
}
@@ -434,7 +399,7 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev,
return -EINVAL;
buf_sz = min(size, SZ_4M);
- addr = aie2_alloc_msg_buffer(ndev, &buf_sz, &dma_addr);
+ addr = amdxdna_alloc_msg_buffer(xdna, &buf_sz, &dma_addr);
if (IS_ERR(addr))
return PTR_ERR(addr);
@@ -442,7 +407,7 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev,
req.buf_size = buf_sz;
req.type = header->type;
- drm_clflush_virt_range(addr, size); /* device can access */
+ drm_clflush_virt_range(addr, req.buf_size); /* device can access */
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret) {
XDNA_ERR(xdna, "Query telemetry failed, status %d", ret);
@@ -466,7 +431,7 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev,
header->minor = resp.minor;
free_buf:
- aie2_free_msg_buffer(ndev, buf_sz, addr, dma_addr);
+ amdxdna_free_msg_buffer(xdna, buf_sz, addr, dma_addr);
return ret;
}
@@ -1176,7 +1141,7 @@ int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
}
buf_size = sizeof(*report);
- buf = aie2_alloc_msg_buffer(ndev, &buf_size, &dma_addr);
+ buf = amdxdna_alloc_msg_buffer(xdna, &buf_size, &dma_addr);
if (IS_ERR(buf)) {
XDNA_ERR(xdna, "Failed to allocate buffer for app health");
return PTR_ERR(buf);
@@ -1186,7 +1151,7 @@ int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
req.context_id = context_id;
req.buf_size = buf_size;
- drm_clflush_virt_range(buf, sizeof(*report));
+ drm_clflush_virt_range(buf, req.buf_size);
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret) {
XDNA_ERR(xdna, "Get app health failed, ret %d status 0x%x", ret, resp.status);
@@ -1197,7 +1162,7 @@ int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
memcpy(report, buf, sizeof(*report));
free_buf:
- aie2_free_msg_buffer(ndev, buf_size, buf, dma_addr);
+ amdxdna_free_msg_buffer(xdna, buf_size, buf, dma_addr);
return ret;
}
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index f0ddb843eb21..6c8a0f70b73d 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -219,13 +219,13 @@ static int aie2_mgmt_fw_query(struct amdxdna_dev_hdl *ndev)
return ret;
}
- ret = aie2_query_aie_metadata(ndev, &ndev->metadata);
+ ret = aie2_query_aie_metadata(ndev, &ndev->aie.metadata);
if (ret) {
XDNA_ERR(ndev->aie.xdna, "Query AIE metadata failed");
return ret;
}
- ndev->total_col = min(aie2_max_col, ndev->metadata.cols);
+ ndev->total_col = min(aie2_max_col, ndev->aie.metadata.cols);
return 0;
}
@@ -658,53 +658,6 @@ static int aie2_get_aie_status(struct amdxdna_client *client,
return 0;
}
-static int aie2_get_aie_metadata(struct amdxdna_client *client,
- struct amdxdna_drm_get_info *args)
-{
- struct amdxdna_drm_query_aie_metadata *meta;
- struct amdxdna_dev *xdna = client->xdna;
- struct amdxdna_dev_hdl *ndev;
- int ret = 0;
- u32 buf_sz;
-
- ndev = xdna->dev_handle;
- meta = kzalloc_obj(*meta);
- if (!meta)
- return -ENOMEM;
-
- meta->col_size = ndev->metadata.size;
- meta->cols = ndev->metadata.cols;
- meta->rows = ndev->metadata.rows;
-
- meta->version.major = ndev->metadata.version.major;
- meta->version.minor = ndev->metadata.version.minor;
-
- meta->core.row_count = ndev->metadata.core.row_count;
- meta->core.row_start = ndev->metadata.core.row_start;
- meta->core.dma_channel_count = ndev->metadata.core.dma_channel_count;
- meta->core.lock_count = ndev->metadata.core.lock_count;
- meta->core.event_reg_count = ndev->metadata.core.event_reg_count;
-
- meta->mem.row_count = ndev->metadata.mem.row_count;
- meta->mem.row_start = ndev->metadata.mem.row_start;
- meta->mem.dma_channel_count = ndev->metadata.mem.dma_channel_count;
- meta->mem.lock_count = ndev->metadata.mem.lock_count;
- meta->mem.event_reg_count = ndev->metadata.mem.event_reg_count;
-
- meta->shim.row_count = ndev->metadata.shim.row_count;
- meta->shim.row_start = ndev->metadata.shim.row_start;
- meta->shim.dma_channel_count = ndev->metadata.shim.dma_channel_count;
- meta->shim.lock_count = ndev->metadata.shim.lock_count;
- meta->shim.event_reg_count = ndev->metadata.shim.event_reg_count;
-
- buf_sz = min(args->buffer_size, sizeof(*meta));
- if (copy_to_user(u64_to_user_ptr(args->buffer), meta, buf_sz))
- ret = -EFAULT;
-
- kfree(meta);
- return ret;
-}
-
static int aie2_get_aie_version(struct amdxdna_client *client,
struct amdxdna_drm_get_info *args)
{
@@ -1039,6 +992,7 @@ static int aie2_get_preempt_state(struct amdxdna_client *client,
static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_info *args)
{
struct amdxdna_dev *xdna = client->xdna;
+ struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
int ret, idx;
if (!drm_dev_enter(&xdna->ddev, &idx))
@@ -1053,7 +1007,7 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
ret = aie2_get_aie_status(client, args);
break;
case DRM_AMDXDNA_QUERY_AIE_METADATA:
- ret = aie2_get_aie_metadata(client, args);
+ ret = amdxdna_get_metadata(&ndev->aie, client, args);
break;
case DRM_AMDXDNA_QUERY_AIE_VERSION:
ret = aie2_get_aie_version(client, args);
diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h
index f12073175676..84bdb3f8b8f9 100644
--- a/drivers/accel/amdxdna/aie2_pci.h
+++ b/drivers/accel/amdxdna/aie2_pci.h
@@ -77,29 +77,6 @@ struct amdxdna_fw_ver;
struct amdxdna_hwctx;
struct amdxdna_sched_job;
-struct aie_version {
- u16 major;
- u16 minor;
-};
-
-struct aie_tile_metadata {
- u16 row_count;
- u16 row_start;
- u16 dma_channel_count;
- u16 lock_count;
- u16 event_reg_count;
-};
-
-struct aie_metadata {
- u32 size;
- u16 cols;
- u16 rows;
- struct aie_version version;
- struct aie_tile_metadata core;
- struct aie_tile_metadata mem;
- struct aie_tile_metadata shim;
-};
-
enum rt_config_category {
AIE2_RT_CFG_INIT,
AIE2_RT_CFG_CLK_GATING,
@@ -177,8 +154,7 @@ struct amdxdna_dev_hdl {
void __iomem *mbox_base;
u32 total_col;
- struct aie_version version;
- struct aie_metadata metadata;
+ struct amdxdna_drm_query_aie_version version;
struct aie2_exec_msg_ops *exec_msg_ops;
/* power management and clock*/
@@ -283,8 +259,10 @@ int aie2_resume_fw(struct amdxdna_dev_hdl *ndev);
int aie2_set_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 value);
int aie2_get_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 *value);
int aie2_assign_mgmt_pasid(struct amdxdna_dev_hdl *ndev, u16 pasid);
-int aie2_query_aie_version(struct amdxdna_dev_hdl *ndev, struct aie_version *version);
-int aie2_query_aie_metadata(struct amdxdna_dev_hdl *ndev, struct aie_metadata *metadata);
+int aie2_query_aie_version(struct amdxdna_dev_hdl *ndev,
+ struct amdxdna_drm_query_aie_version *version);
+int aie2_query_aie_metadata(struct amdxdna_dev_hdl *ndev,
+ struct amdxdna_drm_query_aie_metadata *metadata);
int aie2_query_firmware_version(struct amdxdna_dev_hdl *ndev,
struct amdxdna_fw_ver *fw_ver);
int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
@@ -314,10 +292,6 @@ int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
int aie2_config_debug_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
int (*notify_cb)(void *, void __iomem *, size_t));
int aie2_update_prop_time_quota(struct amdxdna_dev_hdl *ndev, u32 us);
-void *aie2_alloc_msg_buffer(struct amdxdna_dev_hdl *ndev, u32 *size,
- dma_addr_t *dma_addr);
-void aie2_free_msg_buffer(struct amdxdna_dev_hdl *ndev, size_t size,
- void *cpu_addr, dma_addr_t dma_addr);
/* aie2_hwctx.c */
int aie2_hwctx_init(struct amdxdna_hwctx *hwctx);
diff --git a/drivers/accel/amdxdna/aie4_ctx.c b/drivers/accel/amdxdna/aie4_ctx.c
new file mode 100644
index 000000000000..8408b0d2696f
--- /dev/null
+++ b/drivers/accel/amdxdna/aie4_ctx.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026, Advanced Micro Devices, Inc.
+ */
+
+#include <drm/amdxdna_accel.h>
+#include <drm/drm_device.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_print.h>
+#include <drm/gpu_scheduler.h>
+#include <linux/types.h>
+
+#include "aie.h"
+#include "aie4_host_queue.h"
+#include "aie4_msg_priv.h"
+#include "aie4_pci.h"
+#include "amdxdna_ctx.h"
+#include "amdxdna_gem.h"
+#include "amdxdna_mailbox.h"
+#include "amdxdna_mailbox_helper.h"
+#include "amdxdna_pci_drv.h"
+
+static irqreturn_t cert_comp_isr(int irq, void *p)
+{
+ struct cert_comp *cert_comp = p;
+
+ wake_up_all(&cert_comp->waitq);
+ return IRQ_HANDLED;
+}
+
+static struct cert_comp *aie4_lookup_cert_comp(struct amdxdna_dev_hdl *ndev, u32 msix_idx)
+{
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
+ struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
+ struct cert_comp *cert_comp;
+ int ret;
+
+ guard(mutex)(&ndev->cert_comp_lock);
+
+ cert_comp = xa_load(&ndev->cert_comp_xa, msix_idx);
+ if (cert_comp) {
+ kref_get(&cert_comp->kref);
+ return cert_comp;
+ }
+
+ cert_comp = kzalloc_obj(*cert_comp);
+ if (!cert_comp)
+ return NULL;
+
+ cert_comp->ndev = ndev;
+ cert_comp->msix_idx = msix_idx;
+ init_waitqueue_head(&cert_comp->waitq);
+ kref_init(&cert_comp->kref);
+
+ ret = pci_irq_vector(pdev, cert_comp->msix_idx);
+ if (ret < 0) {
+ XDNA_ERR(xdna, "MSI-X idx %u is invalid, ret:%d", msix_idx, ret);
+ goto free_cert_comp;
+ }
+ cert_comp->irq = ret;
+
+ ret = request_irq(cert_comp->irq, cert_comp_isr, 0, "xdna_hsa", cert_comp);
+ if (ret) {
+ XDNA_ERR(xdna, "request irq %d failed %d", cert_comp->irq, ret);
+ goto free_cert_comp;
+ }
+
+ ret = xa_err(xa_store(&ndev->cert_comp_xa, msix_idx, cert_comp, GFP_KERNEL));
+ if (ret) {
+ XDNA_ERR(xdna, "store cert_comp for msix idx %d failed %d", msix_idx, ret);
+ goto free_irq;
+ }
+
+ return cert_comp;
+
+free_irq:
+ free_irq(cert_comp->irq, cert_comp);
+free_cert_comp:
+ kfree(cert_comp);
+ return NULL;
+}
+
+static void cert_comp_release(struct kref *kref)
+{
+ struct cert_comp *cert_comp = container_of(kref, struct cert_comp, kref);
+ struct amdxdna_dev_hdl *ndev = cert_comp->ndev;
+
+ drm_WARN_ON(&ndev->aie.xdna->ddev, !mutex_is_locked(&ndev->cert_comp_lock));
+
+ xa_erase(&ndev->cert_comp_xa, cert_comp->msix_idx);
+ free_irq(cert_comp->irq, cert_comp);
+ kfree(cert_comp);
+}
+
+static void aie4_put_cert_comp(struct cert_comp *cert_comp)
+{
+ struct amdxdna_dev_hdl *ndev;
+
+ ndev = cert_comp->ndev;
+ guard(mutex)(&ndev->cert_comp_lock);
+ kref_put(&cert_comp->kref, cert_comp_release);
+}
+
+static int aie4_msg_destroy_context(struct amdxdna_dev_hdl *ndev, u32 hw_context_id)
+{
+ DECLARE_AIE_MSG(aie4_msg_destroy_hw_context, AIE4_MSG_OP_DESTROY_HW_CONTEXT);
+
+ req.hw_context_id = hw_context_id;
+ return aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+}
+
+static int aie4_hwctx_create(struct amdxdna_hwctx *hwctx)
+{
+ DECLARE_AIE_MSG(aie4_msg_create_hw_context, AIE4_MSG_OP_CREATE_HW_CONTEXT);
+ struct amdxdna_client *client = hwctx->client;
+ struct amdxdna_hwctx_priv *priv = hwctx->priv;
+ struct amdxdna_dev *xdna = hwctx->client->xdna;
+ struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+ int ret;
+
+ drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
+
+ if (!ndev->partition_id || !hwctx->num_tiles) {
+ XDNA_ERR(xdna, "invalid request partition_id %d, num_tiles %d",
+ ndev->partition_id, hwctx->num_tiles);
+ return -EINVAL;
+ }
+
+ req.partition_id = ndev->partition_id;
+ req.request_num_tiles = hwctx->num_tiles;
+ req.pasid = FIELD_PREP(AIE4_MSG_PASID, client->pasid) |
+ FIELD_PREP(AIE4_MSG_PASID_VLD, 1);
+ req.priority_band = hwctx->qos.priority;
+
+ req.hsa_addr_high = upper_32_bits(amdxdna_gem_dev_addr(priv->umq_bo));
+ req.hsa_addr_low = lower_32_bits(amdxdna_gem_dev_addr(priv->umq_bo));
+
+ XDNA_DBG(xdna, "pasid 0x%x, num_tiles %d, hsa[0x%x 0x%x]",
+ req.pasid, req.request_num_tiles, req.hsa_addr_high, req.hsa_addr_low);
+
+ ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+ if (ret) {
+ XDNA_ERR(xdna, "create ctx failed: %d", ret);
+ return ret;
+ }
+
+ XDNA_DBG(xdna, "resp msix: %d, ctx id: %d, doorbell: %d",
+ resp.job_complete_msix_idx,
+ resp.hw_context_id,
+ resp.doorbell_offset);
+
+ /* setup interrupt completion per msix index */
+ priv->cert_comp = aie4_lookup_cert_comp(ndev, resp.job_complete_msix_idx);
+ if (!priv->cert_comp) {
+ aie4_msg_destroy_context(ndev, resp.hw_context_id);
+ return -EINVAL;
+ }
+
+ priv->hw_ctx_id = resp.hw_context_id;
+ hwctx->doorbell_offset = resp.doorbell_offset;
+
+ return 0;
+}
+
+static void aie4_hwctx_destroy(struct amdxdna_hwctx *hwctx)
+{
+ struct amdxdna_client *client = hwctx->client;
+ struct amdxdna_hwctx_priv *priv = hwctx->priv;
+ struct amdxdna_dev *xdna = client->xdna;
+ struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+
+ drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
+
+ aie4_msg_destroy_context(ndev, priv->hw_ctx_id);
+ aie4_put_cert_comp(priv->cert_comp);
+}
+
+static void aie4_hwctx_umq_fini(struct amdxdna_hwctx *hwctx)
+{
+ if (hwctx->priv && hwctx->priv->umq_bo)
+ amdxdna_gem_put_obj(hwctx->priv->umq_bo);
+}
+
+static int aie4_hwctx_umq_init(struct amdxdna_hwctx *hwctx)
+{
+ struct amdxdna_hwctx_priv *priv = hwctx->priv;
+ struct amdxdna_dev *xdna = hwctx->client->xdna;
+ struct amdxdna_gem_obj *umq_bo;
+ struct host_queue_header *qhdr;
+ int ret;
+
+ umq_bo = amdxdna_gem_get_obj(hwctx->client, hwctx->umq_bo_hdl, AMDXDNA_BO_SHARE);
+ if (!umq_bo) {
+ XDNA_ERR(xdna, "cannot find umq_bo handle %d", hwctx->umq_bo_hdl);
+ return -ENOENT;
+ }
+ if (umq_bo->mem.size < sizeof(*qhdr)) {
+ XDNA_ERR(xdna, "umq_bo size is too small");
+ ret = -EINVAL;
+ goto put_umq_bo;
+ }
+
+ /* get kva address for host queue read index and write index */
+ qhdr = amdxdna_gem_vmap(umq_bo);
+ if (!qhdr) {
+ ret = -ENOMEM;
+ goto put_umq_bo;
+ }
+
+ priv->umq_bo = umq_bo;
+ priv->umq_read_index = &qhdr->read_index;
+ priv->umq_write_index = &qhdr->write_index;
+
+ return 0;
+
+put_umq_bo:
+ amdxdna_gem_put_obj(umq_bo);
+ return ret;
+}
+
+int aie4_hwctx_init(struct amdxdna_hwctx *hwctx)
+{
+ struct amdxdna_client *client = hwctx->client;
+ struct amdxdna_dev *xdna = client->xdna;
+ struct amdxdna_hwctx_priv *priv;
+ int ret;
+
+ priv = kzalloc_obj(*priv);
+ if (!priv)
+ return -ENOMEM;
+ hwctx->priv = priv;
+
+ ret = aie4_hwctx_umq_init(hwctx);
+ if (ret)
+ goto free_priv;
+
+ ret = aie4_hwctx_create(hwctx);
+ if (ret)
+ goto umq_fini;
+
+ XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name);
+ return 0;
+
+umq_fini:
+ aie4_hwctx_umq_fini(hwctx);
+free_priv:
+ kfree(priv);
+ hwctx->priv = NULL;
+ return ret;
+}
+
+void aie4_hwctx_fini(struct amdxdna_hwctx *hwctx)
+{
+ aie4_hwctx_destroy(hwctx);
+ aie4_hwctx_umq_fini(hwctx);
+ kfree(hwctx->priv);
+}
+
+static inline bool valid_queue_index(u64 read, u64 write, u32 capacity)
+{
+ return (write >= read) && ((write - read) <= capacity);
+}
+
+static u64 get_read_index(struct amdxdna_hwctx *hwctx)
+{
+ u64 wi = READ_ONCE(*hwctx->priv->umq_write_index);
+ u64 ri = READ_ONCE(*hwctx->priv->umq_read_index);
+ struct amdxdna_dev *xdna = hwctx->client->xdna;
+
+ /*
+ * CERT cannot update read index as uint64 atomically. Driver may read
+ * half-updated read index when it has bits in high 32bit. In case read
+ * index is not valid, wait for some time and retry once. It should
+ * allow CERT to complete the read index update.
+ */
+ if (!valid_queue_index(ri, wi, CTX_MAX_CMDS)) {
+ XDNA_WARN(xdna, "Invalid index, ri %llu, wi %llu", ri, wi);
+ usleep_range(100, 200);
+ ri = READ_ONCE(*hwctx->priv->umq_read_index);
+ if (!valid_queue_index(ri, wi, CTX_MAX_CMDS)) {
+ XDNA_ERR(xdna, "Invalid index after retry, ri %llu, wi %llu", ri, wi);
+ ri = 0;
+ }
+ }
+
+ return ri;
+}
+
+static inline bool check_cmd_done(struct amdxdna_hwctx *hwctx, u64 seq)
+{
+ u64 read_idx = get_read_index(hwctx);
+
+ return read_idx > seq;
+}
+
+int aie4_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq, u32 timeout)
+{
+ unsigned long wait_jifs = MAX_SCHEDULE_TIMEOUT;
+ struct amdxdna_hwctx_priv *priv = hwctx->priv;
+ struct cert_comp *cert_comp = priv->cert_comp;
+ long ret;
+
+ if (timeout)
+ wait_jifs = msecs_to_jiffies(timeout);
+
+ ret = wait_event_interruptible_timeout(cert_comp->waitq,
+ (check_cmd_done(hwctx, seq)),
+ wait_jifs);
+
+ if (!ret)
+ ret = -ETIME;
+
+ return ret <= 0 ? ret : 0;
+}
+
+int aie4_hwctx_valid_doorbell(struct amdxdna_client *client, u32 vm_pgoff)
+{
+ struct amdxdna_hwctx *hwctx;
+ unsigned long hwctx_id;
+ int idx;
+
+ idx = srcu_read_lock(&client->hwctx_srcu);
+ amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
+ if (vm_pgoff == (hwctx->doorbell_offset >> PAGE_SHIFT)) {
+ srcu_read_unlock(&client->hwctx_srcu, idx);
+ return 1;
+ }
+ }
+ srcu_read_unlock(&client->hwctx_srcu, idx);
+
+ return 0;
+}
diff --git a/drivers/accel/amdxdna/aie4_host_queue.h b/drivers/accel/amdxdna/aie4_host_queue.h
new file mode 100644
index 000000000000..1b33eda3f727
--- /dev/null
+++ b/drivers/accel/amdxdna/aie4_host_queue.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026, Advanced Micro Devices, Inc.
+ */
+
+#ifndef _AIE4_HOST_QUEUE_H_
+#define _AIE4_HOST_QUEUE_H_
+
+#include <linux/types.h>
+
+#define CTX_MAX_CMDS 32
+
+struct host_queue_header {
+ __u64 read_index;
+ struct {
+ __u16 major;
+ __u16 minor;
+ } version;
+ __u32 capacity; /* Queue capacity, must be power of two. */
+ __u64 write_index;
+ __u64 data_address; /* The xdna dev addr for payload. */
+};
+
+#endif /* _AIE4_HOST_QUEUE_H_ */
diff --git a/drivers/accel/amdxdna/aie4_message.c b/drivers/accel/amdxdna/aie4_message.c
index d621dd32ac40..88037edbb02a 100644
--- a/drivers/accel/amdxdna/aie4_message.c
+++ b/drivers/accel/amdxdna/aie4_message.c
@@ -25,3 +25,59 @@ int aie4_suspend_fw(struct amdxdna_dev_hdl *ndev)
return ret;
}
+
+int aie4_query_aie_metadata(struct amdxdna_dev_hdl *ndev,
+ struct amdxdna_drm_query_aie_metadata *metadata)
+{
+ DECLARE_AIE_MSG(aie4_msg_aie4_tile_info, AIE4_MSG_OP_AIE_TILE_INFO);
+ int ret;
+
+ ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+ if (ret)
+ return ret;
+
+ metadata->col_size = resp.info.size;
+ metadata->cols = resp.info.cols;
+ metadata->rows = resp.info.rows;
+
+ metadata->version.major = resp.info.major;
+ metadata->version.minor = resp.info.minor;
+
+ metadata->core.row_count = resp.info.core_rows;
+ metadata->core.row_start = resp.info.core_row_start;
+ metadata->core.dma_channel_count = resp.info.core_dma_channels;
+ metadata->core.lock_count = resp.info.core_locks;
+ metadata->core.event_reg_count = resp.info.core_events;
+
+ metadata->mem.row_count = resp.info.mem_rows;
+ metadata->mem.row_start = resp.info.mem_row_start;
+ metadata->mem.dma_channel_count = resp.info.mem_dma_channels;
+ metadata->mem.lock_count = resp.info.mem_locks;
+ metadata->mem.event_reg_count = resp.info.mem_events;
+
+ metadata->shim.row_count = resp.info.shim_rows;
+ metadata->shim.row_start = resp.info.shim_row_start;
+ metadata->shim.dma_channel_count = resp.info.shim_dma_channels;
+ metadata->shim.lock_count = resp.info.shim_locks;
+ metadata->shim.event_reg_count = resp.info.shim_events;
+
+ return 0;
+}
+
+int aie4_attach_work_buffer(struct amdxdna_dev_hdl *ndev)
+{
+ DECLARE_AIE_MSG(aie4_msg_attach_work_buffer, AIE4_MSG_OP_ATTACH_WORK_BUFFER);
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
+ int ret;
+
+ req.buff_addr = ndev->work_buf_addr;
+ req.buff_size = AIE4_WORK_BUFFER_MIN_SIZE;
+
+ ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+ if (ret)
+ XDNA_ERR(xdna, "Failed to attach work buffer, ret %d", ret);
+ else
+ XDNA_DBG(xdna, "Attached work buffer");
+
+ return ret;
+}
diff --git a/drivers/accel/amdxdna/aie4_msg_priv.h b/drivers/accel/amdxdna/aie4_msg_priv.h
index 88463cc3a98a..af0866045b91 100644
--- a/drivers/accel/amdxdna/aie4_msg_priv.h
+++ b/drivers/accel/amdxdna/aie4_msg_priv.h
@@ -6,13 +6,21 @@
#ifndef _AIE4_MSG_PRIV_H_
#define _AIE4_MSG_PRIV_H_
+#include <linux/sizes.h>
#include <linux/types.h>
enum aie4_msg_opcode {
AIE4_MSG_OP_SUSPEND = 0x10003,
+ AIE4_MSG_OP_ATTACH_WORK_BUFFER = 0x1000D,
AIE4_MSG_OP_CREATE_VFS = 0x20001,
AIE4_MSG_OP_DESTROY_VFS = 0x20002,
+
+ AIE4_MSG_OP_CREATE_PARTITION = 0x30001,
+ AIE4_MSG_OP_DESTROY_PARTITION = 0x30002,
+ AIE4_MSG_OP_CREATE_HW_CONTEXT = 0x30003,
+ AIE4_MSG_OP_DESTROY_HW_CONTEXT = 0x30004,
+ AIE4_MSG_OP_AIE_TILE_INFO = 0x30006,
};
enum aie4_msg_status {
@@ -46,4 +54,94 @@ struct aie4_msg_destroy_vfs_resp {
enum aie4_msg_status status;
} __packed;
+struct aie4_msg_create_partition_req {
+ __u32 partition_col_start;
+ __u32 partition_col_count;
+} __packed;
+
+struct aie4_msg_create_partition_resp {
+ enum aie4_msg_status status;
+ __u32 partition_id;
+} __packed;
+
+struct aie4_msg_destroy_partition_req {
+ __u32 partition_id;
+} __packed;
+
+struct aie4_msg_destroy_partition_resp {
+ enum aie4_msg_status status;
+} __packed;
+
+struct aie4_msg_create_hw_context_req {
+ __u32 partition_id;
+ __u32 request_num_tiles;
+ __u32 hsa_addr_high;
+ __u32 hsa_addr_low;
+#define AIE4_MSG_PASID GENMASK(19, 0)
+#define AIE4_MSG_PASID_VLD GENMASK(31, 31)
+ __u32 pasid;
+ __u32 priority_band;
+} __packed;
+
+struct aie4_msg_create_hw_context_resp {
+ enum aie4_msg_status status;
+ __u32 hw_context_id;
+ __u32 doorbell_offset;
+ __u32 job_complete_msix_idx;
+} __packed;
+
+struct aie4_msg_destroy_hw_context_req {
+ __u32 hw_context_id;
+ __u32 resvd1;
+} __packed;
+
+struct aie4_msg_destroy_hw_context_resp {
+ enum aie4_msg_status status;
+} __packed;
+
+struct aie4_tile_info {
+ __u32 size;
+ __u16 major;
+ __u16 minor;
+ __u16 cols;
+ __u16 rows;
+ __u16 core_rows;
+ __u16 mem_rows;
+ __u16 shim_rows;
+ __u16 core_row_start;
+ __u16 mem_row_start;
+ __u16 shim_row_start;
+ __u16 core_dma_channels;
+ __u16 mem_dma_channels;
+ __u16 shim_dma_channels;
+ __u16 core_locks;
+ __u16 mem_locks;
+ __u16 shim_locks;
+ __u16 core_events;
+ __u16 mem_events;
+ __u16 shim_events;
+ __u16 resvd;
+} __packed;
+
+struct aie4_msg_aie4_tile_info_req {
+ __u32 resvd;
+} __packed;
+
+struct aie4_msg_aie4_tile_info_resp {
+ enum aie4_msg_status status;
+ struct aie4_tile_info info;
+} __packed;
+
+#define AIE4_WORK_BUFFER_MIN_SIZE SZ_4M
+
+struct aie4_msg_attach_work_buffer_req {
+ __u64 buff_addr;
+ __u32 reserved;
+ __u32 buff_size;
+} __packed;
+
+struct aie4_msg_attach_work_buffer_resp {
+ enum aie4_msg_status status;
+} __packed;
+
#endif /* _AIE4_MSG_PRIV_H_ */
diff --git a/drivers/accel/amdxdna/aie4_pci.c b/drivers/accel/amdxdna/aie4_pci.c
index 87f80f804f91..a58a83af42a4 100644
--- a/drivers/accel/amdxdna/aie4_pci.c
+++ b/drivers/accel/amdxdna/aie4_pci.c
@@ -9,11 +9,16 @@
#include <linux/firmware.h>
#include <linux/sizes.h>
+#include "aie.h"
+#include "aie4_msg_priv.h"
#include "aie4_pci.h"
+#include "amdxdna_mailbox.h"
+#include "amdxdna_mailbox_helper.h"
#include "amdxdna_pci_drv.h"
#define NO_IOHUB 0
#define PSP_NOTIFY_INTR 0xD007BE11
+#define AIE4_TOTAL_COLUMN 3
/*
* The management mailbox channel is allocated by firmware.
@@ -196,8 +201,9 @@ free_channel:
return ret;
}
-static int aie4_mailbox_init(struct amdxdna_dev *xdna)
+static int aie4_mailbox_init(struct amdxdna_dev_hdl *ndev)
{
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
struct mailbox_info mbox_info;
int ret;
@@ -208,13 +214,13 @@ static int aie4_mailbox_init(struct amdxdna_dev *xdna)
return aie4_mailbox_start(xdna, &mbox_info);
}
-static void aie4_fw_unload(struct amdxdna_dev_hdl *ndev)
+static void aie4_fw_stop(struct amdxdna_dev_hdl *ndev)
{
aie_psp_stop(ndev->aie.psp_hdl);
aie_smu_fini(ndev->aie.smu_hdl);
}
-static int aie4_fw_load(struct amdxdna_dev_hdl *ndev)
+static int aie4_fw_start(struct amdxdna_dev_hdl *ndev)
{
int ret;
@@ -233,49 +239,109 @@ static int aie4_fw_load(struct amdxdna_dev_hdl *ndev)
return ret;
}
-static int aie4_hw_start(struct amdxdna_dev *xdna)
+static int aie4_partition_init(struct amdxdna_dev_hdl *ndev)
{
- struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+ DECLARE_AIE_MSG(aie4_msg_create_partition, AIE4_MSG_OP_CREATE_PARTITION);
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
int ret;
- ret = aie4_fw_load(ndev);
+ req.partition_col_start = 0;
+ req.partition_col_count = AIE4_TOTAL_COLUMN;
+ ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+ if (ret) {
+ XDNA_ERR(xdna, "partition init failed: %d", ret);
+ return ret;
+ }
+
+ ndev->partition_id = resp.partition_id;
+ return 0;
+}
+
+static void aie4_partition_fini(struct amdxdna_dev_hdl *ndev)
+{
+ DECLARE_AIE_MSG(aie4_msg_destroy_partition, AIE4_MSG_OP_DESTROY_PARTITION);
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
+ int ret;
+
+ req.partition_id = ndev->partition_id;
+ ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+ if (ret)
+ XDNA_ERR(xdna, "partition fini failed: %d", ret);
+}
+
+static int aie4_query(struct amdxdna_dev_hdl *ndev)
+{
+ return aie4_query_aie_metadata(ndev, &ndev->aie.metadata);
+}
+
+static int aie4_pf_hw_start(struct amdxdna_dev_hdl *ndev)
+{
+ int ret;
+
+ ret = aie4_fw_start(ndev);
if (ret)
return ret;
- ret = aie4_mailbox_init(xdna);
+ ret = aie4_mailbox_init(ndev);
if (ret)
- goto fw_unload;
+ goto stop_fw;
+
+ ret = aie4_attach_work_buffer(ndev);
+ if (ret)
+ goto mbox_fini;
return 0;
-fw_unload:
- aie4_fw_unload(ndev);
+mbox_fini:
+ aie4_mailbox_fini(ndev);
+stop_fw:
+ aie4_fw_stop(ndev);
return ret;
}
-static void aie4_mgmt_fw_fini(struct amdxdna_dev_hdl *ndev)
+static void aie4_pf_hw_stop(struct amdxdna_dev_hdl *ndev)
+{
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
+
+ drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
+
+ aie4_suspend_fw(ndev);
+ aie4_mailbox_fini(ndev);
+ aie4_fw_stop(ndev);
+}
+
+static int aie4_vf_hw_start(struct amdxdna_dev_hdl *ndev)
{
int ret;
- /* No paired resume needed, fw is stateless */
- ret = aie4_suspend_fw(ndev);
+ ret = aie4_mailbox_init(ndev);
+ if (ret)
+ return ret;
+
+ ret = aie4_query(ndev);
if (ret)
- XDNA_ERR(ndev->aie.xdna, "suspend_fw failed, ret %d", ret);
- else
- XDNA_DBG(ndev->aie.xdna, "npu firmware suspended");
+ goto mailbox_fini;
+
+ ret = aie4_partition_init(ndev);
+ if (ret)
+ goto mailbox_fini;
+
+ return 0;
+
+mailbox_fini:
+ aie4_mailbox_fini(ndev);
+ return ret;
}
-static void aie4_hw_stop(struct amdxdna_dev *xdna)
+static void aie4_vf_hw_stop(struct amdxdna_dev_hdl *ndev)
{
- struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
- aie4_mgmt_fw_fini(ndev);
+ aie4_partition_fini(ndev);
aie4_mailbox_fini(ndev);
-
- aie4_fw_unload(ndev);
}
static int aie4_request_firmware(struct amdxdna_dev_hdl *ndev,
@@ -365,15 +431,44 @@ static int aie4_prepare_firmware(struct amdxdna_dev_hdl *ndev,
return 0;
}
-static int aie4_pcidev_init(struct amdxdna_dev_hdl *ndev)
+static int aie4_load_fw(struct amdxdna_dev_hdl *ndev,
+ void __iomem *tbl[PCI_NUM_RESOURCES])
+{
+ const struct firmware *npufw, *certfw;
+ int ret;
+
+ if (!ndev->priv->npufw_path && !ndev->priv->certfw_path)
+ return 0;
+
+ ret = aie4_request_firmware(ndev, &npufw, &certfw);
+ if (ret)
+ return ret;
+
+ ret = aie4_prepare_firmware(ndev, npufw, certfw, tbl);
+ aie4_release_firmware(ndev, npufw, certfw);
+
+ return ret;
+}
+
+static int aie4m_pcidev_init(struct amdxdna_dev *xdna)
{
- struct amdxdna_dev *xdna = ndev->aie.xdna;
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
+ struct amdxdna_dev_hdl *ndev;
void __iomem *tbl[PCI_NUM_RESOURCES] = {0};
- const struct firmware *npufw, *certfw;
unsigned long bars = 0;
int ret, i;
+ ndev = drmm_kzalloc(&xdna->ddev, sizeof(*ndev), GFP_KERNEL);
+ if (!ndev)
+ return -ENOMEM;
+
+ ndev->priv = xdna->dev_info->dev_priv;
+ ndev->aie.xdna = xdna;
+ xdna->dev_handle = ndev;
+
+ xa_init_flags(&ndev->cert_comp_xa, XA_FLAGS_ALLOC);
+ mutex_init(&ndev->cert_comp_lock);
+
/* Enable managed PCI device */
ret = pcim_enable_device(pdev);
if (ret) {
@@ -409,75 +504,164 @@ static int aie4_pcidev_init(struct amdxdna_dev_hdl *ndev)
pci_set_master(pdev);
- ret = aie4_request_firmware(ndev, &npufw, &certfw);
- if (ret)
- goto clear_master;
-
- ret = aie4_prepare_firmware(ndev, npufw, certfw, tbl);
- aie4_release_firmware(ndev, npufw, certfw);
+ ret = aie4_load_fw(ndev, tbl);
if (ret)
- goto clear_master;
+ return ret;
ret = aie4_irq_init(xdna);
if (ret)
- goto clear_master;
+ return ret;
- ret = aie4_hw_start(xdna);
- if (ret)
- goto clear_master;
+ amdxdna_vbnv_init(xdna);
+ XDNA_DBG(xdna, "init finished");
return 0;
+}
-clear_master:
- pci_clear_master(pdev);
+static int aie4_doorbell_mmap(struct amdxdna_client *client, struct vm_area_struct *vma)
+{
+ struct amdxdna_dev *xdna = client->xdna;
+ struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
+ const struct amdxdna_dev_priv *npriv = xdna->dev_info->dev_priv;
+ phys_addr_t res_start;
+ unsigned long pfn;
+ int ret;
+
+ if (!aie4_hwctx_valid_doorbell(client, vma->vm_pgoff)) {
+ XDNA_ERR(xdna, "Invalid doorbell page offset 0x%lx", vma->vm_pgoff);
+ return -EINVAL;
+ }
+
+ if (vma_pages(vma) != 1) {
+ XDNA_ERR(xdna, "can only map one page, got %ld", vma_pages(vma));
+ return -EINVAL;
+ }
+
+ res_start = pci_resource_start(pdev, xdna->dev_info->doorbell_bar) + npriv->doorbell_off;
+ pfn = PHYS_PFN(res_start) + vma->vm_pgoff;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP);
+ ret = io_remap_pfn_range(vma, vma->vm_start,
+ pfn,
+ PAGE_SIZE,
+ vma->vm_page_prot);
+
+ XDNA_DBG(xdna, "doorbell ret %d", ret);
+ return ret;
+}
+
+static int aie4_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_info *args)
+{
+ struct amdxdna_dev *xdna = client->xdna;
+ struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+ int ret;
+
+ switch (args->param) {
+ case DRM_AMDXDNA_QUERY_AIE_METADATA:
+ ret = amdxdna_get_metadata(&ndev->aie, client, args);
+ break;
+ default:
+ XDNA_ERR(xdna, "Not supported request parameter %u", args->param);
+ ret = -EOPNOTSUPP;
+ }
+
+ XDNA_DBG(xdna, "Got param %d", args->param);
return ret;
}
-static void aie4_pcidev_fini(struct amdxdna_dev_hdl *ndev)
+static int aie4_alloc_work_buffer(struct amdxdna_dev_hdl *ndev)
{
struct amdxdna_dev *xdna = ndev->aie.xdna;
- struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
+ u32 buf_size = AIE4_WORK_BUFFER_MIN_SIZE;
- aie4_hw_stop(xdna);
+ ndev->work_buf = amdxdna_alloc_msg_buffer(xdna, &buf_size,
+ &ndev->work_buf_addr);
+ if (IS_ERR(ndev->work_buf)) {
+ int ret = PTR_ERR(ndev->work_buf);
- pci_clear_master(pdev);
+ XDNA_ERR(xdna, "Failed to alloc work buffer, size 0x%x",
+ AIE4_WORK_BUFFER_MIN_SIZE);
+ ndev->work_buf = NULL;
+ return ret;
+ }
+
+ ndev->work_buf_size = buf_size;
+ XDNA_DBG(xdna, "Work buffer allocated: size 0x%x", buf_size);
+
+ return 0;
}
-static void aie4_fini(struct amdxdna_dev *xdna)
+static void aie4_free_work_buffer(struct amdxdna_dev_hdl *ndev)
{
- struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
+
+ if (!ndev->work_buf)
+ return;
- aie4_sriov_stop(ndev);
- aie4_pcidev_fini(ndev);
+ amdxdna_free_msg_buffer(xdna, ndev->work_buf_size, ndev->work_buf,
+ ndev->work_buf_addr);
+ ndev->work_buf = NULL;
}
-static int aie4_init(struct amdxdna_dev *xdna)
+static int aie4_pf_init(struct amdxdna_dev *xdna)
{
- struct amdxdna_dev_hdl *ndev;
int ret;
- ndev = drmm_kzalloc(&xdna->ddev, sizeof(*ndev), GFP_KERNEL);
- if (!ndev)
- return -ENOMEM;
-
- ndev->priv = xdna->dev_info->dev_priv;
- ndev->aie.xdna = xdna;
- xdna->dev_handle = ndev;
+ ret = aie4m_pcidev_init(xdna);
+ if (ret)
+ return ret;
- ret = aie4_pcidev_init(ndev);
- if (ret) {
- XDNA_ERR(xdna, "Setup PCI device failed, ret %d", ret);
+ ret = aie4_alloc_work_buffer(xdna->dev_handle);
+ if (ret)
return ret;
- }
- amdxdna_vbnv_init(xdna);
- XDNA_DBG(xdna, "aie4 init finished");
+ ret = aie4_pf_hw_start(xdna->dev_handle);
+ if (ret)
+ goto free_work_buf;
+
return 0;
+
+free_work_buf:
+ aie4_free_work_buffer(xdna->dev_handle);
+ return ret;
+}
+
+static int aie4_vf_init(struct amdxdna_dev *xdna)
+{
+ int ret;
+
+ ret = aie4m_pcidev_init(xdna);
+ if (ret)
+ return ret;
+
+ return aie4_vf_hw_start(xdna->dev_handle);
}
-const struct amdxdna_dev_ops aie4_ops = {
- .init = aie4_init,
- .fini = aie4_fini,
+static void aie4_pf_fini(struct amdxdna_dev *xdna)
+{
+ aie4_sriov_stop(xdna->dev_handle);
+ aie4_pf_hw_stop(xdna->dev_handle);
+ aie4_free_work_buffer(xdna->dev_handle);
+}
+
+static void aie4_vf_fini(struct amdxdna_dev *xdna)
+{
+ aie4_vf_hw_stop(xdna->dev_handle);
+}
+
+const struct amdxdna_dev_ops aie4_pf_ops = {
+ .init = aie4_pf_init,
+ .fini = aie4_pf_fini,
.sriov_configure = aie4_sriov_configure,
};
+
+const struct amdxdna_dev_ops aie4_vf_ops = {
+ .init = aie4_vf_init,
+ .fini = aie4_vf_fini,
+ .hwctx_init = aie4_hwctx_init,
+ .hwctx_fini = aie4_hwctx_fini,
+ .mmap = aie4_doorbell_mmap,
+ .cmd_wait = aie4_cmd_wait,
+ .get_aie_info = aie4_get_info,
+};
diff --git a/drivers/accel/amdxdna/aie4_pci.h b/drivers/accel/amdxdna/aie4_pci.h
index aa1495c3370b..3fd5eace3ed7 100644
--- a/drivers/accel/amdxdna/aie4_pci.h
+++ b/drivers/accel/amdxdna/aie4_pci.h
@@ -13,12 +13,30 @@
#include "aie.h"
#include "amdxdna_mailbox.h"
+struct cert_comp {
+ struct amdxdna_dev_hdl *ndev;
+ u32 msix_idx;
+ int irq;
+ struct kref kref;
+ wait_queue_head_t waitq;
+};
+
+struct amdxdna_hwctx_priv {
+ struct amdxdna_gem_obj *umq_bo;
+ u64 *umq_read_index;
+ u64 *umq_write_index;
+
+ struct cert_comp *cert_comp;
+ u32 hw_ctx_id;
+};
+
struct amdxdna_dev_priv {
const char *npufw_path;
const char *certfw_path;
u32 mbox_bar;
u32 mbox_rbuf_bar;
u64 mbox_info_off;
+ u32 doorbell_off;
struct aie_bar_off_pair psp_regs_off[PSP_MAX_REGS];
struct aie_bar_off_pair smu_regs_off[SMU_MAX_REGS];
@@ -31,10 +49,27 @@ struct amdxdna_dev_hdl {
void __iomem *rbuf_base;
struct mailbox *mbox;
+ u32 partition_id;
+
+ struct xarray cert_comp_xa; /* device level indexed by msix id */
+ struct mutex cert_comp_lock; /* protects cert_comp operations*/
+
+ void *work_buf;
+ dma_addr_t work_buf_addr;
+ u32 work_buf_size;
};
/* aie4_message.c */
+int aie4_query_aie_metadata(struct amdxdna_dev_hdl *ndev,
+ struct amdxdna_drm_query_aie_metadata *metadata);
int aie4_suspend_fw(struct amdxdna_dev_hdl *ndev);
+int aie4_attach_work_buffer(struct amdxdna_dev_hdl *ndev);
+
+/* aie4_ctx.c */
+int aie4_hwctx_init(struct amdxdna_hwctx *hwctx);
+void aie4_hwctx_fini(struct amdxdna_hwctx *hwctx);
+int aie4_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq, u32 timeout);
+int aie4_hwctx_valid_doorbell(struct amdxdna_client *client, u32 vm_pgoff);
/* aie4_sriov.c */
#if IS_ENABLED(CONFIG_PCI_IOV)
@@ -48,6 +83,7 @@ static inline int aie4_sriov_stop(struct amdxdna_dev_hdl *ndev)
}
#endif
-extern const struct amdxdna_dev_ops aie4_ops;
+extern const struct amdxdna_dev_ops aie4_pf_ops;
+extern const struct amdxdna_dev_ops aie4_vf_ops;
#endif /* _AIE4_PCI_H_ */
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c
index 2c2c21992c87..b79229a63af3 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.c
+++ b/drivers/accel/amdxdna/amdxdna_ctx.c
@@ -207,6 +207,9 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
if (args->ext || args->ext_flags)
return -EINVAL;
+ if (!xdna->dev_info->ops->hwctx_init)
+ return -EOPNOTSUPP;
+
hwctx = kzalloc_obj(*hwctx);
if (!hwctx)
return -ENOMEM;
@@ -220,6 +223,8 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
hwctx->client = client;
hwctx->fw_ctx_id = -1;
hwctx->num_tiles = args->num_tiles;
+ hwctx->umq_bo_hdl = args->umq_bo;
+ hwctx->doorbell_offset = AMDXDNA_INVALID_DOORBELL_OFFSET;
hwctx->mem_size = args->mem_size;
hwctx->max_opc = args->max_opc;
@@ -252,6 +257,7 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
args->handle = hwctx->id;
args->syncobj_handle = hwctx->syncobj_hdl;
+ args->umq_doorbell = hwctx->doorbell_offset;
atomic64_set(&hwctx->job_submit_cnt, 0);
atomic64_set(&hwctx->job_free_cnt, 0);
@@ -621,3 +627,37 @@ int amdxdna_drm_submit_cmd_ioctl(struct drm_device *dev, void *data, struct drm_
XDNA_ERR(client->xdna, "Invalid command type %d", args->type);
return -EINVAL;
}
+
+int amdxdna_drm_wait_cmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+ struct amdxdna_client *client = filp->driver_priv;
+ struct amdxdna_dev *xdna = to_xdna_dev(dev);
+ struct amdxdna_drm_wait_cmd *args = data;
+ struct amdxdna_hwctx *hwctx;
+ int ret, idx;
+
+ XDNA_DBG(xdna, "PID %d ctx %d timeout set %d ms for cmd %llu",
+ client->pid, args->hwctx, args->timeout, args->seq);
+
+ if (!xdna->dev_info->ops->cmd_wait)
+ return -EOPNOTSUPP;
+
+ idx = srcu_read_lock(&client->hwctx_srcu);
+ hwctx = xa_load(&client->hwctx_xa, args->hwctx);
+ if (!hwctx) {
+ XDNA_DBG(xdna, "PID %d failed to get ctx %d", client->pid, args->hwctx);
+ ret = -EINVAL;
+ goto unlock_ctx_srcu;
+ }
+
+ ret = xdna->dev_info->ops->cmd_wait(hwctx, args->seq, args->timeout);
+
+ XDNA_DBG(xdna, "PID %d ctx %d cmd %lld wait finished, ret %d",
+ client->pid, args->hwctx, args->seq, ret);
+
+ trace_amdxdna_debug_point(current->comm, args->seq, "job returned to user");
+
+unlock_ctx_srcu:
+ srcu_read_unlock(&client->hwctx_srcu, idx);
+ return ret;
+}
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h
index 355798687376..6e3c6371a088 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.h
+++ b/drivers/accel/amdxdna/amdxdna_ctx.h
@@ -14,6 +14,7 @@ struct amdxdna_hwctx_priv;
enum ert_cmd_opcode {
ERT_START_CU = 0,
+ ERT_START_DPU = 18,
ERT_CMD_CHAIN = 19,
ERT_START_NPU = 20,
ERT_START_NPU_PREEMPT = 21,
@@ -105,6 +106,8 @@ struct amdxdna_hwctx {
u32 *col_list;
u32 start_col;
u32 num_col;
+ u32 umq_bo_hdl;
+ u32 doorbell_offset;
u32 num_unused_col;
struct amdxdna_qos_info qos;
@@ -208,12 +211,10 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
u32 *arg_bo_hdls, u32 arg_bo_cnt,
u32 hwctx_hdl, u64 *seq);
-int amdxdna_cmd_wait(struct amdxdna_client *client, u32 hwctx_hdl,
- u64 seq, u32 timeout);
-
int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdxdna_drm_submit_cmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
+int amdxdna_drm_wait_cmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
#endif /* _AMDXDNA_CTX_H_ */
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index ebfc472aa9e7..319d2064fafa 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -212,7 +212,8 @@ static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
mmu_interval_set_seq(&mapp->notifier, cur_seq);
up_write(&xdna->notifier_lock);
- xdna->dev_info->ops->hmm_invalidate(abo, cur_seq);
+ if (xdna->dev_info->ops->hmm_invalidate)
+ xdna->dev_info->ops->hmm_invalidate(abo, cur_seq);
if (range->event == MMU_NOTIFY_UNMAP) {
down_write(&xdna->notifier_lock);
@@ -295,7 +296,7 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
u32 nr_pages;
int ret;
- if (!xdna->dev_info->ops->hmm_invalidate)
+ if (!amdxdna_pasid_on(abo->client))
return 0;
mapp = kzalloc_obj(*mapp);
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index 1b08a08343cf..a6e9be7960c2 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -40,9 +40,10 @@ MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
* 0.7: Support getting power and utilization data
* 0.8: Support BO usage query
* 0.9: Add new device type AMDXDNA_DEV_TYPE_PF
+ * 0.10: Support AIE4 UMQ
*/
#define AMDXDNA_DRIVER_MAJOR 0
-#define AMDXDNA_DRIVER_MINOR 9
+#define AMDXDNA_DRIVER_MINOR 10
/*
* Bind the driver base on (vendor_id, device_id) pair and later use the
@@ -53,7 +54,9 @@ static const struct pci_device_id pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1502) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f0) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f3) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1B0B) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1B0C) },
{0}
};
@@ -65,7 +68,9 @@ static const struct amdxdna_device_id amdxdna_ids[] = {
{ 0x17f0, 0x11, &dev_npu5_info },
{ 0x17f0, 0x20, &dev_npu6_info },
{ 0x17f2, 0x10, &dev_npu3_pf_info },
+ { 0x17f3, 0x10, &dev_npu3_vf_info },
{ 0x1B0B, 0x10, &dev_npu3_pf_info },
+ { 0x1B0C, 0x10, &dev_npu3_vf_info },
{0}
};
@@ -220,6 +225,21 @@ static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struc
return ret;
}
+static int amdxdna_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_file *drm_filp = filp->private_data;
+ struct amdxdna_client *client = drm_filp->driver_priv;
+ struct amdxdna_dev *xdna = client->xdna;
+
+ if (likely(vma->vm_pgoff >= DRM_FILE_PAGE_OFFSET_START))
+ return drm_gem_mmap(filp, vma);
+
+ if (!xdna->dev_info->ops->mmap)
+ return -EOPNOTSUPP;
+
+ return xdna->dev_info->ops->mmap(client, vma);
+}
+
static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {
/* Context */
DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_HWCTX, amdxdna_drm_create_hwctx_ioctl, 0),
@@ -231,6 +251,7 @@ static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(AMDXDNA_SYNC_BO, amdxdna_drm_sync_bo_ioctl, 0),
/* Execution */
DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(AMDXDNA_WAIT_CMD, amdxdna_drm_wait_cmd_ioctl, 0),
/* AIE hardware */
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_ARRAY, amdxdna_drm_get_array_ioctl, 0),
@@ -277,7 +298,7 @@ static const struct file_operations amdxdna_fops = {
.poll = drm_poll,
.read = drm_read,
.llseek = noop_llseek,
- .mmap = drm_gem_mmap,
+ .mmap = amdxdna_drm_gem_mmap,
.show_fdinfo = drm_show_fdinfo,
.fop_flags = FOP_UNSIGNED_OFFSET,
};
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.h b/drivers/accel/amdxdna/amdxdna_pci_drv.h
index b1548cf16f59..471b72299aee 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.h
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.h
@@ -56,12 +56,14 @@ struct amdxdna_dev_ops {
int (*resume)(struct amdxdna_dev *xdna);
int (*suspend)(struct amdxdna_dev *xdna);
int (*sriov_configure)(struct amdxdna_dev *xdna, int num_vfs);
+ int (*mmap)(struct amdxdna_client *client, struct vm_area_struct *vma);
int (*hwctx_init)(struct amdxdna_hwctx *hwctx);
void (*hwctx_fini)(struct amdxdna_hwctx *hwctx);
int (*hwctx_config)(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
int (*hwctx_sync_debug_bo)(struct amdxdna_hwctx *hwctx, u32 debug_bo_hdl);
void (*hmm_invalidate)(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
int (*cmd_submit)(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
+ int (*cmd_wait)(struct amdxdna_hwctx *hwctx, u64 seq, u32 timeout);
int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);
int (*get_array)(struct amdxdna_client *client, struct amdxdna_drm_get_array *args);
@@ -85,6 +87,7 @@ struct amdxdna_dev_info {
int sram_bar;
int psp_bar;
int smu_bar;
+ int doorbell_bar;
int device_type;
int first_col;
u32 dev_mem_buf_shift;
@@ -167,6 +170,7 @@ struct amdxdna_client {
/* Add device info below */
extern const struct amdxdna_dev_info dev_npu1_info;
extern const struct amdxdna_dev_info dev_npu3_pf_info;
+extern const struct amdxdna_dev_info dev_npu3_vf_info;
extern const struct amdxdna_dev_info dev_npu4_info;
extern const struct amdxdna_dev_info dev_npu5_info;
extern const struct amdxdna_dev_info dev_npu6_info;
diff --git a/drivers/accel/amdxdna/npu3_regs.c b/drivers/accel/amdxdna/npu3_regs.c
index acece0faddf2..d76b2e99c308 100644
--- a/drivers/accel/amdxdna/npu3_regs.c
+++ b/drivers/accel/amdxdna/npu3_regs.c
@@ -14,6 +14,9 @@
#define NPU3_MBOX_BUFFER_BAR 2
#define NPU3_MBOX_INFO_OFF 0x0
+#define NPU3_DOORBELL_BAR 2
+#define NPU3_DOORBELL_OFF 0x0
+
/* PCIe BAR Index for NPU3 */
#define NPU3_REG_BAR_INDEX 0
#define NPU3_PSP_BAR_INDEX 4
@@ -45,6 +48,7 @@ static const struct amdxdna_dev_priv npu3_dev_priv = {
.mbox_bar = NPU3_MBOX_BAR,
.mbox_rbuf_bar = NPU3_MBOX_BUFFER_BAR,
.mbox_info_off = NPU3_MBOX_INFO_OFF,
+ .doorbell_off = NPU3_DOORBELL_OFF,
.psp_regs_off = {
DEFINE_BAR_OFFSET(PSP_CMD_REG, NPU3_PSP, MPASP_C2PMSG_123_ALT_1),
DEFINE_BAR_OFFSET(PSP_ARG0_REG, NPU3_PSP, MPASP_C2PMSG_156_ALT_1),
@@ -64,6 +68,14 @@ static const struct amdxdna_dev_priv npu3_dev_priv = {
},
};
+static const struct amdxdna_dev_priv npu3_dev_vf_priv = {
+ /* vf device does not load firmware */
+ .mbox_bar = NPU3_MBOX_BAR,
+ .mbox_rbuf_bar = NPU3_MBOX_BUFFER_BAR,
+ .mbox_info_off = NPU3_MBOX_INFO_OFF,
+ /* vf device does not have smu and psp */
+};
+
const struct amdxdna_dev_info dev_npu3_pf_info = {
.mbox_bar = NPU3_MBOX_BAR,
.sram_bar = NPU3_MBOX_BUFFER_BAR,
@@ -73,5 +85,16 @@ const struct amdxdna_dev_info dev_npu3_pf_info = {
.device_type = AMDXDNA_DEV_TYPE_PF,
.dev_priv = &npu3_dev_priv,
.fw_feature_tbl = npu3_fw_feature_table,
- .ops = &aie4_ops,
+ .ops = &aie4_pf_ops,
+};
+
+const struct amdxdna_dev_info dev_npu3_vf_info = {
+ .mbox_bar = NPU3_MBOX_BAR,
+ .sram_bar = NPU3_MBOX_BUFFER_BAR,
+ .doorbell_bar = NPU3_DOORBELL_BAR,
+ .default_vbnv = "RyzenAI-npu3-vf",
+ .device_type = AMDXDNA_DEV_TYPE_UMQ,
+ .dev_priv = &npu3_dev_vf_priv,
+ .fw_feature_tbl = npu3_fw_feature_table,
+ .ops = &aie4_vf_ops,
};
diff --git a/drivers/accel/qaic/qaic.h b/drivers/accel/qaic/qaic.h
index 83948358ada1..02ca99000e2a 100644
--- a/drivers/accel/qaic/qaic.h
+++ b/drivers/accel/qaic/qaic.h
@@ -151,8 +151,6 @@ struct qaic_device {
struct list_head cntl_xfer_list;
/* Synchronizes MHI control device transactions and its xfer list */
struct mutex cntl_mutex;
- /* Array of DBC struct of this device */
- struct dma_bridge_chan *dbc;
/* Work queue for tasks related to MHI control device */
struct workqueue_struct *cntl_wq;
/* Synchronizes all the users of device during cleanup */
@@ -205,6 +203,8 @@ struct qaic_device {
void *ssr_mhi_buf;
/* DBC which is under SSR. Sentinel U32_MAX would mean that no SSR in progress */
u32 ssr_dbc;
+ /* Array of DBC struct of this device */
+ struct dma_bridge_chan dbc[] __counted_by(num_dbc);
};
struct qaic_drm_device {
diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c
index 1c7c57dabcd6..0acf6cdd44f8 100644
--- a/drivers/accel/qaic/qaic_drv.c
+++ b/drivers/accel/qaic/qaic_drv.c
@@ -43,6 +43,7 @@ MODULE_IMPORT_NS("DMA_BUF");
#define QAIC_DESC "Qualcomm Cloud AI Accelerators"
#define CNTL_MAJOR 5
#define CNTL_MINOR 0
+#define DBC_NUM 16
struct qaic_device_config {
/* Indicates the AIC family the device belongs to */
@@ -405,15 +406,12 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev,
struct drm_device *drm;
int i, ret;
- qdev = devm_kzalloc(dev, sizeof(*qdev), GFP_KERNEL);
+ qdev = devm_kzalloc(dev, struct_size(qdev, dbc, DBC_NUM), GFP_KERNEL);
if (!qdev)
return NULL;
+ qdev->num_dbc = DBC_NUM;
qdev->dev_state = QAIC_OFFLINE;
- qdev->num_dbc = 16;
- qdev->dbc = devm_kcalloc(dev, qdev->num_dbc, sizeof(*qdev->dbc), GFP_KERNEL);
- if (!qdev->dbc)
- return NULL;
qddev = devm_drm_dev_alloc(&pdev->dev, &qaic_accel_driver, struct qaic_drm_device, drm);
if (IS_ERR(qddev))
diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
index 52686672e99f..eb1457376307 100644
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -437,6 +437,9 @@ int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size)
root_count++;
} while (size);
+#ifdef CONFIG_LOCKDEP
+ mm->lock_dep_map = NULL;
+#endif
return 0;
out_free_roots:
@@ -538,6 +541,7 @@ void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear)
unsigned int order;
int i;
+ gpu_buddy_driver_lock_held(mm);
size = mm->size;
for (i = 0; i < mm->n_roots; ++i) {
order = ilog2(size) - ilog2(mm->chunk_size);
@@ -580,6 +584,7 @@ EXPORT_SYMBOL(gpu_buddy_reset_clear);
void gpu_buddy_free_block(struct gpu_buddy *mm,
struct gpu_buddy_block *block)
{
+ gpu_buddy_driver_lock_held(mm);
BUG_ON(!gpu_buddy_block_is_allocated(block));
mm->avail += gpu_buddy_block_size(mm, block);
if (gpu_buddy_block_is_clear(block))
@@ -633,6 +638,7 @@ void gpu_buddy_free_list(struct gpu_buddy *mm,
{
bool mark_clear = flags & GPU_BUDDY_CLEARED;
+ gpu_buddy_driver_lock_held(mm);
__gpu_buddy_free_list(mm, objects, mark_clear, !mark_clear);
}
EXPORT_SYMBOL(gpu_buddy_free_list);
@@ -1172,6 +1178,8 @@ int gpu_buddy_block_trim(struct gpu_buddy *mm,
u64 new_start;
int err;
+ gpu_buddy_driver_lock_held(mm);
+
if (!list_is_singular(blocks))
return -EINVAL;
@@ -1287,6 +1295,8 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
unsigned long pages;
int err;
+ gpu_buddy_driver_lock_held(mm);
+
if (size < mm->chunk_size)
return -EINVAL;
@@ -1475,6 +1485,7 @@ void gpu_buddy_print(struct gpu_buddy *mm)
{
int order;
+ gpu_buddy_driver_lock_held(mm);
pr_info("chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n",
mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index a697cc227e28..a6067471dd56 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -3487,31 +3487,64 @@ static const char *dp_content_type_get_name(enum dp_content_type content_type)
}
}
+static const char *dp_sdp_type_get_name(unsigned char type)
+{
+ switch (type) {
+ case DP_SDP_AUDIO_TIMESTAMP:
+ return "Audio_TimeStamp";
+ case DP_SDP_AUDIO_STREAM:
+ return "Audio_Stream";
+ case DP_SDP_EXTENSION:
+ return "Extension";
+ case DP_SDP_AUDIO_COPYMANAGEMENT:
+ return "Audio_CopyManagement";
+ case DP_SDP_ISRC:
+ return "ISRC";
+ case DP_SDP_VSC:
+ return "VSC";
+ case DP_SDP_PPS:
+ return "PPS";
+ case DP_SDP_VSC_EXT_VESA:
+ return "VSC_EXT_VESA";
+ case DP_SDP_VSC_EXT_CEA:
+ return "VSC_EXT_CEA";
+ case DP_SDP_ADAPTIVE_SYNC:
+ return "Adaptive-Sync";
+ default:
+ return "Unknown";
+ }
+}
+
void drm_dp_vsc_sdp_log(struct drm_printer *p, const struct drm_dp_vsc_sdp *vsc)
{
- drm_printf(p, "DP SDP: VSC, revision %u, length %u\n",
- vsc->revision, vsc->length);
- drm_printf(p, " pixelformat: %s\n",
- dp_pixelformat_get_name(vsc->pixelformat));
- drm_printf(p, " colorimetry: %s\n",
- dp_colorimetry_get_name(vsc->pixelformat, vsc->colorimetry));
- drm_printf(p, " bpc: %u\n", vsc->bpc);
- drm_printf(p, " dynamic range: %s\n",
- dp_dynamic_range_get_name(vsc->dynamic_range));
- drm_printf(p, " content type: %s\n",
- dp_content_type_get_name(vsc->content_type));
+ drm_printf(p, "DP SDP: %s, revision %u, length %u\n",
+ dp_sdp_type_get_name(vsc->sdp_type), vsc->revision, vsc->length);
+
+ drm_printf_indent(p, 1, "pixelformat: %s\n",
+ dp_pixelformat_get_name(vsc->pixelformat));
+ drm_printf_indent(p, 1, "colorimetry: %s\n",
+ dp_colorimetry_get_name(vsc->pixelformat, vsc->colorimetry));
+ drm_printf_indent(p, 1, "bpc: %u\n", vsc->bpc);
+ drm_printf_indent(p, 1, "dynamic range: %s\n",
+ dp_dynamic_range_get_name(vsc->dynamic_range));
+ drm_printf_indent(p, 1, "content type: %s\n",
+ dp_content_type_get_name(vsc->content_type));
}
EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
void drm_dp_as_sdp_log(struct drm_printer *p, const struct drm_dp_as_sdp *as_sdp)
{
- drm_printf(p, "DP SDP: AS_SDP, revision %u, length %u\n",
- as_sdp->revision, as_sdp->length);
- drm_printf(p, " vtotal: %d\n", as_sdp->vtotal);
- drm_printf(p, " target_rr: %d\n", as_sdp->target_rr);
- drm_printf(p, " duration_incr_ms: %d\n", as_sdp->duration_incr_ms);
- drm_printf(p, " duration_decr_ms: %d\n", as_sdp->duration_decr_ms);
- drm_printf(p, " operation_mode: %d\n", as_sdp->mode);
+ drm_printf(p, "DP SDP: %s, revision %u, length %u\n",
+ dp_sdp_type_get_name(as_sdp->sdp_type), as_sdp->revision, as_sdp->length);
+
+ drm_printf_indent(p, 1, "vtotal: %d\n", as_sdp->vtotal);
+ drm_printf_indent(p, 1, "target rr: %d\n", as_sdp->target_rr);
+ drm_printf_indent(p, 1, "duration increase ms: %d\n", as_sdp->duration_incr_ms);
+ drm_printf_indent(p, 1, "duration decrease ms: %d\n", as_sdp->duration_decr_ms);
+ drm_printf_indent(p, 1, "operation mode: %d\n", as_sdp->mode);
+ drm_printf_indent(p, 1, "target rr divider: %s\n",
+ as_sdp->target_rr_divider ? "1.001" : "1.000");
+ drm_printf_indent(p, 1, "coasting vtotal: %d\n", as_sdp->coasting_vtotal);
}
EXPORT_SYMBOL(drm_dp_as_sdp_log);
@@ -4626,8 +4659,6 @@ static const struct backlight_ops dp_aux_bl_ops = {
* Backlight will then be handled transparently without requiring
* any intervention from the driver.
*
- * drm_panel_dp_aux_backlight() must be called after the call to drm_panel_init().
- *
* Return: 0 on success or a negative error code on failure.
*/
int drm_panel_dp_aux_backlight(struct drm_panel *panel, struct drm_dp_aux *aux)
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 35dc4f24ae53..fe72245fb9ca 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -789,6 +789,12 @@ static bool drm_dp_sideband_append_payload(struct drm_dp_sideband_msg_rx *msg,
{
u8 crc4;
+ /* curchunk_len must be >= 1 (min 1 CRC byte) and fit in chunk[] */
+ if (!msg->curchunk_len ||
+ msg->curchunk_len > ARRAY_SIZE(msg->chunk) ||
+ msg->curchunk_idx + replybuflen > ARRAY_SIZE(msg->chunk))
+ return false;
+
memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen);
msg->curchunk_idx += replybuflen;
@@ -799,6 +805,9 @@ static bool drm_dp_sideband_append_payload(struct drm_dp_sideband_msg_rx *msg,
print_hex_dump(KERN_DEBUG, "wrong crc",
DUMP_PREFIX_NONE, 16, 1,
msg->chunk, msg->curchunk_len, false);
+ /* Guard against accumulated msg[] overflow */
+ if (msg->curlen + msg->curchunk_len - 1 > ARRAY_SIZE(msg->msg))
+ return false;
/* copy chunk into bigger msg */
memcpy(&msg->msg[msg->curlen], msg->chunk, msg->curchunk_len - 1);
msg->curlen += msg->curchunk_len - 1;
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index 841f3de5f307..faa025498de4 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -42,6 +42,7 @@ void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p)
{
int order;
+ gpu_buddy_driver_lock_held(mm);
drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n",
mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 365a9c0b522a..958cb605aedd 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1556,10 +1556,7 @@ map_pages:
if (!i)
dma_iova_try_alloc(gpusvm->drm->dev, state,
- npages * PAGE_SIZE >=
- HPAGE_PMD_SIZE ?
- HPAGE_PMD_SIZE : 0,
- npages * PAGE_SIZE);
+ 0, npages * PAGE_SIZE);
if (dma_use_iova(state)) {
err = dma_iova_link(gpusvm->drm->dev, state,
diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
index d82ea7ccb8da..15c78eca180b 100644
--- a/drivers/gpu/drm/drm_pagemap.c
+++ b/drivers/gpu/drm/drm_pagemap.c
@@ -347,10 +347,7 @@ drm_pagemap_migrate_map_system_pages(struct device *dev,
if (!try_alloc) {
dma_iova_try_alloc(dev, &state->dma_state,
- (npages - i) * PAGE_SIZE >=
- HPAGE_PMD_SIZE ?
- HPAGE_PMD_SIZE : 0,
- npages * PAGE_SIZE);
+ 0, npages * PAGE_SIZE);
try_alloc = true;
}
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index a6029b699b73..04f4a31ed27a 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -56,8 +56,9 @@ static LIST_HEAD(panel_list);
* Initialize the panel structure for subsequent registration with
* drm_panel_add().
*/
-void drm_panel_init(struct drm_panel *panel, struct device *dev,
- const struct drm_panel_funcs *funcs, int connector_type)
+static void drm_panel_init(struct drm_panel *panel, struct device *dev,
+ const struct drm_panel_funcs *funcs,
+ int connector_type)
{
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev));
@@ -69,7 +70,6 @@ void drm_panel_init(struct drm_panel *panel, struct device *dev,
panel->funcs = funcs;
panel->connector_type = connector_type;
}
-EXPORT_SYMBOL(drm_panel_init);
/**
* drm_panel_add - add a panel to the global registry
@@ -731,7 +731,6 @@ EXPORT_SYMBOL(devm_drm_panel_add_follower);
* A typical implementation for a panel driver supporting device tree
* will call this function at probe time. Backlight will then be handled
* transparently without requiring any intervention from the driver.
- * drm_panel_of_backlight() must be called after the call to drm_panel_init().
*
* Return: 0 on success or a negative error code on failure.
*/
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 17c2dead2c13..89bd6ca36003 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -684,6 +684,7 @@ static int gud_resume(struct usb_interface *intf)
static const struct usb_device_id gud_id_table[] = {
{ USB_DEVICE_INTERFACE_CLASS(0x1d50, 0x614d, USB_CLASS_VENDOR_SPEC) },
{ USB_DEVICE_INTERFACE_CLASS(0x16d0, 0x10a9, USB_CLASS_VENDOR_SPEC) },
+ { USB_DEVICE_INTERFACE_CLASS(0x1209, 0x4fb3, USB_CLASS_VENDOR_SPEC) },
{ }
};
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
index f9ee7ebfec55..f53dac256ee0 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
@@ -69,5 +69,6 @@ int hibmc_dp_link_training(struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]);
+void hibmc_dp_update_caps(struct hibmc_dp_dev *dp);
#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
index 31316fe1ea8d..0f3662d8737e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
@@ -55,6 +55,7 @@ struct hibmc_dp {
struct drm_dp_aux aux;
struct hibmc_dp_cbar_cfg cfg;
u32 irq_status;
+ int phys_status;
};
int hibmc_dp_hw_init(struct hibmc_dp *dp);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
index 0726cb5b736e..8c53f16db516 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
@@ -325,7 +325,7 @@ static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp)
return hibmc_dp_link_reduce_rate(dp);
}
-static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp)
+void hibmc_dp_update_caps(struct hibmc_dp_dev *dp)
{
dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE];
if (dp->link.cap.link_rate > DP_LINK_BW_8_1 || !dp->link.cap.link_rate)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index e276b8ca213c..3066dc9ebc64 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -32,26 +32,43 @@ struct hibmc_display_panel_pll {
struct hibmc_dislay_pll_config {
u64 hdisplay;
u64 vdisplay;
+ int clock;
u32 pll1_config_value;
u32 pll2_config_value;
};
static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
- {640, 480, CRT_PLL1_HS_25MHZ, CRT_PLL2_HS_25MHZ},
- {800, 600, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
- {1024, 768, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
- {1152, 864, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
- {1280, 768, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
- {1280, 720, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
- {1280, 960, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
- {1280, 1024, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
- {1440, 900, CRT_PLL1_HS_106MHZ, CRT_PLL2_HS_106MHZ},
- {1600, 900, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
- {1600, 1200, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
- {1920, 1080, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
- {1920, 1200, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
+ {640, 480, 25000, CRT_PLL1_HS_25MHZ, CRT_PLL2_HS_25MHZ},
+ {800, 600, 40000, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
+ {1024, 768, 65000, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
+ {1152, 864, 78750, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
+ {1280, 768, 80000, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
+ {1280, 720, 74375, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
+ {1280, 960, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+ {1280, 1024, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+ {1440, 900, 105952, CRT_PLL1_HS_106MHZ, CRT_PLL2_HS_106MHZ},
+ {1600, 900, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+ {1600, 1200, 162500, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
+ {1920, 1080, 148750, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
+ {1920, 1200, 193750, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
};
+static int hibmc_get_best_clock_idx(const struct drm_display_mode *mode)
+{
+ int i, diff;
+
+ for (i = 0; i < ARRAY_SIZE(hibmc_pll_table); i++) {
+ if (hibmc_pll_table[i].hdisplay == mode->hdisplay &&
+ hibmc_pll_table[i].vdisplay == mode->vdisplay) {
+ diff = abs(mode->clock - hibmc_pll_table[i].clock);
+ if (diff < mode->clock / 100) /* tolerance 1/100 */
+ return i;
+ }
+ }
+
+ return -MODE_CLOCK_RANGE;
+}
+
static int hibmc_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
@@ -214,19 +231,15 @@ static enum drm_mode_status
hibmc_crtc_mode_valid(struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{
- size_t i = 0;
int vrefresh = drm_mode_vrefresh(mode);
if (vrefresh < 59 || vrefresh > 61)
return MODE_NOCLOCK;
- for (i = 0; i < ARRAY_SIZE(hibmc_pll_table); i++) {
- if (hibmc_pll_table[i].hdisplay == mode->hdisplay &&
- hibmc_pll_table[i].vdisplay == mode->vdisplay)
- return MODE_OK;
- }
+ if (hibmc_get_best_clock_idx(mode) >= 0)
+ return MODE_OK;
- return MODE_BAD;
+ return MODE_CLOCK_RANGE;
}
static u32 format_pll_reg(void)
@@ -281,23 +294,20 @@ static void set_vclock_hisilicon(struct drm_device *dev, u64 pll)
writel(val, priv->mmio + CRT_PLL1_HS);
}
-static void get_pll_config(u64 x, u64 y, u32 *pll1, u32 *pll2)
+static void get_pll_config(struct drm_display_mode *mode, u32 *pll1, u32 *pll2)
{
- size_t i;
- size_t count = ARRAY_SIZE(hibmc_pll_table);
-
- for (i = 0; i < count; i++) {
- if (hibmc_pll_table[i].hdisplay == x &&
- hibmc_pll_table[i].vdisplay == y) {
- *pll1 = hibmc_pll_table[i].pll1_config_value;
- *pll2 = hibmc_pll_table[i].pll2_config_value;
- return;
- }
+ int idx;
+
+ idx = hibmc_get_best_clock_idx(mode);
+ if (idx < 0) {
+ /* if found none, we use default value */
+ *pll1 = CRT_PLL1_HS_25MHZ;
+ *pll2 = CRT_PLL2_HS_25MHZ;
+ return;
}
- /* if found none, we use default value */
- *pll1 = CRT_PLL1_HS_25MHZ;
- *pll2 = CRT_PLL2_HS_25MHZ;
+ *pll1 = hibmc_pll_table[idx].pll1_config_value;
+ *pll2 = hibmc_pll_table[idx].pll2_config_value;
}
/*
@@ -319,7 +329,7 @@ static u32 display_ctrl_adjust(struct drm_device *dev,
x = mode->hdisplay;
y = mode->vdisplay;
- get_pll_config(x, y, &pll1, &pll2);
+ get_pll_config(mode, &pll1, &pll2);
writel(pll2, priv->mmio + CRT_PLL2_HS);
set_vclock_hisilicon(dev, pll1);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
index 2da04ac89d4d..2e9403b8bf3c 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
@@ -41,6 +41,8 @@ static bool hibmc_dp_get_dpcd(struct hibmc_dp_dev *dp_dev)
if (ret)
return false;
+ hibmc_dp_update_caps(dp_dev);
+
dp_dev->is_branch = drm_dp_is_branch(dp_dev->dpcd);
ret = drm_dp_read_desc(dp_dev->aux, &dp_dev->desc, dp_dev->is_branch);
@@ -59,27 +61,38 @@ static int hibmc_dp_detect(struct drm_connector *connector,
{
struct hibmc_dp *dp = to_hibmc_dp(connector);
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
- int ret;
+ int ret = connector_status_disconnected;
if (dp->irq_status) {
- if (dp_dev->hpd_status != HIBMC_HPD_IN)
- return connector_status_disconnected;
+ if (dp_dev->hpd_status != HIBMC_HPD_IN) {
+ ret = connector_status_disconnected;
+ goto exit;
+ }
}
- if (!hibmc_dp_get_dpcd(dp_dev))
- return connector_status_disconnected;
+ if (!hibmc_dp_get_dpcd(dp_dev)) {
+ ret = connector_status_disconnected;
+ goto exit;
+ }
- if (!dp_dev->is_branch)
- return connector_status_connected;
+ if (!dp_dev->is_branch) {
+ ret = connector_status_connected;
+ goto exit;
+ }
if (drm_dp_read_sink_count_cap(connector, dp_dev->dpcd, &dp_dev->desc) &&
dp_dev->downstream_ports[0] & DP_DS_PORT_HPD) {
ret = drm_dp_read_sink_count(dp_dev->aux);
- if (ret > 0)
- return connector_status_connected;
+ if (ret > 0) {
+ ret = connector_status_connected;
+ goto exit;
+ }
}
- return connector_status_disconnected;
+exit:
+ dp->phys_status = ret;
+
+ return ret;
}
static int hibmc_dp_mode_valid(struct drm_connector *connector,
@@ -241,5 +254,7 @@ int hibmc_dp_init(struct hibmc_drm_private *priv)
connector->polled = DRM_CONNECTOR_POLL_HPD;
+ dp->phys_status = connector_status_disconnected;
+
return 0;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 289304500ab0..99b36de1fe13 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -24,6 +24,7 @@
#include <drm/drm_managed.h>
#include <drm/drm_module.h>
#include <drm/drm_vblank.h>
+#include <drm/drm_probe_helper.h>
#include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h"
@@ -214,6 +215,15 @@ void hibmc_set_current_gate(struct hibmc_drm_private *priv, unsigned int gate)
writel(gate, mmio + gate_reg);
}
+static void hibmc_display_ctrl(struct hibmc_drm_private *priv)
+{
+ u32 reg;
+
+ reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
+ reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
+ writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
+}
+
static void hibmc_hw_config(struct hibmc_drm_private *priv)
{
u32 reg;
@@ -245,6 +255,8 @@ static void hibmc_hw_config(struct hibmc_drm_private *priv)
reg |= HIBMC_MSCCTL_LOCALMEM_RESET(1);
writel(reg, priv->mmio + HIBMC_MISC_CTRL);
+
+ hibmc_display_ctrl(priv);
}
static int hibmc_hw_map(struct hibmc_drm_private *priv)
@@ -355,6 +367,8 @@ static int hibmc_load(struct drm_device *dev)
/* reset all the states of crtc/plane/encoder/connector */
drm_mode_config_reset(dev);
+ drmm_kms_helper_poll_init(dev);
+
return 0;
err:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index ca8502e2760c..cd3a3fca1fe6 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -31,6 +31,7 @@ struct hibmc_vdac {
struct drm_connector connector;
struct i2c_adapter adapter;
struct i2c_algo_bit_data bit_data;
+ int phys_status;
};
struct hibmc_drm_private {
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index 841e81f47b68..b9bd6d33fb0f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -24,28 +24,21 @@
static int hibmc_connector_get_modes(struct drm_connector *connector)
{
+ struct drm_mode_config *mode_config = &connector->dev->mode_config;
struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
- const struct drm_edid *drm_edid;
int count;
- drm_edid = drm_edid_read_ddc(connector, &vdac->adapter);
-
- drm_edid_connector_update(connector, drm_edid);
-
- if (drm_edid) {
- count = drm_edid_connector_add_modes(connector);
+ if (vdac->phys_status == connector_status_connected) {
+ count = drm_connector_helper_get_modes(connector);
+ } else {
+ drm_edid_connector_update(connector, NULL);
+ count = drm_add_modes_noedid(connector,
+ mode_config->max_width,
+ mode_config->max_height);
if (count)
- goto out;
+ drm_set_preferred_mode(connector, 1024, 768);
}
- count = drm_add_modes_noedid(connector,
- connector->dev->mode_config.max_width,
- connector->dev->mode_config.max_height);
- drm_set_preferred_mode(connector, 1024, 768);
-
-out:
- drm_edid_free(drm_edid);
-
return count;
}
@@ -57,10 +50,34 @@ static void hibmc_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
}
+static int hibmc_vdac_detect(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool force)
+{
+ struct hibmc_drm_private *priv = to_hibmc_drm_private(connector->dev);
+ int status = drm_connector_helper_detect_from_ddc(connector, ctx,
+ force);
+ struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
+
+ if (priv->dp.phys_status == connector_status_connected) {
+ vdac->phys_status = status;
+ return status;
+ }
+
+ if (status != vdac->phys_status)
+ ++connector->epoch_counter;
+ vdac->phys_status = status;
+
+ /* When both the DP and VDAC physical status are disconnected,
+ * the "connected" status is returned to support KVM display.
+ */
+ return connector_status_connected;
+}
+
static const struct drm_connector_helper_funcs
hibmc_connector_helper_funcs = {
.get_modes = hibmc_connector_get_modes,
- .detect_ctx = drm_connector_helper_detect_from_ddc,
+ .detect_ctx = hibmc_vdac_detect,
};
static const struct drm_connector_funcs hibmc_connector_funcs = {
@@ -71,26 +88,6 @@ static const struct drm_connector_funcs hibmc_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
-{
- u32 reg;
- struct drm_device *dev = encoder->dev;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
-
- reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
- reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
- reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
- reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
- reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
- writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
-}
-
-static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
- .mode_set = hibmc_encoder_mode_set,
-};
-
int hibmc_vdac_init(struct hibmc_drm_private *priv)
{
struct drm_device *dev = &priv->dev;
@@ -113,8 +110,6 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
goto err;
}
- drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
-
ret = drm_connector_init_with_ddc(dev, connector,
&hibmc_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
@@ -130,6 +125,8 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+ vdac->phys_status = connector_status_disconnected;
+
return 0;
err:
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 86123614b7ba..ed17f6beae9a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5374,8 +5374,8 @@ int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp,
if ((sdp->sdp_header.HB3 & 0x3F) != 9)
return -EINVAL;
- as_sdp->length = sdp->sdp_header.HB3 & DP_ADAPTIVE_SYNC_SDP_LENGTH;
- as_sdp->mode = sdp->db[0] & DP_ADAPTIVE_SYNC_SDP_OPERATION_MODE;
+ as_sdp->length = sdp->sdp_header.HB3 & DP_AS_SDP_LENGTH_MASK;
+ as_sdp->mode = sdp->db[0] & DP_AS_SDP_OPERATION_MODE_MASK;
as_sdp->vtotal = (sdp->db[2] << 8) | sdp->db[1];
as_sdp->target_rr = (u64)sdp->db[3] | ((u64)sdp->db[4] & 0x3);
as_sdp->target_rr_divider = sdp->db[4] & 0x20 ? true : false;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c
index e736318fb0dc..cb74bbec5e9c 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/crc.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c
@@ -16,7 +16,6 @@
#include "nouveau_drv.h"
#include "core.h"
#include "head.h"
-#include "wndw.h"
#include "handles.h"
#include "crc.h"
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
index 6e63df816d85..1155f079b0c3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
@@ -1734,7 +1734,8 @@ r535_disp_new(const struct nvkm_disp_func *hw, struct nvkm_device *device,
struct nvkm_disp_func *rm;
int ret;
- if (!(rm = kzalloc(sizeof(*rm) + 6 * sizeof(rm->user[0]), GFP_KERNEL)))
+ rm = kzalloc_flex(*rm, user, 6);
+ if (!rm)
return -ENOMEM;
rm->dtor = r535_disp_dtor;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
index 958fd78080bd..107bdb642f22 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
@@ -53,7 +53,8 @@ nvkm_vmm_pt_new(const struct nvkm_vmm_desc *desc, bool sparse,
}
}
- if (!(pgt = kzalloc(sizeof(*pgt) + (sizeof(pgt->pte[0]) * lpte), GFP_KERNEL)))
+ pgt = kzalloc_flex(*pgt, pte, lpte);
+ if (!pgt)
return NULL;
pgt->page = page ? page->shift : 0;
pgt->sparse = sparse;
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index f3cdaea89b29..241915e9f495 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1918,6 +1918,7 @@ static const struct panel_delay delay_80_500_e50_d50 = {
* Sort first by vendor, then by product ID.
*/
static const struct edp_panel_entry edp_panels[] = {
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0x0290, &delay_200_500_e50, "B140XTN07.5"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x04a4, &delay_200_500_e50, "B122UAN01.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x0ba4, &delay_200_500_e50, "B140QAX01.H"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x105c, &delay_200_500_e50, "B116XTN01.0"),
@@ -1934,17 +1935,20 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('A', 'U', 'O', 0x239b, &delay_200_500_e50, "B116XAN06.1"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x255c, &delay_200_500_e50, "B116XTN02.5"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x30ed, &delay_200_500_e50, "G156HAN03.0"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0x3c9f, &delay_200_500_e50, "B140HAK03.5"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x403d, &delay_200_500_e50, "B140HAN04.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAN04.0"),
EDP_PANEL_ENTRY2('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0",
&auo_b116xa3_mode),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x435c, &delay_200_500_e50, "Unknown"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0x49ba, &delay_200_500_e50, "B116XTN02.3"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x52b0, &delay_200_500_e50, "B116XAK02.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x582d, &delay_200_500_e50, "B133UAN01.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x635c, &delay_200_500_e50, "B116XAN06.3"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x639c, &delay_200_500_e50, "B140HAK02.7"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x643d, &delay_200_500_e50, "B140HAN06.4"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0x67a8, &delay_200_500_e50, "B140XTK02.4"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x723c, &delay_200_500_e50, "B140XTN07.2"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x73aa, &delay_200_500_e50, "B116XTN02.3"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"),
@@ -1954,7 +1958,9 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('A', 'U', 'O', 0xa7b3, &delay_200_500_e50, "B140UAN04.4"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0xb7a9, &delay_200_500_e50, "B140HAK03.3"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0xc4b4, &delay_200_500_e50, "B116XAT04.1"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0xc7ad, &delay_200_500_e50, "B140HAN07.7"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0xc9a8, &delay_200_500_e50, "B140QAN08.H"),
+ EDP_PANEL_ENTRY('A', 'U', 'O', 0xcb8f, &delay_200_500_e50, "B133HAN06.6"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0xcdba, &delay_200_500_e50, "B140UAX01.2"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0xd497, &delay_200_500_e50, "B120XAN01.0"),
EDP_PANEL_ENTRY('A', 'U', 'O', 0xf390, &delay_200_500_e50, "B140XTN07.7"),
@@ -1990,6 +1996,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x08b2, &delay_200_500_e200, "NT140WHM-N49"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0848, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0849, &delay_200_500_e200, "Unknown"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x090d, &delay_200_500_e50, "NT140WHM-N4T"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x09c3, &delay_200_500_e50, "NT116WHM-N21,836X2"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x094b, &delay_200_500_e50, "NT116WHM-N21"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0951, &delay_200_500_e80, "NV116WHM-N47"),
@@ -2003,6 +2010,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x09ae, &delay_200_500_e200, "NT140FHM-N45"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x09dd, &delay_200_500_e50, "NT116WHM-N21"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a1b, &delay_200_500_e50, "NV133WUM-N63"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a25, &delay_200_500_e50_po2e200, "NV133FHM-N4F V8.0"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a36, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a3e, &delay_200_500_e80_d50, "NV116WHM-N49"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"),
@@ -2016,8 +2024,10 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b43, &delay_200_500_e200, "NV140FHM-T09"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b56, &delay_200_500_e80, "NT140FHM-N47"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b66, &delay_200_500_e80, "NE140WUM-N6G"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b85, &delay_200_500_e50, "NT140WHM-T05"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0c20, &delay_200_500_e80, "NT140FHM-N47"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0c26, &delay_200_500_p2e200, "NV140WUM-T08"),
+ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0c6f, &delay_200_500_e50, "NV140FHM-N40"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0c93, &delay_200_500_e200, "Unknown"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0cb6, &delay_200_500_e200, "NT116WHM-N44"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0cf2, &delay_200_500_e200, "NV156FHM-N4S"),
@@ -2048,6 +2058,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1160, &delay_200_500_e80_d50, "N116BCJ-EAK"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1161, &delay_200_500_e80, "N116BCP-EA2"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1163, &delay_200_500_e80_d50, "N116BCJ-EAK"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x1169, &delay_200_500_e80_d50, "N116BCN-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x117a, &delay_200_500_e80_d50, "N116BCL-EAK"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x124c, &delay_200_500_e80_d50, "N122JCA-ENK"),
@@ -2058,8 +2069,9 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1468, &delay_200_500_e80, "N140HGA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x148f, &delay_200_500_e80, "N140HCA-EAC"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x14a8, &delay_200_500_e80, "N140JCA-ELP"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x14c7, &delay_200_500_e80, "N140HCA-EEK"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d4, &delay_200_500_e80_d50, "N140HCA-EAC"),
- EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d6, &delay_200_500_e80_d50, "N140BGA-EA4"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d6, &delay_200_500_e80, "N140BGA-E54"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1565, &delay_200_500_e80, "N156HCA-EAB"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x156b, &delay_200_500_e80_d50, "N153JCA-ELK"),
@@ -2095,6 +2107,8 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('I', 'V', 'O', 0x854a, &delay_200_500_p2e100, "M133NW4J"),
EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "R133NW4K-R0"),
EDP_PANEL_ENTRY('I', 'V', 'O', 0x8c4d, &delay_200_150_e200, "R140NWFM R1"),
+ EDP_PANEL_ENTRY('I', 'V', 'O', 0x8cd5, &delay_200_500_e200_d10, "M140NWFQ R5"),
+ EDP_PANEL_ENTRY('I', 'V', 'O', 0x8ce6, &delay_200_500_e200, "R140NWFW R0"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x044f, &delay_200_500_e80_d50, "Unknown"),
EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c
index be2cf1440155..53e25d1086db 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e-core.c
@@ -78,9 +78,11 @@ int ili9806e_probe(struct device *dev, void *transport,
bool set_prepare_prev_first = false;
int ret;
- ctx = devm_kzalloc(dev, sizeof(struct ili9806e), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
+ ctx = devm_drm_panel_alloc(dev, __typeof(*ctx), panel,
+ funcs, connector_type);
+
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
dev_set_drvdata(dev, ctx);
ctx->transport = transport;
@@ -103,8 +105,6 @@ int ili9806e_probe(struct device *dev, void *transport,
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
"Failed to get reset-gpios\n");
- drm_panel_init(&ctx->panel, dev, funcs, connector_type);
-
ret = drm_panel_of_backlight(&ctx->panel);
if (ret)
return dev_err_probe(dev, ret, "Failed to get backlight\n");
diff --git a/drivers/gpu/drm/panel/panel-lxd-m9189a.c b/drivers/gpu/drm/panel/panel-lxd-m9189a.c
index 68019e1e43a9..baaf170779e0 100644
--- a/drivers/gpu/drm/panel/panel-lxd-m9189a.c
+++ b/drivers/gpu/drm/panel/panel-lxd-m9189a.c
@@ -165,9 +165,12 @@ static int lxd_m9189_probe(struct mipi_dsi_device *dsi)
struct m9189_panel *m9189;
int ret;
- m9189 = devm_kzalloc(dev, sizeof(*m9189), GFP_KERNEL);
- if (!m9189)
- return -ENOMEM;
+ m9189 = devm_drm_panel_alloc(dev, __typeof(*m9189), panel,
+ &m9189_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ if (IS_ERR(m9189))
+ return PTR_ERR(m9189);
m9189->supply = devm_regulator_get(dev, "power");
if (IS_ERR(m9189->supply))
@@ -191,8 +194,6 @@ static int lxd_m9189_probe(struct mipi_dsi_device *dsi)
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;
- drm_panel_init(&m9189->panel, dev, &m9189_panel_funcs,
- DRM_MODE_CONNECTOR_DSI);
m9189->panel.prepare_prev_first = true;
ret = drm_panel_of_backlight(&m9189->panel);
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt37700f.c b/drivers/gpu/drm/panel/panel-novatek-nt37700f.c
index 74f46a268c0f..c221dd498fed 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt37700f.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt37700f.c
@@ -225,9 +225,12 @@ static int nt37700f_tianma_probe(struct mipi_dsi_device *dsi)
struct nt37700f_tianma *ctx;
int ret;
- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
+ ctx = devm_drm_panel_alloc(dev, __typeof(*ctx), panel,
+ &nt37700f_tianma_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
ctx->supply = devm_regulator_get(dev, "power");
if (IS_ERR(ctx->supply))
@@ -247,8 +250,6 @@ static int nt37700f_tianma_probe(struct mipi_dsi_device *dsi)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
- drm_panel_init(&ctx->panel, dev, &nt37700f_tianma_panel_funcs,
- DRM_MODE_CONNECTOR_DSI);
ctx->panel.prepare_prev_first = true;
ctx->panel.backlight = nt37700f_tianma_create_backlight(dsi);
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
index ea241c89593b..997115b1e541 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -677,9 +677,13 @@ int s6e63m0_probe(struct device *dev, void *trsp,
u32 max_brightness;
int ret;
- ctx = devm_kzalloc(dev, sizeof(struct s6e63m0), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
+ ctx = devm_drm_panel_alloc(dev, __typeof(*ctx), panel,
+ &s6e63m0_drm_funcs,
+ dsi_mode ? DRM_MODE_CONNECTOR_DSI :
+ DRM_MODE_CONNECTOR_DPI);
+
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
ctx->transport_data = trsp;
ctx->dsi_mode = dsi_mode;
@@ -712,10 +716,6 @@ int s6e63m0_probe(struct device *dev, void *trsp,
return PTR_ERR(ctx->reset_gpio);
}
- drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs,
- dsi_mode ? DRM_MODE_CONNECTOR_DSI :
- DRM_MODE_CONNECTOR_DPI);
-
ret = s6e63m0_backlight_register(ctx, max_brightness);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index dd1eaba23ad3..989b030ea22d 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -199,8 +199,6 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
gpiod_set_value(sharp_nt->reset_gpio, 0);
}
- drm_panel_init(&sharp_nt->base, &sharp_nt->dsi->dev,
- &sharp_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
sharp_nt->base.prepare_prev_first = true;
ret = drm_panel_of_backlight(&sharp_nt->base);
@@ -231,9 +229,12 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
MIPI_DSI_CLOCK_NON_CONTINUOUS |
MIPI_DSI_MODE_NO_EOT_PACKET;
- sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
- if (!sharp_nt)
- return -ENOMEM;
+ sharp_nt = devm_drm_panel_alloc(&dsi->dev, __typeof(*sharp_nt), base,
+ &sharp_nt_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ if (IS_ERR(sharp_nt))
+ return PTR_ERR(sharp_nt);
mipi_dsi_set_drvdata(dsi, sharp_nt);
diff --git a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
index c0c95355b743..7f04b7b404e7 100644
--- a/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
+++ b/drivers/gpu/drm/panel/panel-startek-kd070fhfid015.c
@@ -286,9 +286,6 @@ static int stk_panel_add(struct stk_panel *stk)
return ret;
}
- drm_panel_init(&stk->base, &stk->dsi->dev, &stk_panel_funcs,
- DRM_MODE_CONNECTOR_DSI);
-
drm_panel_add(&stk->base);
return 0;
@@ -303,9 +300,12 @@ static int stk_panel_probe(struct mipi_dsi_device *dsi)
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM);
- stk = devm_kzalloc(&dsi->dev, sizeof(*stk), GFP_KERNEL);
- if (!stk)
- return -ENOMEM;
+ stk = devm_drm_panel_alloc(&dsi->dev, __typeof(*stk), base,
+ &stk_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ if (IS_ERR(stk))
+ return PTR_ERR(stk);
mipi_dsi_set_drvdata(dsi, stk);
diff --git a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
index 227f97f9b136..13cfe252a838 100644
--- a/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
+++ b/drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
@@ -162,9 +162,6 @@ static int tdo_tl070wsh30_panel_add(struct tdo_tl070wsh30_panel *tdo_tl070wsh30)
return err;
}
- drm_panel_init(&tdo_tl070wsh30->base, &tdo_tl070wsh30->link->dev,
- &tdo_tl070wsh30_panel_funcs, DRM_MODE_CONNECTOR_DSI);
-
err = drm_panel_of_backlight(&tdo_tl070wsh30->base);
if (err)
return err;
@@ -183,10 +180,13 @@ static int tdo_tl070wsh30_panel_probe(struct mipi_dsi_device *dsi)
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM;
- tdo_tl070wsh30 = devm_kzalloc(&dsi->dev, sizeof(*tdo_tl070wsh30),
- GFP_KERNEL);
- if (!tdo_tl070wsh30)
- return -ENOMEM;
+ tdo_tl070wsh30 = devm_drm_panel_alloc(&dsi->dev,
+ __typeof(*tdo_tl070wsh30), base,
+ &tdo_tl070wsh30_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ if (IS_ERR(tdo_tl070wsh30))
+ return PTR_ERR(tdo_tl070wsh30);
mipi_dsi_set_drvdata(dsi, tdo_tl070wsh30);
tdo_tl070wsh30->link = dsi;
diff --git a/drivers/gpu/drm/panel/panel-truly-nt35597.c b/drivers/gpu/drm/panel/panel-truly-nt35597.c
index d447db912a61..f740b9257c09 100644
--- a/drivers/gpu/drm/panel/panel-truly-nt35597.c
+++ b/drivers/gpu/drm/panel/panel-truly-nt35597.c
@@ -476,8 +476,6 @@ static int truly_nt35597_panel_add(struct truly_nt35597 *ctx)
/* dual port */
gpiod_set_value(ctx->mode_gpio, 0);
- drm_panel_init(&ctx->panel, dev, &truly_nt35597_drm_funcs,
- DRM_MODE_CONNECTOR_DSI);
drm_panel_add(&ctx->panel);
return 0;
@@ -523,10 +521,12 @@ static int truly_nt35597_probe(struct mipi_dsi_device *dsi)
.node = NULL,
};
- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ ctx = devm_drm_panel_alloc(dev, __typeof(*ctx), panel,
+ &truly_nt35597_drm_funcs,
+ DRM_MODE_CONNECTOR_DSI);
- if (!ctx)
- return -ENOMEM;
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
/*
* This device represents itself as one with two input ports which are
diff --git a/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c b/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c
index 413849f7b4de..d5555a173157 100644
--- a/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c
+++ b/drivers/gpu/drm/panel/panel-visionox-g2647fb105.c
@@ -207,9 +207,12 @@ static int visionox_g2647fb105_probe(struct mipi_dsi_device *dsi)
struct visionox_g2647fb105 *ctx;
int ret;
- ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
+ ctx = devm_drm_panel_alloc(dev, __typeof(*ctx), panel,
+ &visionox_g2647fb105_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
ret = devm_regulator_bulk_get_const(dev,
ARRAY_SIZE(visionox_g2647fb105_supplies),
@@ -233,10 +236,6 @@ static int visionox_g2647fb105_probe(struct mipi_dsi_device *dsi)
ctx->panel.prepare_prev_first = true;
- drm_panel_init(&ctx->panel, dev, &visionox_g2647fb105_panel_funcs,
- DRM_MODE_CONNECTOR_DSI);
- ctx->panel.prepare_prev_first = true;
-
ctx->panel.backlight = visionox_g2647fb105_create_backlight(dsi);
if (IS_ERR(ctx->panel.backlight))
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index a7ee14986849..452d0b6d4668 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -2377,14 +2377,20 @@ int panthor_vm_evict_bo_mappings_locked(struct panthor_gem_object *bo)
struct panthor_vm *vm = container_of(vm_bo->vm, struct panthor_vm, base);
struct drm_gpuva *va;
- /* Skip already evicted GPU mappings. */
- if (vm_bo->evicted)
- continue;
-
if (!mutex_trylock(&vm->op_lock))
return -EDEADLK;
- drm_gpuvm_bo_evict(vm_bo, true);
+ /* It can be that the vm_bo was already evicted but a new
+ * mapping pointing to this BO got created in the meantime,
+ * thus turning the vm_bo in partially evicted state. In that case
+ * we don't call drm_gpuvm_bo_evict() again because this would
+ * mess up with the internal gpuvm lists, but we do walk the
+ * VAs on this vm_bo to make sure the non-evicted ones are
+ * torn down.
+ */
+ if (!vm_bo->evicted)
+ drm_gpuvm_bo_evict(vm_bo, true);
+
drm_gpuvm_bo_for_each_va(va, vm_bo) {
struct panthor_vma *vma = container_of(va, struct panthor_vma, base);
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index f17660a71a3e..6f49213e23f8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -84,6 +84,7 @@ struct virtio_gpu_object_params {
uint32_t blob_mem;
uint32_t blob_flags;
uint64_t blob_id;
+ uint32_t blob_hints;
};
struct virtio_gpu_object {
@@ -507,6 +508,7 @@ struct sg_table *virtio_gpu_vram_map_dma_buf(struct virtio_gpu_object *bo,
void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
struct sg_table *sgt,
enum dma_data_direction dir);
+void virtio_gpu_vram_map_deferred(struct virtio_gpu_object_vram *vram);
/* virtgpu_submit.c */
int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index c33c057365f8..01daa72b1310 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -489,6 +489,7 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
params->size = rc_blob->size;
params->blob = true;
params->blob_flags = rc_blob->blob_flags;
+ params->blob_hints = rc_blob->blob_hints;
return 0;
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_vram.c b/drivers/gpu/drm/virtio/virtgpu_vram.c
index 084e80227433..4ae3cbc35dd3 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vram.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vram.c
@@ -3,6 +3,8 @@
#include <linux/dma-mapping.h>
+static DEFINE_MUTEX(map_lock);
+
static void virtio_gpu_vram_free(struct drm_gem_object *obj)
{
struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
@@ -42,6 +44,11 @@ static int virtio_gpu_vram_mmap(struct drm_gem_object *obj,
if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
return -EINVAL;
+ virtio_gpu_vram_map_deferred(vram);
+
+ if (vram->map_state == STATE_INITIALIZING)
+ virtio_gpu_notify(vgdev);
+
wait_event(vgdev->resp_wq, vram->map_state != STATE_INITIALIZING);
if (vram->map_state != STATE_OK)
return -EINVAL;
@@ -218,14 +225,27 @@ int virtio_gpu_vram_create(struct virtio_gpu_device *vgdev,
virtio_gpu_cmd_resource_create_blob(vgdev, &vram->base, params, NULL,
0);
- if (params->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE) {
- ret = virtio_gpu_vram_map(&vram->base);
- if (ret) {
- virtio_gpu_vram_free(obj);
- return ret;
+ if (!(params->blob_hints & DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING)) {
+ if (params->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE) {
+ ret = virtio_gpu_vram_map(&vram->base);
+ if (ret) {
+ virtio_gpu_vram_free(obj);
+ return ret;
+ }
}
}
*bo_ptr = &vram->base;
return 0;
}
+
+void virtio_gpu_vram_map_deferred(struct virtio_gpu_object_vram *vram)
+{
+ if (!(vram->base.blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
+ return;
+
+ mutex_lock(&map_lock);
+ if (!drm_mm_node_allocated(&vram->vram_node))
+ virtio_gpu_vram_map(&vram->base);
+ mutex_unlock(&map_lock);
+}
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
index 6ba47996bc7c..9f67df646955 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -322,6 +322,7 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,
if (err)
return err;
+ gpu_buddy_driver_set_lock(&mgr->mm, &mgr->lock);
ttm_set_driver_manager(&xe->ttm, mem_type, &mgr->manager);
ttm_resource_manager_set_used(&mgr->manager, true);
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 8b15d3eeb716..829e4d98d61c 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -718,6 +718,12 @@
#define DP_EXTENDED_DPRX_SLEEP_WAKE_TIMEOUT_GRANT 0x119 /* 1.4a */
# define DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_GRANTED (1 << 0)
+#define PANEL_REPLAY_CONFIG3 0x11a /* DP 2.1 */
+# define DP_PR_AS_SDP_SETUP_TIME_MASK (3 << 6)
+# define DP_PR_AS_SDP_SETUP_TIME_T1 (0 << 6)
+# define DP_PR_AS_SDP_SETUP_TIME_DYNAMIC (1 << 6) /* DP 2.1 Table 2-227 */
+# define DP_PR_AS_SDP_SETUP_TIME_T2 (2 << 6)
+
#define DP_FEC_CONFIGURATION 0x120 /* 1.4 */
# define DP_FEC_READY (1 << 0)
# define DP_FEC_ERR_COUNT_SEL_MASK (7 << 1)
@@ -1202,12 +1208,11 @@
# define DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_80_MS 0x04
# define DP_DPRX_SLEEP_WAKE_TIMEOUT_PERIOD_100_MS 0x05
-#define DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1 0x2214 /* 2.0 E11 */
-# define DP_ADAPTIVE_SYNC_SDP_SUPPORTED (1 << 0)
-# define DP_ADAPTIVE_SYNC_SDP_OPERATION_MODE GENMASK(1, 0)
-# define DP_ADAPTIVE_SYNC_SDP_LENGTH GENMASK(5, 0)
-# define DP_AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED (1 << 1)
-# define DP_VSC_EXT_SDP_FRAMEWORK_VERSION_1_SUPPORTED (1 << 4)
+#define DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1 0x2214 /* 2.0 E11 */
+# define DP_ADAPTIVE_SYNC_SDP_SUPPORTED BIT(0)
+# define DP_AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED BIT(1)
+# define DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED BIT(2) /* 2.1 */
+# define DP_VSC_EXT_SDP_FRAMEWORK_VERSION_1_SUPPORTED BIT(4)
#define DP_128B132B_SUPPORTED_LINK_RATES 0x2215 /* 2.0 */
# define DP_UHBR10 (1 << 0)
@@ -1870,4 +1875,7 @@ enum operation_mode {
DP_AS_SDP_FAVT_TRR_REACHED = 0x03
};
+#define DP_AS_SDP_OPERATION_MODE_MASK GENMASK(1, 0)
+#define DP_AS_SDP_LENGTH_MASK GENMASK(5, 0)
+
#endif /* _DRM_DP_H_ */
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index 1d0acd58f486..8c2d77a032f0 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -126,6 +126,7 @@ struct drm_dp_as_sdp {
int duration_decr_ms;
bool target_rr_divider;
enum operation_mode mode;
+ int coasting_vtotal;
};
void drm_dp_as_sdp_log(struct drm_printer *p,
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 1fb9148dd095..86b3f9c65c92 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -320,10 +320,6 @@ void *__devm_drm_panel_alloc(struct device *dev, size_t size, size_t offset,
offsetof(type, member), funcs, \
connector_type))
-void drm_panel_init(struct drm_panel *panel, struct device *dev,
- const struct drm_panel_funcs *funcs,
- int connector_type);
-
struct drm_panel *drm_panel_get(struct drm_panel *panel);
void drm_panel_put(struct drm_panel *panel);
diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h
index b510a4812609..ab2639e42c54 100644
--- a/include/drm/ttm/ttm_placement.h
+++ b/include/drm/ttm/ttm_placement.h
@@ -81,8 +81,8 @@
* Structure indicating a possible place to put an object.
*/
struct ttm_place {
- unsigned fpfn;
- unsigned lpfn;
+ uint64_t fpfn;
+ uint64_t lpfn;
uint32_t mem_type;
uint32_t flags;
};
diff --git a/include/linux/gpu_buddy.h b/include/linux/gpu_buddy.h
index 5fa917ba5450..71941a039648 100644
--- a/include/linux/gpu_buddy.h
+++ b/include/linux/gpu_buddy.h
@@ -154,6 +154,7 @@ struct gpu_buddy_block {
* @avail: Total free space currently available for allocation in bytes.
* @clear_avail: Free space available in the clear tree (zeroed memory) in bytes.
* This is a subset of @avail.
+ * @lock_dep_map: Annotates gpu_buddy API with a driver provided lock.
*/
struct gpu_buddy {
/* private: */
@@ -179,8 +180,48 @@ struct gpu_buddy {
u64 size;
u64 avail;
u64 clear_avail;
+#ifdef CONFIG_LOCKDEP
+ struct lockdep_map *lock_dep_map;
+#endif
};
+#ifdef CONFIG_LOCKDEP
+/**
+ * gpu_buddy_driver_set_lock() - Set the lock protecting accesses to GPU BUDDY
+ * @mm: Pointer to GPU buddy structure.
+ * @lock: the lock used to protect the gpu buddy. The locking primitive
+ * must contain a dep_map field.
+ *
+ * Call this to annotate gpu_buddy APIs which access/modify gpu_buddy manager
+ */
+#define gpu_buddy_driver_set_lock(mm, lock) \
+ do { \
+ struct gpu_buddy *__mm = (mm); \
+ if (!WARN(__mm->lock_dep_map, "GPU BUDDY MM lock should be set only once.")) \
+ __mm->lock_dep_map = &(lock)->dep_map; \
+ } while (0)
+#else
+#define gpu_buddy_driver_set_lock(mm, lock) do { (void)(mm); (void)(lock); } while (0)
+#endif
+
+#ifdef CONFIG_LOCKDEP
+/**
+ * gpu_buddy_driver_lock_held() - Assert GPU BUDDY manager lock is held
+ * @mm: Pointer to the GPU BUDDY structure.
+ *
+ * Ensure driver lock is held.
+ */
+static inline void gpu_buddy_driver_lock_held(struct gpu_buddy *mm)
+{
+ if (mm->lock_dep_map)
+ lockdep_assert(lock_is_held_type(mm->lock_dep_map, 0));
+}
+#else
+static inline void gpu_buddy_driver_lock_held(struct gpu_buddy *mm)
+{
+}
+#endif
+
static inline u64
gpu_buddy_block_offset(const struct gpu_buddy_block *block)
{
diff --git a/include/uapi/drm/amdxdna_accel.h b/include/uapi/drm/amdxdna_accel.h
index 0b11e8e3ea5d..51a507561df6 100644
--- a/include/uapi/drm/amdxdna_accel.h
+++ b/include/uapi/drm/amdxdna_accel.h
@@ -18,6 +18,7 @@ extern "C" {
#define AMDXDNA_INVALID_CTX_HANDLE 0
#define AMDXDNA_INVALID_BO_HANDLE 0
#define AMDXDNA_INVALID_FENCE_HANDLE 0
+#define AMDXDNA_INVALID_DOORBELL_OFFSET (~0U)
/*
* Define hardware context priority
@@ -30,6 +31,7 @@ extern "C" {
enum amdxdna_device_type {
AMDXDNA_DEV_TYPE_UNKNOWN = -1,
AMDXDNA_DEV_TYPE_KMQ = 0,
+ AMDXDNA_DEV_TYPE_UMQ = 1,
AMDXDNA_DEV_TYPE_PF = 2,
};
@@ -43,7 +45,8 @@ enum amdxdna_drm_ioctl_id {
DRM_AMDXDNA_EXEC_CMD,
DRM_AMDXDNA_GET_INFO,
DRM_AMDXDNA_SET_STATE,
- DRM_AMDXDNA_GET_ARRAY = 10,
+ DRM_AMDXDNA_WAIT_CMD,
+ DRM_AMDXDNA_GET_ARRAY,
};
/**
@@ -273,6 +276,21 @@ struct amdxdna_drm_exec_cmd {
};
/**
+ * struct amdxdna_drm_wait_cmd - Wait execution command.
+ *
+ * @hwctx: Context handle.
+ * @timeout: timeout in ms, 0 implies infinite wait.
+ * @seq: sequence number of the command returned by execute command.
+ *
+ * Wait a command specified by seq to be completed.
+ */
+struct amdxdna_drm_wait_cmd {
+ __u32 hwctx;
+ __u32 timeout;
+ __u64 seq;
+};
+
+/**
* struct amdxdna_drm_query_aie_status - Query the status of the AIE hardware
* @buffer: The user space buffer that will return the AIE status.
* @buffer_size: The size of the user space buffer.
@@ -737,6 +755,10 @@ struct amdxdna_drm_set_power_mode {
DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDXDNA_GET_ARRAY, \
struct amdxdna_drm_get_array)
+#define DRM_IOCTL_AMDXDNA_WAIT_CMD \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_AMDXDNA_WAIT_CMD, \
+ struct amdxdna_drm_wait_cmd)
+
#if defined(__cplusplus)
} /* extern c end */
#endif
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 15aa0a8f44b0..3a4d4dc635bf 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -224,9 +224,9 @@ extern "C" {
* [31:0] sign:exponent:mantissa 1:8:23
*/
#define DRM_FORMAT_R32F fourcc_code('R', ' ', ' ', 'F') /* [31:0] R 32 little endian */
-#define DRM_FORMAT_GR3232F fourcc_code('G', 'R', ' ', 'F') /* [63:0] R:G 32:32 little endian */
-#define DRM_FORMAT_BGR323232F fourcc_code('B', 'G', 'R', 'F') /* [95:0] R:G:B 32:32:32 little endian */
-#define DRM_FORMAT_ABGR32323232F fourcc_code('A', 'B', '8', 'F') /* [127:0] R:G:B:A 32:32:32:32 little endian */
+#define DRM_FORMAT_GR3232F fourcc_code('G', 'R', ' ', 'F') /* [63:0] G:R 32:32 little endian */
+#define DRM_FORMAT_BGR323232F fourcc_code('B', 'G', 'R', 'F') /* [95:0] B:G:R 32:32:32 little endian */
+#define DRM_FORMAT_ABGR32323232F fourcc_code('A', 'B', '8', 'F') /* [127:0] A:B:G:R 32:32:32:32 little endian */
/*
* RGBA format with 10-bit components packed in 64-bit per pixel, with 6 bits
diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
index 9debb320c34b..ba09a4ee3e77 100644
--- a/include/uapi/drm/virtgpu_drm.h
+++ b/include/uapi/drm/virtgpu_drm.h
@@ -200,6 +200,10 @@ struct drm_virtgpu_resource_create_blob {
__u32 cmd_size;
__u64 cmd;
__u64 blob_id;
+
+#define DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING 0x0001
+ __u32 blob_hints;
+ __u32 pad2;
};
#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001