* [Intel-xe] [PATCH 0/3] Add support for XeLink device
@ 2023-08-08 16:45 David Kershner
2023-08-08 16:45 ` [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink David Kershner
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: David Kershner @ 2023-08-08 16:45 UTC (permalink / raw)
To: david.kershner, intel-xe, michael.j.ruhl, john.fleck,
lucas.demarchi, rodrigo.vivi, matthew.d.roper, matthew.brost
First patch set introduce the needed Xe infrastructure to support
XeLink device.
The XeLink device is a glue-less module attached to a GPU device that
provides connectivity between different GPUs on the same system.
The XeLink is part of the GPU (the register space is part of the GPU
PCIe BAR), so it cannot be a completely separate device driver.
The Linux kernel provides an interface for handling this type of
device, the Auxiliary Bus API.
The Xe and XeLink will use the auxiliary bus to enable the XeLink
and the Xe to probe and communicate.
A followup series will include the XeLink driver code to provide
full functionality for the device.
David Kershner (3):
drm/xe: Introduce a module parameter to control XeLink
drm/xe: Introduce XeLink device
drm/xe: Teach i915 how to use objects with XeLink connectivity
drivers/gpu/drm/xe/Kconfig | 1 +
drivers/gpu/drm/xe/Makefile | 3 +-
drivers/gpu/drm/xe/regs/xe_gt_regs.h | 20 ++
drivers/gpu/drm/xe/xe_bo.c | 47 ++-
drivers/gpu/drm/xe/xe_bo.h | 2 +
drivers/gpu/drm/xe/xe_device.c | 13 +-
drivers/gpu/drm/xe/xe_device_types.h | 27 ++
drivers/gpu/drm/xe/xe_dma_buf.c | 162 ++++++---
drivers/gpu/drm/xe/xe_dma_buf.h | 3 +
drivers/gpu/drm/xe/xe_gt_types.h | 2 +
drivers/gpu/drm/xe/xe_irq.c | 28 +-
drivers/gpu/drm/xe/xe_mmio.c | 2 +-
drivers/gpu/drm/xe/xe_pci.c | 2 +
drivers/gpu/drm/xe/xe_pci_types.h | 1 +
drivers/gpu/drm/xe/xe_pt.c | 7 +-
drivers/gpu/drm/xe/xe_xelink.c | 476 +++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_xelink.h | 38 +++
include/drm/intel_xelink_platform.h | 140 ++++++++
18 files changed, 921 insertions(+), 53 deletions(-)
create mode 100644 drivers/gpu/drm/xe/xe_xelink.c
create mode 100644 drivers/gpu/drm/xe/xe_xelink.h
create mode 100644 include/drm/intel_xelink_platform.h
--
2.35.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink
2023-08-08 16:45 [Intel-xe] [PATCH 0/3] Add support for XeLink device David Kershner
@ 2023-08-08 16:45 ` David Kershner
2023-08-08 18:43 ` Rodrigo Vivi
2023-08-09 3:19 ` Matthew Brost
2023-08-08 16:45 ` [Intel-xe] [PATCH 2/3] drm/xe: Introduce XeLink device David Kershner
2023-08-08 16:45 ` [Intel-xe] [PATCH 3/3] drm/xe: Teach i915 how to use objects with XeLink connectivity David Kershner
2 siblings, 2 replies; 10+ messages in thread
From: David Kershner @ 2023-08-08 16:45 UTC (permalink / raw)
To: david.kershner, intel-xe, michael.j.ruhl, john.fleck,
lucas.demarchi, rodrigo.vivi, matthew.d.roper, matthew.brost
Add a new module parameter to control enable/disable of the XeLink
feature.
Signed-off-by: David Kershner <david.kershner@intel.com>
---
drivers/gpu/drm/xe/Makefile | 3 ++-
drivers/gpu/drm/xe/xe_xelink.c | 17 +++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/xe/xe_xelink.c
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 1b59702cd9f9..d46558cf12a9 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -115,7 +115,8 @@ xe-y += xe_bb.o \
xe_vm_madvise.o \
xe_wait_user_fence.o \
xe_wa.o \
- xe_wopcm.o
+ xe_wopcm.o \
+ xe_xelink.o
# i915 Display compat #defines and #includes
subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
new file mode 100644
index 000000000000..51a31f6a4740
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_xelink.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include <linux/moduleparam.h>
+
+/*
+ * This module parameter is needed because SRIOV PF and XeLink are mutually
+ * exclusive. The driver needs to be able to enable/disable the XeLink
+ * infrastructure (specifically Device Physical Addressing). Since there
+ * will be no enable/disable for the SRIOV PF path, this parameter is
+ * needed to explicitly disable XeLink when SRIOV PF is required.
+ */
+static bool xe_enable_xelink = true;
+module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
+MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
--
2.35.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Intel-xe] [PATCH 2/3] drm/xe: Introduce XeLink device
2023-08-08 16:45 [Intel-xe] [PATCH 0/3] Add support for XeLink device David Kershner
2023-08-08 16:45 ` [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink David Kershner
@ 2023-08-08 16:45 ` David Kershner
2023-08-08 18:43 ` Rodrigo Vivi
2023-08-08 16:45 ` [Intel-xe] [PATCH 3/3] drm/xe: Teach i915 how to use objects with XeLink connectivity David Kershner
2 siblings, 1 reply; 10+ messages in thread
From: David Kershner @ 2023-08-08 16:45 UTC (permalink / raw)
To: david.kershner, intel-xe, michael.j.ruhl, john.fleck,
lucas.demarchi, rodrigo.vivi, matthew.d.roper, matthew.brost
Add XeLink support for PVC devices.
Introduce the initial platform data structure that will be shared
between the Xe driver and the XeLink driver.
If the device is PVC, and there is an XeLink device present, add
and initialize an Auxbus device with the appropriate resources.
Add the XeLink information register.
Add package address register for defining the Device Physical Address
space (DPA).
Add initial interrupt support.
The package address register defines the device physical
address (DPA) space for the given device.
Using the "unique" xa_array index, generate a DPA address
for the device and program the package register appropriately.
Update the LMEM offset to use the DPA address.
Signed-off-by: David Kershner <david.kershner@intel.com>
---
drivers/gpu/drm/xe/Kconfig | 1 +
drivers/gpu/drm/xe/regs/xe_gt_regs.h | 20 ++
drivers/gpu/drm/xe/xe_device.c | 13 +-
drivers/gpu/drm/xe/xe_device_types.h | 27 ++
drivers/gpu/drm/xe/xe_gt_types.h | 2 +
drivers/gpu/drm/xe/xe_irq.c | 28 +-
drivers/gpu/drm/xe/xe_mmio.c | 2 +-
drivers/gpu/drm/xe/xe_pci.c | 2 +
drivers/gpu/drm/xe/xe_pci_types.h | 1 +
drivers/gpu/drm/xe/xe_xelink.c | 447 +++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_xelink.h | 36 +++
include/drm/intel_xelink_platform.h | 140 +++++++++
12 files changed, 716 insertions(+), 3 deletions(-)
create mode 100644 drivers/gpu/drm/xe/xe_xelink.h
create mode 100644 include/drm/intel_xelink_platform.h
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 0a4ea965645b..9d396ca7708a 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -36,6 +36,7 @@ config DRM_XE
select DRM_SCHED
select MMU_NOTIFIER
select WANT_DEV_COREDUMP
+ select AUXILIARY_BUS
help
Experimental driver for Intel Xe series GPUs
diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index d654f3311351..fa78cbcd1058 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -81,6 +81,11 @@
#define GLOBAL_MOCS(i) XE_REG(0x4000 + (i) * 4) /* Global MOCS regs */
#define GFX_CCS_AUX_NV XE_REG(0x4208)
+#define PKG_ADDR_RANGE XE_REG(0x41B0)
+#define PKG_ADDR_RANGE_RANGE_SHIFT 20
+#define PKG_ADDR_RANGE_BASE_SHIFT 1
+#define PKG_ADDR_RANGE_ENABLE 1
+
#define VD0_AUX_NV XE_REG(0x4218)
#define VE0_AUX_NV XE_REG(0x4238)
@@ -88,6 +93,11 @@
#define AUX_INV REG_BIT(0)
#define XEHP_TILE_ADDR_RANGE(_idx) XE_REG_MCR(0x4900 + (_idx) * 4)
+#define XEHP_TILE_LMEM_RANGE_SHIFT 8
+#define XEHP_TILE_LMEM_BASE_SHIFT 1
+#define XEHP_TILE_LMEM_BASE_MASK REG_GENMASK(7, 1)
+#define XEHP_TILE_LMEM_RANGE_MASK REG_GENMASK(14, 8)
+
#define XEHP_FLAT_CCS_BASE_ADDR XE_REG_MCR(0x4910)
#define CHICKEN_RASTER_1 XE_REG_MCR(0x6204, XE_REG_OPTION_MASKED)
@@ -349,6 +359,11 @@
#define RCU_MODE XE_REG(0x14800, XE_REG_OPTION_MASKED)
#define RCU_MODE_CCS_ENABLE REG_BIT(0)
+#define PKG_ADDR_BASE XE_REG(0x108390)
+#define PKG_ADDR_BASE_RANGE_SHIFT 20
+#define PKG_ADDR_BASE_BASE_SHIFT 1
+#define PKG_ADDR_BASE_ENABLE 1
+
#define FORCEWAKE_ACK_GT XE_REG(0x130044)
#define FORCEWAKE_KERNEL BIT(0)
#define FORCEWAKE_USER BIT(1)
@@ -397,4 +412,9 @@
#define XEHPC_BCS5_BCS6_INTR_MASK XE_REG(0x190118)
#define XEHPC_BCS7_BCS8_INTR_MASK XE_REG(0x19011c)
+#define PUNIT_MMIO_CR_POC_STRAPS XE_REG(0x281078)
+#define NUM_TILES_MASK REG_GENMASK(1, 0)
+#define CD_ALIVE REG_BIT(2)
+#define SOCKET_ID_MASK REG_GENMASK(7, 3)
+
#endif
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 766df07de979..296953b7d512 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
/*
- * Copyright © 2021 Intel Corporation
+ * Copyright © 2021 - 2023 Intel Corporation
*/
#include "xe_device.h"
@@ -34,6 +34,7 @@
#include "xe_vm.h"
#include "xe_vm_madvise.h"
#include "xe_wait_user_fence.h"
+#include "xe_xelink.h"
#ifdef CONFIG_LOCKDEP
struct lockdep_map xe_device_mem_access_lockdep_map = {
@@ -262,6 +263,8 @@ int xe_device_probe(struct xe_device *xe)
if (err)
return err;
+ xe_xelink_init_early(xe);
+
for_each_tile(tile, xe, id) {
err = xe_tile_alloc(tile);
if (err)
@@ -272,6 +275,8 @@ int xe_device_probe(struct xe_device *xe)
if (err)
return err;
+ xe_xelink_init_mmio(xe);
+
for_each_gt(gt, xe, id) {
err = xe_pcode_probe(gt);
if (err)
@@ -292,6 +297,8 @@ int xe_device_probe(struct xe_device *xe)
goto err_irq_shutdown;
}
+ xe_xelink_init(xe);
+
err = xe_mmio_probe_vram(xe);
if (err)
goto err_irq_shutdown;
@@ -333,6 +340,8 @@ int xe_device_probe(struct xe_device *xe)
xe_display_register(xe);
+ xe_xelink_init_aux(xe);
+
xe_debugfs_register(xe);
err = drmm_add_action_or_reset(&xe->drm, xe_device_sanitize, xe);
@@ -365,6 +374,8 @@ void xe_device_remove(struct xe_device *xe)
xe_display_unlink(xe);
+ xe_xelink_remove(xe);
+
xe_irq_shutdown(xe);
}
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index f84ecb976f5d..7b27a5178aca 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -16,6 +16,7 @@
#include "xe_gt_types.h"
#include "xe_platform_types.h"
#include "xe_step_types.h"
+#include "xe_xelink.h"
#if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
#include "ext/intel_device_info.h"
@@ -219,6 +220,10 @@ struct xe_device {
u8 has_asid:1;
/** @force_execlist: Forced execlist submission */
u8 force_execlist:1;
+ /** @has_xelink: Has XeLink */
+ u8 has_xelink:1;
+ /** @enable_guc: GuC submission enabled */
+ u8 enable_guc:1;
/** @has_flat_ccs: Whether flat CCS metadata is used */
u8 has_flat_ccs:1;
/** @has_4tile: Whether tile-4 tiling is supported */
@@ -376,6 +381,28 @@ struct xe_device {
*/
struct task_struct *pm_callback_task;
+ /** @intel_xelink: XeLink information, for those gpus with XeLink connectivity */
+ struct {
+ /** @ops: shared interface operations */
+ const struct xelink_ops *ops;
+ /** @handle: XeLink device handle */
+ void *handle;
+ /** @pd: platform data needed for auxiliary bus */
+ struct xelink_pdata *pd;
+ /** @dpa: base device physical address */
+ u64 dpa;
+ /** @irq_base: base IRQ for multi tile devices */
+ int irq_base;
+ /** @index: internal index for xe devices */
+ int index;
+ /** @xelink_id: XeLink id generated by the XeLink device */
+ u32 xelink_id;
+ /** @socket_id: socket from certain platforms */
+ u8 socket_id;
+ /* @present: Reflect PUNIT presence information */
+ bool present;
+ } intel_xelink;
+
/* private: */
#if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index 35b8c19fa8bf..e9e551fea95b 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -346,6 +346,8 @@ struct xe_gt {
/** @oob: bitmap with active OOB workaroudns */
unsigned long *oob;
} wa_active;
+ /** @xelink_irq: IRQ value assigned to the ANR HW */
+ int xelink_irq;
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
index 2022a5643e01..aaf9569426cc 100644
--- a/drivers/gpu/drm/xe/xe_irq.c
+++ b/drivers/gpu/drm/xe/xe_irq.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
/*
- * Copyright © 2021 Intel Corporation
+ * Copyright © 2021 - 2023 Intel Corporation
*/
#include "xe_irq.h"
+#include <linux/irq.h>
#include <linux/sched/clock.h>
#include <drm/drm_managed.h>
@@ -27,6 +28,15 @@
#define IIR(offset) XE_REG(offset + 0x8)
#define IER(offset) XE_REG(offset + 0xc)
+/* Define the BAR and offset for XeLink CSRs */
+#define XE_XELINK_IRQ BIT(8)
+#define CD_BASE_OFFSET 0x291000
+#define CD_BAR_SIZE (256 * 1024)
+
+#define CPORT_MBDB_CSRS XE_REG(CD_BASE_OFFSET + 0x6000)
+#define CPORT_MBDB_CSRS_END XE_REG(CD_BASE_OFFSET + 0x1000)
+#define CPORT_MBDB_INT_ENABLE_MASK XE_REG(CD_BASE_OFFSET + 0x8)
+
static void assert_iir_is_zero(struct xe_gt *mmio, struct xe_reg reg)
{
u32 val = xe_mmio_read32(mmio, reg);
@@ -362,6 +372,18 @@ static void dg1_intr_enable(struct xe_device *xe, bool stall)
xe_mmio_read32(mmio, DG1_MSTR_TILE_INTR);
}
+/*
+ * xelink_irq_handler - handle XeLink IRQs
+ *
+ * PVC can have an XeLink attached. Handle the IRQs that are sourced by
+ * the device supporting the XeLink.
+ */
+static void xelink_irq_handler(struct xe_gt *gt, const u32 master_ctl)
+{
+ if (master_ctl & XE_XELINK_IRQ)
+ generic_handle_irq(gt->xelink_irq);
+}
+
/*
* Top-level interrupt handler for Xe_LP+ and beyond. These platforms have
* a "master tile" interrupt register which must be consulted before the
@@ -423,6 +445,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
xe_display_irq_handler(xe, master_ctl);
gu_misc_iir = gu_misc_irq_ack(xe, master_ctl);
}
+ xelink_irq_handler(mmio, master_ctl);
}
dg1_intr_enable(xe, false);
@@ -469,6 +492,9 @@ static void gt_irq_reset(struct xe_tile *tile)
xe_mmio_write32(mmio, GPM_WGBOXPERF_INTR_MASK, ~0);
xe_mmio_write32(mmio, GUC_SG_INTR_ENABLE, 0);
xe_mmio_write32(mmio, GUC_SG_INTR_MASK, ~0);
+
+ if (tile->xe->intel_xelink.present)
+ xe_mmio_write64(mmio, CPORT_MBDB_INT_ENABLE_MASK, 0);
}
static void xelp_irq_reset(struct xe_tile *tile)
diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index aa9c573b1243..1b0184135d45 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -173,7 +173,7 @@ static int xe_determine_lmem_bar_size(struct xe_device *xe)
if (!xe->mem.vram.io_size)
return -EIO;
- xe->mem.vram.base = 0; /* DPA offset */
+ xe->mem.vram.base = xe->intel_xelink.dpa;
/* set up a map to the total memory area. */
xe->mem.vram.mapping = ioremap_wc(xe->mem.vram.io_start, xe->mem.vram.io_size);
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 46e3a9632efe..a2258524c577 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -162,6 +162,7 @@ static const struct xe_graphics_desc graphics_xehpc = {
.has_asid = 1,
.has_flat_ccs = 0,
+ .has_xelink = 1,
.has_link_copy_engine = 1,
.supports_usm = 1,
};
@@ -563,6 +564,7 @@ static int xe_info_init(struct xe_device *xe,
xe->info.vm_max_level = graphics_desc->vm_max_level;
xe->info.supports_usm = graphics_desc->supports_usm;
xe->info.has_asid = graphics_desc->has_asid;
+ xe->info.has_xelink = graphics_desc->has_xelink;
xe->info.has_flat_ccs = graphics_desc->has_flat_ccs;
xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation;
xe->info.has_link_copy_engine = graphics_desc->has_link_copy_engine;
diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h
index ba31b933eb8e..85fec0c9e638 100644
--- a/drivers/gpu/drm/xe/xe_pci_types.h
+++ b/drivers/gpu/drm/xe/xe_pci_types.h
@@ -22,6 +22,7 @@ struct xe_graphics_desc {
u8 max_remote_tiles:2;
u8 has_asid:1;
+ u8 has_xelink:1;
u8 has_flat_ccs:1;
u8 has_link_copy_engine:1;
u8 has_range_tlb_invalidation:1;
diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
index 51a31f6a4740..ac4cff76f81d 100644
--- a/drivers/gpu/drm/xe/xe_xelink.c
+++ b/drivers/gpu/drm/xe/xe_xelink.c
@@ -3,7 +3,20 @@
* Copyright © 2023 Intel Corporation
*/
+#include <linux/auxiliary_bus.h>
+#include <linux/firmware.h>
+#include <linux/irq.h>
#include <linux/moduleparam.h>
+#include <linux/xarray.h>
+
+#include <drm/intel_xelink_platform.h>
+
+#include "xe_device.h"
+#include "xe_mmio.h"
+#include "xe_gt_mcr.h"
+#include "xe_xelink.h"
+#include "regs/xe_reg_defs.h"
+#include "regs/xe_gt_regs.h"
/*
* This module parameter is needed because SRIOV PF and XeLink are mutually
@@ -15,3 +28,437 @@
static bool xe_enable_xelink = true;
module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
+
+#define HAS_XELINK(xe) ((xe)->info.has_xelink)
+/* Define the BAR and offset for the XeLink CSRs */
+#define GTTMMADR_BAR 0
+#define CD_BASE_OFFSET 0x291000
+#define CD_BAR_SIZE (256 * 1024)
+
+/* Xarray of XeLink devices */
+static DEFINE_XARRAY_ALLOC(intel_fdevs);
+
+static struct query_info *default_query(void *handle, u32 xelink_id)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static int default_handle_event(void *handle, enum xelink_parent_event event)
+{
+ return -EOPNOTSUPP;
+}
+
+static const struct xelink_ops default_ops = {
+ .connectivity_query = default_query,
+ .parent_event = default_handle_event,
+};
+
+static int register_dev(void *parent, void *handle, u32 xelink_id,
+ const struct xelink_ops *ops)
+{
+ struct xe_device *xe = parent;
+
+ WARN(xe->intel_xelink.ops != &default_ops, "XeLink: already registered");
+
+ xe->intel_xelink.handle = handle;
+ xe->intel_xelink.xelink_id = xelink_id;
+ xe->intel_xelink.ops = ops;
+
+ drm_info(&xe->drm, "XeLink: registered: 0x%x\n", xelink_id);
+
+ return 0;
+}
+
+static void unregister_dev(void *parent, const void *handle)
+{
+ struct xe_device *xe = parent;
+
+ WARN(xe->intel_xelink.handle != handle, "XeLink: invalid handle");
+
+ drm_info(&xe->drm, "XeLink: unregistered: 0x%x\n",
+ xe->intel_xelink.xelink_id);
+ xe->intel_xelink.handle = NULL;
+ xe->intel_xelink.ops = &default_ops;
+}
+
+static int dev_event(void *parent, void *handle, enum xelink_dev_event event,
+ void *event_data)
+{
+ return 0;
+}
+
+/**
+ * init_pd - Allocate and initialize platform specific data
+ * @xe: Valid xe instance
+ *
+ * Return:
+ * * pd - initialized xelink_pdata,
+ * * NULL - Allocation failure
+ */
+static struct xelink_pdata *init_pd(struct xe_device *xe)
+{
+ struct xelink_pdata *pd;
+ u32 reg;
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return NULL;
+
+ pd->version = XELINK_VERSION;
+ pd->parent = xe;
+ pd->product = XELINK_PONTEVECCHIO;
+ pd->index = xe->intel_xelink.index & 0xFFFF;
+ pd->sd_cnt = xe->info.tile_count;
+ pd->socket_id = xe->intel_xelink.socket_id;
+ pd->slot = PCI_SLOT(to_pci_dev(xe->drm.dev)->devfn);
+
+ pd->resources = NULL;
+ pd->num_resources = 0;
+ pd->register_dev = register_dev;
+ pd->unregister_dev = unregister_dev;
+ pd->dev_event = dev_event;
+
+ /*
+ * Calculate the actual DPA offset and size (in GB) for the device.
+ * Each tile will have the same amount of memory, so we only need to
+ * read the first one.
+ */
+ reg = xe_gt_mcr_unicast_read_any(xe_device_get_root_tile(xe)->primary_gt,
+ XEHP_TILE_ADDR_RANGE(0)) & XEHP_TILE_LMEM_RANGE_MASK;
+
+ // TILE0 is < 8Gb, PVC needs 8GB, so fake it.
+ if (reg >> XEHP_TILE_LMEM_RANGE_SHIFT < 8) {
+ drm_err(&xe->drm, "XEHP_TILE0_ADDR_RANGE: %x\n", reg);
+ reg = 8 << XEHP_TILE_LMEM_RANGE_SHIFT;
+ }
+ pd->dpa.pkg_offset = (u32)xe->intel_xelink.index * MAX_DPA_SIZE;
+ pd->dpa.pkg_size = (reg >> XEHP_TILE_LMEM_RANGE_SHIFT) * pd->sd_cnt;
+
+ return pd;
+}
+
+/**
+ * init_resource - Create the resource array, and apply the appropriate data
+ * @xe: valid xe instance
+ * @res_cnt: pointer to return number of allocated resources
+ *
+ * First resource [0] is for the IRQ(s). Each device gets 1 IRQ. Subsequent
+ * resources describe the IO memory space for the device(s).
+ *
+ * Make sure to set the gt->xelink_irq value.
+ *
+ * Return:
+ * * res - Initialized resource array
+ * * NULL - Allocaction failure
+ */
+static struct resource *init_resource(struct xe_device *xe,
+ u32 *res_cnt)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+ struct xe_gt *gt;
+ struct resource *res_base, *res;
+ u32 cnt = xe->info.tile_count * 2;
+ unsigned int i;
+
+ /* Each sd gets one resource for IRQ and one for MEM */
+ res_base = kcalloc(cnt, sizeof(*res_base), GFP_KERNEL);
+ if (!res_base)
+ return NULL;
+
+ res = res_base;
+ for_each_gt(gt, xe, i) {
+ res->start = xe->intel_xelink.irq_base + i;
+ res->end = xe->intel_xelink.irq_base + i;
+ res->flags = IORESOURCE_IRQ;
+ res++;
+
+ res->start = pci_resource_start(pdev, GTTMMADR_BAR) + CD_BASE_OFFSET +
+ i * gt_to_tile(gt)->mmio.size;
+ res->end = res->start + CD_BAR_SIZE - 1;
+ res->flags = IORESOURCE_MEM;
+ drm_info(&xe->drm, "XeLink: mem_resource = %pR\n", res);
+ res++;
+ gt->xelink_irq = xe->intel_xelink.irq_base + i;
+ }
+
+ *res_cnt = cnt;
+ return res_base;
+}
+
+/**
+ * xelink_irq_mask - Null callback. Masking/unmasking happens in the parent
+ * driver
+ * @d: Valid irq_data information
+ */
+static void xelink_irq_mask(struct irq_data *d)
+{
+}
+
+static void xelink_irq_unmask(struct irq_data *d)
+{
+}
+
+static struct irq_chip xelink_irq_chip = {
+ .name = "xelink_irq_chip",
+ .irq_mask = xelink_irq_mask,
+ .irq_unmask = xelink_irq_unmask,
+};
+
+/**
+ * init_irq_desc - Allocate IRQ descriptors to use for the xelink
+ * @xe: Valid xe instance
+ *
+ * Allocate the required IRQ descriptor(s) and initialize the
+ * appropriate state.
+ *
+ * Return:
+ * * 0 - Success
+ * * errno - Error that occurred
+ */
+static int init_irq_desc(struct xe_device *xe)
+{
+ unsigned int num_subdevs = xe->info.tile_count;
+ int err;
+ int irq;
+ int irq_base;
+
+ irq_base = irq_alloc_descs(-1, 0, num_subdevs, 0);
+ if (irq_base < 0) {
+ err = irq_base;
+ goto cleanup;
+ }
+
+ err = 0;
+ for (irq = irq_base; !err && irq < irq_base + num_subdevs; irq++) {
+ irq_set_chip_and_handler_name(irq, &xelink_irq_chip,
+ handle_simple_irq,
+ "xelink_irq_handler");
+ err = irq_set_chip_data(irq, xe);
+ }
+
+ if (err) {
+ irq_free_descs(irq_base, num_subdevs);
+ goto cleanup;
+ }
+
+ drm_info(&xe->drm, "XeLink: IRQ base: %d cnt: %d\n", irq_base,
+ num_subdevs);
+
+ xe->intel_xelink.irq_base = irq_base;
+
+ return 0;
+
+cleanup:
+ xe->intel_xelink.index = err;
+ drm_err(&xe->drm, "XeLink: Failed to allocate IRQ data: %d\n", err);
+ return err;
+}
+
+/**
+ * xe_xelink_init_early - Set the XeLink info to the defaults
+ * @xe: valid xe instance
+ *
+ * index is set to ENODEV to show that, by default, there is no device.
+ * If any of the initialization steps fail, it will be set to the appropriate
+ * errno value.
+ */
+void xe_xelink_init_early(struct xe_device *xe)
+{
+ xe->intel_xelink.ops = &default_ops;
+ xe->intel_xelink.index = -ENODEV;
+}
+
+/**
+ * xe_xelink_init_mmio - check if XeLink is available via MMIO
+ * @xe: valid xe instance
+ *
+ * Read the relevant regs to check for XeLink availability and get the socket id
+ */
+void xe_xelink_init_mmio(struct xe_device *xe)
+{
+ u32 xelink_info;
+
+ if (!HAS_XELINK(xe) || !xe_enable_xelink)
+ return;
+
+ xelink_info = xe_mmio_read32(xe_device_get_root_tile(xe)->primary_gt,
+ PUNIT_MMIO_CR_POC_STRAPS);
+
+ xe->intel_xelink.socket_id = REG_FIELD_GET(SOCKET_ID_MASK, xelink_info);
+
+ if (REG_FIELD_GET(CD_ALIVE, xelink_info)) {
+ drm_info(&xe->drm, "XeLink available\n");
+ xe->intel_xelink.present = true;
+ }
+}
+
+/**
+ * xe_xelink_init - Allocate device index and complete initial HW setup
+ * @xe: valid device instance
+ *
+ * NOTE: index is zero inited. If the XeLink is not present, or an error occurs
+ * during setup, this must be 0 for the range registers.
+ *
+ */
+void xe_xelink_init(struct xe_device *xe)
+{
+ struct xe_gt *gt;
+ static u32 last_id;
+ unsigned int i;
+ u32 index = 0;
+ u32 range;
+ u32 base;
+ int err;
+
+ if (!HAS_XELINK(xe))
+ return;
+
+ if (!xe->intel_xelink.present)
+ goto set_range;
+
+ err = init_irq_desc(xe);
+ if (err) {
+ xe->intel_xelink.index = err;
+ goto set_range;
+ }
+
+ /*
+ * Try the socket id first. Systems with this feature, will
+ * get a deterministic value. If not, try with the cyclic.
+ */
+ err = xa_insert(&intel_fdevs, xe->intel_xelink.socket_id, xe,
+ GFP_KERNEL);
+ if (!err)
+ index = xe->intel_xelink.socket_id;
+
+ /* socket_id is not available */
+ if (err == -EBUSY) {
+ /*
+ * NOTE: index is only updated on success i.e. >= 0
+ * < 0 err, 0 ok, > 0 wrapped
+ */
+ err = xa_alloc_cyclic(&intel_fdevs, &index, xe,
+ XA_LIMIT(0, MAX_DEVICE_COUNT - 1),
+ &last_id, GFP_KERNEL);
+ }
+ if (err < 0) {
+ index = 0;
+ xe->intel_xelink.index = err;
+ drm_err(&xe->drm,
+ "XeLink: Failed to allocate index: %d\n",
+ err);
+ irq_free_descs(xe->intel_xelink.irq_base,
+ xe->info.tile_count);
+ goto set_range;
+ }
+ xe->intel_xelink.index = index;
+ xe->intel_xelink.dpa = (u64)index * MAX_DPA_SIZE * SZ_1G;
+ drm_info(&xe->drm, "XeLink: [dpa 0x%llx-0x%llx\n", xe->intel_xelink.dpa,
+ ((u64)index + 1) * MAX_DPA_SIZE * SZ_1G - 1);
+
+ /*
+ * Set range has to be done for all devices that support device
+ * address space, regardless of presence or error.
+ */
+set_range:
+ /* Set GAM address range registers */
+ range = index * MAX_DPA_SIZE << PKG_ADDR_RANGE_BASE_SHIFT;
+ range |= MAX_DPA_SIZE << PKG_ADDR_RANGE_RANGE_SHIFT;
+ range |= PKG_ADDR_RANGE_ENABLE;
+
+ /* set SGunit address range register */
+ base = index * MAX_DPA_SIZE << PKG_ADDR_BASE_BASE_SHIFT;
+ base |= MAX_DPA_SIZE << PKG_ADDR_BASE_RANGE_SHIFT;
+ base |= PKG_ADDR_BASE_ENABLE;
+
+ /* Needs to be set for each gt */
+ for_each_gt(gt, xe, i) {
+ xe_mmio_write32(gt, PKG_ADDR_RANGE, range);
+ xe_mmio_write32(gt, PKG_ADDR_BASE, base);
+ }
+}
+
+static void xe_xelink_release_dev(struct device *dev)
+{
+ struct auxiliary_device *aux = to_auxiliary_dev(dev);
+ struct xelink_pdata *pd = container_of(aux, struct xelink_pdata, aux_dev);
+
+ kfree(pd->resources);
+ pd->resources = NULL;
+
+ kfree(pd);
+}
+
+/**
+ * xe_xelink_init_aux - Initialize resources and add auxiliary bus interface
+ * @xe: valid xe instance
+ *
+ */
+void xe_xelink_init_aux(struct xe_device *xe)
+{
+ struct device *dev = &to_pci_dev(xe->drm.dev)->dev;
+ struct resource *res = NULL;
+ struct xelink_pdata *pd;
+ int err = -ENOMEM;
+ u32 res_cnt;
+
+ if (!xe->intel_xelink.present)
+ return;
+
+ if (xe->intel_xelink.index < 0) {
+ err = xe->intel_xelink.index;
+ goto fail;
+ }
+
+ pd = init_pd(xe);
+ if (!pd)
+ goto cleanup;
+
+ res = init_resource(xe, &res_cnt);
+ if (!res)
+ goto cleanup;
+
+ pd->resources = res;
+ pd->num_resources = res_cnt;
+
+ pd->aux_dev.name = "xelink";
+ pd->aux_dev.id = pd->index;
+ pd->aux_dev.dev.parent = dev;
+ pd->aux_dev.dev.release = xe_xelink_release_dev;
+
+ err = auxiliary_device_init(&pd->aux_dev);
+ if (err)
+ goto cleanup;
+
+ err = auxiliary_device_add(&pd->aux_dev);
+ if (err) {
+ auxiliary_device_uninit(&pd->aux_dev);
+ goto cleanup;
+ }
+
+ xe->intel_xelink.pd = pd;
+
+ return;
+
+cleanup:
+ xa_erase(&intel_fdevs, xe->intel_xelink.index);
+ irq_free_descs(xe->intel_xelink.irq_base, xe->info.tile_count);
+ kfree(res);
+ kfree(pd);
+ xe->intel_xelink.index = err;
+fail:
+ drm_err(&xe->drm, "XeLink: Failed to initialize err: %d\n", err);
+}
+
+void xe_xelink_remove(struct xe_device *xe)
+{
+ if (xe->intel_xelink.index < 0)
+ return;
+
+ auxiliary_device_delete(&xe->intel_xelink.pd->aux_dev);
+ auxiliary_device_uninit(&xe->intel_xelink.pd->aux_dev);
+ xa_erase(&intel_fdevs, xe->intel_xelink.index);
+ irq_free_descs(xe->intel_xelink.irq_base, xe->info.tile_count);
+
+ xe->intel_xelink.ops = &default_ops;
+}
diff --git a/drivers/gpu/drm/xe/xe_xelink.h b/drivers/gpu/drm/xe/xe_xelink.h
new file mode 100644
index 000000000000..e17faacc7b1c
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_xelink.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2019 - 2023 Intel Corporation
+ */
+
+#ifndef _XE_XELINK_H_
+#define _XE_XELINK_H_
+
+/*
+ * Define the maximum number of devices instances based on the amount of
+ * FID space.
+ *
+ * XARRAY limits are "inclusive", but using this value as a range check
+ * outside of xarray, makes the exclusive upper bound a little easier to
+ * deal with.
+ *
+ * I.e.:
+ * [0 - 256)
+ *
+ * Less than HW supports, but more than will be currently possible.
+ *
+ */
+#define MAX_DEVICE_COUNT 256
+
+/* Fixed Device Physical Address (DPA) size for a device/package (in GB) */
+#define MAX_DPA_SIZE 128
+
+struct xe_device;
+
+void xe_xelink_init_early(struct xe_device *xe);
+void xe_xelink_init_mmio(struct xe_device *xe);
+void xe_xelink_init(struct xe_device *xe);
+void xe_xelink_init_aux(struct xe_device *xe);
+void xe_xelink_remove(struct xe_device *xe);
+
+#endif
diff --git a/include/drm/intel_xelink_platform.h b/include/drm/intel_xelink_platform.h
new file mode 100644
index 000000000000..86eeb10fdc1e
--- /dev/null
+++ b/include/drm/intel_xelink_platform.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2019 - 2023 Intel Corporation.
+ */
+
+#ifndef __INTEL_XELINK_PLATFORM_H
+#define __INTEL_XELINK_PLATFORM_H
+
+#define XELINK_VERSION 1
+
+#include <linux/auxiliary_bus.h>
+#include <linux/types.h>
+
+/**
+ * enum product_type - Product type identifying the parent
+ * @XELINK_UNDEFINED: no product type hints
+ * @XELINK_PONTEVECCHIO: parent is a PVC
+ * @XELINK_PRODUCTS: end of the list
+ *
+ */
+enum product_type {
+ XELINK_UNDEFINED,
+ XELINK_PONTEVECCHIO,
+ XELINK_PRODUCTS
+};
+
+/**
+ * enum xelink_dev_event - events generated to the parent device
+ * @XELINK_DEV_REMOVE: Xelink device was removed
+ * @XELINK_DEV_ERROR: An error occurred
+ * @XELINK_DEV_EVENTS: end of list
+ *
+ * Connectivity events, possible errors, etc.
+ */
+enum xelink_dev_event {
+ XELINK_DEV_REMOVE,
+ XELINK_DEV_EVENTS
+};
+
+/**
+ * enum xelink_parent_event - Events generated by the parent device
+ * @XELINK_PARENT_PCIE_ERR: Parent had a PCI error
+ * @XELINK_PARENT_MAPPING_GET: Notify XeLink of buffer mapping
+ * @XELINK_PARENT_MAPPING_PUT: Notify XeLink of buffer unmapping
+ *
+ * These are examples.
+ */
+enum xelink_parent_event {
+ XELINK_PARENT_PCIE_ERR,
+ XELINK_PARENT_MAPPING_GET,
+ XELINK_PARENT_MAPPING_PUT,
+};
+
+/**
+ * struct sd2sd_info - Subdevice to subdevice connectivity info
+ * @bandwidth: in Gbps units not factoring in width or quality degredation
+ * @latency: in 1/10 hops units
+ */
+struct sd2sd_info {
+ u16 bandwidth;
+ u16 latency;
+};
+
+/**
+ * struct query_info - connectivity query response information
+ * @src_cnt: Requester subdevice count
+ * @dst_cnt: Destination path count
+ * @sd2sd: array of src/dst bandwidth/latency information
+ *
+ * Query info will be a variably sized data structure allocated by the
+ * XeLink driver. The access will be indexed by
+ * (src_index * dst_cnt) + dst_index
+ *
+ * The caller will need to free the buffer when done.
+ */
+struct query_info {
+ u8 src_cnt;
+ u8 dst_cnt;
+ struct sd2sd_info sd2sd[];
+};
+
+/**
+ * struct xelink_ops - Communication path from parent to XeLink instance
+ * @connectivity_query: Query a device for xelink_id connectivity
+ * @parent_event: Any events needed by the XeLink device
+ *
+ * connectivity_query() returns:
+ * a populated query_info on success,
+ * an ERR_PTR() on failure
+ *
+ */
+struct xelink_ops {
+ struct query_info *(*connectivity_query)(void *handle, u32 xelink_id);
+ int (*parent_event)(void *handle, enum xelink_parent_event event);
+};
+
+struct dpa_space {
+ u32 pkg_offset;
+ u16 pkg_size;
+};
+
+/**
+ * struct xelink_pdata - Platform specific data that needs to be shared
+ * @version: PSD version information
+ * @parent: Handle to use when calling the parent device
+ * @product: a product hint for any necessary special case requirements
+ * @index: unique device index. This will be part of the device name
+ * @dpa: Device physical address offset and size
+ * @sd_cnt: parent subdevice count
+ * @socket_id: device socket information
+ * @slot: PCI/CXL slot number
+ * @aux_dev: Auxiliary bus device
+ * @resources: Array of resources (Assigned by Xe, the IRQ/MEM for the device)
+ * @num_resources: number of resources in resources array
+ * @register_dev: Register a XeLink instance and ops with the parent device
+ * @unregister_dev: Unregister a XeLink instance from the parent device
+ * @dev_event: Notify parent that an event has occurred
+ */
+struct xelink_pdata {
+ u16 version;
+ void *parent;
+ enum product_type product;
+ u16 index;
+ struct dpa_space dpa;
+ u8 sd_cnt;
+ u8 socket_id;
+ u8 slot;
+
+ struct auxiliary_device aux_dev;
+ struct resource *resources;
+ u32 num_resources;
+
+ int (*register_dev)(void *parent, void *handle, u32 xelink_id,
+ const struct xelink_ops *ops);
+ void (*unregister_dev)(void *parent, const void *handle);
+ int (*dev_event)(void *parent, void *handle,
+ enum xelink_dev_event event, void *event_data);
+};
+
+#endif /* __INTEL_XELINK_PLATFORM_H */
--
2.35.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Intel-xe] [PATCH 3/3] drm/xe: Teach i915 how to use objects with XeLink connectivity
2023-08-08 16:45 [Intel-xe] [PATCH 0/3] Add support for XeLink device David Kershner
2023-08-08 16:45 ` [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink David Kershner
2023-08-08 16:45 ` [Intel-xe] [PATCH 2/3] drm/xe: Introduce XeLink device David Kershner
@ 2023-08-08 16:45 ` David Kershner
2023-08-08 18:41 ` Rodrigo Vivi
2 siblings, 1 reply; 10+ messages in thread
From: David Kershner @ 2023-08-08 16:45 UTC (permalink / raw)
To: david.kershner, intel-xe, michael.j.ruhl, john.fleck,
lucas.demarchi, rodrigo.vivi, matthew.d.roper, matthew.brost
The XeLink device offers fabric backed memory. Page table entries
need to be aware of this fact so that the access occur over the
fabric rather than to the system or local device memory.
Objects are shared via dma-buf, and then fabric connectivity is
checked during the _get_pages() pass.
Objects do NOT need to be dma mapped because system dma does not
occur.
The Device Physical Address (DPA) is the memory range assigned
to the fabric device at driver init. This address is what will
need to be programmed into the page table entry. In addition
the PTE_LM bit needs to be set.
Address information is provided in a scatter/gather table.
Teach the dma-buf interface and the page table entries all about
fabric backed memory.
Signed-off-by: David Kershner <david.kershner@intel.com>
---
drivers/gpu/drm/xe/xe_bo.c | 47 ++++++++-
drivers/gpu/drm/xe/xe_bo.h | 2 +
drivers/gpu/drm/xe/xe_dma_buf.c | 162 +++++++++++++++++++++++---------
drivers/gpu/drm/xe/xe_dma_buf.h | 3 +
drivers/gpu/drm/xe/xe_pt.c | 7 +-
drivers/gpu/drm/xe/xe_xelink.c | 12 +++
drivers/gpu/drm/xe/xe_xelink.h | 2 +
7 files changed, 186 insertions(+), 49 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 284c86107a5f..f48e917b3e28 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -8,6 +8,7 @@
#include <linux/dma-buf.h>
#include <drm/drm_drv.h>
+#include <drm/drm_gem.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/ttm/ttm_device.h>
#include <drm/ttm/ttm_placement.h>
@@ -524,6 +525,32 @@ static int xe_bo_trigger_rebind(struct xe_device *xe, struct xe_bo *bo,
return ret;
}
+/**
+ * map_xelink_connectivity - check for XeLink and create a mappable sgt
+ * if available
+ * @bo: object to check XeLink connectivity
+ *
+ * Returns sgt or -errno on error, -EIO indicates no XeLink connectivity.
+ */
+static struct sg_table *map_xelink_connectivity(struct xe_bo *bo)
+{
+ struct dma_buf_attachment *attach = bo->ttm.base.import_attach;
+ struct xe_bo *import;
+
+ if (!(bo->flags & XE_BO_XELINK_AVAIL))
+ return ERR_PTR(-EIO);
+
+ import = gem_to_xe_bo(attach->dmabuf->priv);
+
+ /* Make sure the object didn't migrate */
+ if (!xe_bo_is_vram(import)) {
+ bo->flags &= ~XE_BO_XELINK_AVAIL;
+ return ERR_PTR(-EIO);
+ }
+
+ return xe_dma_buf_map(attach, DMA_NONE);
+}
+
/*
* The dma-buf map_attachment() / unmap_attachment() is hooked up here.
* Note that unmapping the attachment is deferred to the next
@@ -540,6 +567,7 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
struct xe_ttm_tt *xe_tt = container_of(ttm_bo->ttm, struct xe_ttm_tt,
ttm);
struct sg_table *sg;
+ struct xe_bo *bo;
XE_WARN_ON(!attach);
XE_WARN_ON(!ttm_bo->ttm);
@@ -547,12 +575,27 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
if (new_res->mem_type == XE_PL_SYSTEM)
goto out;
+ bo = ttm_to_xe_bo(ttm_bo);
if (ttm_bo->sg) {
- dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
+ if (bo->flags & XE_BO_XELINK_AVAIL) {
+ struct xe_bo *export;
+ //export = dma_buf_to_obj(attach->dmabuf);
+ export = gem_to_xe_bo(attach->dmabuf->priv);
+ xe_xelink_mapping_put(to_xe_device(export->ttm.base.dev)); // don't do?
+ xe_xelink_mapping_put(to_xe_device(ttm_bo->base.dev)); // don't do?
+ sg_free_table(ttm_bo->sg);
+ kfree(ttm_bo->sg);
+ } else {
+ dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
+ }
ttm_bo->sg = NULL;
}
- sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ sg = map_xelink_connectivity(bo);
+
+ if (IS_ERR(sg) && PTR_ERR(sg) == -EIO)
+ sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+
if (IS_ERR(sg))
return PTR_ERR(sg);
diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h
index 0823dda0f31b..d7bf00c52c29 100644
--- a/drivers/gpu/drm/xe/xe_bo.h
+++ b/drivers/gpu/drm/xe/xe_bo.h
@@ -33,6 +33,8 @@
#define XE_BO_FIXED_PLACEMENT_BIT BIT(11)
#define XE_BO_PAGETABLE BIT(12)
#define XE_BO_NEEDS_CPU_ACCESS BIT(13)
+#define XE_BO_XELINK_AVAIL BIT(14)
+
/* this one is trigger internally only */
#define XE_BO_INTERNAL_TEST BIT(30)
#define XE_BO_INTERNAL_64K BIT(31)
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
index 975dee1f770f..e511b09b8556 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.c
+++ b/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -11,6 +11,7 @@
#include <drm/drm_device.h>
#include <drm/drm_prime.h>
+#include <drm/intel_xelink_platform.h>
#include <drm/ttm/ttm_tt.h>
#include "tests/xe_test.h"
@@ -21,21 +22,6 @@
MODULE_IMPORT_NS(DMA_BUF);
-static int xe_dma_buf_attach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *attach)
-{
- struct drm_gem_object *obj = attach->dmabuf->priv;
-
- if (attach->peer2peer &&
- pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
- attach->peer2peer = false;
-
- if (!attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
- return -EOPNOTSUPP;
-
- xe_device_mem_access_get(to_xe_device(obj->dev));
- return 0;
-}
static void xe_dma_buf_detach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
@@ -68,8 +54,8 @@ static void xe_dma_buf_unpin(struct dma_buf_attachment *attach)
xe_bo_unpin_external(bo);
}
-static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
- enum dma_data_direction dir)
+struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
{
struct dma_buf *dma_buf = attach->dmabuf;
struct drm_gem_object *obj = dma_buf->priv;
@@ -160,34 +146,6 @@ static int xe_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
return 0;
}
-const struct dma_buf_ops xe_dmabuf_ops = {
- .attach = xe_dma_buf_attach,
- .detach = xe_dma_buf_detach,
- .pin = xe_dma_buf_pin,
- .unpin = xe_dma_buf_unpin,
- .map_dma_buf = xe_dma_buf_map,
- .unmap_dma_buf = xe_dma_buf_unmap,
- .release = drm_gem_dmabuf_release,
- .begin_cpu_access = xe_dma_buf_begin_cpu_access,
- .mmap = drm_gem_dmabuf_mmap,
- .vmap = drm_gem_dmabuf_vmap,
- .vunmap = drm_gem_dmabuf_vunmap,
-};
-
-struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
-{
- struct xe_bo *bo = gem_to_xe_bo(obj);
- struct dma_buf *buf;
-
- if (bo->vm)
- return ERR_PTR(-EPERM);
-
- buf = drm_gem_prime_export(obj, flags);
- if (!IS_ERR(buf))
- buf->ops = &xe_dmabuf_ops;
-
- return buf;
-}
static struct drm_gem_object *
xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage,
@@ -240,6 +198,120 @@ struct dma_buf_test_params {
container_of(_priv, struct dma_buf_test_params, base)
#endif
+static int xe_dma_buf_attach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach);
+
+const struct dma_buf_ops xe_dmabuf_ops = {
+ .attach = xe_dma_buf_attach,
+ .detach = xe_dma_buf_detach,
+ .pin = xe_dma_buf_pin,
+ .unpin = xe_dma_buf_unpin,
+ .map_dma_buf = xe_dma_buf_map,
+ .unmap_dma_buf = xe_dma_buf_unmap,
+ .release = drm_gem_dmabuf_release,
+ .begin_cpu_access = xe_dma_buf_begin_cpu_access,
+ .mmap = drm_gem_dmabuf_mmap,
+ .vmap = drm_gem_dmabuf_vmap,
+ .vunmap = drm_gem_dmabuf_vunmap,
+};
+
+/*
+ * update_xelink - check for XeLink connectivity if available
+ * @obj: object to check XeLink connectivity
+ *
+ * If the imported object is a i915 dma-buf, and LMEM based, query to see if
+ * there is a XeLink, and if the XeLink is connected set the XeLink bit.
+ *
+ * 0 no connectivity, use P2P if available
+ * 1 XeLink is available
+ * -1 XeLink only is requested, and there is no XeLink
+ *
+ */
+static int update_xelink(struct dma_buf *dma_buf, struct xe_bo *bo)
+{
+ struct xe_bo *import;
+ struct xe_device *src;
+ struct xe_device *dst;
+ struct query_info *qi;
+ int connected;
+ int i;
+ int n;
+
+ /* Verify that both sides are xe devices */
+ if (dma_buf->ops != &xe_dmabuf_ops ||
+ !bo || bo->ttm.base.import_attach->importer_ops != &xe_dma_buf_attach_ops)
+ return 0;
+
+ import = gem_to_xe_bo(dma_buf->priv);
+ if (!xe_bo_is_vram(import))
+ return 0;
+
+ src = xe_bo_device(bo);
+ dst = xe_bo_device(import);
+
+ qi = src->intel_xelink.ops->connectivity_query(src->intel_xelink.handle,
+ dst->intel_xelink.xelink_id);
+ if (IS_ERR(qi))
+ return 0;
+
+ /*
+ * Examine the query information. A zero bandwidth link indicates we
+ * are NOT connected.
+ */
+ connected = 1;
+ for (i = 0, n = qi->src_cnt * qi->dst_cnt; i < n && connected; i++)
+ if (!qi->sd2sd[i].bandwidth)
+ connected = 0;
+
+ /* we are responsible for freeing qi */
+ kfree(qi);
+
+ if (connected) {
+ if (xe_xelink_mapping_get(src))
+ return 0;
+ if (xe_xelink_mapping_get(dst)) {
+ xe_xelink_mapping_put(src);
+ return 0;
+ }
+ bo->flags |= XE_BO_XELINK_AVAIL;
+ }
+
+ return connected;
+}
+
+static int xe_dma_buf_attach(struct dma_buf *dmabuf,
+ struct dma_buf_attachment *attach)
+{
+ struct drm_gem_object *obj = attach->dmabuf->priv;
+ int xelink;
+
+ xelink = update_xelink(dmabuf, attach->importer_priv);
+
+ if (attach->peer2peer &&
+ pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
+ attach->peer2peer = false;
+
+ if (!xelink && !attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
+ return -EOPNOTSUPP;
+
+ xe_device_mem_access_get(to_xe_device(obj->dev));
+ return 0;
+}
+
+struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
+{
+ struct xe_bo *bo = gem_to_xe_bo(obj);
+ struct dma_buf *buf;
+
+ if (bo->vm)
+ return ERR_PTR(-EPERM);
+
+ buf = drm_gem_prime_export(obj, flags);
+ if (!IS_ERR(buf))
+ buf->ops = &xe_dmabuf_ops;
+
+ return buf;
+}
+
struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.h b/drivers/gpu/drm/xe/xe_dma_buf.h
index 861dd28a862c..36771a50451e 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.h
+++ b/drivers/gpu/drm/xe/xe_dma_buf.h
@@ -7,9 +7,12 @@
#define _XE_DMA_BUF_H_
#include <drm/drm_gem.h>
+#include <linux/dma-direction.h>
struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags);
struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf);
+struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir);
#endif
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 5709518e314b..2c8698216581 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -130,6 +130,10 @@ u64 xe_pte_encode(struct xe_bo *bo, u64 offset, enum xe_cache_level cache,
if (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo))
pte |= XE_PPGTT_PTE_DM;
+/* DAK */
+ if (xe_bo_is_vram(bo) || bo->flags & XE_BO_XELINK_AVAIL)
+ pte |= XE_PPGTT_PTE_DM;
+
return __pte_encode(pte, cache, NULL, pt_level);
}
@@ -144,8 +148,7 @@ static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm,
if (level == 0) {
u64 empty = xe_pte_encode(vm->scratch_bo[id], 0,
XE_CACHE_WB, 0);
-
- return empty;
+return empty;
} else {
return xe_pde_encode(vm->scratch_pt[id][level - 1]->bo, 0,
XE_CACHE_WB);
diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
index ac4cff76f81d..00bebad1c899 100644
--- a/drivers/gpu/drm/xe/xe_xelink.c
+++ b/drivers/gpu/drm/xe/xe_xelink.c
@@ -462,3 +462,15 @@ void xe_xelink_remove(struct xe_device *xe)
xe->intel_xelink.ops = &default_ops;
}
+
+int xe_xelink_mapping_get(struct xe_device *xe)
+{
+ return xe->intel_xelink.ops->parent_event(xe->intel_xelink.handle,
+ XELINK_PARENT_MAPPING_GET);
+}
+
+int xe_xelink_mapping_put(struct xe_device *xe)
+{
+ return xe->intel_xelink.ops->parent_event(xe->intel_xelink.handle,
+ XELINK_PARENT_MAPPING_PUT);
+}
diff --git a/drivers/gpu/drm/xe/xe_xelink.h b/drivers/gpu/drm/xe/xe_xelink.h
index e17faacc7b1c..12feb5b04d23 100644
--- a/drivers/gpu/drm/xe/xe_xelink.h
+++ b/drivers/gpu/drm/xe/xe_xelink.h
@@ -31,6 +31,8 @@ void xe_xelink_init_early(struct xe_device *xe);
void xe_xelink_init_mmio(struct xe_device *xe);
void xe_xelink_init(struct xe_device *xe);
void xe_xelink_init_aux(struct xe_device *xe);
+int xe_xelink_mapping_get(struct xe_device *xe);
+int xe_xelink_mapping_put(struct xe_device *xe);
void xe_xelink_remove(struct xe_device *xe);
#endif
--
2.35.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Intel-xe] [PATCH 3/3] drm/xe: Teach i915 how to use objects with XeLink connectivity
2023-08-08 16:45 ` [Intel-xe] [PATCH 3/3] drm/xe: Teach i915 how to use objects with XeLink connectivity David Kershner
@ 2023-08-08 18:41 ` Rodrigo Vivi
0 siblings, 0 replies; 10+ messages in thread
From: Rodrigo Vivi @ 2023-08-08 18:41 UTC (permalink / raw)
To: David Kershner; +Cc: lucas.demarchi, john.fleck, matthew.d.roper, intel-xe
On Tue, Aug 08, 2023 at 12:45:34PM -0400, David Kershner wrote:
> The XeLink device offers fabric backed memory. Page table entries
> need to be aware of this fact so that the access occur over the
> fabric rather than to the system or local device memory.
>
> Objects are shared via dma-buf, and then fabric connectivity is
> checked during the _get_pages() pass.
>
> Objects do NOT need to be dma mapped because system dma does not
> occur.
>
> The Device Physical Address (DPA) is the memory range assigned
> to the fabric device at driver init. This address is what will
> need to be programmed into the page table entry. In addition
> the PTE_LM bit needs to be set.
>
> Address information is provided in a scatter/gather table.
>
> Teach the dma-buf interface and the page table entries all about
> fabric backed memory.
>
> Signed-off-by: David Kershner <david.kershner@intel.com>
> ---
> drivers/gpu/drm/xe/xe_bo.c | 47 ++++++++-
> drivers/gpu/drm/xe/xe_bo.h | 2 +
> drivers/gpu/drm/xe/xe_dma_buf.c | 162 +++++++++++++++++++++++---------
> drivers/gpu/drm/xe/xe_dma_buf.h | 3 +
> drivers/gpu/drm/xe/xe_pt.c | 7 +-
> drivers/gpu/drm/xe/xe_xelink.c | 12 +++
> drivers/gpu/drm/xe/xe_xelink.h | 2 +
> 7 files changed, 186 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
> index 284c86107a5f..f48e917b3e28 100644
> --- a/drivers/gpu/drm/xe/xe_bo.c
> +++ b/drivers/gpu/drm/xe/xe_bo.c
> @@ -8,6 +8,7 @@
> #include <linux/dma-buf.h>
>
> #include <drm/drm_drv.h>
> +#include <drm/drm_gem.h>
> #include <drm/drm_gem_ttm_helper.h>
> #include <drm/ttm/ttm_device.h>
> #include <drm/ttm/ttm_placement.h>
> @@ -524,6 +525,32 @@ static int xe_bo_trigger_rebind(struct xe_device *xe, struct xe_bo *bo,
> return ret;
> }
>
> +/**
> + * map_xelink_connectivity - check for XeLink and create a mappable sgt
> + * if available
> + * @bo: object to check XeLink connectivity
> + *
> + * Returns sgt or -errno on error, -EIO indicates no XeLink connectivity.
> + */
> +static struct sg_table *map_xelink_connectivity(struct xe_bo *bo)
> +{
> + struct dma_buf_attachment *attach = bo->ttm.base.import_attach;
> + struct xe_bo *import;
> +
> + if (!(bo->flags & XE_BO_XELINK_AVAIL))
> + return ERR_PTR(-EIO);
> +
> + import = gem_to_xe_bo(attach->dmabuf->priv);
> +
> + /* Make sure the object didn't migrate */
> + if (!xe_bo_is_vram(import)) {
> + bo->flags &= ~XE_BO_XELINK_AVAIL;
> + return ERR_PTR(-EIO);
> + }
> +
> + return xe_dma_buf_map(attach, DMA_NONE);
> +}
> +
> /*
> * The dma-buf map_attachment() / unmap_attachment() is hooked up here.
> * Note that unmapping the attachment is deferred to the next
> @@ -540,6 +567,7 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
> struct xe_ttm_tt *xe_tt = container_of(ttm_bo->ttm, struct xe_ttm_tt,
> ttm);
> struct sg_table *sg;
> + struct xe_bo *bo;
>
> XE_WARN_ON(!attach);
> XE_WARN_ON(!ttm_bo->ttm);
> @@ -547,12 +575,27 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
> if (new_res->mem_type == XE_PL_SYSTEM)
> goto out;
>
> + bo = ttm_to_xe_bo(ttm_bo);
> if (ttm_bo->sg) {
> - dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
> + if (bo->flags & XE_BO_XELINK_AVAIL) {
> + struct xe_bo *export;
> + //export = dma_buf_to_obj(attach->dmabuf);
please no!
> + export = gem_to_xe_bo(attach->dmabuf->priv);
> + xe_xelink_mapping_put(to_xe_device(export->ttm.base.dev)); // don't do?
if in doubt we should do something like:
/* XXX: Don't do? */
xe_xelink_mapping_put(to_xe_device(export->ttm.base.dev));
but let's not use // comments....
> + xe_xelink_mapping_put(to_xe_device(ttm_bo->base.dev)); // don't do?
> + sg_free_table(ttm_bo->sg);
> + kfree(ttm_bo->sg);
> + } else {
> + dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
> + }
> ttm_bo->sg = NULL;
> }
>
> - sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> + sg = map_xelink_connectivity(bo);
> +
> + if (IS_ERR(sg) && PTR_ERR(sg) == -EIO)
> + sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> +
> if (IS_ERR(sg))
> return PTR_ERR(sg);
>
> diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h
> index 0823dda0f31b..d7bf00c52c29 100644
> --- a/drivers/gpu/drm/xe/xe_bo.h
> +++ b/drivers/gpu/drm/xe/xe_bo.h
> @@ -33,6 +33,8 @@
> #define XE_BO_FIXED_PLACEMENT_BIT BIT(11)
> #define XE_BO_PAGETABLE BIT(12)
> #define XE_BO_NEEDS_CPU_ACCESS BIT(13)
> +#define XE_BO_XELINK_AVAIL BIT(14)
> +
> /* this one is trigger internally only */
> #define XE_BO_INTERNAL_TEST BIT(30)
> #define XE_BO_INTERNAL_64K BIT(31)
> diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
> index 975dee1f770f..e511b09b8556 100644
> --- a/drivers/gpu/drm/xe/xe_dma_buf.c
> +++ b/drivers/gpu/drm/xe/xe_dma_buf.c
> @@ -11,6 +11,7 @@
>
> #include <drm/drm_device.h>
> #include <drm/drm_prime.h>
> +#include <drm/intel_xelink_platform.h>
> #include <drm/ttm/ttm_tt.h>
>
> #include "tests/xe_test.h"
> @@ -21,21 +22,6 @@
>
> MODULE_IMPORT_NS(DMA_BUF);
>
> -static int xe_dma_buf_attach(struct dma_buf *dmabuf,
> - struct dma_buf_attachment *attach)
> -{
> - struct drm_gem_object *obj = attach->dmabuf->priv;
> -
> - if (attach->peer2peer &&
> - pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
> - attach->peer2peer = false;
> -
> - if (!attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
> - return -EOPNOTSUPP;
> -
> - xe_device_mem_access_get(to_xe_device(obj->dev));
> - return 0;
> -}
>
> static void xe_dma_buf_detach(struct dma_buf *dmabuf,
> struct dma_buf_attachment *attach)
> @@ -68,8 +54,8 @@ static void xe_dma_buf_unpin(struct dma_buf_attachment *attach)
> xe_bo_unpin_external(bo);
> }
>
> -static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
> - enum dma_data_direction dir)
> +struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
> + enum dma_data_direction dir)
> {
> struct dma_buf *dma_buf = attach->dmabuf;
> struct drm_gem_object *obj = dma_buf->priv;
> @@ -160,34 +146,6 @@ static int xe_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
> return 0;
> }
>
> -const struct dma_buf_ops xe_dmabuf_ops = {
> - .attach = xe_dma_buf_attach,
> - .detach = xe_dma_buf_detach,
> - .pin = xe_dma_buf_pin,
> - .unpin = xe_dma_buf_unpin,
> - .map_dma_buf = xe_dma_buf_map,
> - .unmap_dma_buf = xe_dma_buf_unmap,
> - .release = drm_gem_dmabuf_release,
> - .begin_cpu_access = xe_dma_buf_begin_cpu_access,
> - .mmap = drm_gem_dmabuf_mmap,
> - .vmap = drm_gem_dmabuf_vmap,
> - .vunmap = drm_gem_dmabuf_vunmap,
> -};
> -
> -struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
> -{
> - struct xe_bo *bo = gem_to_xe_bo(obj);
> - struct dma_buf *buf;
> -
> - if (bo->vm)
> - return ERR_PTR(-EPERM);
> -
> - buf = drm_gem_prime_export(obj, flags);
> - if (!IS_ERR(buf))
> - buf->ops = &xe_dmabuf_ops;
> -
> - return buf;
> -}
>
> static struct drm_gem_object *
> xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage,
> @@ -240,6 +198,120 @@ struct dma_buf_test_params {
> container_of(_priv, struct dma_buf_test_params, base)
> #endif
>
> +static int xe_dma_buf_attach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach);
> +
> +const struct dma_buf_ops xe_dmabuf_ops = {
> + .attach = xe_dma_buf_attach,
> + .detach = xe_dma_buf_detach,
> + .pin = xe_dma_buf_pin,
> + .unpin = xe_dma_buf_unpin,
> + .map_dma_buf = xe_dma_buf_map,
> + .unmap_dma_buf = xe_dma_buf_unmap,
> + .release = drm_gem_dmabuf_release,
> + .begin_cpu_access = xe_dma_buf_begin_cpu_access,
> + .mmap = drm_gem_dmabuf_mmap,
> + .vmap = drm_gem_dmabuf_vmap,
> + .vunmap = drm_gem_dmabuf_vunmap,
> +};
> +
> +/*
> + * update_xelink - check for XeLink connectivity if available
> + * @obj: object to check XeLink connectivity
> + *
> + * If the imported object is a i915 dma-buf, and LMEM based, query to see if
> + * there is a XeLink, and if the XeLink is connected set the XeLink bit.
> + *
> + * 0 no connectivity, use P2P if available
> + * 1 XeLink is available
> + * -1 XeLink only is requested, and there is no XeLink
> + *
> + */
> +static int update_xelink(struct dma_buf *dma_buf, struct xe_bo *bo)
> +{
> + struct xe_bo *import;
> + struct xe_device *src;
> + struct xe_device *dst;
> + struct query_info *qi;
> + int connected;
> + int i;
> + int n;
> +
> + /* Verify that both sides are xe devices */
> + if (dma_buf->ops != &xe_dmabuf_ops ||
> + !bo || bo->ttm.base.import_attach->importer_ops != &xe_dma_buf_attach_ops)
> + return 0;
> +
> + import = gem_to_xe_bo(dma_buf->priv);
> + if (!xe_bo_is_vram(import))
> + return 0;
> +
> + src = xe_bo_device(bo);
> + dst = xe_bo_device(import);
> +
> + qi = src->intel_xelink.ops->connectivity_query(src->intel_xelink.handle,
> + dst->intel_xelink.xelink_id);
> + if (IS_ERR(qi))
> + return 0;
> +
> + /*
> + * Examine the query information. A zero bandwidth link indicates we
> + * are NOT connected.
> + */
> + connected = 1;
> + for (i = 0, n = qi->src_cnt * qi->dst_cnt; i < n && connected; i++)
> + if (!qi->sd2sd[i].bandwidth)
> + connected = 0;
> +
> + /* we are responsible for freeing qi */
> + kfree(qi);
> +
> + if (connected) {
> + if (xe_xelink_mapping_get(src))
> + return 0;
> + if (xe_xelink_mapping_get(dst)) {
> + xe_xelink_mapping_put(src);
> + return 0;
> + }
> + bo->flags |= XE_BO_XELINK_AVAIL;
> + }
> +
> + return connected;
> +}
> +
> +static int xe_dma_buf_attach(struct dma_buf *dmabuf,
> + struct dma_buf_attachment *attach)
> +{
> + struct drm_gem_object *obj = attach->dmabuf->priv;
> + int xelink;
> +
> + xelink = update_xelink(dmabuf, attach->importer_priv);
> +
> + if (attach->peer2peer &&
> + pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
> + attach->peer2peer = false;
> +
> + if (!xelink && !attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
> + return -EOPNOTSUPP;
> +
> + xe_device_mem_access_get(to_xe_device(obj->dev));
> + return 0;
> +}
> +
> +struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
> +{
> + struct xe_bo *bo = gem_to_xe_bo(obj);
> + struct dma_buf *buf;
> +
> + if (bo->vm)
> + return ERR_PTR(-EPERM);
> +
> + buf = drm_gem_prime_export(obj, flags);
> + if (!IS_ERR(buf))
> + buf->ops = &xe_dmabuf_ops;
> +
> + return buf;
> +}
> +
> struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
> struct dma_buf *dma_buf)
> {
> diff --git a/drivers/gpu/drm/xe/xe_dma_buf.h b/drivers/gpu/drm/xe/xe_dma_buf.h
> index 861dd28a862c..36771a50451e 100644
> --- a/drivers/gpu/drm/xe/xe_dma_buf.h
> +++ b/drivers/gpu/drm/xe/xe_dma_buf.h
> @@ -7,9 +7,12 @@
> #define _XE_DMA_BUF_H_
>
> #include <drm/drm_gem.h>
> +#include <linux/dma-direction.h>
>
> struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags);
> struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
> struct dma_buf *dma_buf);
> +struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
> + enum dma_data_direction dir);
>
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 5709518e314b..2c8698216581 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -130,6 +130,10 @@ u64 xe_pte_encode(struct xe_bo *bo, u64 offset, enum xe_cache_level cache,
> if (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo))
> pte |= XE_PPGTT_PTE_DM;
>
> +/* DAK */
> + if (xe_bo_is_vram(bo) || bo->flags & XE_BO_XELINK_AVAIL)
> + pte |= XE_PPGTT_PTE_DM;
> +
> return __pte_encode(pte, cache, NULL, pt_level);
> }
>
> @@ -144,8 +148,7 @@ static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm,
> if (level == 0) {
> u64 empty = xe_pte_encode(vm->scratch_bo[id], 0,
> XE_CACHE_WB, 0);
> -
> - return empty;
> +return empty;
> } else {
> return xe_pde_encode(vm->scratch_pt[id][level - 1]->bo, 0,
> XE_CACHE_WB);
> diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
> index ac4cff76f81d..00bebad1c899 100644
> --- a/drivers/gpu/drm/xe/xe_xelink.c
> +++ b/drivers/gpu/drm/xe/xe_xelink.c
> @@ -462,3 +462,15 @@ void xe_xelink_remove(struct xe_device *xe)
>
> xe->intel_xelink.ops = &default_ops;
> }
> +
> +int xe_xelink_mapping_get(struct xe_device *xe)
> +{
> + return xe->intel_xelink.ops->parent_event(xe->intel_xelink.handle,
> + XELINK_PARENT_MAPPING_GET);
> +}
> +
> +int xe_xelink_mapping_put(struct xe_device *xe)
> +{
> + return xe->intel_xelink.ops->parent_event(xe->intel_xelink.handle,
> + XELINK_PARENT_MAPPING_PUT);
> +}
> diff --git a/drivers/gpu/drm/xe/xe_xelink.h b/drivers/gpu/drm/xe/xe_xelink.h
> index e17faacc7b1c..12feb5b04d23 100644
> --- a/drivers/gpu/drm/xe/xe_xelink.h
> +++ b/drivers/gpu/drm/xe/xe_xelink.h
> @@ -31,6 +31,8 @@ void xe_xelink_init_early(struct xe_device *xe);
> void xe_xelink_init_mmio(struct xe_device *xe);
> void xe_xelink_init(struct xe_device *xe);
> void xe_xelink_init_aux(struct xe_device *xe);
> +int xe_xelink_mapping_get(struct xe_device *xe);
> +int xe_xelink_mapping_put(struct xe_device *xe);
> void xe_xelink_remove(struct xe_device *xe);
>
> #endif
> --
> 2.35.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Intel-xe] [PATCH 2/3] drm/xe: Introduce XeLink device
2023-08-08 16:45 ` [Intel-xe] [PATCH 2/3] drm/xe: Introduce XeLink device David Kershner
@ 2023-08-08 18:43 ` Rodrigo Vivi
0 siblings, 0 replies; 10+ messages in thread
From: Rodrigo Vivi @ 2023-08-08 18:43 UTC (permalink / raw)
To: David Kershner; +Cc: lucas.demarchi, john.fleck, matthew.d.roper, intel-xe
On Tue, Aug 08, 2023 at 12:45:33PM -0400, David Kershner wrote:
> Add XeLink support for PVC devices.
>
> Introduce the initial platform data structure that will be shared
> between the Xe driver and the XeLink driver.
>
> If the device is PVC, and there is an XeLink device present, add
> and initialize an Auxbus device with the appropriate resources.
>
> Add the XeLink information register.
>
> Add package address register for defining the Device Physical Address
> space (DPA).
>
> Add initial interrupt support.
>
> The package address register defines the device physical
> address (DPA) space for the given device.
>
> Using the "unique" xa_array index, generate a DPA address
> for the device and program the package register appropriately.
>
> Update the LMEM offset to use the DPA address.
>
> Signed-off-by: David Kershner <david.kershner@intel.com>
> ---
> drivers/gpu/drm/xe/Kconfig | 1 +
> drivers/gpu/drm/xe/regs/xe_gt_regs.h | 20 ++
> drivers/gpu/drm/xe/xe_device.c | 13 +-
> drivers/gpu/drm/xe/xe_device_types.h | 27 ++
> drivers/gpu/drm/xe/xe_gt_types.h | 2 +
> drivers/gpu/drm/xe/xe_irq.c | 28 +-
> drivers/gpu/drm/xe/xe_mmio.c | 2 +-
> drivers/gpu/drm/xe/xe_pci.c | 2 +
> drivers/gpu/drm/xe/xe_pci_types.h | 1 +
> drivers/gpu/drm/xe/xe_xelink.c | 447 +++++++++++++++++++++++++++
> drivers/gpu/drm/xe/xe_xelink.h | 36 +++
> include/drm/intel_xelink_platform.h | 140 +++++++++
> 12 files changed, 716 insertions(+), 3 deletions(-)
> create mode 100644 drivers/gpu/drm/xe/xe_xelink.h
> create mode 100644 include/drm/intel_xelink_platform.h
>
> diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
> index 0a4ea965645b..9d396ca7708a 100644
> --- a/drivers/gpu/drm/xe/Kconfig
> +++ b/drivers/gpu/drm/xe/Kconfig
> @@ -36,6 +36,7 @@ config DRM_XE
> select DRM_SCHED
> select MMU_NOTIFIER
> select WANT_DEV_COREDUMP
> + select AUXILIARY_BUS
> help
> Experimental driver for Intel Xe series GPUs
>
> diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> index d654f3311351..fa78cbcd1058 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> @@ -81,6 +81,11 @@
> #define GLOBAL_MOCS(i) XE_REG(0x4000 + (i) * 4) /* Global MOCS regs */
> #define GFX_CCS_AUX_NV XE_REG(0x4208)
>
> +#define PKG_ADDR_RANGE XE_REG(0x41B0)
> +#define PKG_ADDR_RANGE_RANGE_SHIFT 20
> +#define PKG_ADDR_RANGE_BASE_SHIFT 1
> +#define PKG_ADDR_RANGE_ENABLE 1
> +
> #define VD0_AUX_NV XE_REG(0x4218)
> #define VE0_AUX_NV XE_REG(0x4238)
>
> @@ -88,6 +93,11 @@
> #define AUX_INV REG_BIT(0)
>
> #define XEHP_TILE_ADDR_RANGE(_idx) XE_REG_MCR(0x4900 + (_idx) * 4)
> +#define XEHP_TILE_LMEM_RANGE_SHIFT 8
> +#define XEHP_TILE_LMEM_BASE_SHIFT 1
> +#define XEHP_TILE_LMEM_BASE_MASK REG_GENMASK(7, 1)
> +#define XEHP_TILE_LMEM_RANGE_MASK REG_GENMASK(14, 8)
> +
> #define XEHP_FLAT_CCS_BASE_ADDR XE_REG_MCR(0x4910)
>
> #define CHICKEN_RASTER_1 XE_REG_MCR(0x6204, XE_REG_OPTION_MASKED)
> @@ -349,6 +359,11 @@
> #define RCU_MODE XE_REG(0x14800, XE_REG_OPTION_MASKED)
> #define RCU_MODE_CCS_ENABLE REG_BIT(0)
>
> +#define PKG_ADDR_BASE XE_REG(0x108390)
> +#define PKG_ADDR_BASE_RANGE_SHIFT 20
> +#define PKG_ADDR_BASE_BASE_SHIFT 1
> +#define PKG_ADDR_BASE_ENABLE 1
> +
> #define FORCEWAKE_ACK_GT XE_REG(0x130044)
> #define FORCEWAKE_KERNEL BIT(0)
> #define FORCEWAKE_USER BIT(1)
> @@ -397,4 +412,9 @@
> #define XEHPC_BCS5_BCS6_INTR_MASK XE_REG(0x190118)
> #define XEHPC_BCS7_BCS8_INTR_MASK XE_REG(0x19011c)
>
> +#define PUNIT_MMIO_CR_POC_STRAPS XE_REG(0x281078)
> +#define NUM_TILES_MASK REG_GENMASK(1, 0)
> +#define CD_ALIVE REG_BIT(2)
> +#define SOCKET_ID_MASK REG_GENMASK(7, 3)
> +
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
> index 766df07de979..296953b7d512 100644
> --- a/drivers/gpu/drm/xe/xe_device.c
> +++ b/drivers/gpu/drm/xe/xe_device.c
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: MIT
> /*
> - * Copyright © 2021 Intel Corporation
> + * Copyright © 2021 - 2023 Intel Corporation
we should probably do a fixup patch on the original files changing everything to 2023...
> */
>
> #include "xe_device.h"
> @@ -34,6 +34,7 @@
> #include "xe_vm.h"
> #include "xe_vm_madvise.h"
> #include "xe_wait_user_fence.h"
> +#include "xe_xelink.h"
>
> #ifdef CONFIG_LOCKDEP
> struct lockdep_map xe_device_mem_access_lockdep_map = {
> @@ -262,6 +263,8 @@ int xe_device_probe(struct xe_device *xe)
> if (err)
> return err;
>
> + xe_xelink_init_early(xe);
> +
> for_each_tile(tile, xe, id) {
> err = xe_tile_alloc(tile);
> if (err)
> @@ -272,6 +275,8 @@ int xe_device_probe(struct xe_device *xe)
> if (err)
> return err;
>
> + xe_xelink_init_mmio(xe);
> +
> for_each_gt(gt, xe, id) {
> err = xe_pcode_probe(gt);
> if (err)
> @@ -292,6 +297,8 @@ int xe_device_probe(struct xe_device *xe)
> goto err_irq_shutdown;
> }
>
> + xe_xelink_init(xe);
> +
> err = xe_mmio_probe_vram(xe);
> if (err)
> goto err_irq_shutdown;
> @@ -333,6 +340,8 @@ int xe_device_probe(struct xe_device *xe)
>
> xe_display_register(xe);
>
> + xe_xelink_init_aux(xe);
> +
> xe_debugfs_register(xe);
>
> err = drmm_add_action_or_reset(&xe->drm, xe_device_sanitize, xe);
> @@ -365,6 +374,8 @@ void xe_device_remove(struct xe_device *xe)
>
> xe_display_unlink(xe);
>
> + xe_xelink_remove(xe);
> +
> xe_irq_shutdown(xe);
> }
>
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
> index f84ecb976f5d..7b27a5178aca 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -16,6 +16,7 @@
> #include "xe_gt_types.h"
> #include "xe_platform_types.h"
> #include "xe_step_types.h"
> +#include "xe_xelink.h"
>
> #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
> #include "ext/intel_device_info.h"
> @@ -219,6 +220,10 @@ struct xe_device {
> u8 has_asid:1;
> /** @force_execlist: Forced execlist submission */
> u8 force_execlist:1;
> + /** @has_xelink: Has XeLink */
> + u8 has_xelink:1;
> + /** @enable_guc: GuC submission enabled */
> + u8 enable_guc:1;
> /** @has_flat_ccs: Whether flat CCS metadata is used */
> u8 has_flat_ccs:1;
> /** @has_4tile: Whether tile-4 tiling is supported */
> @@ -376,6 +381,28 @@ struct xe_device {
> */
> struct task_struct *pm_callback_task;
>
> + /** @intel_xelink: XeLink information, for those gpus with XeLink connectivity */
> + struct {
> + /** @ops: shared interface operations */
> + const struct xelink_ops *ops;
> + /** @handle: XeLink device handle */
> + void *handle;
> + /** @pd: platform data needed for auxiliary bus */
> + struct xelink_pdata *pd;
> + /** @dpa: base device physical address */
> + u64 dpa;
> + /** @irq_base: base IRQ for multi tile devices */
> + int irq_base;
> + /** @index: internal index for xe devices */
> + int index;
> + /** @xelink_id: XeLink id generated by the XeLink device */
> + u32 xelink_id;
> + /** @socket_id: socket from certain platforms */
> + u8 socket_id;
> + /* @present: Reflect PUNIT presence information */
> + bool present;
> + } intel_xelink;
> +
> /* private: */
>
> #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
> diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
> index 35b8c19fa8bf..e9e551fea95b 100644
> --- a/drivers/gpu/drm/xe/xe_gt_types.h
> +++ b/drivers/gpu/drm/xe/xe_gt_types.h
> @@ -346,6 +346,8 @@ struct xe_gt {
> /** @oob: bitmap with active OOB workaroudns */
> unsigned long *oob;
> } wa_active;
> + /** @xelink_irq: IRQ value assigned to the ANR HW */
> + int xelink_irq;
> };
>
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
> index 2022a5643e01..aaf9569426cc 100644
> --- a/drivers/gpu/drm/xe/xe_irq.c
> +++ b/drivers/gpu/drm/xe/xe_irq.c
> @@ -1,10 +1,11 @@
> // SPDX-License-Identifier: MIT
> /*
> - * Copyright © 2021 Intel Corporation
> + * Copyright © 2021 - 2023 Intel Corporation
> */
>
> #include "xe_irq.h"
>
> +#include <linux/irq.h>
> #include <linux/sched/clock.h>
>
> #include <drm/drm_managed.h>
> @@ -27,6 +28,15 @@
> #define IIR(offset) XE_REG(offset + 0x8)
> #define IER(offset) XE_REG(offset + 0xc)
>
> +/* Define the BAR and offset for XeLink CSRs */
> +#define XE_XELINK_IRQ BIT(8)
> +#define CD_BASE_OFFSET 0x291000
> +#define CD_BAR_SIZE (256 * 1024)
> +
> +#define CPORT_MBDB_CSRS XE_REG(CD_BASE_OFFSET + 0x6000)
> +#define CPORT_MBDB_CSRS_END XE_REG(CD_BASE_OFFSET + 0x1000)
> +#define CPORT_MBDB_INT_ENABLE_MASK XE_REG(CD_BASE_OFFSET + 0x8)
> +
> static void assert_iir_is_zero(struct xe_gt *mmio, struct xe_reg reg)
> {
> u32 val = xe_mmio_read32(mmio, reg);
> @@ -362,6 +372,18 @@ static void dg1_intr_enable(struct xe_device *xe, bool stall)
> xe_mmio_read32(mmio, DG1_MSTR_TILE_INTR);
> }
>
> +/*
> + * xelink_irq_handler - handle XeLink IRQs
> + *
> + * PVC can have an XeLink attached. Handle the IRQs that are sourced by
> + * the device supporting the XeLink.
> + */
> +static void xelink_irq_handler(struct xe_gt *gt, const u32 master_ctl)
> +{
> + if (master_ctl & XE_XELINK_IRQ)
> + generic_handle_irq(gt->xelink_irq);
> +}
> +
> /*
> * Top-level interrupt handler for Xe_LP+ and beyond. These platforms have
> * a "master tile" interrupt register which must be consulted before the
> @@ -423,6 +445,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
> xe_display_irq_handler(xe, master_ctl);
> gu_misc_iir = gu_misc_irq_ack(xe, master_ctl);
> }
> + xelink_irq_handler(mmio, master_ctl);
> }
>
> dg1_intr_enable(xe, false);
> @@ -469,6 +492,9 @@ static void gt_irq_reset(struct xe_tile *tile)
> xe_mmio_write32(mmio, GPM_WGBOXPERF_INTR_MASK, ~0);
> xe_mmio_write32(mmio, GUC_SG_INTR_ENABLE, 0);
> xe_mmio_write32(mmio, GUC_SG_INTR_MASK, ~0);
> +
> + if (tile->xe->intel_xelink.present)
> + xe_mmio_write64(mmio, CPORT_MBDB_INT_ENABLE_MASK, 0);
> }
>
> static void xelp_irq_reset(struct xe_tile *tile)
> diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
> index aa9c573b1243..1b0184135d45 100644
> --- a/drivers/gpu/drm/xe/xe_mmio.c
> +++ b/drivers/gpu/drm/xe/xe_mmio.c
> @@ -173,7 +173,7 @@ static int xe_determine_lmem_bar_size(struct xe_device *xe)
> if (!xe->mem.vram.io_size)
> return -EIO;
>
> - xe->mem.vram.base = 0; /* DPA offset */
> + xe->mem.vram.base = xe->intel_xelink.dpa;
>
> /* set up a map to the total memory area. */
> xe->mem.vram.mapping = ioremap_wc(xe->mem.vram.io_start, xe->mem.vram.io_size);
> diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
> index 46e3a9632efe..a2258524c577 100644
> --- a/drivers/gpu/drm/xe/xe_pci.c
> +++ b/drivers/gpu/drm/xe/xe_pci.c
> @@ -162,6 +162,7 @@ static const struct xe_graphics_desc graphics_xehpc = {
>
> .has_asid = 1,
> .has_flat_ccs = 0,
> + .has_xelink = 1,
> .has_link_copy_engine = 1,
> .supports_usm = 1,
> };
> @@ -563,6 +564,7 @@ static int xe_info_init(struct xe_device *xe,
> xe->info.vm_max_level = graphics_desc->vm_max_level;
> xe->info.supports_usm = graphics_desc->supports_usm;
> xe->info.has_asid = graphics_desc->has_asid;
> + xe->info.has_xelink = graphics_desc->has_xelink;
> xe->info.has_flat_ccs = graphics_desc->has_flat_ccs;
> xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation;
> xe->info.has_link_copy_engine = graphics_desc->has_link_copy_engine;
> diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h
> index ba31b933eb8e..85fec0c9e638 100644
> --- a/drivers/gpu/drm/xe/xe_pci_types.h
> +++ b/drivers/gpu/drm/xe/xe_pci_types.h
> @@ -22,6 +22,7 @@ struct xe_graphics_desc {
> u8 max_remote_tiles:2;
>
> u8 has_asid:1;
> + u8 has_xelink:1;
> u8 has_flat_ccs:1;
> u8 has_link_copy_engine:1;
> u8 has_range_tlb_invalidation:1;
> diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
> index 51a31f6a4740..ac4cff76f81d 100644
> --- a/drivers/gpu/drm/xe/xe_xelink.c
> +++ b/drivers/gpu/drm/xe/xe_xelink.c
> @@ -3,7 +3,20 @@
> * Copyright © 2023 Intel Corporation
> */
>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/firmware.h>
> +#include <linux/irq.h>
> #include <linux/moduleparam.h>
> +#include <linux/xarray.h>
> +
> +#include <drm/intel_xelink_platform.h>
> +
> +#include "xe_device.h"
> +#include "xe_mmio.h"
> +#include "xe_gt_mcr.h"
> +#include "xe_xelink.h"
> +#include "regs/xe_reg_defs.h"
> +#include "regs/xe_gt_regs.h"
>
> /*
> * This module parameter is needed because SRIOV PF and XeLink are mutually
> @@ -15,3 +28,437 @@
> static bool xe_enable_xelink = true;
> module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
> MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
> +
> +#define HAS_XELINK(xe) ((xe)->info.has_xelink)
> +/* Define the BAR and offset for the XeLink CSRs */
> +#define GTTMMADR_BAR 0
> +#define CD_BASE_OFFSET 0x291000
> +#define CD_BAR_SIZE (256 * 1024)
> +
> +/* Xarray of XeLink devices */
> +static DEFINE_XARRAY_ALLOC(intel_fdevs);
> +
> +static struct query_info *default_query(void *handle, u32 xelink_id)
> +{
> + return ERR_PTR(-EOPNOTSUPP);
> +}
> +
> +static int default_handle_event(void *handle, enum xelink_parent_event event)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +static const struct xelink_ops default_ops = {
> + .connectivity_query = default_query,
> + .parent_event = default_handle_event,
> +};
> +
> +static int register_dev(void *parent, void *handle, u32 xelink_id,
> + const struct xelink_ops *ops)
> +{
> + struct xe_device *xe = parent;
> +
> + WARN(xe->intel_xelink.ops != &default_ops, "XeLink: already registered");
> +
> + xe->intel_xelink.handle = handle;
> + xe->intel_xelink.xelink_id = xelink_id;
> + xe->intel_xelink.ops = ops;
> +
> + drm_info(&xe->drm, "XeLink: registered: 0x%x\n", xelink_id);
> +
> + return 0;
> +}
> +
> +static void unregister_dev(void *parent, const void *handle)
> +{
> + struct xe_device *xe = parent;
> +
> + WARN(xe->intel_xelink.handle != handle, "XeLink: invalid handle");
> +
> + drm_info(&xe->drm, "XeLink: unregistered: 0x%x\n",
> + xe->intel_xelink.xelink_id);
> + xe->intel_xelink.handle = NULL;
> + xe->intel_xelink.ops = &default_ops;
> +}
> +
> +static int dev_event(void *parent, void *handle, enum xelink_dev_event event,
> + void *event_data)
> +{
> + return 0;
> +}
> +
> +/**
> + * init_pd - Allocate and initialize platform specific data
> + * @xe: Valid xe instance
> + *
> + * Return:
> + * * pd - initialized xelink_pdata,
> + * * NULL - Allocation failure
> + */
> +static struct xelink_pdata *init_pd(struct xe_device *xe)
> +{
> + struct xelink_pdata *pd;
> + u32 reg;
> +
> + pd = kzalloc(sizeof(*pd), GFP_KERNEL);
> + if (!pd)
> + return NULL;
> +
> + pd->version = XELINK_VERSION;
> + pd->parent = xe;
> + pd->product = XELINK_PONTEVECCHIO;
> + pd->index = xe->intel_xelink.index & 0xFFFF;
> + pd->sd_cnt = xe->info.tile_count;
> + pd->socket_id = xe->intel_xelink.socket_id;
> + pd->slot = PCI_SLOT(to_pci_dev(xe->drm.dev)->devfn);
> +
> + pd->resources = NULL;
> + pd->num_resources = 0;
> + pd->register_dev = register_dev;
> + pd->unregister_dev = unregister_dev;
> + pd->dev_event = dev_event;
> +
> + /*
> + * Calculate the actual DPA offset and size (in GB) for the device.
> + * Each tile will have the same amount of memory, so we only need to
> + * read the first one.
> + */
> + reg = xe_gt_mcr_unicast_read_any(xe_device_get_root_tile(xe)->primary_gt,
> + XEHP_TILE_ADDR_RANGE(0)) & XEHP_TILE_LMEM_RANGE_MASK;
> +
> + // TILE0 is < 8Gb, PVC needs 8GB, so fake it.
> + if (reg >> XEHP_TILE_LMEM_RANGE_SHIFT < 8) {
> + drm_err(&xe->drm, "XEHP_TILE0_ADDR_RANGE: %x\n", reg);
> + reg = 8 << XEHP_TILE_LMEM_RANGE_SHIFT;
> + }
> + pd->dpa.pkg_offset = (u32)xe->intel_xelink.index * MAX_DPA_SIZE;
> + pd->dpa.pkg_size = (reg >> XEHP_TILE_LMEM_RANGE_SHIFT) * pd->sd_cnt;
> +
> + return pd;
> +}
> +
> +/**
> + * init_resource - Create the resource array, and apply the appropriate data
> + * @xe: valid xe instance
> + * @res_cnt: pointer to return number of allocated resources
> + *
> + * First resource [0] is for the IRQ(s). Each device gets 1 IRQ. Subsequent
> + * resources describe the IO memory space for the device(s).
> + *
> + * Make sure to set the gt->xelink_irq value.
> + *
> + * Return:
> + * * res - Initialized resource array
> + * * NULL - Allocaction failure
> + */
> +static struct resource *init_resource(struct xe_device *xe,
> + u32 *res_cnt)
> +{
> + struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
> + struct xe_gt *gt;
> + struct resource *res_base, *res;
> + u32 cnt = xe->info.tile_count * 2;
> + unsigned int i;
> +
> + /* Each sd gets one resource for IRQ and one for MEM */
> + res_base = kcalloc(cnt, sizeof(*res_base), GFP_KERNEL);
> + if (!res_base)
> + return NULL;
> +
> + res = res_base;
> + for_each_gt(gt, xe, i) {
> + res->start = xe->intel_xelink.irq_base + i;
> + res->end = xe->intel_xelink.irq_base + i;
> + res->flags = IORESOURCE_IRQ;
> + res++;
> +
> + res->start = pci_resource_start(pdev, GTTMMADR_BAR) + CD_BASE_OFFSET +
> + i * gt_to_tile(gt)->mmio.size;
> + res->end = res->start + CD_BAR_SIZE - 1;
> + res->flags = IORESOURCE_MEM;
> + drm_info(&xe->drm, "XeLink: mem_resource = %pR\n", res);
> + res++;
> + gt->xelink_irq = xe->intel_xelink.irq_base + i;
> + }
> +
> + *res_cnt = cnt;
> + return res_base;
> +}
> +
> +/**
> + * xelink_irq_mask - Null callback. Masking/unmasking happens in the parent
> + * driver
> + * @d: Valid irq_data information
> + */
> +static void xelink_irq_mask(struct irq_data *d)
> +{
> +}
> +
> +static void xelink_irq_unmask(struct irq_data *d)
> +{
> +}
> +
> +static struct irq_chip xelink_irq_chip = {
> + .name = "xelink_irq_chip",
> + .irq_mask = xelink_irq_mask,
> + .irq_unmask = xelink_irq_unmask,
> +};
> +
> +/**
> + * init_irq_desc - Allocate IRQ descriptors to use for the xelink
> + * @xe: Valid xe instance
> + *
> + * Allocate the required IRQ descriptor(s) and initialize the
> + * appropriate state.
> + *
> + * Return:
> + * * 0 - Success
> + * * errno - Error that occurred
> + */
> +static int init_irq_desc(struct xe_device *xe)
> +{
> + unsigned int num_subdevs = xe->info.tile_count;
> + int err;
> + int irq;
> + int irq_base;
> +
> + irq_base = irq_alloc_descs(-1, 0, num_subdevs, 0);
> + if (irq_base < 0) {
> + err = irq_base;
> + goto cleanup;
> + }
> +
> + err = 0;
> + for (irq = irq_base; !err && irq < irq_base + num_subdevs; irq++) {
> + irq_set_chip_and_handler_name(irq, &xelink_irq_chip,
> + handle_simple_irq,
> + "xelink_irq_handler");
> + err = irq_set_chip_data(irq, xe);
> + }
> +
> + if (err) {
> + irq_free_descs(irq_base, num_subdevs);
> + goto cleanup;
> + }
> +
> + drm_info(&xe->drm, "XeLink: IRQ base: %d cnt: %d\n", irq_base,
> + num_subdevs);
> +
> + xe->intel_xelink.irq_base = irq_base;
> +
> + return 0;
> +
> +cleanup:
> + xe->intel_xelink.index = err;
> + drm_err(&xe->drm, "XeLink: Failed to allocate IRQ data: %d\n", err);
> + return err;
> +}
> +
> +/**
> + * xe_xelink_init_early - Set the XeLink info to the defaults
> + * @xe: valid xe instance
> + *
> + * index is set to ENODEV to show that, by default, there is no device.
> + * If any of the initialization steps fail, it will be set to the appropriate
> + * errno value.
> + */
> +void xe_xelink_init_early(struct xe_device *xe)
> +{
> + xe->intel_xelink.ops = &default_ops;
> + xe->intel_xelink.index = -ENODEV;
> +}
> +
> +/**
> + * xe_xelink_init_mmio - check if XeLink is available via MMIO
> + * @xe: valid xe instance
> + *
> + * Read the relevant regs to check for XeLink availability and get the socket id
> + */
> +void xe_xelink_init_mmio(struct xe_device *xe)
> +{
> + u32 xelink_info;
> +
> + if (!HAS_XELINK(xe) || !xe_enable_xelink)
> + return;
> +
> + xelink_info = xe_mmio_read32(xe_device_get_root_tile(xe)->primary_gt,
> + PUNIT_MMIO_CR_POC_STRAPS);
> +
> + xe->intel_xelink.socket_id = REG_FIELD_GET(SOCKET_ID_MASK, xelink_info);
> +
> + if (REG_FIELD_GET(CD_ALIVE, xelink_info)) {
> + drm_info(&xe->drm, "XeLink available\n");
> + xe->intel_xelink.present = true;
> + }
> +}
> +
> +/**
> + * xe_xelink_init - Allocate device index and complete initial HW setup
> + * @xe: valid device instance
> + *
> + * NOTE: index is zero inited. If the XeLink is not present, or an error occurs
> + * during setup, this must be 0 for the range registers.
> + *
> + */
> +void xe_xelink_init(struct xe_device *xe)
> +{
> + struct xe_gt *gt;
> + static u32 last_id;
> + unsigned int i;
> + u32 index = 0;
> + u32 range;
> + u32 base;
> + int err;
> +
> + if (!HAS_XELINK(xe))
> + return;
> +
> + if (!xe->intel_xelink.present)
> + goto set_range;
> +
> + err = init_irq_desc(xe);
> + if (err) {
> + xe->intel_xelink.index = err;
> + goto set_range;
> + }
> +
> + /*
> + * Try the socket id first. Systems with this feature, will
> + * get a deterministic value. If not, try with the cyclic.
> + */
> + err = xa_insert(&intel_fdevs, xe->intel_xelink.socket_id, xe,
> + GFP_KERNEL);
> + if (!err)
> + index = xe->intel_xelink.socket_id;
> +
> + /* socket_id is not available */
> + if (err == -EBUSY) {
> + /*
> + * NOTE: index is only updated on success i.e. >= 0
> + * < 0 err, 0 ok, > 0 wrapped
> + */
> + err = xa_alloc_cyclic(&intel_fdevs, &index, xe,
> + XA_LIMIT(0, MAX_DEVICE_COUNT - 1),
> + &last_id, GFP_KERNEL);
> + }
> + if (err < 0) {
> + index = 0;
> + xe->intel_xelink.index = err;
> + drm_err(&xe->drm,
> + "XeLink: Failed to allocate index: %d\n",
> + err);
> + irq_free_descs(xe->intel_xelink.irq_base,
> + xe->info.tile_count);
> + goto set_range;
> + }
> + xe->intel_xelink.index = index;
> + xe->intel_xelink.dpa = (u64)index * MAX_DPA_SIZE * SZ_1G;
> + drm_info(&xe->drm, "XeLink: [dpa 0x%llx-0x%llx\n", xe->intel_xelink.dpa,
> + ((u64)index + 1) * MAX_DPA_SIZE * SZ_1G - 1);
> +
> + /*
> + * Set range has to be done for all devices that support device
> + * address space, regardless of presence or error.
> + */
> +set_range:
> + /* Set GAM address range registers */
> + range = index * MAX_DPA_SIZE << PKG_ADDR_RANGE_BASE_SHIFT;
> + range |= MAX_DPA_SIZE << PKG_ADDR_RANGE_RANGE_SHIFT;
> + range |= PKG_ADDR_RANGE_ENABLE;
> +
> + /* set SGunit address range register */
> + base = index * MAX_DPA_SIZE << PKG_ADDR_BASE_BASE_SHIFT;
> + base |= MAX_DPA_SIZE << PKG_ADDR_BASE_RANGE_SHIFT;
> + base |= PKG_ADDR_BASE_ENABLE;
> +
> + /* Needs to be set for each gt */
> + for_each_gt(gt, xe, i) {
> + xe_mmio_write32(gt, PKG_ADDR_RANGE, range);
> + xe_mmio_write32(gt, PKG_ADDR_BASE, base);
> + }
> +}
> +
> +static void xe_xelink_release_dev(struct device *dev)
> +{
> + struct auxiliary_device *aux = to_auxiliary_dev(dev);
> + struct xelink_pdata *pd = container_of(aux, struct xelink_pdata, aux_dev);
> +
> + kfree(pd->resources);
> + pd->resources = NULL;
> +
> + kfree(pd);
> +}
> +
> +/**
> + * xe_xelink_init_aux - Initialize resources and add auxiliary bus interface
> + * @xe: valid xe instance
> + *
> + */
> +void xe_xelink_init_aux(struct xe_device *xe)
> +{
> + struct device *dev = &to_pci_dev(xe->drm.dev)->dev;
> + struct resource *res = NULL;
> + struct xelink_pdata *pd;
> + int err = -ENOMEM;
> + u32 res_cnt;
> +
> + if (!xe->intel_xelink.present)
> + return;
> +
> + if (xe->intel_xelink.index < 0) {
> + err = xe->intel_xelink.index;
> + goto fail;
> + }
> +
> + pd = init_pd(xe);
> + if (!pd)
> + goto cleanup;
> +
> + res = init_resource(xe, &res_cnt);
> + if (!res)
> + goto cleanup;
> +
> + pd->resources = res;
> + pd->num_resources = res_cnt;
> +
> + pd->aux_dev.name = "xelink";
> + pd->aux_dev.id = pd->index;
> + pd->aux_dev.dev.parent = dev;
> + pd->aux_dev.dev.release = xe_xelink_release_dev;
> +
> + err = auxiliary_device_init(&pd->aux_dev);
> + if (err)
> + goto cleanup;
> +
> + err = auxiliary_device_add(&pd->aux_dev);
> + if (err) {
> + auxiliary_device_uninit(&pd->aux_dev);
> + goto cleanup;
> + }
> +
> + xe->intel_xelink.pd = pd;
> +
> + return;
> +
> +cleanup:
> + xa_erase(&intel_fdevs, xe->intel_xelink.index);
> + irq_free_descs(xe->intel_xelink.irq_base, xe->info.tile_count);
> + kfree(res);
> + kfree(pd);
> + xe->intel_xelink.index = err;
> +fail:
> + drm_err(&xe->drm, "XeLink: Failed to initialize err: %d\n", err);
> +}
> +
> +void xe_xelink_remove(struct xe_device *xe)
> +{
> + if (xe->intel_xelink.index < 0)
> + return;
> +
> + auxiliary_device_delete(&xe->intel_xelink.pd->aux_dev);
> + auxiliary_device_uninit(&xe->intel_xelink.pd->aux_dev);
> + xa_erase(&intel_fdevs, xe->intel_xelink.index);
> + irq_free_descs(xe->intel_xelink.irq_base, xe->info.tile_count);
> +
> + xe->intel_xelink.ops = &default_ops;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_xelink.h b/drivers/gpu/drm/xe/xe_xelink.h
> new file mode 100644
> index 000000000000..e17faacc7b1c
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_xelink.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2019 - 2023 Intel Corporation
> + */
> +
> +#ifndef _XE_XELINK_H_
> +#define _XE_XELINK_H_
> +
> +/*
> + * Define the maximum number of devices instances based on the amount of
> + * FID space.
> + *
> + * XARRAY limits are "inclusive", but using this value as a range check
> + * outside of xarray, makes the exclusive upper bound a little easier to
> + * deal with.
> + *
> + * I.e.:
> + * [0 - 256)
> + *
> + * Less than HW supports, but more than will be currently possible.
> + *
> + */
> +#define MAX_DEVICE_COUNT 256
> +
> +/* Fixed Device Physical Address (DPA) size for a device/package (in GB) */
> +#define MAX_DPA_SIZE 128
> +
> +struct xe_device;
> +
> +void xe_xelink_init_early(struct xe_device *xe);
> +void xe_xelink_init_mmio(struct xe_device *xe);
> +void xe_xelink_init(struct xe_device *xe);
> +void xe_xelink_init_aux(struct xe_device *xe);
> +void xe_xelink_remove(struct xe_device *xe);
> +
> +#endif
> diff --git a/include/drm/intel_xelink_platform.h b/include/drm/intel_xelink_platform.h
> new file mode 100644
> index 000000000000..86eeb10fdc1e
> --- /dev/null
> +++ b/include/drm/intel_xelink_platform.h
> @@ -0,0 +1,140 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright(c) 2019 - 2023 Intel Corporation.
> + */
> +
> +#ifndef __INTEL_XELINK_PLATFORM_H
> +#define __INTEL_XELINK_PLATFORM_H
> +
> +#define XELINK_VERSION 1
> +
> +#include <linux/auxiliary_bus.h>
> +#include <linux/types.h>
> +
> +/**
> + * enum product_type - Product type identifying the parent
> + * @XELINK_UNDEFINED: no product type hints
> + * @XELINK_PONTEVECCHIO: parent is a PVC
> + * @XELINK_PRODUCTS: end of the list
> + *
> + */
> +enum product_type {
> + XELINK_UNDEFINED,
> + XELINK_PONTEVECCHIO,
> + XELINK_PRODUCTS
> +};
> +
> +/**
> + * enum xelink_dev_event - events generated to the parent device
> + * @XELINK_DEV_REMOVE: Xelink device was removed
> + * @XELINK_DEV_ERROR: An error occurred
> + * @XELINK_DEV_EVENTS: end of list
> + *
> + * Connectivity events, possible errors, etc.
> + */
> +enum xelink_dev_event {
> + XELINK_DEV_REMOVE,
> + XELINK_DEV_EVENTS
> +};
> +
> +/**
> + * enum xelink_parent_event - Events generated by the parent device
> + * @XELINK_PARENT_PCIE_ERR: Parent had a PCI error
> + * @XELINK_PARENT_MAPPING_GET: Notify XeLink of buffer mapping
> + * @XELINK_PARENT_MAPPING_PUT: Notify XeLink of buffer unmapping
> + *
> + * These are examples.
> + */
> +enum xelink_parent_event {
> + XELINK_PARENT_PCIE_ERR,
> + XELINK_PARENT_MAPPING_GET,
> + XELINK_PARENT_MAPPING_PUT,
> +};
> +
> +/**
> + * struct sd2sd_info - Subdevice to subdevice connectivity info
> + * @bandwidth: in Gbps units not factoring in width or quality degredation
> + * @latency: in 1/10 hops units
> + */
> +struct sd2sd_info {
> + u16 bandwidth;
> + u16 latency;
> +};
> +
> +/**
> + * struct query_info - connectivity query response information
> + * @src_cnt: Requester subdevice count
> + * @dst_cnt: Destination path count
> + * @sd2sd: array of src/dst bandwidth/latency information
> + *
> + * Query info will be a variably sized data structure allocated by the
> + * XeLink driver. The access will be indexed by
> + * (src_index * dst_cnt) + dst_index
> + *
> + * The caller will need to free the buffer when done.
> + */
> +struct query_info {
> + u8 src_cnt;
> + u8 dst_cnt;
> + struct sd2sd_info sd2sd[];
> +};
> +
> +/**
> + * struct xelink_ops - Communication path from parent to XeLink instance
> + * @connectivity_query: Query a device for xelink_id connectivity
> + * @parent_event: Any events needed by the XeLink device
> + *
> + * connectivity_query() returns:
> + * a populated query_info on success,
> + * an ERR_PTR() on failure
> + *
> + */
> +struct xelink_ops {
> + struct query_info *(*connectivity_query)(void *handle, u32 xelink_id);
> + int (*parent_event)(void *handle, enum xelink_parent_event event);
> +};
> +
> +struct dpa_space {
> + u32 pkg_offset;
> + u16 pkg_size;
> +};
> +
> +/**
> + * struct xelink_pdata - Platform specific data that needs to be shared
> + * @version: PSD version information
> + * @parent: Handle to use when calling the parent device
> + * @product: a product hint for any necessary special case requirements
> + * @index: unique device index. This will be part of the device name
> + * @dpa: Device physical address offset and size
> + * @sd_cnt: parent subdevice count
> + * @socket_id: device socket information
> + * @slot: PCI/CXL slot number
> + * @aux_dev: Auxiliary bus device
> + * @resources: Array of resources (Assigned by Xe, the IRQ/MEM for the device)
> + * @num_resources: number of resources in resources array
> + * @register_dev: Register a XeLink instance and ops with the parent device
> + * @unregister_dev: Unregister a XeLink instance from the parent device
> + * @dev_event: Notify parent that an event has occurred
> + */
> +struct xelink_pdata {
> + u16 version;
> + void *parent;
> + enum product_type product;
> + u16 index;
> + struct dpa_space dpa;
> + u8 sd_cnt;
> + u8 socket_id;
> + u8 slot;
> +
> + struct auxiliary_device aux_dev;
> + struct resource *resources;
> + u32 num_resources;
> +
> + int (*register_dev)(void *parent, void *handle, u32 xelink_id,
> + const struct xelink_ops *ops);
> + void (*unregister_dev)(void *parent, const void *handle);
> + int (*dev_event)(void *parent, void *handle,
> + enum xelink_dev_event event, void *event_data);
> +};
> +
> +#endif /* __INTEL_XELINK_PLATFORM_H */
> --
> 2.35.1
>
Everything else looks good to me. It would be good to get a deeper reviewer from
the Xelink team.
Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink
2023-08-08 16:45 ` [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink David Kershner
@ 2023-08-08 18:43 ` Rodrigo Vivi
2023-08-09 10:26 ` Jani Nikula
2023-08-09 3:19 ` Matthew Brost
1 sibling, 1 reply; 10+ messages in thread
From: Rodrigo Vivi @ 2023-08-08 18:43 UTC (permalink / raw)
To: David Kershner; +Cc: lucas.demarchi, john.fleck, matthew.d.roper, intel-xe
On Tue, Aug 08, 2023 at 12:45:32PM -0400, David Kershner wrote:
> Add a new module parameter to control enable/disable of the XeLink
> feature.
>
> Signed-off-by: David Kershner <david.kershner@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
> ---
> drivers/gpu/drm/xe/Makefile | 3 ++-
> drivers/gpu/drm/xe/xe_xelink.c | 17 +++++++++++++++++
> 2 files changed, 19 insertions(+), 1 deletion(-)
> create mode 100644 drivers/gpu/drm/xe/xe_xelink.c
>
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index 1b59702cd9f9..d46558cf12a9 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -115,7 +115,8 @@ xe-y += xe_bb.o \
> xe_vm_madvise.o \
> xe_wait_user_fence.o \
> xe_wa.o \
> - xe_wopcm.o
> + xe_wopcm.o \
> + xe_xelink.o
>
> # i915 Display compat #defines and #includes
> subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
> diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
> new file mode 100644
> index 000000000000..51a31f6a4740
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_xelink.c
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include <linux/moduleparam.h>
> +
> +/*
> + * This module parameter is needed because SRIOV PF and XeLink are mutually
> + * exclusive. The driver needs to be able to enable/disable the XeLink
> + * infrastructure (specifically Device Physical Addressing). Since there
> + * will be no enable/disable for the SRIOV PF path, this parameter is
> + * needed to explicitly disable XeLink when SRIOV PF is required.
> + */
> +static bool xe_enable_xelink = true;
> +module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
> +MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
> --
> 2.35.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink
2023-08-08 16:45 ` [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink David Kershner
2023-08-08 18:43 ` Rodrigo Vivi
@ 2023-08-09 3:19 ` Matthew Brost
1 sibling, 0 replies; 10+ messages in thread
From: Matthew Brost @ 2023-08-09 3:19 UTC (permalink / raw)
To: David Kershner
Cc: lucas.demarchi, john.fleck, rodrigo.vivi, matthew.d.roper,
intel-xe
On Tue, Aug 08, 2023 at 12:45:32PM -0400, David Kershner wrote:
> Add a new module parameter to control enable/disable of the XeLink
> feature.
>
> Signed-off-by: David Kershner <david.kershner@intel.com>
> ---
> drivers/gpu/drm/xe/Makefile | 3 ++-
> drivers/gpu/drm/xe/xe_xelink.c | 17 +++++++++++++++++
I find the name 'xe_xelink' kinda offensive. This is just an opinion but
can we find a better name?
xe_fabric_link?
xe_link?
Open to other ideas.
Matt
> 2 files changed, 19 insertions(+), 1 deletion(-)
> create mode 100644 drivers/gpu/drm/xe/xe_xelink.c
>
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index 1b59702cd9f9..d46558cf12a9 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -115,7 +115,8 @@ xe-y += xe_bb.o \
> xe_vm_madvise.o \
> xe_wait_user_fence.o \
> xe_wa.o \
> - xe_wopcm.o
> + xe_wopcm.o \
> + xe_xelink.o
>
> # i915 Display compat #defines and #includes
> subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
> diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
> new file mode 100644
> index 000000000000..51a31f6a4740
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_xelink.c
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include <linux/moduleparam.h>
> +
> +/*
> + * This module parameter is needed because SRIOV PF and XeLink are mutually
> + * exclusive. The driver needs to be able to enable/disable the XeLink
> + * infrastructure (specifically Device Physical Addressing). Since there
> + * will be no enable/disable for the SRIOV PF path, this parameter is
> + * needed to explicitly disable XeLink when SRIOV PF is required.
> + */
> +static bool xe_enable_xelink = true;
> +module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
> +MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
> --
> 2.35.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink
2023-08-08 18:43 ` Rodrigo Vivi
@ 2023-08-09 10:26 ` Jani Nikula
2023-08-10 22:17 ` Rodrigo Vivi
0 siblings, 1 reply; 10+ messages in thread
From: Jani Nikula @ 2023-08-09 10:26 UTC (permalink / raw)
To: Rodrigo Vivi, David Kershner
Cc: matthew.d.roper, lucas.demarchi, john.fleck, intel-xe
On Tue, 08 Aug 2023, Rodrigo Vivi <rodrigo.vivi@intel.com> wrote:
> On Tue, Aug 08, 2023 at 12:45:32PM -0400, David Kershner wrote:
>> Add a new module parameter to control enable/disable of the XeLink
>> feature.
>>
>> Signed-off-by: David Kershner <david.kershner@intel.com>
>
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Basically the direction from upstream is crystal clear, and has been for
years: never ask users to modify module parameters for normal operation.
Also, it's not possible to adjust this per-device.
Why are we still doing this?
BR,
Jani.
>
>> ---
>> drivers/gpu/drm/xe/Makefile | 3 ++-
>> drivers/gpu/drm/xe/xe_xelink.c | 17 +++++++++++++++++
>> 2 files changed, 19 insertions(+), 1 deletion(-)
>> create mode 100644 drivers/gpu/drm/xe/xe_xelink.c
>>
>> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
>> index 1b59702cd9f9..d46558cf12a9 100644
>> --- a/drivers/gpu/drm/xe/Makefile
>> +++ b/drivers/gpu/drm/xe/Makefile
>> @@ -115,7 +115,8 @@ xe-y += xe_bb.o \
>> xe_vm_madvise.o \
>> xe_wait_user_fence.o \
>> xe_wa.o \
>> - xe_wopcm.o
>> + xe_wopcm.o \
>> + xe_xelink.o
>>
>> # i915 Display compat #defines and #includes
>> subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
>> diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
>> new file mode 100644
>> index 000000000000..51a31f6a4740
>> --- /dev/null
>> +++ b/drivers/gpu/drm/xe/xe_xelink.c
>> @@ -0,0 +1,17 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2023 Intel Corporation
>> + */
>> +
>> +#include <linux/moduleparam.h>
>> +
>> +/*
>> + * This module parameter is needed because SRIOV PF and XeLink are mutually
>> + * exclusive. The driver needs to be able to enable/disable the XeLink
>> + * infrastructure (specifically Device Physical Addressing). Since there
>> + * will be no enable/disable for the SRIOV PF path, this parameter is
>> + * needed to explicitly disable XeLink when SRIOV PF is required.
>> + */
>> +static bool xe_enable_xelink = true;
>> +module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
>> +MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
>> --
>> 2.35.1
>>
--
Jani Nikula, Intel Open Source Graphics Center
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink
2023-08-09 10:26 ` Jani Nikula
@ 2023-08-10 22:17 ` Rodrigo Vivi
0 siblings, 0 replies; 10+ messages in thread
From: Rodrigo Vivi @ 2023-08-10 22:17 UTC (permalink / raw)
To: Jani Nikula; +Cc: lucas.demarchi, matthew.d.roper, john.fleck, intel-xe
On Wed, Aug 09, 2023 at 01:26:22PM +0300, Jani Nikula wrote:
> On Tue, 08 Aug 2023, Rodrigo Vivi <rodrigo.vivi@intel.com> wrote:
> > On Tue, Aug 08, 2023 at 12:45:32PM -0400, David Kershner wrote:
> >> Add a new module parameter to control enable/disable of the XeLink
> >> feature.
> >>
> >> Signed-off-by: David Kershner <david.kershner@intel.com>
> >
> > Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
>
> Basically the direction from upstream is crystal clear, and has been for
> years: never ask users to modify module parameters for normal operation.
>
> Also, it's not possible to adjust this per-device.
>
> Why are we still doing this?
Well, the last time that I looked to it was many years ago. So, someone
from the XeLink team can correct me if I am wrong or add more info.
From what I can remember, the DPA configuration needs to be set at
probe and after set I'm not confident that we have a way out of it.
And if that was set, the SRIOV cannot be used.
But right, it should be better if we could rewind the DPA settings,
and unload xelink when SRIOV starts?
Or do we have a way to block the 'child-modules'? Maybe that would
be better than the modparam itself in case we cannot rewind DPA
settings.
>
>
> BR,
> Jani.
>
>
> >
> >> ---
> >> drivers/gpu/drm/xe/Makefile | 3 ++-
> >> drivers/gpu/drm/xe/xe_xelink.c | 17 +++++++++++++++++
> >> 2 files changed, 19 insertions(+), 1 deletion(-)
> >> create mode 100644 drivers/gpu/drm/xe/xe_xelink.c
> >>
> >> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> >> index 1b59702cd9f9..d46558cf12a9 100644
> >> --- a/drivers/gpu/drm/xe/Makefile
> >> +++ b/drivers/gpu/drm/xe/Makefile
> >> @@ -115,7 +115,8 @@ xe-y += xe_bb.o \
> >> xe_vm_madvise.o \
> >> xe_wait_user_fence.o \
> >> xe_wa.o \
> >> - xe_wopcm.o
> >> + xe_wopcm.o \
> >> + xe_xelink.o
> >>
> >> # i915 Display compat #defines and #includes
> >> subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
> >> diff --git a/drivers/gpu/drm/xe/xe_xelink.c b/drivers/gpu/drm/xe/xe_xelink.c
> >> new file mode 100644
> >> index 000000000000..51a31f6a4740
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/xe/xe_xelink.c
> >> @@ -0,0 +1,17 @@
> >> +// SPDX-License-Identifier: MIT
> >> +/*
> >> + * Copyright © 2023 Intel Corporation
> >> + */
> >> +
> >> +#include <linux/moduleparam.h>
> >> +
> >> +/*
> >> + * This module parameter is needed because SRIOV PF and XeLink are mutually
> >> + * exclusive. The driver needs to be able to enable/disable the XeLink
> >> + * infrastructure (specifically Device Physical Addressing). Since there
> >> + * will be no enable/disable for the SRIOV PF path, this parameter is
> >> + * needed to explicitly disable XeLink when SRIOV PF is required.
> >> + */
> >> +static bool xe_enable_xelink = true;
> >> +module_param_named(enable_xelink, xe_enable_xelink, bool, 0400);
> >> +MODULE_PARM_DESC(enable_xelink, "Enable XeLink feature (default: true)");
> >> --
> >> 2.35.1
> >>
>
> --
> Jani Nikula, Intel Open Source Graphics Center
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-08-10 22:17 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-08 16:45 [Intel-xe] [PATCH 0/3] Add support for XeLink device David Kershner
2023-08-08 16:45 ` [Intel-xe] [PATCH 1/3] drm/xe: Introduce a module parameter to control XeLink David Kershner
2023-08-08 18:43 ` Rodrigo Vivi
2023-08-09 10:26 ` Jani Nikula
2023-08-10 22:17 ` Rodrigo Vivi
2023-08-09 3:19 ` Matthew Brost
2023-08-08 16:45 ` [Intel-xe] [PATCH 2/3] drm/xe: Introduce XeLink device David Kershner
2023-08-08 18:43 ` Rodrigo Vivi
2023-08-08 16:45 ` [Intel-xe] [PATCH 3/3] drm/xe: Teach i915 how to use objects with XeLink connectivity David Kershner
2023-08-08 18:41 ` Rodrigo Vivi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox