From: "Anoop, Vijay" <anoop.c.vijay@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: umesh.nerlige.ramappa@intel.com, badal.nilawar@intel.com,
rodrigo.vivi@intel.com, aravind.iddamsetty@intel.com,
riana.tauro@intel.com, anshuman.gupta@intel.com,
matthew.d.roper@intel.com, michael.j.ruhl@intel.com,
paul.e.luse@intel.com, mohamed.mansoor.v@intel.com,
kam.nasim@intel.com, anoop.c.vijay@intel.com
Subject: [RFC v1 4/5] drm/xe/fwctl: Add Xe FWCTL infrastructure support
Date: Fri, 20 Mar 2026 00:25:32 -0700 [thread overview]
Message-ID: <20260320072528.1780651-11-anoop.c.vijay@intel.com> (raw)
In-Reply-To: <20260320072528.1780651-7-anoop.c.vijay@intel.com>
From: Anoop Vijay <anoop.c.vijay@intel.com>
Add core infrastructure required to support FWCTL subsystem in Xe driver.
This introduces a generic xe_fwctl device context, integrates FWCTL state
into xe_device, and sets up device registration and cleanup.
This provides foundation for future firmware-specific FWCTL handlers.
Signed-off-by: Anoop Vijay <anoop.c.vijay@intel.com>
---
Documentation/userspace-api/fwctl/index.rst | 1 +
drivers/gpu/drm/xe/Kconfig | 1 +
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/xe_device.c | 5 +
drivers/gpu/drm/xe/xe_device_types.h | 4 +
drivers/gpu/drm/xe/xe_fwctl.c | 200 ++++++++++++++++++++
drivers/gpu/drm/xe/xe_fwctl.h | 15 ++
include/uapi/fwctl/xe.h | 4 +
8 files changed, 231 insertions(+)
create mode 100644 drivers/gpu/drm/xe/xe_fwctl.c
create mode 100644 drivers/gpu/drm/xe/xe_fwctl.h
diff --git a/Documentation/userspace-api/fwctl/index.rst b/Documentation/userspace-api/fwctl/index.rst
index 316ac456ad3b..7ef115216316 100644
--- a/Documentation/userspace-api/fwctl/index.rst
+++ b/Documentation/userspace-api/fwctl/index.rst
@@ -12,3 +12,4 @@ to securely construct and execute RPCs inside device firmware.
fwctl
fwctl-cxl
pds_fwctl
+ xe_fwctl
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 4d7dcaff2b91..b215ccdc1911 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -46,6 +46,7 @@ config DRM_XE
select WANT_DEV_COREDUMP
select AUXILIARY_BUS
select REGMAP if I2C
+ select FWCTL
help
Driver for Intel Xe2 series GPUs and later. Experimental support
for Xe series is also available.
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index f9abaf687d46..6d47d5d59cf4 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -47,6 +47,7 @@ xe-y += xe_bb.o \
xe_exec_queue.o \
xe_execlist.o \
xe_force_wake.o \
+ xe_fwctl.o \
xe_ggtt.o \
xe_gpu_scheduler.o \
xe_gsc.o \
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index c70d4ae413a9..8771c40d1582 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -35,6 +35,7 @@
#include "xe_exec.h"
#include "xe_exec_queue.h"
#include "xe_force_wake.h"
+#include "xe_fwctl.h"
#include "xe_ggtt.h"
#include "xe_gt.h"
#include "xe_gt_mcr.h"
@@ -996,6 +997,10 @@ int xe_device_probe(struct xe_device *xe)
xe_debugfs_register(xe);
+ err = xe_fwctl_init(xe);
+ if (err)
+ goto err_unregister_display;
+
err = xe_hwmon_register(xe);
if (err)
goto err_unregister_display;
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 150c76b2acaf..78262e60d7a2 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -38,6 +38,7 @@
struct drm_pagemap_shrinker;
struct intel_display;
struct intel_dg_nvm_dev;
+struct xe_fwctl;
struct xe_ggtt;
struct xe_i2c;
struct xe_pat_ops;
@@ -514,6 +515,9 @@ struct xe_device {
/** @sc: System Controller */
struct xe_sysctrl sc;
+ /** @fwctl: FWCTL device for firmware management */
+ struct xe_fwctl *fwctl;
+
/** @atomic_svm_timeslice_ms: Atomic SVM fault timeslice MS */
u32 atomic_svm_timeslice_ms;
diff --git a/drivers/gpu/drm/xe/xe_fwctl.c b/drivers/gpu/drm/xe/xe_fwctl.c
new file mode 100644
index 000000000000..72124b5b3c87
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_fwctl.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+/**
+ * DOC: Xe FWCTL
+ *
+ * Xe FWCTL implements generic FWCTL IOCTLs to provide userspace access to
+ * firmware management interfaces on Intel Xe discrete GPUs.
+ *
+ * Driver registers a FWCTL device during xe_device initialization and
+ * dispatches firmware RPCs to an appropriate handler based on firmware_type
+ * field in RPC header.
+ *
+ * Each firmware type implements xe_fw_ops interface, providing:
+ * - validate_scope(): Validate whether RPC command is allowed for requested
+ * access scope (CONFIGURATION, DEBUG_READ_ONLY, DEBUG_WRITE_FULL).
+ * - rpc(): Execute firmware RPC and return response.
+ *
+ * Userspace should first issue FWCTL_INFO ioctl and check capability flags to
+ * determine supported firmware types and commands.
+ *
+ * After verifying support, userspace may issue FWCTL_RPC with input and output
+ * buffers pointing to struct fwctl_rpc_xe or firmware‑specific RPC structure
+ * allocated by userspace. Input and output lengths must match structure size.
+ *
+ * Unsupported or invalid commands return -EBADMSG.
+ *
+ * Example:
+ *
+ * .. code-block:: C
+ *
+ * struct fwctl_info_xe xe_info = {0};
+ * struct fwctl_info info = {
+ * .size = sizeof(info),
+ * .device_data_len = sizeof(xe_info),
+ * .out_device_data = (uint64_t)&xe_info,
+ * };
+ *
+ * int fd = open("/dev/fwctl/fwctl0", O_RDWR);
+ * ioctl(fd, FWCTL_INFO, &info);
+ *
+ * struct xe_sysctrl_rpc req = { ... };
+ * struct xe_sysctrl_rpc resp = {0};
+ * struct fwctl_rpc rpc = {
+ * .size = sizeof(struct fwctl_rpc),
+ * .scope = FWCTL_RPC_DEBUG_READ_ONLY,
+ * .in_len = sizeof(req),
+ * .out_len = sizeof(resp),
+ * .in = (uint64_t)&req,
+ * .out = (uint64_t)&resp,
+ * };
+ *
+ * ioctl(fd, FWCTL_RPC, &rpc);
+ */
+
+#include <linux/fwctl.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include <uapi/fwctl/fwctl.h>
+#include <uapi/fwctl/xe.h>
+
+#include "xe_device.h"
+#include "xe_fwctl.h"
+#include "xe_fwctl_types.h"
+#include "xe_pm.h"
+#include "xe_printk.h"
+
+DEFINE_FREE(xe_fwctl, struct xe_fwctl *, if (_T) fwctl_put(&_T->fwctl))
+
+static const struct xe_fw_ops *fw_ops_table[XE_FW_MAX] = {
+ /* [XE_FW_...] = &ops, */
+};
+
+static int xe_fwctl_uctx_open(struct fwctl_uctx *uctx)
+{
+ struct xe_fwctl *fwctl = container_of(uctx->fwctl,
+ struct xe_fwctl,
+ fwctl);
+ struct xe_device *xe = fwctl->xe;
+
+ xe_pm_runtime_get(xe);
+
+ return 0;
+}
+
+static void xe_fwctl_uctx_close(struct fwctl_uctx *uctx)
+{
+ struct xe_fwctl *fwctl = container_of(uctx->fwctl,
+ struct xe_fwctl,
+ fwctl);
+ struct xe_device *xe = fwctl->xe;
+
+ xe_pm_runtime_put(xe);
+}
+
+static void *xe_fwctl_info(struct fwctl_uctx *uctx, size_t *length)
+{
+ struct xe_fwctl *fwctl = container_of(uctx->fwctl,
+ struct xe_fwctl,
+ fwctl);
+ struct xe_device *xe = fwctl->xe;
+ struct fwctl_info_xe *info;
+
+ info = kzalloc_obj(*info);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ info->fw_caps = 0;
+ info->platform = xe->info.platform;
+
+ *length = sizeof(*info);
+ return info;
+}
+
+static void *xe_fwctl_rpc(struct fwctl_uctx *uctx,
+ enum fwctl_rpc_scope scope,
+ void *rpc_in, size_t in_len,
+ size_t *out_len)
+{
+ struct xe_fwctl *fwctl = container_of(uctx->fwctl,
+ struct xe_fwctl,
+ fwctl);
+ struct xe_device *xe = fwctl->xe;
+ const struct fwctl_rpc_xe *hdr = rpc_in;
+ const struct xe_fw_ops *ops;
+ void *resp;
+
+ if (in_len < sizeof(*hdr))
+ return ERR_PTR(-EMSGSIZE);
+
+ if (hdr->firmware_type >= XE_FW_MAX)
+ return ERR_PTR(-EINVAL);
+
+ ops = fw_ops_table[hdr->firmware_type];
+ if (!ops)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (ops->validate_scope &&
+ !ops->validate_scope(rpc_in, in_len, scope))
+ return ERR_PTR(-EBADMSG);
+
+ resp = ops->rpc(xe, scope, rpc_in, in_len, out_len);
+ if (IS_ERR(resp))
+ xe_err(xe, "FWCTL RPC failed: fw=%s err=%ld\n",
+ ops->name ?: "unknown", PTR_ERR(resp));
+
+ return resp;
+}
+
+static const struct fwctl_ops xe_fwctl_ops = {
+ .device_type = FWCTL_DEVICE_TYPE_XE,
+ .uctx_size = sizeof(struct xe_fwctl_uctx),
+ .open_uctx = xe_fwctl_uctx_open,
+ .close_uctx = xe_fwctl_uctx_close,
+ .info = xe_fwctl_info,
+ .fw_rpc = xe_fwctl_rpc,
+};
+
+static void xe_fwctl_fini(void *dev)
+{
+ struct xe_fwctl *fwctl = dev;
+
+ fwctl_unregister(&fwctl->fwctl);
+ fwctl_put(&fwctl->fwctl);
+}
+
+/**
+ * xe_fwctl_init() - Initialize FWCTL for Xe device
+ * @xe: xe device instance
+ *
+ * Creates and registers FWCTL device for firmware management.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int xe_fwctl_init(struct xe_device *xe)
+{
+ struct xe_fwctl *fwctl __free(xe_fwctl) =
+ fwctl_alloc_device(xe->drm.dev, &xe_fwctl_ops,
+ struct xe_fwctl, fwctl);
+
+ int ret;
+
+ if (!fwctl)
+ return -ENOMEM;
+
+ fwctl->xe = xe;
+
+ ret = fwctl_register(&fwctl->fwctl);
+ if (ret)
+ return ret;
+
+ xe->fwctl = fwctl;
+
+ return devm_add_action_or_reset(xe->drm.dev, xe_fwctl_fini,
+ no_free_ptr(fwctl));
+}
+
+MODULE_IMPORT_NS("FWCTL");
diff --git a/drivers/gpu/drm/xe/xe_fwctl.h b/drivers/gpu/drm/xe/xe_fwctl.h
new file mode 100644
index 000000000000..190405720892
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_fwctl.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _XE_FWCTL_H_
+#define _XE_FWCTL_H_
+
+#include <linux/types.h>
+
+struct xe_device;
+
+int xe_fwctl_init(struct xe_device *xe);
+
+#endif
diff --git a/include/uapi/fwctl/xe.h b/include/uapi/fwctl/xe.h
index fb5612dec610..3720f188a7ec 100644
--- a/include/uapi/fwctl/xe.h
+++ b/include/uapi/fwctl/xe.h
@@ -16,6 +16,10 @@
* through the kernel FWCTL framework.
*/
+enum xe_firmware_type {
+ XE_FW_MAX = 1,
+};
+
/**
* struct fwctl_info_xe - FWCTL Information struct for Xe
*
--
2.43.0
next prev parent reply other threads:[~2026-03-20 7:25 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-20 7:25 [RFC v1 0/5] drm/xe/fwctl: Add FWCTL interface for Xe firmware management Anoop, Vijay
2026-03-20 7:25 ` [RFC v1 1/5] drm/xe/xe_sysctrl: Add System Controller support Anoop, Vijay
2026-03-20 7:25 ` [RFC v1 2/5] drm/xe/fwctl: Add uAPI definitions for Xe FWCTL support Anoop, Vijay
2026-05-07 21:05 ` Rodrigo Vivi
2026-03-20 7:25 ` [RFC v1 3/5] drm/xe/fwctl: Add Xe FWCTL type definitions Anoop, Vijay
2026-05-07 21:07 ` Rodrigo Vivi
2026-03-20 7:25 ` Anoop, Vijay [this message]
2026-03-20 7:25 ` [RFC v1 5/5] drm/xe/fwctl: Add System Controller FWCTL RPC handler Anoop, Vijay
2026-05-07 21:12 ` Rodrigo Vivi
2026-03-20 7:30 ` ✗ CI.checkpatch: warning for drm/xe/fwctl: Add FWCTL interface for Xe firmware management Patchwork
2026-03-20 7:32 ` ✓ CI.KUnit: success " Patchwork
2026-03-20 7:46 ` ✗ CI.checksparse: warning " Patchwork
2026-03-20 8:20 ` ✓ Xe.CI.BAT: success " Patchwork
2026-03-21 3:59 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-04-28 0:12 ` [RFC v1 0/5] " Anoop Vijay
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260320072528.1780651-11-anoop.c.vijay@intel.com \
--to=anoop.c.vijay@intel.com \
--cc=anshuman.gupta@intel.com \
--cc=aravind.iddamsetty@intel.com \
--cc=badal.nilawar@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=kam.nasim@intel.com \
--cc=matthew.d.roper@intel.com \
--cc=michael.j.ruhl@intel.com \
--cc=mohamed.mansoor.v@intel.com \
--cc=paul.e.luse@intel.com \
--cc=riana.tauro@intel.com \
--cc=rodrigo.vivi@intel.com \
--cc=umesh.nerlige.ramappa@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox