Driver Changes:

- drm/xe: Move xe_uc_fw_abi.h to abi/ (Michal Wajdeczko)
 - drm/xe: Restore IDLEDLY regiter on engine reset (Balasubramani Vivekanandan)
 - drm/xe/pm: Do early initialization in init_early() (Michal Wajdeczko)
 - drm/xe/pm: Don't access device in init_early() (Michal Wajdeczko)
 - drm/xe: Separate early xe_device initialization (Michal Wajdeczko)
 - drm/xe: Move xe->info.devid|revid initialization (Michal Wajdeczko)
 - drm/xe: Move xe->info.force_execlist initialization (Michal Wajdeczko)
 - drm/xe: Drop unused param from xe_device_create() (Michal Wajdeczko)
 - drm/xe: Use raw device ID to find sub-platform descriptor (Michal Wajdeczko)
 - drm/xe: Assign queue name in time for drm_sched_init (Tvrtko Ursulin)
 - drm/xe/rtp: Implement a structured parser for rule matching (Gustavo Sousa)
 - drm/xe/rtp: Fully parse the ruleset (Gustavo Sousa)
 - drm/xe/rtp: Extract rule_match_item() (Gustavo Sousa)
 - drm/xe/rtp: Do not break parsing when missing context (Gustavo Sousa)
 - drm/xe/rtp: Don't short-circuit to false in or-yes case (Gustavo Sousa)
 - drm/xe/rtp: Drop rule matching cases from rtp_to_sr_cases and rtp_cases (Gustavo Sousa)
 - drm/xe/rtp: Write kunit test cases specific for rule matching (Gustavo Sousa)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRskUM7w1oG5rx2IZO4FpNVCsYGvwUCahg6XQAKCRC4FpNVCsYG
 v1tjAP9yDWHxY1ZLkfg3boEWRrWy5HidWRYXRPEcHFZy9asj9QD/YtTu+ZBEVQuY
 p4pyZSYwgDQYFSQI7ajF2yWj2P1KWgs=
 =njjy
 -----END PGP SIGNATURE-----

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

Driver Changes:
- drm/xe: Move xe_uc_fw_abi.h to abi/ (Michal Wajdeczko)
- drm/xe: Restore IDLEDLY regiter on engine reset (Balasubramani Vivekanandan)
- drm/xe/pm: Do early initialization in init_early() (Michal Wajdeczko)
- drm/xe/pm: Don't access device in init_early() (Michal Wajdeczko)
- drm/xe: Separate early xe_device initialization (Michal Wajdeczko)
- drm/xe: Move xe->info.devid|revid initialization (Michal Wajdeczko)
- drm/xe: Move xe->info.force_execlist initialization (Michal Wajdeczko)
- drm/xe: Drop unused param from xe_device_create() (Michal Wajdeczko)
- drm/xe: Use raw device ID to find sub-platform descriptor (Michal Wajdeczko)
- drm/xe: Assign queue name in time for drm_sched_init (Tvrtko Ursulin)
- drm/xe/rtp: Implement a structured parser for rule matching (Gustavo Sousa)
- drm/xe/rtp: Fully parse the ruleset (Gustavo Sousa)
- drm/xe/rtp: Extract rule_match_item() (Gustavo Sousa)
- drm/xe/rtp: Do not break parsing when missing context (Gustavo Sousa)
- drm/xe/rtp: Don't short-circuit to false in or-yes case (Gustavo Sousa)
- drm/xe/rtp: Drop rule matching cases from rtp_to_sr_cases and rtp_cases (Gustavo Sousa)
- drm/xe/rtp: Write kunit test cases specific for rule matching (Gustavo Sousa)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/ahg7tgWh8djEngjM@fedora
This commit is contained in:
Dave Airlie 2026-06-03 08:58:56 +10:00
commit 5ebf57fb7c
17 changed files with 644 additions and 329 deletions

View File

@ -7,10 +7,10 @@ Firmware
Firmware Layout
===============
.. kernel-doc:: drivers/gpu/drm/xe/xe_uc_fw_abi.h
.. kernel-doc:: drivers/gpu/drm/xe/abi/uc_fw_abi.h
:doc: CSS-based Firmware Layout
.. kernel-doc:: drivers/gpu/drm/xe/xe_uc_fw_abi.h
.. kernel-doc:: drivers/gpu/drm/xe/abi/uc_fw_abi.h
:doc: GSC-based Firmware Layout
Write Once Protected Content Memory (WOPCM) Layout

View File

@ -3,8 +3,8 @@
* Copyright © 2022 Intel Corporation
*/
#ifndef _XE_UC_FW_ABI_H_
#define _XE_UC_FW_ABI_H_
#ifndef _ABI_UC_FW_ABI_H
#define _ABI_UC_FW_ABI_H
#include <linux/build_bug.h>
#include <linux/types.h>

View File

