* [PATCH] This enables HuC firmware initialization and authentication on DG2 hardware when using the Xe DRM driver.
@ 2026-07-30 16:30 Danayer
0 siblings, 0 replies; 3+ messages in thread
From: Danayer @ 2026-07-30 16:30 UTC (permalink / raw)
To: intel-gfx; +Cc: Seliverstov Daniil Denisovich
From: Seliverstov Daniil Denisovich <daniil.seliverstov2003@gmail.com>
* drm/xe: add DG2 HuC GSC support and MEI integration
Add DG2-specific GSC/MEI handling for Xe driver.
Changes include:
- add DG2 MEI GSC interface support
- add HuC firmware parsing for GSC BPDT/CPD layout
- improve HuC loading and authentication handling
- add GSC register definitions and firmware ABI updates
- add Xe MEI DG2 module support
- update Xe workarounds and engine handling for HuC/GSC
- update MEI GSC support for DG2
Signed-off-by: Seliverstov Daniil Denisovich <daniil.seliverstov2003@gmail.com>
---
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 1 +
drivers/gpu/drm/xe/xe_gsc.c | 5 +-
drivers/gpu/drm/xe/xe_heci_gsc.c | 213 ++++++++++++++++----------
drivers/gpu/drm/xe/xe_heci_gsc.h | 12 +-
drivers/gpu/drm/xe/xe_huc.c | 65 ++++++++
drivers/gpu/drm/xe/xe_huc_types.h | 3 +
drivers/gpu/drm/xe/xe_mei_dg2.c | 121 +++++++++++++++
drivers/gpu/drm/xe/xe_mei_dg2.h | 14 ++
drivers/gpu/drm/xe/xe_uc_fw.c | 44 +++++-
drivers/gpu/drm/xe/xe_wa.c | 3 +-
drivers/misc/mei/gsc-me.c | 5 +
12 files changed, 391 insertions(+), 96 deletions(-)
create mode 100644 drivers/gpu/drm/xe/xe_mei_dg2.c
create mode 100644 drivers/gpu/drm/xe/xe_mei_dg2.h
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 6d728f8c4c392b..596669e2b55364 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -53,6 +53,7 @@ xe-y += xe_bb.o \
xe_gsc_debugfs.o \
xe_gsc_proxy.o \
xe_gsc_submit.o \
+ xe_mei_dg2.o \
xe_gt.o \
xe_gt_ccs_mode.o \
xe_gt_clock.o \
diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
index 180be82672ab59..6b7551bcfb7abc 100644
--- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
@@ -20,6 +20,7 @@
#define DG1_GSC_HECI2_BASE 0x00259000
#define PVC_GSC_HECI2_BASE 0x00285000
+#define DG2_GSC_HECI1_BASE 0x00373000
#define DG2_GSC_HECI2_BASE 0x00374000
#define HECI_H_CSR(base) XE_REG((base) + 0x4)
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index aab59dc647fbd1..ef3647a57d4432 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -467,8 +467,11 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
if (!xe_uc_fw_is_available(&gsc->fw))
return 0;
- if (!hwe)
+ if (!hwe) {
+ if (xe->info.platform == XE_DG2)
+ return 0;
return -ENODEV;
+ }
bo = xe_managed_bo_create_pin_map(xe, tile, SZ_4M,
XE_BO_FLAG_STOLEN |
diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.c b/drivers/gpu/drm/xe/xe_heci_gsc.c
index 5af8903e10af2e..69414e9510f2e0 100644
--- a/drivers/gpu/drm/xe/xe_heci_gsc.c
+++ b/drivers/gpu/drm/xe/xe_heci_gsc.c
@@ -15,8 +15,14 @@
#include "regs/xe_gsc_regs.h"
#include "xe_platform_types.h"
#include "xe_survivability_mode.h"
+#include "xe_gt.h"
+#include "xe_gt_printk.h"
+#include "xe_mmio.h"
+#include "xe_bo.h"
+#include "xe_map.h"
+#include "xe_force_wake.h"
-#define GSC_BAR_LENGTH 0x00000FFC
+#define GSC_BAR_LENGTH 0x00000FFC
static void heci_gsc_irq_mask(struct irq_data *d)
{
@@ -37,7 +43,8 @@ static const struct irq_chip heci_gsc_irq_chip = {
static int heci_gsc_irq_init(int irq)
{
irq_set_chip_and_handler_name(irq, &heci_gsc_irq_chip,
- handle_simple_irq, "heci_gsc_irq_handler");
+ handle_simple_irq,
+ "heci_gsc_irq_handler");
return irq_set_chip_data(irq, NULL);
}
@@ -57,6 +64,7 @@ struct heci_gsc_def {
size_t bar_size;
bool use_polling;
bool slow_firmware;
+ size_t lmem_size;
};
/* gsc resources and definitions */
@@ -66,10 +74,19 @@ static const struct heci_gsc_def heci_gsc_def_dg1 = {
.bar_size = GSC_BAR_LENGTH,
};
-static const struct heci_gsc_def heci_gsc_def_dg2 = {
- .name = "mei-gscfi",
- .bar = DG2_GSC_HECI2_BASE,
- .bar_size = GSC_BAR_LENGTH,
+static const struct heci_gsc_def heci_gsc_def_dg2[] = {
+ {
+ .name = "mei-gsc",
+ .bar = DG2_GSC_HECI1_BASE,
+ .bar_size = GSC_BAR_LENGTH,
+ .use_polling = true, /* Bypass broken HECI1 interrupts on DG2 */
+ .lmem_size = SZ_4M,
+ },
+ {
+ .name = "mei-gscfi",
+ .bar = DG2_GSC_HECI2_BASE,
+ .bar_size = GSC_BAR_LENGTH,
+ }
};
static const struct heci_gsc_def heci_gsc_def_pvc = {
@@ -82,6 +99,7 @@ static const struct heci_gsc_def heci_gsc_def_pvc = {
static void heci_gsc_release_dev(struct device *dev)
{
struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
+
struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev);
kfree(adev);
@@ -90,51 +108,59 @@ static void heci_gsc_release_dev(struct device *dev)
static void xe_heci_gsc_fini(void *arg)
{
struct xe_heci_gsc *heci_gsc = arg;
-
- if (heci_gsc->adev) {
- struct auxiliary_device *aux_dev = &heci_gsc->adev->aux_dev;
-
- auxiliary_device_delete(aux_dev);
- auxiliary_device_uninit(aux_dev);
- heci_gsc->adev = NULL;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (heci_gsc->adev[i]) {
+ struct auxiliary_device *aux_dev =
+ &heci_gsc->adev[i]->aux_dev;
+ auxiliary_device_delete(aux_dev);
+ auxiliary_device_uninit(aux_dev);
+ heci_gsc->adev[i] = NULL;
+ }
+ if (heci_gsc->irq[i] >= 0)
+ irq_free_desc(heci_gsc->irq[i]);
+ heci_gsc->irq[i] = -1;
+
+ if (heci_gsc->gem_obj[i]) {
+ xe_bo_unpin_map_no_vm(heci_gsc->gem_obj[i]);
+ heci_gsc->gem_obj[i] = NULL;
+ }
}
-
- if (heci_gsc->irq >= 0)
- irq_free_desc(heci_gsc->irq);
-
- heci_gsc->irq = -1;
}
static int heci_gsc_irq_setup(struct xe_device *xe)
{
struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
- int ret;
-
- heci_gsc->irq = irq_alloc_desc(0);
- if (heci_gsc->irq < 0) {
- drm_err(&xe->drm, "gsc irq error %d\n", heci_gsc->irq);
- return heci_gsc->irq;
+ int i, ret;
+
+ for (i = 0; i < 2; i++) {
+ heci_gsc->irq[i] = irq_alloc_desc(0);
+ if (heci_gsc->irq[i] < 0) {
+ drm_err(&xe->drm, "gsc irq error %d\n",
+ heci_gsc->irq[i]);
+ return heci_gsc->irq[i];
+ }
+ ret = heci_gsc_irq_init(heci_gsc->irq[i]);
+ if (ret < 0)
+ drm_err(&xe->drm, "gsc irq init failed %d\n", ret);
}
-
- ret = heci_gsc_irq_init(heci_gsc->irq);
- if (ret < 0)
- drm_err(&xe->drm, "gsc irq init failed %d\n", ret);
-
- return ret;
+ return 0;
}
-static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *def)
+static int heci_gsc_add_device(struct xe_device *xe,
+ const struct heci_gsc_def *def, int intf_id)
{
struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
struct auxiliary_device *aux_dev;
struct mei_aux_device *adev;
int ret;
-
adev = kzalloc_obj(*adev);
if (!adev)
return -ENOMEM;
- adev->irq = heci_gsc->irq;
+
+ adev->irq = def->use_polling ? -1 : heci_gsc->irq[intf_id];
adev->bar.parent = &pdev->resource[0];
adev->bar.start = def->bar + pdev->resource[0].start;
adev->bar.end = adev->bar.start + def->bar_size - 1;
@@ -142,10 +168,35 @@ static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *
adev->bar.desc = IORES_DESC_NONE;
adev->slow_firmware = def->slow_firmware;
+ if (def->lmem_size) {
+ struct xe_tile *tile = xe_device_get_root_tile(xe);
+ struct xe_bo *bo;
+
+ bo = xe_bo_create_pin_map_novm(xe, tile, def->lmem_size,
+ ttm_bo_type_kernel,
+ XE_BO_FLAG_VRAM0, false);
+ if (!IS_ERR(bo)) {
+ xe_map_memset(xe, &bo->vmap, 0, 0, def->lmem_size);
+ heci_gsc->gem_obj[intf_id] = bo;
+ adev->ext_op_mem.start = xe_bo_main_addr(bo, PAGE_SIZE);
+ adev->ext_op_mem.end =
+ adev->ext_op_mem.start + def->lmem_size;
+ xe_gt_dbg(tile->primary_gt,
+ "GSC HECI%d: VRAM at DPA 0x%llx\n",
+ intf_id + 1,
+ (unsigned long long)adev->ext_op_mem.start);
+ } else {
+ drm_warn(&xe->drm, "GSC HECI%d: Failed to alloc LMEM\n",
+ intf_id + 1);
+ }
+ }
+
aux_dev = &adev->aux_dev;
aux_dev->name = def->name;
+ /* Add intf_id to ensure unique device IDs */
aux_dev->id = (pci_domain_nr(pdev->bus) << 16) |
- PCI_DEVID(pdev->bus->number, pdev->devfn);
+ PCI_DEVID(pdev->bus->number, pdev->devfn) |
+ (intf_id << 8);
aux_dev->dev.parent = &pdev->dev;
aux_dev->dev.release = heci_gsc_release_dev;
@@ -156,13 +207,11 @@ static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *
return ret;
}
- heci_gsc->adev = adev; /* needed by the notifier */
+ heci_gsc->adev[intf_id] = adev;
ret = auxiliary_device_add(aux_dev);
if (ret < 0) {
drm_err(&xe->drm, "gsc aux add failed %d\n", ret);
- heci_gsc->adev = NULL;
-
- /* adev will be freed with the put_device() and .release sequence */
+ heci_gsc->adev[intf_id] = NULL;
auxiliary_device_uninit(aux_dev);
}
return ret;
@@ -171,78 +220,74 @@ static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *
int xe_heci_gsc_init(struct xe_device *xe)
{
struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
- const struct heci_gsc_def *def = NULL;
int ret;
if (!xe->info.has_heci_gscfi && !xe->info.has_heci_cscfi)
return 0;
- heci_gsc->irq = -1;
-
- if (xe->info.platform == XE_BATTLEMAGE) {
- def = &heci_gsc_def_dg2;
- } else if (xe->info.platform == XE_PVC) {
- def = &heci_gsc_def_pvc;
- } else if (xe->info.platform == XE_DG2) {
- def = &heci_gsc_def_dg2;
- } else if (xe->info.platform == XE_DG1) {
- def = &heci_gsc_def_dg1;
- }
-
- if (!def || !def->name) {
- drm_warn(&xe->drm, "HECI is not implemented!\n");
- return 0;
- }
+ heci_gsc->irq[0] = -1;
+ heci_gsc->irq[1] = -1;
+ heci_gsc->gem_obj[0] = NULL;
+ heci_gsc->gem_obj[1] = NULL;
ret = devm_add_action_or_reset(xe->drm.dev, xe_heci_gsc_fini, heci_gsc);
if (ret)
return ret;
- if (!def->use_polling && !xe_survivability_mode_is_boot_enabled(xe)) {
+ if (!xe_survivability_mode_is_boot_enabled(xe)) {
ret = heci_gsc_irq_setup(xe);
if (ret)
return ret;
}
- return heci_gsc_add_device(xe, def);
-}
+ if (xe->info.platform == XE_DG2) {
+ struct xe_gt *gt = xe->tiles[0].primary_gt;
+ u32 val;
-void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
-{
- int ret;
+ /* Wake up GSC to unmask HECI1 interrupts and clock gating */
+ if (xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC) == 0) {
+ val = xe_mmio_read32(>->mmio, XE_REG(0x1900f4));
+ val &= ~(BIT(15) | BIT(14));
+ xe_mmio_write32(>->mmio, XE_REG(0x1900f4), val);
- if ((iir & GSC_IRQ_INTF(1)) == 0)
- return;
+ val = xe_mmio_read32(>->mmio, XE_REG(0x190044));
+ val |= BIT(15) | BIT(14);
+ xe_mmio_write32(>->mmio, XE_REG(0x190044), val);
- if (!xe->info.has_heci_gscfi) {
- drm_warn_once(&xe->drm, "GSC irq: not supported");
- return;
- }
+ xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
+ }
- if (xe->heci_gsc.irq < 0)
- return;
+ heci_gsc_add_device(xe, &heci_gsc_def_dg2[0], 0);
+ heci_gsc_add_device(xe, &heci_gsc_def_dg2[1], 1);
+ return 0;
+ } else if (xe->info.platform == XE_BATTLEMAGE) {
+ return heci_gsc_add_device(xe, &heci_gsc_def_dg2[1], 1);
+ } else if (xe->info.platform == XE_PVC) {
+ return heci_gsc_add_device(xe, &heci_gsc_def_pvc, 1);
+ } else if (xe->info.platform == XE_DG1) {
+ return heci_gsc_add_device(xe, &heci_gsc_def_dg1, 1);
+ }
- ret = generic_handle_irq_safe(xe->heci_gsc.irq);
- if (ret)
- drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
+ return 0;
}
-void xe_heci_csc_irq_handler(struct xe_device *xe, u32 iir)
+void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
{
- int ret;
-
- if ((iir & CSC_IRQ_INTF(1)) == 0)
+ if (!xe->info.has_heci_gscfi)
return;
- if (!xe->info.has_heci_cscfi) {
- drm_warn_once(&xe->drm, "CSC irq: not supported");
- return;
- }
+ if ((iir & GSC_IRQ_INTF(0)) && xe->heci_gsc.irq[0] >= 0)
+ generic_handle_irq_safe(xe->heci_gsc.irq[0]);
+
+ if ((iir & GSC_IRQ_INTF(1)) && xe->heci_gsc.irq[1] >= 0)
+ generic_handle_irq_safe(xe->heci_gsc.irq[1]);
+}
- if (xe->heci_gsc.irq < 0)
+void xe_heci_csc_irq_handler(struct xe_device *xe, u32 iir)
+{
+ if ((iir & CSC_IRQ_INTF(1)) == 0 || !xe->info.has_heci_cscfi ||
+ xe->heci_gsc.irq[1] < 0)
return;
- ret = generic_handle_irq_safe(xe->heci_gsc.irq);
- if (ret)
- drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
+ generic_handle_irq_safe(xe->heci_gsc.irq[1]);
}
diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.h b/drivers/gpu/drm/xe/xe_heci_gsc.h
index a76f4122b7788a..80efc20922032b 100644
--- a/drivers/gpu/drm/xe/xe_heci_gsc.h
+++ b/drivers/gpu/drm/xe/xe_heci_gsc.h
@@ -9,6 +9,7 @@
struct xe_device;
struct mei_aux_device;
+struct xe_bo;
/*
* GSC HECI1 bit corresponds to bit15 and HECI2 to bit14.
@@ -24,13 +25,14 @@ struct mei_aux_device;
/**
* struct xe_heci_gsc - graphics security controller for xe, HECI interface
*
- * @adev : pointer to mei auxiliary device structure
- * @irq : irq number
- *
+ * @adev: array of pointers to mei auxiliary device structures
+ * @irq: array of irq numbers
+ * @gem_obj: array of pointers to allocated VRAM memory objects
*/
struct xe_heci_gsc {
- struct mei_aux_device *adev;
- int irq;
+ struct mei_aux_device *adev[2];
+ int irq[2];
+ struct xe_bo *gem_obj[2];
};
int xe_heci_gsc_init(struct xe_device *xe);
diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c
index 57afe21444b183..fde982431ccaa2 100644
--- a/drivers/gpu/drm/xe/xe_huc.c
+++ b/drivers/gpu/drm/xe/xe_huc.c
@@ -12,6 +12,8 @@
#include "abi/gsc_pxp_commands_abi.h"
#include "regs/xe_gsc_regs.h"
#include "regs/xe_guc_regs.h"
+#include "xe_pm.h"
+#include "xe_mei_dg2.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_force_wake.h"
@@ -42,6 +44,8 @@ huc_to_guc(struct xe_huc *huc)
return &container_of(huc, struct xe_uc, huc)->guc;
}
+static void xe_huc_auth_work(struct work_struct *work);
+
#define PXP43_HUC_AUTH_INOUT_SIZE SZ_4K
static int huc_alloc_gsc_pkt(struct xe_huc *huc)
{
@@ -67,6 +71,7 @@ int xe_huc_init(struct xe_huc *huc)
struct xe_gt *gt = huc_to_gt(huc);
struct xe_device *xe = gt_to_xe(gt);
int ret;
+ INIT_DELAYED_WORK(&huc->auth_work, xe_huc_auth_work);
huc->fw.type = XE_UC_FW_TYPE_HUC;
@@ -228,6 +233,39 @@ static const struct {
HECI1_FWSTS5_HUC_AUTH_DONE },
};
+static void xe_huc_auth_work(struct work_struct *work)
+{
+ struct xe_huc *huc = container_of(work, struct xe_huc, auth_work.work);
+ struct xe_gt *gt = huc_to_gt(huc);
+ struct xe_device *xe = gt_to_xe(gt);
+ int ret;
+
+ xe_pm_runtime_get(xe);
+
+ ret = xe_mei_dg2_auth_huc(xe, huc);
+ if (ret == -EAGAIN || ret == -ENODEV) {
+ schedule_delayed_work(&huc->auth_work, msecs_to_jiffies(1000));
+ goto out;
+ }
+
+ if (ret)
+ goto fail;
+
+ ret = xe_mmio_wait32(>->mmio, huc_auth_modes[XE_HUC_AUTH_VIA_GUC].reg,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ 100000, NULL, false);
+ if (ret)
+ goto fail;
+
+ xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
+ goto out;
+fail:
+ xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
+out:
+ xe_pm_runtime_put(xe);
+}
+
bool xe_huc_is_authenticated(struct xe_huc *huc, enum xe_huc_auth_types type)
{
struct xe_gt *gt = huc_to_gt(huc);
@@ -253,6 +291,33 @@ int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type)
if (!xe_uc_fw_is_loaded(&huc->fw))
return -ENOEXEC;
+ if (huc_to_xe(huc)->info.platform == XE_DG2) {
+ ret = xe_mei_dg2_auth_huc(huc_to_xe(huc), huc);
+ if (ret == -EAGAIN || ret == -ENODEV) {
+ xe_gt_dbg(gt, "HuC: MEI not ready, deferring authentication\n");
+ schedule_delayed_work(&huc->auth_work, msecs_to_jiffies(1000));
+ return 0;
+ }
+
+ if (ret) {
+ xe_gt_err(gt, "HuC: failed to trigger auth via MEI: %pe\n", ERR_PTR(ret));
+ goto fail;
+ }
+
+ ret = xe_mmio_wait32(>->mmio, huc_auth_modes[XE_HUC_AUTH_VIA_GUC].reg,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ 100000, NULL, false);
+ if (ret) {
+ xe_gt_err(gt, "HuC: firmware not verified by MEI: %pe\n", ERR_PTR(ret));
+ goto fail;
+ }
+
+ xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
+ xe_gt_dbg(gt, "HuC: authenticated via MEI\n");
+ return 0;
+ }
+
switch (type) {
case XE_HUC_AUTH_VIA_GUC:
ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) +
diff --git a/drivers/gpu/drm/xe/xe_huc_types.h b/drivers/gpu/drm/xe/xe_huc_types.h
index cfbaa5e0dfcac6..0e97a4d087b578 100644
--- a/drivers/gpu/drm/xe/xe_huc_types.h
+++ b/drivers/gpu/drm/xe/xe_huc_types.h
@@ -19,6 +19,9 @@ struct xe_huc {
/** @gsc_pkt: bo to store the packet for auth via GSC */
struct xe_bo *gsc_pkt;
+
+ /** @auth_work: deferred authentication deferred work */
+ struct delayed_work auth_work;
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_mei_dg2.c b/drivers/gpu/drm/xe/xe_mei_dg2.c
new file mode 100644
index 00000000000000..dee1646de83dfd
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_mei_dg2.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (c) 2026 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/mei_cl_bus.h>
+#include <drm/drm_managed.h>
+#include <uapi/drm/xe_drm.h>
+
+#include "xe_mei_dg2.h"
+#include "xe_bo.h"
+#include "xe_device.h"
+#include "xe_gt.h"
+#include "xe_huc.h"
+
+#define PXP_APIVER(x, y) (((x) & 0xFFFF) << 16 | ((y) & 0xFFFF))
+#define PXP_STATUS_SUCCESS 0x0
+#define PXP_STATUS_OP_NOT_PERMITTED 0x1003
+
+struct pxp_cmd_header {
+ u32 api_version;
+ u32 command_id;
+ u32 status;
+ u32 buffer_len;
+} __packed;
+
+#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
+
+struct pxp43_start_huc_auth_in {
+ struct pxp_cmd_header header;
+ __le64 huc_base_address;
+} __packed;
+
+struct pxp43_huc_auth_out {
+ struct pxp_cmd_header header;
+} __packed;
+
+static int match_pxp_client(struct device *dev, void *data)
+{
+ if (!dev->bus || !dev->bus->name || strcmp(dev->bus->name, "mei") != 0)
+ return 0;
+
+ if (strstr(dev_name(dev), "fbf6fcf1")) {
+ struct device **result = data;
+ *result = dev;
+ return 1;
+ }
+ return 0;
+}
+
+static int find_pxp_client_deep(struct device *dev, void *data)
+{
+ if (match_pxp_client(dev, data))
+ return 1;
+ return device_for_each_child(dev, data, find_pxp_client_deep);
+}
+
+int xe_mei_dg2_auth_huc(struct xe_device *xe, struct xe_huc *huc)
+{
+ struct device *cl_dev = NULL;
+ struct mei_cl_device *cldev;
+ struct pxp43_start_huc_auth_in in = { 0 };
+ struct pxp43_huc_auth_out out = { 0 };
+ ssize_t byte;
+ int ret;
+ static int retry_count;
+
+ device_for_each_child(xe->drm.dev, &cl_dev, find_pxp_client_deep);
+
+ if (!cl_dev) {
+ if (retry_count++ % 5 == 0)
+ drm_info(
+ &xe->drm,
+ "HuC auth: waiting for MEI PXP client (HECI1) to initialize...\n");
+ return -EAGAIN;
+ }
+
+ get_device(cl_dev);
+ cldev = to_mei_cl_device(cl_dev);
+
+ if (!mei_cldev_enabled(cldev)) {
+ ret = mei_cldev_enable(cldev);
+ if (ret) {
+ put_device(cl_dev);
+ return -EAGAIN;
+ }
+ }
+
+ in.header.api_version = PXP_APIVER(4, 3);
+ in.header.command_id = PXP43_CMDID_START_HUC_AUTH;
+ in.header.buffer_len = sizeof(in.huc_base_address);
+ in.huc_base_address =
+ cpu_to_le64(xe_bo_main_addr(huc->fw.bo, PAGE_SIZE));
+
+ byte = mei_cldev_send(cldev, (u8 *)&in, sizeof(in));
+ if (byte < 0) {
+ put_device(cl_dev);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&out, sizeof(out));
+ if (byte < 0) {
+ put_device(cl_dev);
+ return byte;
+ }
+
+ put_device(cl_dev);
+ if (out.header.status == PXP_STATUS_OP_NOT_PERMITTED) {
+ drm_info(
+ &xe->drm,
+ "HuC auth: GSC reports already authenticated (0x1003).\n");
+ return 0;
+ } else if (out.header.status != PXP_STATUS_SUCCESS) {
+ drm_err(&xe->drm, "HuC auth MEI rejected: status 0x%x\n",
+ out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/xe/xe_mei_dg2.h b/drivers/gpu/drm/xe/xe_mei_dg2.h
new file mode 100644
index 00000000000000..4a469fc7d8185c
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_mei_dg2.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (c) 2026 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __XE_MEI_DG2_H__
+#define __XE_MEI_DG2_H__
+
+#include "xe_device.h"
+#include "xe_huc.h"
+
+int xe_mei_dg2_auth_huc(struct xe_device *xe, struct xe_huc *huc);
+
+#endif /* __XE_MEI_DG2_H__ */
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index a8e6f18cc9b4aa..edc8019bea9598 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -133,6 +133,7 @@ struct fw_blobs_by_type {
fw_def(BATTLEMAGE, GT_TYPE_ANY, no_ver(xe, huc, bmg)) \
fw_def(LUNARLAKE, GT_TYPE_ANY, no_ver(xe, huc, lnl)) \
fw_def(METEORLAKE, GT_TYPE_ANY, no_ver(i915, huc_gsc, mtl)) \
+ fw_def(DG2, GT_TYPE_ANY, no_ver(i915, huc_gsc, dg2)) \
fw_def(DG1, GT_TYPE_ANY, no_ver(i915, huc, dg1)) \
fw_def(ALDERLAKE_P, GT_TYPE_ANY, no_ver(i915, huc, tgl)) \
fw_def(ALDERLAKE_S, GT_TYPE_ANY, no_ver(i915, huc, tgl)) \
@@ -488,6 +489,26 @@ static u32 entry_offset(const struct gsc_cpd_header_v2 *header, const char *name
return 0;
}
+static int parse_manifest_direct(struct xe_uc_fw *uc_fw, const void *data, size_t size)
+{
+ struct xe_gt *gt = uc_fw_to_gt(uc_fw);
+ const struct gsc_manifest_header *manifest = data;
+ struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
+
+ /* 0x4 is the expected header_type for a manifest */
+ if (size < sizeof(*manifest) || manifest->header_type != 0x4) {
+ xe_gt_err(gt, "Direct manifest too small or invalid!\n");
+ return -ENODATA;
+ }
+
+ release->major = manifest->fw_version.major;
+ release->minor = manifest->fw_version.minor;
+ release->patch = manifest->fw_version.hotfix;
+
+ uc_fw->has_gsc_headers = true;
+ return 0;
+}
+
/* Refer to the "GSC-based Firmware Layout" documentation entry for details */
static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t size,
const char *manifest_entry, const char *css_entry)
@@ -654,9 +675,20 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
case XE_UC_FW_TYPE_GSC:
return parse_gsc_layout(uc_fw, fw->data, fw->size);
case XE_UC_FW_TYPE_HUC:
- ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
- if (!ret || ret != -ENOENT)
- return ret;
+ if (uc_fw_to_xe(uc_fw)->info.platform == XE_DG2) {
+ /* Check if binary starts directly with manifest */
+ if (fw->size >= sizeof(u32) && *(const u32 *)fw->data == 0x4)
+ return parse_manifest_direct(uc_fw, fw->data, fw->size);
+
+ /* DG2 HuC is loaded via MEI, so we don't need a CSS header (pass NULL) */
+ ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", NULL);
+ if (!ret || ret != -ENOENT)
+ return ret;
+ } else {
+ ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
+ if (!ret || ret != -ENOENT)
+ return ret;
+ }
fallthrough;
case XE_UC_FW_TYPE_GUC:
return parse_css_header(uc_fw, fw->data, fw->size);
@@ -780,12 +812,14 @@ static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmwar
XE_UC_FIRMWARE_MISSING :
XE_UC_FIRMWARE_ERROR);
- if (err == -ENOENT)
+ if (err == -ENOENT) {
xe_gt_info(gt, "%s firmware %s not found\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
- else
+ } else {
xe_gt_notice(gt, "%s firmware %s: fetch failed with error %pe\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, ERR_PTR(err));
+ }
+
xe_gt_info(gt, "%s firmware(s) can be downloaded from %s\n",
xe_uc_fw_type_repr(uc_fw->type), XE_UC_FIRMWARE_URL);
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index 139434946f8f82..6ac486877e8d27 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -137,7 +137,8 @@ VISIBLE_IF_KUNIT const struct xe_rtp_table_sr gt_was = XE_RTP_TABLE_SR(
XE_RTP_RULES(MEDIA_VERSION_RANGE(1200, 1255),
ENGINE_CLASS(VIDEO_DECODE),
FUNC(xe_rtp_match_even_instance)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS)),
+ XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS,
+ XE_RTP_ACTION_FLAG(ENGINE_BASE))),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
},
{ XE_RTP_NAME("14011059788"),
diff --git a/drivers/misc/mei/gsc-me.c b/drivers/misc/mei/gsc-me.c
index 73d5beeb9c3454..0741962a2e7934 100644
--- a/drivers/misc/mei/gsc-me.c
+++ b/drivers/misc/mei/gsc-me.c
@@ -278,6 +278,10 @@ static const struct auxiliary_device_id mei_gsc_id_table[] = {
.name = "xe.mei-gscfi",
.driver_data = MEI_ME_GSCFI_CFG,
},
+ {
+ .name = "xe.mei-gsc",
+ .driver_data = MEI_ME_GSC_CFG,
+ },
{
/* sentinel */
}
@@ -299,5 +303,6 @@ MODULE_AUTHOR("Intel Corporation");
MODULE_ALIAS("auxiliary:i915.mei-gsc");
MODULE_ALIAS("auxiliary:i915.mei-gscfi");
MODULE_ALIAS("auxiliary:xe.mei-gscfi");
+MODULE_ALIAS("auxiliary:xe.mei-gsc");
MODULE_DESCRIPTION("Intel(R) Graphics System Controller");
MODULE_LICENSE("GPL");
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH] This enables HuC firmware initialization and authentication on DG2 hardware when using the Xe DRM driver.
@ 2026-07-30 16:43 Seliverstov Daniil Denisovich
2026-08-01 12:34 ` kernel test robot
0 siblings, 1 reply; 3+ messages in thread
From: Seliverstov Daniil Denisovich @ 2026-07-30 16:43 UTC (permalink / raw)
To: intel-gfx; +Cc: Seliverstov Daniil Denisovich
* drm/xe: add DG2 HuC GSC support and MEI integration
Add DG2-specific GSC/MEI handling for Xe driver.
Changes include:
- add DG2 MEI GSC interface support
- add HuC firmware parsing for GSC BPDT/CPD layout
- improve HuC loading and authentication handling
- add GSC register definitions and firmware ABI updates
- add Xe MEI DG2 module support
- update Xe workarounds and engine handling for HuC/GSC
- update MEI GSC support for DG2
Signed-off-by: Seliverstov Daniil Denisovich <daniil.seliverstov2003@gmail.com>
---
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 1 +
drivers/gpu/drm/xe/xe_gsc.c | 5 +-
drivers/gpu/drm/xe/xe_heci_gsc.c | 213 ++++++++++++++++----------
drivers/gpu/drm/xe/xe_heci_gsc.h | 12 +-
drivers/gpu/drm/xe/xe_huc.c | 65 ++++++++
drivers/gpu/drm/xe/xe_huc_types.h | 3 +
drivers/gpu/drm/xe/xe_mei_dg2.c | 121 +++++++++++++++
drivers/gpu/drm/xe/xe_mei_dg2.h | 14 ++
drivers/gpu/drm/xe/xe_uc_fw.c | 44 +++++-
drivers/gpu/drm/xe/xe_wa.c | 3 +-
drivers/misc/mei/gsc-me.c | 5 +
12 files changed, 391 insertions(+), 96 deletions(-)
create mode 100644 drivers/gpu/drm/xe/xe_mei_dg2.c
create mode 100644 drivers/gpu/drm/xe/xe_mei_dg2.h
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 6d728f8c4c392b..596669e2b55364 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -53,6 +53,7 @@ xe-y += xe_bb.o \
xe_gsc_debugfs.o \
xe_gsc_proxy.o \
xe_gsc_submit.o \
+ xe_mei_dg2.o \
xe_gt.o \
xe_gt_ccs_mode.o \
xe_gt_clock.o \
diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
index 180be82672ab59..6b7551bcfb7abc 100644
--- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h
@@ -20,6 +20,7 @@
#define DG1_GSC_HECI2_BASE 0x00259000
#define PVC_GSC_HECI2_BASE 0x00285000
+#define DG2_GSC_HECI1_BASE 0x00373000
#define DG2_GSC_HECI2_BASE 0x00374000
#define HECI_H_CSR(base) XE_REG((base) + 0x4)
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index aab59dc647fbd1..ef3647a57d4432 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -467,8 +467,11 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
if (!xe_uc_fw_is_available(&gsc->fw))
return 0;
- if (!hwe)
+ if (!hwe) {
+ if (xe->info.platform == XE_DG2)
+ return 0;
return -ENODEV;
+ }
bo = xe_managed_bo_create_pin_map(xe, tile, SZ_4M,
XE_BO_FLAG_STOLEN |
diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.c b/drivers/gpu/drm/xe/xe_heci_gsc.c
index 5af8903e10af2e..69414e9510f2e0 100644
--- a/drivers/gpu/drm/xe/xe_heci_gsc.c
+++ b/drivers/gpu/drm/xe/xe_heci_gsc.c
@@ -15,8 +15,14 @@
#include "regs/xe_gsc_regs.h"
#include "xe_platform_types.h"
#include "xe_survivability_mode.h"
+#include "xe_gt.h"
+#include "xe_gt_printk.h"
+#include "xe_mmio.h"
+#include "xe_bo.h"
+#include "xe_map.h"
+#include "xe_force_wake.h"
-#define GSC_BAR_LENGTH 0x00000FFC
+#define GSC_BAR_LENGTH 0x00000FFC
static void heci_gsc_irq_mask(struct irq_data *d)
{
@@ -37,7 +43,8 @@ static const struct irq_chip heci_gsc_irq_chip = {
static int heci_gsc_irq_init(int irq)
{
irq_set_chip_and_handler_name(irq, &heci_gsc_irq_chip,
- handle_simple_irq, "heci_gsc_irq_handler");
+ handle_simple_irq,
+ "heci_gsc_irq_handler");
return irq_set_chip_data(irq, NULL);
}
@@ -57,6 +64,7 @@ struct heci_gsc_def {
size_t bar_size;
bool use_polling;
bool slow_firmware;
+ size_t lmem_size;
};
/* gsc resources and definitions */
@@ -66,10 +74,19 @@ static const struct heci_gsc_def heci_gsc_def_dg1 = {
.bar_size = GSC_BAR_LENGTH,
};
-static const struct heci_gsc_def heci_gsc_def_dg2 = {
- .name = "mei-gscfi",
- .bar = DG2_GSC_HECI2_BASE,
- .bar_size = GSC_BAR_LENGTH,
+static const struct heci_gsc_def heci_gsc_def_dg2[] = {
+ {
+ .name = "mei-gsc",
+ .bar = DG2_GSC_HECI1_BASE,
+ .bar_size = GSC_BAR_LENGTH,
+ .use_polling = true, /* Bypass broken HECI1 interrupts on DG2 */
+ .lmem_size = SZ_4M,
+ },
+ {
+ .name = "mei-gscfi",
+ .bar = DG2_GSC_HECI2_BASE,
+ .bar_size = GSC_BAR_LENGTH,
+ }
};
static const struct heci_gsc_def heci_gsc_def_pvc = {
@@ -82,6 +99,7 @@ static const struct heci_gsc_def heci_gsc_def_pvc = {
static void heci_gsc_release_dev(struct device *dev)
{
struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
+
struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev);
kfree(adev);
@@ -90,51 +108,59 @@ static void heci_gsc_release_dev(struct device *dev)
static void xe_heci_gsc_fini(void *arg)
{
struct xe_heci_gsc *heci_gsc = arg;
-
- if (heci_gsc->adev) {
- struct auxiliary_device *aux_dev = &heci_gsc->adev->aux_dev;
-
- auxiliary_device_delete(aux_dev);
- auxiliary_device_uninit(aux_dev);
- heci_gsc->adev = NULL;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (heci_gsc->adev[i]) {
+ struct auxiliary_device *aux_dev =
+ &heci_gsc->adev[i]->aux_dev;
+ auxiliary_device_delete(aux_dev);
+ auxiliary_device_uninit(aux_dev);
+ heci_gsc->adev[i] = NULL;
+ }
+ if (heci_gsc->irq[i] >= 0)
+ irq_free_desc(heci_gsc->irq[i]);
+ heci_gsc->irq[i] = -1;
+
+ if (heci_gsc->gem_obj[i]) {
+ xe_bo_unpin_map_no_vm(heci_gsc->gem_obj[i]);
+ heci_gsc->gem_obj[i] = NULL;
+ }
}
-
- if (heci_gsc->irq >= 0)
- irq_free_desc(heci_gsc->irq);
-
- heci_gsc->irq = -1;
}
static int heci_gsc_irq_setup(struct xe_device *xe)
{
struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
- int ret;
-
- heci_gsc->irq = irq_alloc_desc(0);
- if (heci_gsc->irq < 0) {
- drm_err(&xe->drm, "gsc irq error %d\n", heci_gsc->irq);
- return heci_gsc->irq;
+ int i, ret;
+
+ for (i = 0; i < 2; i++) {
+ heci_gsc->irq[i] = irq_alloc_desc(0);
+ if (heci_gsc->irq[i] < 0) {
+ drm_err(&xe->drm, "gsc irq error %d\n",
+ heci_gsc->irq[i]);
+ return heci_gsc->irq[i];
+ }
+ ret = heci_gsc_irq_init(heci_gsc->irq[i]);
+ if (ret < 0)
+ drm_err(&xe->drm, "gsc irq init failed %d\n", ret);
}
-
- ret = heci_gsc_irq_init(heci_gsc->irq);
- if (ret < 0)
- drm_err(&xe->drm, "gsc irq init failed %d\n", ret);
-
- return ret;
+ return 0;
}
-static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *def)
+static int heci_gsc_add_device(struct xe_device *xe,
+ const struct heci_gsc_def *def, int intf_id)
{
struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
struct auxiliary_device *aux_dev;
struct mei_aux_device *adev;
int ret;
-
adev = kzalloc_obj(*adev);
if (!adev)
return -ENOMEM;
- adev->irq = heci_gsc->irq;
+
+ adev->irq = def->use_polling ? -1 : heci_gsc->irq[intf_id];
adev->bar.parent = &pdev->resource[0];
adev->bar.start = def->bar + pdev->resource[0].start;
adev->bar.end = adev->bar.start + def->bar_size - 1;
@@ -142,10 +168,35 @@ static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *
adev->bar.desc = IORES_DESC_NONE;
adev->slow_firmware = def->slow_firmware;
+ if (def->lmem_size) {
+ struct xe_tile *tile = xe_device_get_root_tile(xe);
+ struct xe_bo *bo;
+
+ bo = xe_bo_create_pin_map_novm(xe, tile, def->lmem_size,
+ ttm_bo_type_kernel,
+ XE_BO_FLAG_VRAM0, false);
+ if (!IS_ERR(bo)) {
+ xe_map_memset(xe, &bo->vmap, 0, 0, def->lmem_size);
+ heci_gsc->gem_obj[intf_id] = bo;
+ adev->ext_op_mem.start = xe_bo_main_addr(bo, PAGE_SIZE);
+ adev->ext_op_mem.end =
+ adev->ext_op_mem.start + def->lmem_size;
+ xe_gt_dbg(tile->primary_gt,
+ "GSC HECI%d: VRAM at DPA 0x%llx\n",
+ intf_id + 1,
+ (unsigned long long)adev->ext_op_mem.start);
+ } else {
+ drm_warn(&xe->drm, "GSC HECI%d: Failed to alloc LMEM\n",
+ intf_id + 1);
+ }
+ }
+
aux_dev = &adev->aux_dev;
aux_dev->name = def->name;
+ /* Add intf_id to ensure unique device IDs */
aux_dev->id = (pci_domain_nr(pdev->bus) << 16) |
- PCI_DEVID(pdev->bus->number, pdev->devfn);
+ PCI_DEVID(pdev->bus->number, pdev->devfn) |
+ (intf_id << 8);
aux_dev->dev.parent = &pdev->dev;
aux_dev->dev.release = heci_gsc_release_dev;
@@ -156,13 +207,11 @@ static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *
return ret;
}
- heci_gsc->adev = adev; /* needed by the notifier */
+ heci_gsc->adev[intf_id] = adev;
ret = auxiliary_device_add(aux_dev);
if (ret < 0) {
drm_err(&xe->drm, "gsc aux add failed %d\n", ret);
- heci_gsc->adev = NULL;
-
- /* adev will be freed with the put_device() and .release sequence */
+ heci_gsc->adev[intf_id] = NULL;
auxiliary_device_uninit(aux_dev);
}
return ret;
@@ -171,78 +220,74 @@ static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *
int xe_heci_gsc_init(struct xe_device *xe)
{
struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
- const struct heci_gsc_def *def = NULL;
int ret;
if (!xe->info.has_heci_gscfi && !xe->info.has_heci_cscfi)
return 0;
- heci_gsc->irq = -1;
-
- if (xe->info.platform == XE_BATTLEMAGE) {
- def = &heci_gsc_def_dg2;
- } else if (xe->info.platform == XE_PVC) {
- def = &heci_gsc_def_pvc;
- } else if (xe->info.platform == XE_DG2) {
- def = &heci_gsc_def_dg2;
- } else if (xe->info.platform == XE_DG1) {
- def = &heci_gsc_def_dg1;
- }
-
- if (!def || !def->name) {
- drm_warn(&xe->drm, "HECI is not implemented!\n");
- return 0;
- }
+ heci_gsc->irq[0] = -1;
+ heci_gsc->irq[1] = -1;
+ heci_gsc->gem_obj[0] = NULL;
+ heci_gsc->gem_obj[1] = NULL;
ret = devm_add_action_or_reset(xe->drm.dev, xe_heci_gsc_fini, heci_gsc);
if (ret)
return ret;
- if (!def->use_polling && !xe_survivability_mode_is_boot_enabled(xe)) {
+ if (!xe_survivability_mode_is_boot_enabled(xe)) {
ret = heci_gsc_irq_setup(xe);
if (ret)
return ret;
}
- return heci_gsc_add_device(xe, def);
-}
+ if (xe->info.platform == XE_DG2) {
+ struct xe_gt *gt = xe->tiles[0].primary_gt;
+ u32 val;
-void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
-{
- int ret;
+ /* Wake up GSC to unmask HECI1 interrupts and clock gating */
+ if (xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC) == 0) {
+ val = xe_mmio_read32(>->mmio, XE_REG(0x1900f4));
+ val &= ~(BIT(15) | BIT(14));
+ xe_mmio_write32(>->mmio, XE_REG(0x1900f4), val);
- if ((iir & GSC_IRQ_INTF(1)) == 0)
- return;
+ val = xe_mmio_read32(>->mmio, XE_REG(0x190044));
+ val |= BIT(15) | BIT(14);
+ xe_mmio_write32(>->mmio, XE_REG(0x190044), val);
- if (!xe->info.has_heci_gscfi) {
- drm_warn_once(&xe->drm, "GSC irq: not supported");
- return;
- }
+ xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
+ }
- if (xe->heci_gsc.irq < 0)
- return;
+ heci_gsc_add_device(xe, &heci_gsc_def_dg2[0], 0);
+ heci_gsc_add_device(xe, &heci_gsc_def_dg2[1], 1);
+ return 0;
+ } else if (xe->info.platform == XE_BATTLEMAGE) {
+ return heci_gsc_add_device(xe, &heci_gsc_def_dg2[1], 1);
+ } else if (xe->info.platform == XE_PVC) {
+ return heci_gsc_add_device(xe, &heci_gsc_def_pvc, 1);
+ } else if (xe->info.platform == XE_DG1) {
+ return heci_gsc_add_device(xe, &heci_gsc_def_dg1, 1);
+ }
- ret = generic_handle_irq_safe(xe->heci_gsc.irq);
- if (ret)
- drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
+ return 0;
}
-void xe_heci_csc_irq_handler(struct xe_device *xe, u32 iir)
+void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
{
- int ret;
-
- if ((iir & CSC_IRQ_INTF(1)) == 0)
+ if (!xe->info.has_heci_gscfi)
return;
- if (!xe->info.has_heci_cscfi) {
- drm_warn_once(&xe->drm, "CSC irq: not supported");
- return;
- }
+ if ((iir & GSC_IRQ_INTF(0)) && xe->heci_gsc.irq[0] >= 0)
+ generic_handle_irq_safe(xe->heci_gsc.irq[0]);
+
+ if ((iir & GSC_IRQ_INTF(1)) && xe->heci_gsc.irq[1] >= 0)
+ generic_handle_irq_safe(xe->heci_gsc.irq[1]);
+}
- if (xe->heci_gsc.irq < 0)
+void xe_heci_csc_irq_handler(struct xe_device *xe, u32 iir)
+{
+ if ((iir & CSC_IRQ_INTF(1)) == 0 || !xe->info.has_heci_cscfi ||
+ xe->heci_gsc.irq[1] < 0)
return;
- ret = generic_handle_irq_safe(xe->heci_gsc.irq);
- if (ret)
- drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
+ generic_handle_irq_safe(xe->heci_gsc.irq[1]);
}
diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.h b/drivers/gpu/drm/xe/xe_heci_gsc.h
index a76f4122b7788a..80efc20922032b 100644
--- a/drivers/gpu/drm/xe/xe_heci_gsc.h
+++ b/drivers/gpu/drm/xe/xe_heci_gsc.h
@@ -9,6 +9,7 @@
struct xe_device;
struct mei_aux_device;
+struct xe_bo;
/*
* GSC HECI1 bit corresponds to bit15 and HECI2 to bit14.
@@ -24,13 +25,14 @@ struct mei_aux_device;
/**
* struct xe_heci_gsc - graphics security controller for xe, HECI interface
*
- * @adev : pointer to mei auxiliary device structure
- * @irq : irq number
- *
+ * @adev: array of pointers to mei auxiliary device structures
+ * @irq: array of irq numbers
+ * @gem_obj: array of pointers to allocated VRAM memory objects
*/
struct xe_heci_gsc {
- struct mei_aux_device *adev;
- int irq;
+ struct mei_aux_device *adev[2];
+ int irq[2];
+ struct xe_bo *gem_obj[2];
};
int xe_heci_gsc_init(struct xe_device *xe);
diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c
index 57afe21444b183..fde982431ccaa2 100644
--- a/drivers/gpu/drm/xe/xe_huc.c
+++ b/drivers/gpu/drm/xe/xe_huc.c
@@ -12,6 +12,8 @@
#include "abi/gsc_pxp_commands_abi.h"
#include "regs/xe_gsc_regs.h"
#include "regs/xe_guc_regs.h"
+#include "xe_pm.h"
+#include "xe_mei_dg2.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_force_wake.h"
@@ -42,6 +44,8 @@ huc_to_guc(struct xe_huc *huc)
return &container_of(huc, struct xe_uc, huc)->guc;
}
+static void xe_huc_auth_work(struct work_struct *work);
+
#define PXP43_HUC_AUTH_INOUT_SIZE SZ_4K
static int huc_alloc_gsc_pkt(struct xe_huc *huc)
{
@@ -67,6 +71,7 @@ int xe_huc_init(struct xe_huc *huc)
struct xe_gt *gt = huc_to_gt(huc);
struct xe_device *xe = gt_to_xe(gt);
int ret;
+ INIT_DELAYED_WORK(&huc->auth_work, xe_huc_auth_work);
huc->fw.type = XE_UC_FW_TYPE_HUC;
@@ -228,6 +233,39 @@ static const struct {
HECI1_FWSTS5_HUC_AUTH_DONE },
};
+static void xe_huc_auth_work(struct work_struct *work)
+{
+ struct xe_huc *huc = container_of(work, struct xe_huc, auth_work.work);
+ struct xe_gt *gt = huc_to_gt(huc);
+ struct xe_device *xe = gt_to_xe(gt);
+ int ret;
+
+ xe_pm_runtime_get(xe);
+
+ ret = xe_mei_dg2_auth_huc(xe, huc);
+ if (ret == -EAGAIN || ret == -ENODEV) {
+ schedule_delayed_work(&huc->auth_work, msecs_to_jiffies(1000));
+ goto out;
+ }
+
+ if (ret)
+ goto fail;
+
+ ret = xe_mmio_wait32(>->mmio, huc_auth_modes[XE_HUC_AUTH_VIA_GUC].reg,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ 100000, NULL, false);
+ if (ret)
+ goto fail;
+
+ xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
+ goto out;
+fail:
+ xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
+out:
+ xe_pm_runtime_put(xe);
+}
+
bool xe_huc_is_authenticated(struct xe_huc *huc, enum xe_huc_auth_types type)
{
struct xe_gt *gt = huc_to_gt(huc);
@@ -253,6 +291,33 @@ int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type)
if (!xe_uc_fw_is_loaded(&huc->fw))
return -ENOEXEC;
+ if (huc_to_xe(huc)->info.platform == XE_DG2) {
+ ret = xe_mei_dg2_auth_huc(huc_to_xe(huc), huc);
+ if (ret == -EAGAIN || ret == -ENODEV) {
+ xe_gt_dbg(gt, "HuC: MEI not ready, deferring authentication\n");
+ schedule_delayed_work(&huc->auth_work, msecs_to_jiffies(1000));
+ return 0;
+ }
+
+ if (ret) {
+ xe_gt_err(gt, "HuC: failed to trigger auth via MEI: %pe\n", ERR_PTR(ret));
+ goto fail;
+ }
+
+ ret = xe_mmio_wait32(>->mmio, huc_auth_modes[XE_HUC_AUTH_VIA_GUC].reg,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ huc_auth_modes[XE_HUC_AUTH_VIA_GUC].val,
+ 100000, NULL, false);
+ if (ret) {
+ xe_gt_err(gt, "HuC: firmware not verified by MEI: %pe\n", ERR_PTR(ret));
+ goto fail;
+ }
+
+ xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
+ xe_gt_dbg(gt, "HuC: authenticated via MEI\n");
+ return 0;
+ }
+
switch (type) {
case XE_HUC_AUTH_VIA_GUC:
ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) +
diff --git a/drivers/gpu/drm/xe/xe_huc_types.h b/drivers/gpu/drm/xe/xe_huc_types.h
index cfbaa5e0dfcac6..0e97a4d087b578 100644
--- a/drivers/gpu/drm/xe/xe_huc_types.h
+++ b/drivers/gpu/drm/xe/xe_huc_types.h
@@ -19,6 +19,9 @@ struct xe_huc {
/** @gsc_pkt: bo to store the packet for auth via GSC */
struct xe_bo *gsc_pkt;
+
+ /** @auth_work: deferred authentication deferred work */
+ struct delayed_work auth_work;
};
#endif
diff --git a/drivers/gpu/drm/xe/xe_mei_dg2.c b/drivers/gpu/drm/xe/xe_mei_dg2.c
new file mode 100644
index 00000000000000..dee1646de83dfd
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_mei_dg2.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (c) 2026 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/mei_cl_bus.h>
+#include <drm/drm_managed.h>
+#include <uapi/drm/xe_drm.h>
+
+#include "xe_mei_dg2.h"
+#include "xe_bo.h"
+#include "xe_device.h"
+#include "xe_gt.h"
+#include "xe_huc.h"
+
+#define PXP_APIVER(x, y) (((x) & 0xFFFF) << 16 | ((y) & 0xFFFF))
+#define PXP_STATUS_SUCCESS 0x0
+#define PXP_STATUS_OP_NOT_PERMITTED 0x1003
+
+struct pxp_cmd_header {
+ u32 api_version;
+ u32 command_id;
+ u32 status;
+ u32 buffer_len;
+} __packed;
+
+#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
+
+struct pxp43_start_huc_auth_in {
+ struct pxp_cmd_header header;
+ __le64 huc_base_address;
+} __packed;
+
+struct pxp43_huc_auth_out {
+ struct pxp_cmd_header header;
+} __packed;
+
+static int match_pxp_client(struct device *dev, void *data)
+{
+ if (!dev->bus || !dev->bus->name || strcmp(dev->bus->name, "mei") != 0)
+ return 0;
+
+ if (strstr(dev_name(dev), "fbf6fcf1")) {
+ struct device **result = data;
+ *result = dev;
+ return 1;
+ }
+ return 0;
+}
+
+static int find_pxp_client_deep(struct device *dev, void *data)
+{
+ if (match_pxp_client(dev, data))
+ return 1;
+ return device_for_each_child(dev, data, find_pxp_client_deep);
+}
+
+int xe_mei_dg2_auth_huc(struct xe_device *xe, struct xe_huc *huc)
+{
+ struct device *cl_dev = NULL;
+ struct mei_cl_device *cldev;
+ struct pxp43_start_huc_auth_in in = { 0 };
+ struct pxp43_huc_auth_out out = { 0 };
+ ssize_t byte;
+ int ret;
+ static int retry_count;
+
+ device_for_each_child(xe->drm.dev, &cl_dev, find_pxp_client_deep);
+
+ if (!cl_dev) {
+ if (retry_count++ % 5 == 0)
+ drm_info(
+ &xe->drm,
+ "HuC auth: waiting for MEI PXP client (HECI1) to initialize...\n");
+ return -EAGAIN;
+ }
+
+ get_device(cl_dev);
+ cldev = to_mei_cl_device(cl_dev);
+
+ if (!mei_cldev_enabled(cldev)) {
+ ret = mei_cldev_enable(cldev);
+ if (ret) {
+ put_device(cl_dev);
+ return -EAGAIN;
+ }
+ }
+
+ in.header.api_version = PXP_APIVER(4, 3);
+ in.header.command_id = PXP43_CMDID_START_HUC_AUTH;
+ in.header.buffer_len = sizeof(in.huc_base_address);
+ in.huc_base_address =
+ cpu_to_le64(xe_bo_main_addr(huc->fw.bo, PAGE_SIZE));
+
+ byte = mei_cldev_send(cldev, (u8 *)&in, sizeof(in));
+ if (byte < 0) {
+ put_device(cl_dev);
+ return byte;
+ }
+
+ byte = mei_cldev_recv(cldev, (u8 *)&out, sizeof(out));
+ if (byte < 0) {
+ put_device(cl_dev);
+ return byte;
+ }
+
+ put_device(cl_dev);
+ if (out.header.status == PXP_STATUS_OP_NOT_PERMITTED) {
+ drm_info(
+ &xe->drm,
+ "HuC auth: GSC reports already authenticated (0x1003).\n");
+ return 0;
+ } else if (out.header.status != PXP_STATUS_SUCCESS) {
+ drm_err(&xe->drm, "HuC auth MEI rejected: status 0x%x\n",
+ out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/xe/xe_mei_dg2.h b/drivers/gpu/drm/xe/xe_mei_dg2.h
new file mode 100644
index 00000000000000..4a469fc7d8185c
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_mei_dg2.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (c) 2026 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __XE_MEI_DG2_H__
+#define __XE_MEI_DG2_H__
+
+#include "xe_device.h"
+#include "xe_huc.h"
+
+int xe_mei_dg2_auth_huc(struct xe_device *xe, struct xe_huc *huc);
+
+#endif /* __XE_MEI_DG2_H__ */
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index a8e6f18cc9b4aa..edc8019bea9598 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -133,6 +133,7 @@ struct fw_blobs_by_type {
fw_def(BATTLEMAGE, GT_TYPE_ANY, no_ver(xe, huc, bmg)) \
fw_def(LUNARLAKE, GT_TYPE_ANY, no_ver(xe, huc, lnl)) \
fw_def(METEORLAKE, GT_TYPE_ANY, no_ver(i915, huc_gsc, mtl)) \
+ fw_def(DG2, GT_TYPE_ANY, no_ver(i915, huc_gsc, dg2)) \
fw_def(DG1, GT_TYPE_ANY, no_ver(i915, huc, dg1)) \
fw_def(ALDERLAKE_P, GT_TYPE_ANY, no_ver(i915, huc, tgl)) \
fw_def(ALDERLAKE_S, GT_TYPE_ANY, no_ver(i915, huc, tgl)) \
@@ -488,6 +489,26 @@ static u32 entry_offset(const struct gsc_cpd_header_v2 *header, const char *name
return 0;
}
+static int parse_manifest_direct(struct xe_uc_fw *uc_fw, const void *data, size_t size)
+{
+ struct xe_gt *gt = uc_fw_to_gt(uc_fw);
+ const struct gsc_manifest_header *manifest = data;
+ struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];
+
+ /* 0x4 is the expected header_type for a manifest */
+ if (size < sizeof(*manifest) || manifest->header_type != 0x4) {
+ xe_gt_err(gt, "Direct manifest too small or invalid!\n");
+ return -ENODATA;
+ }
+
+ release->major = manifest->fw_version.major;
+ release->minor = manifest->fw_version.minor;
+ release->patch = manifest->fw_version.hotfix;
+
+ uc_fw->has_gsc_headers = true;
+ return 0;
+}
+
/* Refer to the "GSC-based Firmware Layout" documentation entry for details */
static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t size,
const char *manifest_entry, const char *css_entry)
@@ -654,9 +675,20 @@ static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)
case XE_UC_FW_TYPE_GSC:
return parse_gsc_layout(uc_fw, fw->data, fw->size);
case XE_UC_FW_TYPE_HUC:
- ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
- if (!ret || ret != -ENOENT)
- return ret;
+ if (uc_fw_to_xe(uc_fw)->info.platform == XE_DG2) {
+ /* Check if binary starts directly with manifest */
+ if (fw->size >= sizeof(u32) && *(const u32 *)fw->data == 0x4)
+ return parse_manifest_direct(uc_fw, fw->data, fw->size);
+
+ /* DG2 HuC is loaded via MEI, so we don't need a CSS header (pass NULL) */
+ ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", NULL);
+ if (!ret || ret != -ENOENT)
+ return ret;
+ } else {
+ ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");
+ if (!ret || ret != -ENOENT)
+ return ret;
+ }
fallthrough;
case XE_UC_FW_TYPE_GUC:
return parse_css_header(uc_fw, fw->data, fw->size);
@@ -780,12 +812,14 @@ static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmwar
XE_UC_FIRMWARE_MISSING :
XE_UC_FIRMWARE_ERROR);
- if (err == -ENOENT)
+ if (err == -ENOENT) {
xe_gt_info(gt, "%s firmware %s not found\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);
- else
+ } else {
xe_gt_notice(gt, "%s firmware %s: fetch failed with error %pe\n",
xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, ERR_PTR(err));
+ }
+
xe_gt_info(gt, "%s firmware(s) can be downloaded from %s\n",
xe_uc_fw_type_repr(uc_fw->type), XE_UC_FIRMWARE_URL);
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index 139434946f8f82..6ac486877e8d27 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -137,7 +137,8 @@ VISIBLE_IF_KUNIT const struct xe_rtp_table_sr gt_was = XE_RTP_TABLE_SR(
XE_RTP_RULES(MEDIA_VERSION_RANGE(1200, 1255),
ENGINE_CLASS(VIDEO_DECODE),
FUNC(xe_rtp_match_even_instance)),
- XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS)),
+ XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), IECPUNIT_CLKGATE_DIS,
+ XE_RTP_ACTION_FLAG(ENGINE_BASE))),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
},
{ XE_RTP_NAME("14011059788"),
diff --git a/drivers/misc/mei/gsc-me.c b/drivers/misc/mei/gsc-me.c
index 73d5beeb9c3454..0741962a2e7934 100644
--- a/drivers/misc/mei/gsc-me.c
+++ b/drivers/misc/mei/gsc-me.c
@@ -278,6 +278,10 @@ static const struct auxiliary_device_id mei_gsc_id_table[] = {
.name = "xe.mei-gscfi",
.driver_data = MEI_ME_GSCFI_CFG,
},
+ {
+ .name = "xe.mei-gsc",
+ .driver_data = MEI_ME_GSC_CFG,
+ },
{
/* sentinel */
}
@@ -299,5 +303,6 @@ MODULE_AUTHOR("Intel Corporation");
MODULE_ALIAS("auxiliary:i915.mei-gsc");
MODULE_ALIAS("auxiliary:i915.mei-gscfi");
MODULE_ALIAS("auxiliary:xe.mei-gscfi");
+MODULE_ALIAS("auxiliary:xe.mei-gsc");
MODULE_DESCRIPTION("Intel(R) Graphics System Controller");
MODULE_LICENSE("GPL");
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] This enables HuC firmware initialization and authentication on DG2 hardware when using the Xe DRM driver.
2026-07-30 16:43 [PATCH] This enables HuC firmware initialization and authentication on DG2 hardware when using the Xe DRM driver Seliverstov Daniil Denisovich
@ 2026-08-01 12:34 ` kernel test robot
0 siblings, 0 replies; 3+ messages in thread
From: kernel test robot @ 2026-08-01 12:34 UTC (permalink / raw)
To: Seliverstov Daniil Denisovich, intel-gfx
Cc: llvm, oe-kbuild-all, Seliverstov Daniil Denisovich
Hi Seliverstov,
kernel test robot noticed the following build errors:
[auto build test ERROR on drm-xe/drm-xe-next]
[also build test ERROR on drm-tip/drm-tip char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus linus/master v7.2-rc5 next-20260731]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Seliverstov-Daniil-Denisovich/This-enables-HuC-firmware-initialization-and-authentication-on-DG2-hardware-when-using-the-Xe-DRM-driver/20260801-003327
base: https://gitlab.freedesktop.org/drm/xe/kernel.git drm-xe-next
patch link: https://lore.kernel.org/r/20260730164334.8424-1-daniil.seliverstov2003%40gmail.com
patch subject: [PATCH] This enables HuC firmware initialization and authentication on DG2 hardware when using the Xe DRM driver.
config: x86_64-buildonly-randconfig-005-20260801 (https://download.01.org/0day-ci/archive/20260801/202608012014.L7f9m7Nm-lkp@intel.com/config)
compiler: clang version 22.1.3 (https://github.com/llvm/llvm-project e9846648fd6183ee6d8cbdb4502213fcf902a211)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260801/202608012014.L7f9m7Nm-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608012014.L7f9m7Nm-lkp@intel.com/
All errors (new ones prefixed by >>, old ones prefixed by <<):
>> ERROR: modpost: "mei_cldev_enabled" [drivers/gpu/drm/xe/xe.ko] undefined!
>> ERROR: modpost: "mei_cldev_enable" [drivers/gpu/drm/xe/xe.ko] undefined!
>> ERROR: modpost: "mei_cldev_send" [drivers/gpu/drm/xe/xe.ko] undefined!
>> ERROR: modpost: "mei_cldev_recv" [drivers/gpu/drm/xe/xe.ko] undefined!
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-01 12:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30 16:43 [PATCH] This enables HuC firmware initialization and authentication on DG2 hardware when using the Xe DRM driver Seliverstov Daniil Denisovich
2026-08-01 12:34 ` kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2026-07-30 16:30 Danayer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.