@ -311,6 +311,11 @@ const void *xe_pci_id_gen_param(struct kunit *test, const void *prev, char *desc
}
EXPORT_SYMBOL_IF_KUNIT(xe_pci_id_gen_param);
static void fake_init_devid(struct xe_device *xe)
{
/* Nothing to do, just keep zero. */
}
static int fake_read_gmdid(struct xe_device *xe, enum xe_gmdid_type type,
u32 *ver, u32 *revid)
{
@ -369,6 +374,7 @@ int xe_pci_fake_device_init(struct xe_device *xe)
xe->sriov.__mode = data && data->sriov_mode ?
data->sriov_mode : XE_SRIOV_MODE_NONE;
kunit_activate_static_stub(test, init_devid, fake_init_devid);
kunit_activate_static_stub(test, read_gmdid, fake_read_gmdid);
kunit_activate_static_stub(test, xe_info_probe_tile_count,
fake_xe_info_probe_tile_count);

View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0 AND MIT
/*
* Copyright © 2026 Intel Corporation
*/
#include "tests/xe_rtp_test.h"
#include <kunit/visibility.h>
/**
* xe_rtp_rule_matches - Check if a set of RTP rule set match against the
* device/GT/hwe
* @xe: The xe device
* @gt: The GT struct (may be NULL)
* @hwe: The hw_engine (may be NULL)
* @rules: The array of rules to match against
* @n_rules: Number of items in @rules
* @err: Pointer (may be NULL) to set error number.
*
* This parses the set of rules and check if they match against the passed
* parameters.
*
* If passed, @err is updated with a non-zero negative error number or zero if
* no errors were found during the parsing/evaluation of rules.
*
* Returns true if there is a match and false if there is no match or if an
* error was found.
*/
bool xe_rtp_rule_matches(const struct xe_device *xe,
struct xe_gt *gt,
struct xe_hw_engine *hwe,
const struct xe_rtp_rule *rules,
unsigned int n_rules,
int *err)
{
return rule_matches_with_err(xe, gt, hwe, rules, n_rules, err);
}
EXPORT_SYMBOL_IF_KUNIT(xe_rtp_rule_matches);

View File

@ -21,6 +21,7 @@
#include "xe_pci_test.h"
#include "xe_reg_sr.h"
#include "xe_rtp.h"
#include "xe_rtp_test.h"
#define REGULAR_REG1 XE_REG(1)
#define REGULAR_REG2 XE_REG(2)
@ -37,6 +38,14 @@
#undef XE_REG_MCR
#define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1)
struct rtp_rules_test_case {
const char *name;
bool expected_match;
int expected_err;
const struct xe_rtp_rule *rules;
u8 n_rules;
};
struct rtp_to_sr_test_case {
const char *name;
struct xe_reg expected_reg;
@ -83,6 +92,194 @@ static bool match_no(const struct xe_device *xe, const struct xe_gt *gt,
return false;
}
static const struct rtp_rules_test_case rtp_rules_cases[] = {
/*
* Single rules.
*
* TODO: Include other types of rules as well: GRAPHICS_VERSION(),
* MEDIA_VERSION(), etc.
*/
{
.name = "no",
.expected_match = false,
XE_RTP_RULES(FUNC(match_no)),
},
{
.name = "yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_yes)),
},
/* Conjunctions with 2 operands. */
{
.name = "no-and-no",
.expected_match = false,
XE_RTP_RULES(FUNC(match_no), FUNC(match_no)),
},
{
.name = "no-and-yes",
.expected_match = false,
XE_RTP_RULES(FUNC(match_no), FUNC(match_yes)),
},
{
.name = "yes-and-no",
.expected_match = false,
XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)),
},
{
.name = "yes-and-yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_yes), FUNC(match_yes)),
},
/* Disjunctions with 2 operands. */
{
.name = "no-or-no",
.expected_match = false,
XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)),
},
{
.name = "no-or-yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)),
},
{
.name = "yes-or-no",
.expected_match = true,
XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)),
},
{
.name = "yes-or-yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_yes)),
},
/* Conjunction and disjunctions. */
{
.name = "no-yes-or-yes-no",
.expected_match = false,
XE_RTP_RULES(FUNC(match_no), FUNC(match_yes), OR,
FUNC(match_yes), FUNC(match_no)),
},
{
.name = "no-yes-or-yes-yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_no), FUNC(match_yes), OR,
FUNC(match_yes), FUNC(match_yes)),
},
{
.name = "yes-yes-or-no-yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_yes), FUNC(match_yes), OR,
FUNC(match_no), FUNC(match_yes)),
},
{
.name = "yes-yes-or-yes-yes",
.expected_match = true,
XE_RTP_RULES(FUNC(match_yes), FUNC(match_yes), OR,
FUNC(match_yes), FUNC(match_yes)),
},
{
.name = "no-no-or-yes-or-no",
.expected_match = true,
XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR,
FUNC(match_yes), OR,
FUNC(match_no)),
},
/* Syntax errors. */
{
.name = "or",
.expected_match = false,
.expected_err = -EINVAL,
XE_RTP_RULES(OR),
},
{
.name = "or-yes",
.expected_match = true,
.expected_err = -EINVAL,
XE_RTP_RULES(OR, FUNC(match_yes)),
},
{
.name = "or-no",
.expected_match = false,
.expected_err = -EINVAL,
XE_RTP_RULES(OR, FUNC(match_no)),
},
{
.name = "yes-or",
.expected_match = true,
.expected_err = -EINVAL,
XE_RTP_RULES(FUNC(match_yes), OR),
},
{
.name = "no-or",
.expected_match = false,
.expected_err = -EINVAL,
XE_RTP_RULES(FUNC(match_no), OR),
},
{
.name = "no-or-or-yes",
.expected_match = true,
.expected_err = -EINVAL,
XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)),
},
{
.name = "yes-or-or-no",
.expected_match = true,
.expected_err = -EINVAL,
XE_RTP_RULES(FUNC(match_yes), OR, OR, FUNC(match_no)),
},
{
.name = "no-or-or-no",
.expected_match = false,
.expected_err = -EINVAL,
XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_no)),
},
/* No match because hwe is NULL. */
{
.name = "missing-context-engine-class",
.expected_match = false,
XE_RTP_RULES(ENGINE_CLASS(RENDER)),
},
/*
* Missing context (hwe==NULL) does not cause parsing to stop, hence we
* expect a match.
*/
{
.name = "missing-context-engine-class-or-yes",
.expected_match = true,
XE_RTP_RULES(ENGINE_CLASS(RENDER), OR, FUNC(match_yes)),
},
/*
* Missing context (hwe==NULL) does not cause parsing to stop, hence we
* expect a syntax error.
*/
{
.name = "missing-context-engine-class-or-or-yes",
.expected_match = true,
.expected_err = -EINVAL,
XE_RTP_RULES(ENGINE_CLASS(RENDER), OR, OR, FUNC(match_yes)),
},
};
static void xe_rtp_rules_tests(struct kunit *test)
{
const struct rtp_rules_test_case *param = test->param_value;
struct xe_device *xe = test->priv;
struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
int err;
bool match;
match = xe_rtp_rule_matches(xe, gt, NULL, param->rules, param->n_rules, &err);
KUNIT_EXPECT_EQ(test, match, param->expected_match);
KUNIT_EXPECT_EQ(test, err, param->expected_err);
}
static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
{
.name = "coalesce-same-reg",
@ -124,80 +321,6 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
{}
},
},
{
.name = "match-or",
.expected_reg = REGULAR_REG1,
.expected_set_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),
.expected_clr_bits = REG_BIT(0) | REG_BIT(1) | REG_BIT(2),
.expected_active = BIT(0) | BIT(1) | BIT(2),
.expected_count_sr_entries = 1,
.entries = (const struct xe_rtp_entry_sr[]) {
{ XE_RTP_NAME("first"),
XE_RTP_RULES(FUNC(match_yes), OR, FUNC(match_no)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
},
{ XE_RTP_NAME("middle"),
XE_RTP_RULES(FUNC(match_no), FUNC(match_no), OR,
FUNC(match_yes), OR,
FUNC(match_no)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
{ XE_RTP_NAME("last"),
XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))
},
{ XE_RTP_NAME("no-match"),
XE_RTP_RULES(FUNC(match_no), OR, FUNC(match_no)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(3)))
},
{}
},
},
{
.name = "match-or-xfail",
.expected_reg = REGULAR_REG1,
.expected_count_sr_entries = 0,
.entries = (const struct xe_rtp_entry_sr[]) {
{ XE_RTP_NAME("leading-or"),
XE_RTP_RULES(OR, FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
},
{ XE_RTP_NAME("trailing-or"),
/*
* First condition is match_no, otherwise the failure
* wouldn't really trigger as RTP stops processing as
* soon as it has a matching set of rules
*/
XE_RTP_RULES(FUNC(match_no), OR),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
{ XE_RTP_NAME("no-or-or-yes"),
XE_RTP_RULES(FUNC(match_no), OR, OR, FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(2)))
},
{}
},
},
{
.name = "no-match-no-add-multiple-rules",
.expected_reg = REGULAR_REG1,
.expected_set_bits = REG_BIT(0),
.expected_clr_bits = REG_BIT(0),
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
/* Don't coalesce second entry due to one of the rules */
.entries = (const struct xe_rtp_entry_sr[]) {
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
},
{ XE_RTP_NAME("basic-2"),
XE_RTP_RULES(FUNC(match_yes), FUNC(match_no)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
{}
},
},
{
.name = "two-regs-two-entries",
.expected_reg = REGULAR_REG1,
@ -458,16 +581,15 @@ static const struct rtp_test_case rtp_cases[] = {
},
},
{
.name = "inactive-1st_or_active-inactive",
.name = "inactive-active-inactive",
.expected_active = BIT(1),
.entries = (const struct xe_rtp_entry[]) {
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r2_or_conditions"),
XE_RTP_RULES(FUNC(match_yes), OR,
FUNC(match_no), OR,
FUNC(match_no)) },
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_yes)),
},
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
@ -475,50 +597,15 @@ static const struct rtp_test_case rtp_cases[] = {
},
},
{
.name = "inactive-2nd_or_active-inactive",
.expected_active = BIT(1),
.entries = (const struct xe_rtp_entry[]) {
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r2_or_conditions"),
XE_RTP_RULES(FUNC(match_no), OR,
FUNC(match_yes), OR,
FUNC(match_no)) },
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
{}
},
},
{
.name = "inactive-last_or_active-inactive",
.expected_active = BIT(1),
.entries = (const struct xe_rtp_entry[]) {
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r2_or_conditions"),
XE_RTP_RULES(FUNC(match_no), OR,
FUNC(match_no), OR,
FUNC(match_yes)) },
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
{}
},
},
{
.name = "inactive-no_or_active-inactive",
.name = "inactive-inactive-inactive",
.expected_active = 0,
.entries = (const struct xe_rtp_entry[]) {
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r2_or_conditions"),
XE_RTP_RULES(FUNC(match_no), OR,
FUNC(match_no), OR,
FUNC(match_no)) },
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
@ -544,6 +631,13 @@ static void xe_rtp_process_tests(struct kunit *test)
KUNIT_EXPECT_EQ(test, active, param->expected_active);
}
static void rtp_rules_desc(const struct rtp_rules_test_case *t, char *desc)
{
strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
}
KUNIT_ARRAY_PARAM(rtp_rules, rtp_rules_cases, rtp_rules_desc);
static void rtp_to_sr_desc(const struct rtp_to_sr_test_case *t, char *desc)
{
strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
@ -591,6 +685,7 @@ static void xe_rtp_test_exit(struct kunit *test)
}
static struct kunit_case xe_rtp_tests[] = {
KUNIT_CASE_PARAM(xe_rtp_rules_tests, rtp_rules_gen_params),
KUNIT_CASE_PARAM(xe_rtp_process_to_sr_tests, rtp_to_sr_gen_params),
KUNIT_CASE_PARAM(xe_rtp_process_tests, rtp_gen_params),
{}

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 AND MIT */
/*
* Copyright © 2026 Intel Corporation
*/
#ifndef _XE_RTP_TEST_H_
#define _XE_RTP_TEST_H_
#include <linux/types.h>
struct xe_device;
struct xe_gt;
struct xe_hw_engine;
struct xe_rtp_rule;
bool xe_rtp_rule_matches(const struct xe_device *xe,
struct xe_gt *gt,
struct xe_hw_engine *hwe,
const struct xe_rtp_rule *rules,
unsigned int n_rules,
int *err);
#endif

View File

@ -475,8 +475,15 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy)
ttm_device_fini(&xe->ttm);
}
struct xe_device *xe_device_create(struct pci_dev *pdev,
const struct pci_device_id *ent)
/**
* xe_device_create() - Create a new &xe_device instance
* @pdev: the parent &pci_dev
*
* Allocate and initialize a device managed Xe device structure.
*
* Return: pointer to new &xe_device on success, or ERR_PTR on failure.
*/
struct xe_device *xe_device_create(struct pci_dev *pdev)
{
const struct drm_driver *driver = &regular_driver;
struct xe_device *xe;
@ -499,30 +506,45 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
if (IS_ERR(xe))
return xe;
err = xe_device_init_early(xe);
if (err)
return ERR_PTR(err);
return xe;
}
ALLOW_ERROR_INJECTION(xe_device_create, ERRNO); /* See xe_pci_probe() */
/**
* xe_device_init_early() - Initialize a new &xe_device instance
* @xe: the &xe_device to initialize
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_device_init_early(struct xe_device *xe)
{
int err;
err = ttm_device_init(&xe->ttm, &xe_ttm_funcs, xe->drm.dev,
xe->drm.anon_inode->i_mapping,
xe->drm.vma_offset_manager, 0);
if (WARN_ON(err))
return ERR_PTR(err);
if (err)
return err;
xe_bo_dev_init(&xe->bo_device);
err = drmm_add_action_or_reset(&xe->drm, xe_device_destroy, NULL);
if (err)
return ERR_PTR(err);
return err;
err = xe_shrinker_create(xe);
if (err)
return ERR_PTR(err);
return err;
xe->info.devid = pdev->device;
xe->info.revid = pdev->revision;
xe->info.force_execlist = xe_modparam.force_execlist;
xe->atomic_svm_timeslice_ms = 5;
xe->min_run_period_lr_ms = 5;
err = xe_irq_init(xe);
if (err)
return ERR_PTR(err);
return err;
xe_validation_device_init(&xe->val);
@ -532,7 +554,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
err = xe_pagemap_shrinker_create(xe);
if (err)
return ERR_PTR(err);
return err;
xa_init_flags(&xe->usm.asid_to_vm, XA_FLAGS_ALLOC);
@ -551,7 +573,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
err = xe_bo_pinned_init(xe);
if (err)
return ERR_PTR(err);
return err;
xe->preempt_fence_wq = alloc_ordered_workqueue("xe-preempt-fence-wq",
WQ_MEM_RECLAIM);
@ -565,16 +587,19 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
* drmm_add_action_or_reset register above
*/
drm_err(&xe->drm, "Failed to allocate xe workqueues\n");
return ERR_PTR(-ENOMEM);
return -ENOMEM;
}
err = drmm_mutex_init(&xe->drm, &xe->pmt.lock);
if (err)
return ERR_PTR(err);
return err;
return xe;
err = xe_pm_init_early(xe);
if (err)
return err;
return 0;
}
ALLOW_ERROR_INJECTION(xe_device_create, ERRNO); /* See xe_pci_probe() */
static bool xe_driver_flr_disabled(struct xe_device *xe)
{

View File

@ -43,8 +43,8 @@ static inline struct xe_device *ttm_to_xe_device(struct ttm_device *ttm)
return container_of(ttm, struct xe_device, ttm);
}
struct xe_device *xe_device_create(struct pci_dev *pdev,
const struct pci_device_id *ent);
struct xe_device *xe_device_create(struct pci_dev *pdev);
int xe_device_init_early(struct xe_device *xe);
int xe_device_probe_early(struct xe_device *xe);
int xe_device_probe(struct xe_device *xe);
void xe_device_remove(struct xe_device *xe);

View File

@ -768,6 +768,11 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads,
}
}
if (XE_GT_WA(hwe->gt, 16023105232))
guc_mmio_regset_write_one(ads, regset_map,
RING_IDLEDLY(hwe->mmio_base),
count++);
return count;
}

View File

@ -408,46 +408,43 @@ void xe_guc_submit_disable(struct xe_guc *guc)
guc->submission_state.enabled = false;
}
static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, u32 xa_count)
static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q,
int count)
{
int i;
lockdep_assert_held(&guc->submission_state.lock);
mutex_lock(&guc->submission_state.lock);
for (i = 0; i < xa_count; ++i)
xa_erase(&guc->submission_state.exec_queue_lookup, q->guc->id + i);
for (i = 0; i < count; ++i)
xa_erase(&guc->submission_state.exec_queue_lookup,
q->guc->id + i);
xe_guc_id_mgr_release_locked(&guc->submission_state.idm,
q->guc->id, q->width);
if (xa_empty(&guc->submission_state.exec_queue_lookup))
wake_up(&guc->submission_state.fini_wq);
mutex_unlock(&guc->submission_state.lock);
}
static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
{
int ret;
int i;
/*
* Must use GFP_NOWAIT as this lock is in the dma fence signalling path,
* worse case user gets -ENOMEM on engine create and has to try again.
*
* FIXME: Have caller pre-alloc or post-alloc /w GFP_KERNEL to prevent
* failure.
*/
lockdep_assert_held(&guc->submission_state.lock);
int ret, i;
mutex_lock(&guc->submission_state.lock);
ret = xe_guc_id_mgr_reserve_locked(&guc->submission_state.idm,
q->width);
mutex_unlock(&guc->submission_state.lock);
if (ret < 0)
return ret;
q->guc->id = ret;
/* Reserve empty slots. */
for (i = 0; i < q->width; ++i) {
ret = xa_err(xa_store(&guc->submission_state.exec_queue_lookup,
q->guc->id + i, q, GFP_NOWAIT));
ret = xa_insert(&guc->submission_state.exec_queue_lookup,
q->guc->id + i, NULL, GFP_KERNEL);
if (ret)
goto err_release;
}
@ -460,11 +457,24 @@ static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
return ret;
}
static void publish_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
{
int i;
lockdep_assert_held(&guc->submission_state.lock);
for (i = 0; i < q->width; ++i) {
void *old;
old = xa_store(&guc->submission_state.exec_queue_lookup,
q->guc->id + i, q, GFP_NOWAIT);
XE_WARN_ON(old || xa_is_err(old));
}
}
static void release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
{
mutex_lock(&guc->submission_state.lock);
__release_guc_id(guc, q, q->width);
mutex_unlock(&guc->submission_state.lock);
}
struct exec_queue_policy {
@ -1961,6 +1971,12 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
msecs_to_jiffies(q->sched_props.job_timeout_ms);
err = alloc_guc_id(guc, q);
if (err)
goto err_free;
xe_exec_queue_assign_name(q, q->guc->id);
/*
* Use primary queue's submit_wq for all secondary queues of a
* multi queue group. This serialization avoids any locking around
@ -1977,28 +1993,21 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
timeout, guc_to_gt(guc)->ordered_wq, NULL,
q->name, gt_to_xe(q->gt)->drm.dev);
if (err)
goto err_free;
goto err_release_id;
sched = &ge->sched;
err = xe_sched_entity_init(&ge->entity, sched);
if (err)
goto err_sched;
mutex_lock(&guc->submission_state.lock);
err = alloc_guc_id(guc, q);
if (err)
goto err_entity;
q->entity = &ge->entity;
mutex_lock(&guc->submission_state.lock);
if (xe_guc_read_stopped(guc) || vf_recovery(guc))
xe_sched_stop(sched);
publish_guc_id(guc, q);
mutex_unlock(&guc->submission_state.lock);
xe_exec_queue_assign_name(q, q->guc->id);
/*
* Maintain secondary queues of the multi queue group in a list
* for handling dependencies across the queues in the group.
@ -2021,11 +2030,10 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
return 0;
err_entity:
mutex_unlock(&guc->submission_state.lock);
xe_sched_entity_fini(&ge->entity);
err_sched:
xe_sched_fini(&ge->sched);
err_release_id:
release_guc_id(guc, q);
err_free:
kfree(ge);

View File

@ -10,7 +10,8 @@
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include "xe_uc_fw_abi.h"
#include "abi/uc_fw_abi.h"
#define XE_LB_MAX_PAYLOAD_SIZE SZ_4K

View File

@ -575,14 +575,14 @@ static bool id_blocked(u16 device_id)
}
static const struct xe_subplatform_desc *
find_subplatform(const struct xe_device *xe, const struct xe_device_desc *desc)
find_subplatform(const struct xe_device_desc *desc, u16 devid)
{
const struct xe_subplatform_desc *sp;
const u16 *id;
for (sp = desc->subplatforms; sp && sp->subplatform; sp++)
for (id = sp->pciidlist; *id; id++)
if (*id == xe->info.devid)
if (*id == devid)
return sp;
return NULL;
@ -726,6 +726,16 @@ static int handle_gmdid(struct xe_device *xe,
return 0;
}
static void init_devid(struct xe_device *xe)
{
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
KUNIT_STATIC_STUB_REDIRECT(init_devid, xe);
xe->info.devid = pdev->device;
xe->info.revid = pdev->revision;
}
/*
* Initialize device info content that only depends on static driver_data
* passed to the driver at probe time from PCI ID table.
@ -741,6 +751,8 @@ static int xe_info_init_early(struct xe_device *xe,
xe->info.subplatform = subplatform_desc ?
subplatform_desc->subplatform : XE_SUBPLATFORM_NONE;
init_devid(xe);
xe->info.dma_mask_size = desc->dma_mask_size;
xe->info.va_bits = desc->va_bits;
xe->info.vm_max_level = desc->vm_max_level;
@ -777,6 +789,7 @@ static int xe_info_init_early(struct xe_device *xe,
xe->info.probe_display = IS_ENABLED(CONFIG_DRM_XE_DISPLAY) &&
xe_modparam.probe_display &&
desc->has_display;
xe->info.force_execlist = xe_modparam.force_execlist;
xe_assert(xe, desc->max_gt_per_tile > 0);
xe_assert(xe, desc->max_gt_per_tile <= XE_MAX_GT_PER_TILE);
@ -1064,6 +1077,8 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct xe_device *xe;
int err;
subplatform_desc = find_subplatform(desc, pdev->device);
xe_configfs_check_device(pdev);
if (desc->require_force_probe && !id_forced(pdev->device)) {
@ -1091,14 +1106,13 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
return err;
xe = xe_device_create(pdev, ent);
xe = xe_device_create(pdev);
if (IS_ERR(xe))
return PTR_ERR(xe);
pci_set_drvdata(pdev, &xe->drm);
xe_pm_assert_unbounded_bridge(xe);
subplatform_desc = find_subplatform(xe, desc);
pci_set_master(pdev);
@ -1153,7 +1167,7 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
str_yes_no(xe_device_has_sriov(xe)),
xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
err = xe_pm_init_early(xe);
err = xe_pm_probe(xe);
if (err)
return err;
@ -1165,9 +1179,6 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_driver_cleanup;
drm_dbg(&xe->drm, "d3cold: capable=%s\n",
str_yes_no(xe->d3cold.capable));
return 0;
err_driver_cleanup:

View File

@ -24,6 +24,7 @@
#include "xe_irq.h"
#include "xe_late_bind_fw.h"
#include "xe_pcode.h"
#include "xe_printk.h"
#include "xe_pxp.h"
#include "xe_sriov_vf_ccs.h"
#include "xe_sysctrl.h"
@ -349,10 +350,22 @@ static void xe_pm_runtime_init(struct xe_device *xe)
pm_runtime_put(dev);
}
/**
* xe_pm_init_early() - Initialize Xe Power Management
* @xe: the &xe_device instance
*
* Initialize everything that is a "software-only" state that does not
* require access to any of the device's hardware data.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_pm_init_early(struct xe_device *xe)
{
int err;
init_completion(&xe->pm_block);
complete_all(&xe->pm_block);
INIT_LIST_HEAD(&xe->rebind_resume_list);
INIT_LIST_HEAD(&xe->mem_access.vram_userfault.list);
err = drmm_mutex_init(&xe->drm, &xe->mem_access.vram_userfault.lock);
@ -363,11 +376,30 @@ int xe_pm_init_early(struct xe_device *xe)
if (err)
return err;
xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe);
err = drmm_mutex_init(&xe->drm, &xe->rebind_resume_lock);
if (err)
return err;
return 0;
}
ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */
/**
* xe_pm_probe() - Initialize Xe Power Management
* @xe: the &xe_device instance
*
* Check d3cold capability.
*
* Return: 0 on success or a negative error code on failure.
*/
int xe_pm_probe(struct xe_device *xe)
{
xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe);
xe_dbg(xe, "d3cold: capable=%s\n", str_yes_no(xe->d3cold.capable));
return 0;
}
static u32 vram_threshold_value(struct xe_device *xe)
{
if (xe->info.platform == XE_BATTLEMAGE) {
@ -459,14 +491,6 @@ int xe_pm_init(struct xe_device *xe)
if (err)
return err;
err = drmm_mutex_init(&xe->drm, &xe->rebind_resume_lock);
if (err)
goto err_unregister;
init_completion(&xe->pm_block);
complete_all(&xe->pm_block);
INIT_LIST_HEAD(&xe->rebind_resume_list);
/* For now suspend/resume is only allowed with GuC */
if (!xe_device_uc_enabled(xe))
return 0;

View File

@ -17,6 +17,7 @@ int xe_pm_suspend(struct xe_device *xe);
int xe_pm_resume(struct xe_device *xe);
int xe_pm_init_early(struct xe_device *xe);
int xe_pm_probe(struct xe_device *xe);
int xe_pm_init(struct xe_device *xe);
void xe_pm_fini(struct xe_device *xe);
bool xe_pm_runtime_suspended(struct xe_device *xe);

View File

@ -30,146 +30,199 @@ static bool has_samedia(const struct xe_device *xe)
return xe->info.media_verx100 >= 1300;
}
struct rule_match_ctx {
const struct xe_device *xe;
struct xe_gt *gt;
struct xe_hw_engine *hwe;
const struct xe_rtp_rule *rules;
const unsigned int n_rules;
unsigned int head;
int err;
};
static bool rule_is_item(const struct xe_rtp_rule *r)
{
return r->match_type != XE_RTP_MATCH_OR;
}
static bool rule_match_item(struct rule_match_ctx *match_ctx)
{
const struct xe_device *xe = match_ctx->xe;
struct xe_gt *gt = match_ctx->gt;
struct xe_hw_engine *hwe = match_ctx->hwe;
const struct xe_rtp_rule *r = &match_ctx->rules[match_ctx->head];
switch (r->match_type) {
case XE_RTP_MATCH_PLATFORM:
return xe->info.platform == r->platform;
case XE_RTP_MATCH_SUBPLATFORM:
return xe->info.platform == r->platform &&
xe->info.subplatform == r->subplatform;
case XE_RTP_MATCH_PLATFORM_STEP:
if (drm_WARN_ON(&xe->drm, xe->info.step.platform == STEP_NONE))
return false;
return xe->info.step.platform >= r->step_start &&
xe->info.step.platform < r->step_end;
case XE_RTP_MATCH_GRAPHICS_VERSION:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.graphics_verx100 == r->ver_start &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
case XE_RTP_MATCH_GRAPHICS_VERSION_RANGE:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.graphics_verx100 >= r->ver_start &&
xe->info.graphics_verx100 <= r->ver_end &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
case XE_RTP_MATCH_GRAPHICS_VERSION_ANY_GT:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.graphics_verx100 == r->ver_start;
case XE_RTP_MATCH_GRAPHICS_STEP:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.step.graphics >= r->step_start &&
xe->info.step.graphics < r->step_end &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
case XE_RTP_MATCH_MEDIA_VERSION:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.media_verx100 == r->ver_start &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
case XE_RTP_MATCH_MEDIA_VERSION_RANGE:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.media_verx100 >= r->ver_start &&
xe->info.media_verx100 <= r->ver_end &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
case XE_RTP_MATCH_MEDIA_STEP:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.step.media >= r->step_start &&
xe->info.step.media < r->step_end &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
case XE_RTP_MATCH_MEDIA_VERSION_ANY_GT:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
return xe->info.media_verx100 == r->ver_start;
case XE_RTP_MATCH_INTEGRATED:
return !xe->info.is_dgfx;
case XE_RTP_MATCH_DISCRETE:
return xe->info.is_dgfx;
case XE_RTP_MATCH_ENGINE_CLASS:
if (drm_WARN_ON(&xe->drm, !hwe))
return false;
return hwe->class == r->engine_class;
case XE_RTP_MATCH_NOT_ENGINE_CLASS:
if (drm_WARN_ON(&xe->drm, !hwe))
return false;
return hwe->class != r->engine_class;
case XE_RTP_MATCH_FUNC:
return r->match_func(xe, gt, hwe);
default:
drm_warn(&xe->drm, "Invalid RTP match %u\n",
r->match_type);
return false;
}
}
/*
* Match a conjunctive set of rules (rules joined by an implicit "AND").
*
* Once one item evaluates to false, the remaining items are not evaluated
* anymore. Nevetheless, all rules are consumed to allow detecting syntax
* errors.
*/
static bool rule_match_and(struct rule_match_ctx *match_ctx, bool parse_only)
{
bool match = true;
unsigned int count = 0;
while (match_ctx->head < match_ctx->n_rules &&
rule_is_item(&match_ctx->rules[match_ctx->head])) {
if (!parse_only)
match = rule_match_item(match_ctx);
if (!match)
parse_only = true;
match_ctx->head++;
count++;
}
if (drm_WARN_ON(&match_ctx->xe->drm, !count)) {
match_ctx->err = -EINVAL;
if (!parse_only)
match = false;
}
return match;
}
/*
* Match a disjunctive set of rules (subset of rules joined by
* "XE_RTP_MATCH_OR").
*
* Once one subset evaluates to true, the remaining items are not evaluated
* anymore. Nevetheless, all rules are consumed to allow detecting syntax
* errors.
*/
static bool rule_match_or(struct rule_match_ctx *match_ctx)
{
bool match = rule_match_and(match_ctx, false);
while (match_ctx->head < match_ctx->n_rules &&
match_ctx->rules[match_ctx->head].match_type == XE_RTP_MATCH_OR) {
/* Consume XE_RTP_MATCH_OR. */
match_ctx->head++;
match = rule_match_and(match_ctx, match);
}
return match;
}
static bool rule_matches_with_err(const struct xe_device *xe,
struct xe_gt *gt,
struct xe_hw_engine *hwe,
const struct xe_rtp_rule *rules,
unsigned int n_rules,
int *err)
{
struct rule_match_ctx match_ctx = {
.xe = xe,
.gt = gt,
.hwe = hwe,
.rules = rules,
.n_rules = n_rules,
};
bool match = rule_match_or(&match_ctx);
if (err)
*err = match_ctx.err;
return match;
}
static bool rule_matches(const struct xe_device *xe,
struct xe_gt *gt,
struct xe_hw_engine *hwe,
const struct xe_rtp_rule *rules,
unsigned int n_rules)
{
const struct xe_rtp_rule *r;
unsigned int i, rcount = 0;
bool match;
for (r = rules, i = 0; i < n_rules; r = &rules[++i]) {
switch (r->match_type) {
case XE_RTP_MATCH_OR:
/*
* This is only reached if a complete set of
* rules passed or none were evaluated. For both cases,
* shortcut the other rules and return the proper value.
*/
goto done;
case XE_RTP_MATCH_PLATFORM:
match = xe->info.platform == r->platform;
break;
case XE_RTP_MATCH_SUBPLATFORM:
match = xe->info.platform == r->platform &&
xe->info.subplatform == r->subplatform;
break;
case XE_RTP_MATCH_PLATFORM_STEP:
if (drm_WARN_ON(&xe->drm, xe->info.step.platform == STEP_NONE))
return false;
match = xe->info.step.platform >= r->step_start &&
xe->info.step.platform < r->step_end;
break;
case XE_RTP_MATCH_GRAPHICS_VERSION:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.graphics_verx100 == r->ver_start &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
break;
case XE_RTP_MATCH_GRAPHICS_VERSION_RANGE:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.graphics_verx100 >= r->ver_start &&
xe->info.graphics_verx100 <= r->ver_end &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
break;
case XE_RTP_MATCH_GRAPHICS_VERSION_ANY_GT:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.graphics_verx100 == r->ver_start;
break;
case XE_RTP_MATCH_GRAPHICS_STEP:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.step.graphics >= r->step_start &&
xe->info.step.graphics < r->step_end &&
(!has_samedia(xe) || !xe_gt_is_media_type(gt));
break;
case XE_RTP_MATCH_MEDIA_VERSION:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.media_verx100 == r->ver_start &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
break;
case XE_RTP_MATCH_MEDIA_VERSION_RANGE:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.media_verx100 >= r->ver_start &&
xe->info.media_verx100 <= r->ver_end &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
break;
case XE_RTP_MATCH_MEDIA_STEP:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.step.media >= r->step_start &&
xe->info.step.media < r->step_end &&
(!has_samedia(xe) || xe_gt_is_media_type(gt));
break;
case XE_RTP_MATCH_MEDIA_VERSION_ANY_GT:
if (drm_WARN_ON(&xe->drm, !gt))
return false;
match = xe->info.media_verx100 == r->ver_start;
break;
case XE_RTP_MATCH_INTEGRATED:
match = !xe->info.is_dgfx;
break;
case XE_RTP_MATCH_DISCRETE:
match = xe->info.is_dgfx;
break;
case XE_RTP_MATCH_ENGINE_CLASS:
if (drm_WARN_ON(&xe->drm, !hwe))
return false;
match = hwe->class == r->engine_class;
break;
case XE_RTP_MATCH_NOT_ENGINE_CLASS:
if (drm_WARN_ON(&xe->drm, !hwe))
return false;
match = hwe->class != r->engine_class;
break;
case XE_RTP_MATCH_FUNC:
match = r->match_func(xe, gt, hwe);
break;
default:
drm_warn(&xe->drm, "Invalid RTP match %u\n",
r->match_type);
match = false;
}
if (!match) {
/*
* Advance rules until we find XE_RTP_MATCH_OR to check
* if there's another set of conditions to check
*/
while (++i < n_rules && rules[i].match_type != XE_RTP_MATCH_OR)
;
if (i >= n_rules)
return false;
rcount = 0;
} else {
rcount++;
}
}
done:
if (drm_WARN_ON(&xe->drm, !rcount))
return false;
return true;
return rule_matches_with_err(xe, gt, hwe, rules, n_rules, NULL);
}
static void rtp_add_sr_entry(const struct xe_rtp_action *action,
@ -412,3 +465,7 @@ bool xe_rtp_match_has_msix(const struct xe_device *xe,
{
return xe_device_has_msix(xe);
}
#if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
#include "tests/xe_rtp.c"
#endif

View File

@ -394,18 +394,39 @@ struct xe_reg_sr;
* XE_RTP_RULES - Helper to set multiple rules to a struct xe_rtp_entry_sr entry
* @...: Rules
*
* At least one rule is needed and up to 12 are supported. Multiple rules are
* AND'ed together, i.e. all the rules must evaluate to true for the entry to
* be processed. See XE_RTP_MATCH_* for the possible match rules. Example:
* When an RTP table is being processed, the rules of each entry are evaluated
* to check if they match the target entity (platform, gt or hwe, depending on
* the specific RTP table).
*
* The sequence of arguments of this macro must follow the following eBNF
* grammar::
*
* rules = disjunction;
* disjunction = conjunction, { "OR", conjunction };
* conjunction = single_rule, { single_rule };
* (* the AND operator is implicit *)
* single_rule = ? GRAPHICS_VERSION(...), MEDIA_VERSION(...),
* FUNC(...), etc ?
*
* Examples:
*
* .. code-block:: c
*
* const struct xe_rtp_entry_sr wa_entries[] = {
* ...
* { XE_RTP_NAME("test-entry"),
* { XE_RTP_NAME("entry-a"),
* // Match DG2-G10 with graphics steppings A0 up-to B0
* // (exclusive).
* XE_RTP_RULES(SUBPLATFORM(DG2, G10), GRAPHICS_STEP(A0, B0)),
* ...
* },
* { XE_RTP_NAME("entry-b"),
* // Match graphics version 20 (all steppings) or graphics
* // version 30 steppings A0 up-to B0 (exclusive).
* XE_RTP_RULES(GRAPHICS_VERSION(2000), OR,
* GRAPHICS_VERSION(3000), GRAPHICS_STEP(A0, B0))
* ...
* },
* ...
* };
*/

View File

@ -8,8 +8,8 @@
#include <linux/errno.h>
#include "abi/uc_fw_abi.h"
#include "xe_macros.h"
#include "xe_uc_fw_abi.h"
#include "xe_uc_fw_types.h"
struct drm_printer;