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

Driver Changes:
More xe3p support (Harish, Brian, Balasubramani, Matt Roper)
Make panic support work on VRAM for display (Maarten)
Fix stolen size check (Shuicheng)
xe_pci_test update (Gustavo)
VF migration updates (Tomasz)
A couple of fixes around allocation and PM references (Matt Brost)
Migration update for the MEM_COPY instruction (Matt Auld)
Initial CRI support (Balasubramani, Matt Roper)
Use SVM range helpers in PT layer (Matt Brost)
Drop MAX_GT_TYPE_CHARS constant (Matt Roper)
Fix spelling and typos (Sanjay)
Fix VF FLR synchronization between all GTs (Michal)
Add a Workaround (Nitin)
Access VF's register using dedicated MMIO view (Michal)

Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/aQCl9uJxN6CWJ8Vg@fedora
This commit is contained in:
Simona Vetter
2025-10-31 18:40:53 +01:00
63 changed files with 534 additions and 216 deletions

View File

@@ -8,20 +8,23 @@
#include "intel_fb.h"
#include "intel_panic.h"
#include "xe_bo.h"
#include "xe_res_cursor.h"
struct intel_panic {
struct page **pages;
struct xe_res_cursor res;
struct iosys_map vmap;
int page;
void *vaddr;
};
static void xe_panic_kunmap(struct intel_panic *panic)
{
if (panic->vaddr) {
drm_clflush_virt_range(panic->vaddr, PAGE_SIZE);
kunmap_local(panic->vaddr);
panic->vaddr = NULL;
if (!panic->vmap.is_iomem && iosys_map_is_set(&panic->vmap)) {
drm_clflush_virt_range(panic->vmap.vaddr, PAGE_SIZE);
kunmap_local(panic->vmap.vaddr);
}
iosys_map_clear(&panic->vmap);
panic->page = -1;
}
/*
@@ -46,15 +49,29 @@ static void xe_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int
new_page = offset >> PAGE_SHIFT;
offset = offset % PAGE_SIZE;
if (new_page != panic->page) {
xe_panic_kunmap(panic);
if (xe_bo_is_vram(bo)) {
/* Display is always mapped on root tile */
struct xe_vram_region *vram = xe_bo_device(bo)->mem.vram;
if (panic->page < 0 || new_page < panic->page) {
xe_res_first(bo->ttm.resource, new_page * PAGE_SIZE,
bo->ttm.base.size - new_page * PAGE_SIZE, &panic->res);
} else {
xe_res_next(&panic->res, PAGE_SIZE * (new_page - panic->page));
}
iosys_map_set_vaddr_iomem(&panic->vmap,
vram->mapping + panic->res.start);
} else {
xe_panic_kunmap(panic);
iosys_map_set_vaddr(&panic->vmap,
ttm_bo_kmap_try_from_panic(&bo->ttm,
new_page));
}
panic->page = new_page;
panic->vaddr = ttm_bo_kmap_try_from_panic(&bo->ttm,
panic->page);
}
if (panic->vaddr) {
u32 *pix = panic->vaddr + offset;
*pix = color;
}
if (iosys_map_is_set(&panic->vmap))
iosys_map_wr(&panic->vmap, offset, u32, color);
}
struct intel_panic *intel_panic_alloc(void)
@@ -68,6 +85,12 @@ struct intel_panic *intel_panic_alloc(void)
int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
{
struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private;
struct xe_bo *bo = gem_to_xe_bo(intel_fb_bo(&fb->base));
if (xe_bo_is_vram(bo) && !xe_bo_is_visible_vram(bo))
return -ENODEV;
panic->page = -1;
sb->set_pixel = xe_panic_page_set_pixel;
return 0;
@@ -76,5 +99,4 @@ int intel_panic_setup(struct intel_panic *panic, struct drm_scanout_buffer *sb)
void intel_panic_finish(struct intel_panic *panic)
{
xe_panic_kunmap(panic);
panic->page = -1;
}

View File

@@ -31,6 +31,12 @@
#define XY_FAST_COPY_BLT_D1_DST_TILE4 REG_BIT(30)
#define XE2_XY_FAST_COPY_BLT_MOCS_INDEX_MASK GENMASK(23, 20)
#define MEM_COPY_CMD (2 << 29 | 0x5a << 22 | 0x8)
#define MEM_COPY_PAGE_COPY_MODE REG_BIT(19)
#define MEM_COPY_MATRIX_COPY REG_BIT(17)
#define MEM_COPY_SRC_MOCS_INDEX_MASK GENMASK(31, 28)
#define MEM_COPY_DST_MOCS_INDEX_MASK GENMASK(6, 3)
#define PVC_MEM_SET_CMD (2 << 29 | 0x5b << 22)
#define PVC_MEM_SET_CMD_LEN_DW 7
#define PVC_MEM_SET_MATRIX REG_BIT(17)

View File

@@ -37,6 +37,12 @@
#define GMD_ID XE_REG(0xd8c)
#define GMD_ID_ARCH_MASK REG_GENMASK(31, 22)
#define GMD_ID_RELEASE_MASK REG_GENMASK(21, 14)
/*
* Spec defines these bits as "Reserved", but then make them assume some
* meaning that depends on the ARCH. To avoid any confusion, call them
* SUBIP_FLAG_MASK.
*/
#define GMD_ID_SUBIP_FLAG_MASK REG_GENMASK(13, 6)
#define GMD_ID_REVID REG_GENMASK(5, 0)
#define FORCEWAKE_ACK_GSC XE_REG(0xdf8)
@@ -168,6 +174,7 @@
#define XEHP_SLICE_COMMON_ECO_CHICKEN1 XE_REG_MCR(0x731c, XE_REG_OPTION_MASKED)
#define MSC_MSAA_REODER_BUF_BYPASS_DISABLE REG_BIT(14)
#define FAST_CLEAR_VALIGN_FIX REG_BIT(13)
#define XE2LPM_CCCHKNREG1 XE_REG(0x82a8)
@@ -544,6 +551,9 @@
#define SARB_CHICKEN1 XE_REG_MCR(0xe90c)
#define COMP_CKN_IN REG_GENMASK(30, 29)
#define MAIN_GAMCTRL_MODE XE_REG(0xef00)
#define MAIN_GAMCTRL_QUEUE_SELECT REG_BIT(0)
#define RCU_MODE XE_REG(0x14800, XE_REG_OPTION_MASKED)
#define RCU_MODE_FIXED_SLICE_CCS_MODE REG_BIT(1)
#define RCU_MODE_CCS_ENABLE REG_BIT(0)

View File

@@ -44,21 +44,27 @@ static void check_media_ip(struct kunit *test)
KUNIT_ASSERT_EQ(test, mask, 0);
}
static void check_platform_gt_count(struct kunit *test)
static void check_platform_desc(struct kunit *test)
{
const struct pci_device_id *pci = test->param_value;
const struct xe_device_desc *desc =
(const struct xe_device_desc *)pci->driver_data;
int max_gt = desc->max_gt_per_tile;
KUNIT_ASSERT_GT(test, max_gt, 0);
KUNIT_ASSERT_LE(test, max_gt, XE_MAX_GT_PER_TILE);
KUNIT_EXPECT_GT(test, desc->dma_mask_size, 0);
KUNIT_EXPECT_GT(test, (unsigned int)desc->max_gt_per_tile, 0);
KUNIT_EXPECT_LE(test, (unsigned int)desc->max_gt_per_tile, XE_MAX_GT_PER_TILE);
KUNIT_EXPECT_GT(test, desc->va_bits, 0);
KUNIT_EXPECT_LE(test, desc->va_bits, 64);
KUNIT_EXPECT_GT(test, desc->vm_max_level, 0);
}
static struct kunit_case xe_pci_tests[] = {
KUNIT_CASE_PARAM(check_graphics_ip, xe_pci_graphics_ip_gen_param),
KUNIT_CASE_PARAM(check_media_ip, xe_pci_media_ip_gen_param),
KUNIT_CASE_PARAM(check_platform_gt_count, xe_pci_id_gen_param),
KUNIT_CASE_PARAM(check_platform_desc, xe_pci_id_gen_param),
{}
};

View File

@@ -610,6 +610,23 @@ static bool xe_ttm_resource_visible(struct ttm_resource *mem)
return vres->used_visible_size == mem->size;
}
/**
* xe_bo_is_visible_vram - check if BO is placed entirely in visible VRAM.
* @bo: The BO
*
* This function checks whether a given BO resides entirely in memory visible from the CPU
*
* Returns: true if the BO is entirely visible, false otherwise.
*
*/
bool xe_bo_is_visible_vram(struct xe_bo *bo)
{
if (drm_WARN_ON(bo->ttm.base.dev, !xe_bo_is_vram(bo)))
return false;
return xe_ttm_resource_visible(bo->ttm.resource);
}
static int xe_ttm_io_mem_reserve(struct ttm_device *bdev,
struct ttm_resource *mem)
{
@@ -1635,7 +1652,7 @@ static int xe_ttm_access_memory(struct ttm_buffer_object *ttm_bo,
if (!mem_type_is_vram(ttm_bo->resource->mem_type))
return -EIO;
if (!xe_ttm_resource_visible(ttm_bo->resource) || len >= SZ_16K) {
if (!xe_bo_is_visible_vram(bo) || len >= SZ_16K) {
struct xe_migrate *migrate =
mem_type_to_migrate(xe, ttm_bo->resource->mem_type);
@@ -2105,7 +2122,7 @@ void xe_bo_free(struct xe_bo *bo)
* if the function should allocate a new one.
* @tile: The tile to select for migration of this bo, and the tile used for
* GGTT binding if any. Only to be non-NULL for ttm_bo_type_kernel bos.
* @resv: Pointer to a locked shared reservation object to use fo this bo,
* @resv: Pointer to a locked shared reservation object to use for this bo,
* or NULL for the xe_bo to use its own.
* @bulk: The bulk move to use for LRU bumping, or NULL for external bos.
* @size: The storage size to use for the bo.
@@ -2259,6 +2276,12 @@ static int __xe_bo_fixed_placement(struct xe_device *xe,
struct ttm_place *place = bo->placements;
u32 vram_flag, vram_stolen_flags;
/*
* to allow fixed placement in GGTT of a VF, post-migration fixups would have to
* include selecting a new fixed offset and shifting the page ranges for it
*/
xe_assert(xe, !IS_SRIOV_VF(xe) || !(bo->flags & XE_BO_FLAG_GGTT));
if (flags & (XE_BO_FLAG_USER | XE_BO_FLAG_SYSTEM))
return -EINVAL;
@@ -2629,7 +2652,7 @@ struct xe_bo *xe_bo_create_pin_map(struct xe_device *xe, struct xe_tile *tile,
* @size: The storage size to use for the bo.
* @type: The TTM buffer object type.
* @flags: XE_BO_FLAG_ flags.
* @intr: Whether to execut any waits for backing store interruptible.
* @intr: Whether to execute any waits for backing store interruptible.
*
* Create a pinned and mapped bo. The bo will be external and not associated
* with a VM.

View File

@@ -274,6 +274,7 @@ int xe_bo_read(struct xe_bo *bo, u64 offset, void *dst, int size);
bool mem_type_is_vram(u32 mem_type);
bool xe_bo_is_vram(struct xe_bo *bo);
bool xe_bo_is_visible_vram(struct xe_bo *bo);
bool xe_bo_is_stolen(struct xe_bo *bo);
bool xe_bo_is_stolen_devmem(struct xe_bo *bo);
bool xe_bo_is_vm_bound(struct xe_bo *bo);

View File

@@ -12,7 +12,7 @@
* BO management
* =============
*
* TTM manages (placement, eviction, etc...) all BOs in XE.
* TTM manages (placement, eviction, etc...) all BOs in Xe.
*
* BO creation
* ===========
@@ -29,7 +29,7 @@
* a kernel BO (e.g. engine state, memory for page tables, etc...). These BOs
* are typically mapped in the GGTT (any kernel BOs aside memory for page tables
* are in the GGTT), are pinned (can't move or be evicted at runtime), have a
* vmap (XE can access the memory via xe_map layer) and have contiguous physical
* vmap (Xe can access the memory via xe_map layer) and have contiguous physical
* memory.
*
* More details of why kernel BOs are pinned and contiguous below.
@@ -40,7 +40,7 @@
* A user BO is created via the DRM_IOCTL_XE_GEM_CREATE IOCTL. Once it is
* created the BO can be mmap'd (via DRM_IOCTL_XE_GEM_MMAP_OFFSET) for user
* access and it can be bound for GPU access (via DRM_IOCTL_XE_VM_BIND). All
* user BOs are evictable and user BOs are never pinned by XE. The allocation of
* user BOs are evictable and user BOs are never pinned by Xe. The allocation of
* the backing store can be deferred from creation time until first use which is
* either mmap, bind, or pagefault.
*
@@ -84,7 +84,7 @@
* ====================
*
* All eviction (or in other words, moving a BO from one memory location to
* another) is routed through TTM with a callback into XE.
* another) is routed through TTM with a callback into Xe.
*
* Runtime eviction
* ----------------

View File

@@ -27,7 +27,7 @@
* Overview
* ========
*
* Configfs is a filesystem-based manager of kernel objects. XE KMD registers a
* Configfs is a filesystem-based manager of kernel objects. Xe KMD registers a
* configfs subsystem called ``xe`` that creates a directory in the mounted
* configfs directory. The user can create devices under this directory and
* configure them as necessary. See Documentation/filesystems/configfs.rst for
@@ -301,7 +301,6 @@ struct engine_info {
/* Some helpful macros to aid on the sizing of buffer allocation when parsing */
#define MAX_ENGINE_CLASS_CHARS 5
#define MAX_ENGINE_INSTANCE_CHARS 2
#define MAX_GT_TYPE_CHARS 7
static const struct engine_info engine_info[] = {
{ .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK, .engine_class = XE_ENGINE_CLASS_RENDER },
@@ -313,7 +312,7 @@ static const struct engine_info engine_info[] = {
};
static const struct {
const char name[MAX_GT_TYPE_CHARS + 1];
const char *name;
enum xe_gt_type type;
} gt_types[] = {
{ .name = "primary", .type = XE_GT_TYPE_MAIN },

View File

@@ -1217,7 +1217,7 @@ static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
*
* /sys/bus/pci/devices/<device>/survivability_mode
*
* - Admin/userpsace consumer can use firmware flashing tools like fwupd to flash
* - Admin/userspace consumer can use firmware flashing tools like fwupd to flash
* firmware and restore device to normal operation.
*/

View File

@@ -222,7 +222,7 @@ struct xe_tile {
};
/**
* struct xe_device - Top level struct of XE device
* struct xe_device - Top level struct of Xe device
*/
struct xe_device {
/** @drm: drm device */
@@ -245,9 +245,9 @@ struct xe_device {
u32 media_verx100;
/** @info.mem_region_mask: mask of valid memory regions */
u32 mem_region_mask;
/** @info.platform: XE platform enum */
/** @info.platform: Xe platform enum */
enum xe_platform platform;
/** @info.subplatform: XE subplatform enum */
/** @info.subplatform: Xe subplatform enum */
enum xe_subplatform subplatform;
/** @info.devid: device ID */
u16 devid;
@@ -300,6 +300,8 @@ struct xe_device {
* pcode mailbox commands.
*/
u8 has_mbx_power_limits:1;
/** @info.has_mem_copy_instr: Device supports MEM_COPY instruction */
u8 has_mem_copy_instr:1;
/** @info.has_pxp: Device has PXP support */
u8 has_pxp:1;
/** @info.has_range_tlb_inval: Has range based TLB invalidations */
@@ -659,7 +661,7 @@ struct xe_device {
};
/**
* struct xe_file - file handle for XE driver
* struct xe_file - file handle for Xe driver
*/
struct xe_file {
/** @xe: xe DEVICE **/

View File

@@ -33,7 +33,7 @@
* - Binding at exec time
* - Flow controlling the ring at exec time
*
* In XE we avoid all of this complication by not allowing a BO list to be
* In Xe we avoid all of this complication by not allowing a BO list to be
* passed into an exec, using the dma-buf implicit sync uAPI, have binds as
* separate operations, and using the DRM scheduler to flow control the ring.
* Let's deep dive on each of these.

View File

@@ -52,7 +52,7 @@ enum xe_force_wake_domains {
};
/**
* struct xe_force_wake_domain - XE force wake domains
* struct xe_force_wake_domain - Xe force wake domains
*/
struct xe_force_wake_domain {
/** @id: domain force wake id */
@@ -70,7 +70,7 @@ struct xe_force_wake_domain {
};
/**
* struct xe_force_wake - XE force wake
* struct xe_force_wake - Xe force wake
*/
struct xe_force_wake {
/** @gt: back pointers to GT */

View File

@@ -312,6 +312,9 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
ggtt->pt_ops = &xelp_pt_ops;
ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM);
if (!ggtt->wq)
return -ENOMEM;
__xe_ggtt_init_early(ggtt, xe_wopcm_size(xe));
err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt);

View File

@@ -818,17 +818,19 @@ static int gt_reset(struct xe_gt *gt)
unsigned int fw_ref;
int err;
if (xe_device_wedged(gt_to_xe(gt)))
return -ECANCELED;
if (xe_device_wedged(gt_to_xe(gt))) {
err = -ECANCELED;
goto err_pm_put;
}
/* We only support GT resets with GuC submission */
if (!xe_device_uc_enabled(gt_to_xe(gt)))
return -ENODEV;
if (!xe_device_uc_enabled(gt_to_xe(gt))) {
err = -ENODEV;
goto err_pm_put;
}
xe_gt_info(gt, "reset started\n");
xe_pm_runtime_get(gt_to_xe(gt));
if (xe_fault_inject_gt_reset()) {
err = -ECANCELED;
goto err_fail;
@@ -875,6 +877,7 @@ err_fail:
xe_gt_err(gt, "reset failed (%pe)\n", ERR_PTR(err));
xe_device_declare_wedged(gt_to_xe(gt));
err_pm_put:
xe_pm_runtime_put(gt_to_xe(gt));
return err;
@@ -896,7 +899,9 @@ void xe_gt_reset_async(struct xe_gt *gt)
return;
xe_gt_info(gt, "reset queued\n");
queue_work(gt->ordered_wq, &gt->reset.worker);
xe_pm_runtime_get_noresume(gt_to_xe(gt));
if (!queue_work(gt->ordered_wq, &gt->reset.worker))
xe_pm_runtime_put(gt_to_xe(gt));
}
void xe_gt_suspend_prepare(struct xe_gt *gt)

View File

@@ -36,7 +36,7 @@
* - act_freq: The actual resolved frequency decided by PCODE.
* - cur_freq: The current one requested by GuC PC to the PCODE.
* - rpn_freq: The Render Performance (RP) N level, which is the minimal one.
* - rpa_freq: The Render Performance (RP) A level, which is the achiveable one.
* - rpa_freq: The Render Performance (RP) A level, which is the achievable one.
* Calculated by PCODE at runtime based on multiple running conditions
* - rpe_freq: The Render Performance (RP) E level, which is the efficient one.
* Calculated by PCODE at runtime based on multiple running conditions

View File

@@ -268,13 +268,14 @@ static const struct xe_mmio_range xe3p_xpc_gam_grp1_steering_table[] = {
{},
};
static const struct xe_mmio_range xe3p_xpc_psmi_grp19_steering_table[] = {
{ 0x00B500, 0x00B5FF },
static const struct xe_mmio_range xe3p_xpc_node_steering_table[] = {
{ 0x00B000, 0x00B0FF },
{ 0x00D880, 0x00D8FF },
{},
};
static const struct xe_mmio_range xe3p_xpc_instance0_steering_table[] = {
{ 0x00B600, 0x00B6FF }, /* PSMI0 */
{ 0x00B500, 0x00B6FF }, /* PSMI */
{ 0x00C800, 0x00CFFF }, /* GAMCTRL */
{ 0x00F000, 0x00F0FF }, /* GAMCTRL */
{},
@@ -282,9 +283,22 @@ static const struct xe_mmio_range xe3p_xpc_instance0_steering_table[] = {
static void init_steering_l3bank(struct xe_gt *gt)
{
struct xe_device *xe = gt_to_xe(gt);
struct xe_mmio *mmio = &gt->mmio;
if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) {
if (GRAPHICS_VER(xe) >= 35) {
unsigned int first_bank = xe_l3_bank_mask_ffs(gt->fuse_topo.l3_bank_mask);
const int banks_per_node = 4;
unsigned int node = first_bank / banks_per_node;
/* L3BANK ranges place node in grpID, bank in instanceid */
gt->steering[L3BANK].group_target = node;
gt->steering[L3BANK].instance_target = first_bank % banks_per_node;
/* NODE ranges split the node across grpid and instanceid */
gt->steering[NODE].group_target = node >> 1;
gt->steering[NODE].instance_target = node & 1;
} else if (GRAPHICS_VERx100(xe) >= 1270) {
u32 mslice_mask = REG_FIELD_GET(MEML3_EN_MASK,
xe_mmio_read32(mmio, MIRROR_FUSE3));
u32 bank_mask = REG_FIELD_GET(GT_L3_EXC_MASK,
@@ -297,7 +311,7 @@ static void init_steering_l3bank(struct xe_gt *gt)
gt->steering[L3BANK].group_target = __ffs(mslice_mask);
gt->steering[L3BANK].instance_target =
bank_mask & BIT(0) ? 0 : 2;
} else if (gt_to_xe(gt)->info.platform == XE_DG2) {
} else if (xe->info.platform == XE_DG2) {
u32 mslice_mask = REG_FIELD_GET(MEML3_EN_MASK,
xe_mmio_read32(mmio, MIRROR_FUSE3));
u32 bank = __ffs(mslice_mask) * 8;
@@ -452,12 +466,6 @@ static void init_steering_sqidi_psmi(struct xe_gt *gt)
gt->steering[SQIDI_PSMI].instance_target = select & 0x1;
}
static void init_steering_psmi(struct xe_gt *gt)
{
gt->steering[PSMI19].group_target = 19;
gt->steering[PSMI19].instance_target = 0;
}
static void init_steering_gam1(struct xe_gt *gt)
{
gt->steering[GAM1].group_target = 1;
@@ -469,12 +477,12 @@ static const struct {
void (*init)(struct xe_gt *gt);
} xe_steering_types[] = {
[L3BANK] = { "L3BANK", init_steering_l3bank },
[NODE] = { "NODE", NULL }, /* initialized by l3bank init */
[MSLICE] = { "MSLICE", init_steering_mslice },
[LNCF] = { "LNCF", NULL }, /* initialized by mslice init */
[DSS] = { "DSS / XeCore", init_steering_dss },
[OADDRM] = { "OADDRM / GPMXMT", init_steering_oaddrm },
[SQIDI_PSMI] = { "SQIDI_PSMI", init_steering_sqidi_psmi },
[PSMI19] = { "PSMI[19]", init_steering_psmi },
[GAM1] = { "GAMWKRS / STLB / GAMREQSTRM", init_steering_gam1 },
[INSTANCE0] = { "INSTANCE 0", NULL },
[IMPLICIT_STEERING] = { "IMPLICIT", NULL },
@@ -524,7 +532,8 @@ void xe_gt_mcr_init_early(struct xe_gt *gt)
gt->steering[DSS].ranges = xe3p_xpc_xecore_steering_table;
gt->steering[GAM1].ranges = xe3p_xpc_gam_grp1_steering_table;
gt->steering[INSTANCE0].ranges = xe3p_xpc_instance0_steering_table;
gt->steering[PSMI19].ranges = xe3p_xpc_psmi_grp19_steering_table;
gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table;
gt->steering[NODE].ranges = xe3p_xpc_node_steering_table;
} else if (GRAPHICS_VER(xe) >= 20) {
gt->steering[DSS].ranges = xe2lpg_dss_steering_table;
gt->steering[SQIDI_PSMI].ranges = xe2lpg_sqidi_psmi_steering_table;

View File

@@ -158,39 +158,19 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt)
xe_gt_sriov_pf_service_update(gt);
}
static u32 pf_get_vf_regs_stride(struct xe_device *xe)
{
return GRAPHICS_VERx100(xe) > 1200 ? 0x400 : 0x1000;
}
static struct xe_reg xe_reg_vf_to_pf(struct xe_reg vf_reg, unsigned int vfid, u32 stride)
{
struct xe_reg pf_reg = vf_reg;
pf_reg.vf = 0;
pf_reg.addr += stride * vfid;
return pf_reg;
}
static void pf_clear_vf_scratch_regs(struct xe_gt *gt, unsigned int vfid)
{
u32 stride = pf_get_vf_regs_stride(gt_to_xe(gt));
struct xe_reg scratch;
int n, count;
struct xe_mmio mmio;
int n;
xe_mmio_init_vf_view(&mmio, &gt->mmio, vfid);
if (xe_gt_is_media_type(gt)) {
count = MED_VF_SW_FLAG_COUNT;
for (n = 0; n < count; n++) {
scratch = xe_reg_vf_to_pf(MED_VF_SW_FLAG(n), vfid, stride);
xe_mmio_write32(&gt->mmio, scratch, 0);
}
for (n = 0; n < MED_VF_SW_FLAG_COUNT; n++)
xe_mmio_write32(&mmio, MED_VF_SW_FLAG(n), 0);
} else {
count = VF_SW_FLAG_COUNT;
for (n = 0; n < count; n++) {
scratch = xe_reg_vf_to_pf(VF_SW_FLAG(n), vfid, stride);
xe_mmio_write32(&gt->mmio, scratch, 0);
}
for (n = 0; n < VF_SW_FLAG_COUNT; n++)
xe_mmio_write32(&mmio, VF_SW_FLAG(n), 0);
}
}

View File

@@ -997,6 +997,8 @@ static void pf_exit_vf_flr_wip(struct xe_gt *gt, unsigned int vfid)
pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_GUC_DONE);
pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_WAIT_GUC);
pf_escape_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SEND_START);
xe_sriov_pf_control_sync_flr(gt_to_xe(gt), vfid);
}
}

View File

@@ -31,7 +31,6 @@
#include "xe_lrc.h"
#include "xe_memirq.h"
#include "xe_mmio.h"
#include "xe_pm.h"
#include "xe_sriov.h"
#include "xe_sriov_vf.h"
#include "xe_sriov_vf_ccs.h"
@@ -739,7 +738,7 @@ static void vf_start_migration_recovery(struct xe_gt *gt)
gt->sriov.vf.migration.recovery_queued = true;
WRITE_ONCE(gt->sriov.vf.migration.recovery_inprogress, true);
WRITE_ONCE(gt->sriov.vf.migration.ggtt_need_fixes, true);
smp_wmb(); /* Ensure above writes visable before wake */
smp_wmb(); /* Ensure above writes visible before wake */
xe_guc_ct_wake_waiters(&gt->uc.guc.ct);
@@ -1218,7 +1217,6 @@ static void vf_post_migration_recovery(struct xe_gt *gt)
xe_gt_sriov_dbg(gt, "migration recovery in progress\n");
xe_pm_runtime_get(xe);
retry = vf_post_migration_shutdown(gt);
if (retry)
goto queue;
@@ -1241,12 +1239,10 @@ static void vf_post_migration_recovery(struct xe_gt *gt)
vf_post_migration_kickstart(gt);
xe_pm_runtime_put(xe);
xe_gt_sriov_notice(gt, "migration recovery ended\n");
return;
fail:
vf_post_migration_abort(gt);
xe_pm_runtime_put(xe);
xe_gt_sriov_err(gt, "migration recovery failed (%pe)\n", ERR_PTR(err));
xe_device_declare_wedged(xe);
return;
@@ -1254,7 +1250,6 @@ fail:
queue:
xe_gt_sriov_info(gt, "Re-queuing migration recovery\n");
queue_work(gt->ordered_wq, &gt->sriov.vf.migration.worker);
xe_pm_runtime_put(xe);
}
static void migration_worker_func(struct work_struct *w)

View File

@@ -309,6 +309,13 @@ xe_dss_mask_group_ffs(const xe_dss_mask_t mask, int groupsize, int groupnum)
return find_next_bit(mask, XE_MAX_DSS_FUSE_BITS, groupnum * groupsize);
}
/* Used to obtain the index of the first L3 bank. */
unsigned int
xe_l3_bank_mask_ffs(const xe_l3_bank_mask_t mask)
{
return find_first_bit(mask, XE_MAX_L3_BANK_MASK_BITS);
}
/**
* xe_gt_topology_has_dss_in_quadrant - check fusing of DSS in GT quadrant
* @gt: GT to check

View File

@@ -40,6 +40,8 @@ xe_gt_topology_mask_last_dss(const xe_dss_mask_t mask)
unsigned int
xe_dss_mask_group_ffs(const xe_dss_mask_t mask, int groupsize, int groupnum);
unsigned int
xe_l3_bank_mask_ffs(const xe_l3_bank_mask_t mask);
bool
xe_gt_topology_has_dss_in_quadrant(struct xe_gt *gt, int quad);

View File

@@ -66,20 +66,13 @@ struct xe_mmio_range {
*/
enum xe_steering_type {
L3BANK,
NODE,
MSLICE,
LNCF,
DSS,
OADDRM,
SQIDI_PSMI,
/*
* The bspec lists multiple ranges as "PSMI," but the different
* ranges with that label have different grpid steering values so we
* treat them independently in code. Note that the ranges with grpid=0
* are included in the INSTANCE0 group above.
*/
PSMI19,
/*
* Although most GAM ranges must be steered to (0,0) and thus use the
* INSTANCE0 type farther down, some platforms have special rules

View File

@@ -91,6 +91,9 @@ static u32 guc_ctl_feature_flags(struct xe_guc *guc)
if (xe_configfs_get_psmi_enabled(to_pci_dev(xe->drm.dev)))
flags |= GUC_CTL_ENABLE_PSMI_LOGGING;
if (xe_guc_using_main_gamctrl_queues(guc))
flags |= GUC_CTL_MAIN_GAMCTRL_QUEUES;
return flags;
}
@@ -1255,8 +1258,13 @@ int xe_guc_min_load_for_hwconfig(struct xe_guc *guc)
int xe_guc_upload(struct xe_guc *guc)
{
struct xe_gt *gt = guc_to_gt(guc);
xe_guc_ads_populate(&guc->ads);
if (xe_guc_using_main_gamctrl_queues(guc))
xe_mmio_write32(&gt->mmio, MAIN_GAMCTRL_MODE, MAIN_GAMCTRL_QUEUE_SELECT);
return __xe_guc_upload(guc);
}
@@ -1657,6 +1665,44 @@ void xe_guc_declare_wedged(struct xe_guc *guc)
xe_guc_submit_wedge(guc);
}
/**
* xe_guc_using_main_gamctrl_queues() - Detect which reporting queues to use.
* @guc: The GuC object
*
* For Xe3p and beyond, we want to program the hardware to use the
* "Main GAMCTRL queue" rather than the legacy queue before we upload
* the GuC firmware. This will allow the GuC to use a new set of
* registers for pagefault handling and avoid some unnecessary
* complications with MCR register range handling.
*
* Return: true if can use new main gamctrl queues.
*/
bool xe_guc_using_main_gamctrl_queues(struct xe_guc *guc)
{
struct xe_gt *gt = guc_to_gt(guc);
/*
* For Xe3p media gt (35), the GuC and the CS subunits may be still Xe3
* that lacks the Main GAMCTRL support. Reserved bits from the GMD_ID
* inform the IP version of the subunits.
*/
if (xe_gt_is_media_type(gt) && MEDIA_VER(gt_to_xe(gt)) == 35) {
u32 val = xe_mmio_read32(&gt->mmio, GMD_ID);
u32 subip = REG_FIELD_GET(GMD_ID_SUBIP_FLAG_MASK, val);
if (!subip)
return true;
xe_gt_WARN(gt, subip != 1,
"GMD_ID has unknown value in the SUBIP_FLAG field - 0x%x\n",
subip);
return false;
}
return GT_VER(gt) >= 35;
}
#if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
#include "tests/xe_guc_g2g_test.c"
#endif

View File

@@ -52,6 +52,7 @@ void xe_guc_stop_prepare(struct xe_guc *guc);
void xe_guc_stop(struct xe_guc *guc);
int xe_guc_start(struct xe_guc *guc);
void xe_guc_declare_wedged(struct xe_guc *guc);
bool xe_guc_using_main_gamctrl_queues(struct xe_guc *guc);
#if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
int xe_guc_g2g_test_notification(struct xe_guc *guc, u32 *payload, u32 len);

View File

@@ -820,16 +820,20 @@ static void guc_mmio_reg_state_init(struct xe_guc_ads *ads)
static void guc_um_init_params(struct xe_guc_ads *ads)
{
u32 um_queue_offset = guc_ads_um_queues_offset(ads);
struct xe_guc *guc = ads_to_guc(ads);
u64 base_dpa;
u32 base_ggtt;
bool with_dpa;
int i;
with_dpa = !xe_guc_using_main_gamctrl_queues(guc);
base_ggtt = xe_bo_ggtt_addr(ads->bo) + um_queue_offset;
base_dpa = xe_bo_main_addr(ads->bo, PAGE_SIZE) + um_queue_offset;
for (i = 0; i < GUC_UM_HW_QUEUE_MAX; ++i) {
ads_blob_write(ads, um_init_params.queue_params[i].base_dpa,
base_dpa + (i * GUC_UM_QUEUE_SIZE));
with_dpa ? (base_dpa + (i * GUC_UM_QUEUE_SIZE)) : 0);
ads_blob_write(ads, um_init_params.queue_params[i].base_ggtt_address,
base_ggtt + (i * GUC_UM_QUEUE_SIZE));
ads_blob_write(ads, um_init_params.queue_params[i].size_in_bytes,

View File

@@ -14,7 +14,7 @@ struct xe_bo;
* struct xe_guc_ads - GuC additional data structures (ADS)
*/
struct xe_guc_ads {
/** @bo: XE BO for GuC ads blob */
/** @bo: Xe BO for GuC ads blob */
struct xe_bo *bo;
/** @golden_lrc_size: golden LRC size */
size_t golden_lrc_size;

View File

@@ -126,7 +126,7 @@ struct xe_fast_req_fence {
* for the H2G and G2H requests sent and received through the buffers.
*/
struct xe_guc_ct {
/** @bo: XE BO for CT */
/** @bo: Xe BO for CT */
struct xe_bo *bo;
/** @lock: protects everything in CT layer */
struct mutex lock;

View File

@@ -113,6 +113,7 @@ struct guc_update_exec_queue_policy {
#define GUC_CTL_ENABLE_SLPC BIT(2)
#define GUC_CTL_ENABLE_LITE_RESTORE BIT(4)
#define GUC_CTL_ENABLE_PSMI_LOGGING BIT(7)
#define GUC_CTL_MAIN_GAMCTRL_QUEUES BIT(9)
#define GUC_CTL_DISABLE_SCHEDULER BIT(14)
#define GUC_CTL_DEBUG 3

View File

@@ -44,7 +44,7 @@ struct xe_guc_log_snapshot {
struct xe_guc_log {
/** @level: GuC log level */
u32 level;
/** @bo: XE BO for GuC log */
/** @bo: Xe BO for GuC log */
struct xe_bo *bo;
/** @stats: logging related stats */
struct {

View File

@@ -1920,7 +1920,7 @@ static bool guc_exec_queue_reset_status(struct xe_exec_queue *q)
}
/*
* All of these functions are an abstraction layer which other parts of XE can
* All of these functions are an abstraction layer which other parts of Xe can
* use to trap into the GuC backend. All of these functions, aside from init,
* really shouldn't do much other than trap into the DRM scheduler which
* synchronizes these operations.

View File

@@ -207,7 +207,7 @@ static const struct xe_tlb_inval_ops guc_tlb_inval_ops = {
* @guc: GuC object
* @tlb_inval: TLB invalidation client
*
* Inititialize GuC TLB invalidation by setting back pointer in TLB invalidation
* Initialize GuC TLB invalidation by setting back pointer in TLB invalidation
* client to the GuC and setting GuC backend ops.
*/
void xe_guc_tlb_inval_init_early(struct xe_guc *guc,

View File

@@ -14,9 +14,9 @@
* DOC: Map layer
*
* All access to any memory shared with a device (both sysmem and vram) in the
* XE driver should go through this layer (xe_map). This layer is built on top
* Xe driver should go through this layer (xe_map). This layer is built on top
* of :ref:`driver-api/device-io:Generalizing Access to System and I/O Memory`
* and with extra hooks into the XE driver that allows adding asserts to memory
* and with extra hooks into the Xe driver that allows adding asserts to memory
* accesses (e.g. for blocking runtime_pm D3Cold on Discrete Graphics).
*/

View File

@@ -699,9 +699,9 @@ static void emit_copy_ccs(struct xe_gt *gt, struct xe_bb *bb,
}
#define EMIT_COPY_DW 10
static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
u64 src_ofs, u64 dst_ofs, unsigned int size,
unsigned int pitch)
static void emit_xy_fast_copy(struct xe_gt *gt, struct xe_bb *bb, u64 src_ofs,
u64 dst_ofs, unsigned int size,
unsigned int pitch)
{
struct xe_device *xe = gt_to_xe(gt);
u32 mocs = 0;
@@ -730,6 +730,61 @@ static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
bb->cs[bb->len++] = upper_32_bits(src_ofs);
}
#define PAGE_COPY_MODE_PS SZ_256 /* hw uses 256 bytes as the page-size */
static void emit_mem_copy(struct xe_gt *gt, struct xe_bb *bb, u64 src_ofs,
u64 dst_ofs, unsigned int size, unsigned int pitch)
{
u32 mode, copy_type, width;
xe_gt_assert(gt, IS_ALIGNED(size, pitch));
xe_gt_assert(gt, pitch <= U16_MAX);
xe_gt_assert(gt, pitch);
xe_gt_assert(gt, size);
if (IS_ALIGNED(size, PAGE_COPY_MODE_PS) &&
IS_ALIGNED(lower_32_bits(src_ofs), PAGE_COPY_MODE_PS) &&
IS_ALIGNED(lower_32_bits(dst_ofs), PAGE_COPY_MODE_PS)) {
mode = MEM_COPY_PAGE_COPY_MODE;
copy_type = 0; /* linear copy */
width = size / PAGE_COPY_MODE_PS;
} else if (pitch > 1) {
xe_gt_assert(gt, size / pitch <= U16_MAX);
mode = 0; /* BYTE_COPY */
copy_type = MEM_COPY_MATRIX_COPY;
width = pitch;
} else {
mode = 0; /* BYTE_COPY */
copy_type = 0; /* linear copy */
width = size;
}
xe_gt_assert(gt, width <= U16_MAX);
bb->cs[bb->len++] = MEM_COPY_CMD | mode | copy_type;
bb->cs[bb->len++] = width - 1;
bb->cs[bb->len++] = size / pitch - 1; /* ignored by hw for page-copy/linear above */
bb->cs[bb->len++] = pitch - 1;
bb->cs[bb->len++] = pitch - 1;
bb->cs[bb->len++] = lower_32_bits(src_ofs);
bb->cs[bb->len++] = upper_32_bits(src_ofs);
bb->cs[bb->len++] = lower_32_bits(dst_ofs);
bb->cs[bb->len++] = upper_32_bits(dst_ofs);
bb->cs[bb->len++] = FIELD_PREP(MEM_COPY_SRC_MOCS_INDEX_MASK, gt->mocs.uc_index) |
FIELD_PREP(MEM_COPY_DST_MOCS_INDEX_MASK, gt->mocs.uc_index);
}
static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
u64 src_ofs, u64 dst_ofs, unsigned int size,
unsigned int pitch)
{
struct xe_device *xe = gt_to_xe(gt);
if (xe->info.has_mem_copy_instr)
emit_mem_copy(gt, bb, src_ofs, dst_ofs, size, pitch);
else
emit_xy_fast_copy(gt, bb, src_ofs, dst_ofs, size, pitch);
}
static u64 xe_migrate_batch_base(struct xe_migrate *m, bool usm)
{
return usm ? m->usm_batch_base_ofs : m->batch_base_ofs;
@@ -847,7 +902,7 @@ struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
&ccs_it);
while (size) {
u32 batch_size = 2; /* arb_clear() + MI_BATCH_BUFFER_END */
u32 batch_size = 1; /* MI_BATCH_BUFFER_END */
struct xe_sched_job *job;
struct xe_bb *bb;
u32 flush_flags = 0;
@@ -1312,7 +1367,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
/* Calculate final sizes and batch size.. */
pte_flags = clear_vram ? PTE_UPDATE_FLAG_IS_VRAM : 0;
batch_size = 2 +
batch_size = 1 +
pte_update_size(m, pte_flags, src, &src_it,
&clear_L0, &clear_L0_ofs, &clear_L0_pt,
clear_bo_data ? emit_clear_cmd_len(gt) : 0, 0,
@@ -1798,11 +1853,15 @@ static void build_pt_update_batch_sram(struct xe_migrate *m,
u32 ptes;
int i = 0;
xe_tile_assert(m->tile, PAGE_ALIGNED(size));
ptes = DIV_ROUND_UP(size, gpu_page_size);
while (ptes) {
u32 chunk = min(MAX_PTE_PER_SDI, ptes);
chunk = ALIGN_DOWN(chunk, PAGE_SIZE / XE_PAGE_SIZE);
if (!level)
chunk = ALIGN_DOWN(chunk, PAGE_SIZE / XE_PAGE_SIZE);
bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk);
bb->cs[bb->len++] = pt_offset;
bb->cs[bb->len++] = 0;
@@ -1811,12 +1870,13 @@ static void build_pt_update_batch_sram(struct xe_migrate *m,
ptes -= chunk;
while (chunk--) {
u64 addr = sram_addr[i].addr & ~(gpu_page_size - 1);
u64 pte, orig_addr = addr;
u64 addr = sram_addr[i].addr;
u64 pte;
xe_tile_assert(m->tile, sram_addr[i].proto ==
DRM_INTERCONNECT_SYSTEM);
xe_tile_assert(m->tile, addr);
xe_tile_assert(m->tile, PAGE_ALIGNED(addr));
again:
pte = m->q->vm->pt_ops->pte_encode_addr(m->tile->xe,
@@ -1827,7 +1887,7 @@ again:
if (gpu_page_size < PAGE_SIZE) {
addr += XE_PAGE_SIZE;
if (orig_addr + PAGE_SIZE != addr) {
if (!PAGE_ALIGNED(addr)) {
chunk--;
goto again;
}
@@ -1860,6 +1920,25 @@ enum xe_migrate_copy_dir {
#define XE_CACHELINE_BYTES 64ull
#define XE_CACHELINE_MASK (XE_CACHELINE_BYTES - 1)
static u32 xe_migrate_copy_pitch(struct xe_device *xe, u32 len)
{
u32 pitch;
if (IS_ALIGNED(len, PAGE_SIZE))
pitch = PAGE_SIZE;
else if (IS_ALIGNED(len, SZ_4K))
pitch = SZ_4K;
else if (IS_ALIGNED(len, SZ_256))
pitch = SZ_256;
else if (IS_ALIGNED(len, 4))
pitch = 4;
else
pitch = 1;
xe_assert(xe, pitch > 1 || xe->info.has_mem_copy_instr);
return pitch;
}
static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
unsigned long len,
unsigned long sram_offset,
@@ -1871,25 +1950,25 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
struct xe_device *xe = gt_to_xe(gt);
bool use_usm_batch = xe->info.has_usm;
struct dma_fence *fence = NULL;
u32 batch_size = 2;
u32 batch_size = 1;
u64 src_L0_ofs, dst_L0_ofs;
struct xe_sched_job *job;
struct xe_bb *bb;
u32 update_idx, pt_slot = 0;
unsigned long npages = DIV_ROUND_UP(len + sram_offset, PAGE_SIZE);
unsigned int pitch = len >= PAGE_SIZE && !(len & ~PAGE_MASK) ?
PAGE_SIZE : 4;
unsigned int pitch = xe_migrate_copy_pitch(xe, len);
int err;
unsigned long i, j;
bool use_pde = xe_migrate_vram_use_pde(sram_addr, len + sram_offset);
if (drm_WARN_ON(&xe->drm, (len & XE_CACHELINE_MASK) ||
(sram_offset | vram_addr) & XE_CACHELINE_MASK))
if (!xe->info.has_mem_copy_instr &&
drm_WARN_ON(&xe->drm,
(!IS_ALIGNED(len, pitch)) || (sram_offset | vram_addr) & XE_CACHELINE_MASK))
return ERR_PTR(-EOPNOTSUPP);
xe_assert(xe, npages * PAGE_SIZE <= MAX_PREEMPTDISABLE_TRANSFER);
batch_size += pte_update_cmd_size(len);
batch_size += pte_update_cmd_size(npages << PAGE_SHIFT);
batch_size += EMIT_COPY_DW;
bb = xe_bb_new(gt, batch_size, use_usm_batch);
@@ -1918,10 +1997,10 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
if (use_pde)
build_pt_update_batch_sram(m, bb, m->large_page_copy_pdes,
sram_addr, len + sram_offset, 1);
sram_addr, npages << PAGE_SHIFT, 1);
else
build_pt_update_batch_sram(m, bb, pt_slot * XE_PAGE_SIZE,
sram_addr, len + sram_offset, 0);
sram_addr, npages << PAGE_SHIFT, 0);
if (dir == XE_MIGRATE_COPY_TO_VRAM) {
if (use_pde)
@@ -1981,7 +2060,7 @@ err:
*
* Copy from an array dma addresses to a VRAM device physical address
*
* Return: dma fence for migrate to signal completion on succees, ERR_PTR on
* Return: dma fence for migrate to signal completion on success, ERR_PTR on
* failure
*/
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
@@ -2002,7 +2081,7 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
*
* Copy from a VRAM device physical address to an array dma addresses
*
* Return: dma fence for migrate to signal completion on succees, ERR_PTR on
* Return: dma fence for migrate to signal completion on success, ERR_PTR on
* failure
*/
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
@@ -2103,8 +2182,10 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
xe_bo_assert_held(bo);
/* Use bounce buffer for small access and unaligned access */
if (!IS_ALIGNED(len, XE_CACHELINE_BYTES) ||
!IS_ALIGNED((unsigned long)buf + offset, XE_CACHELINE_BYTES)) {
if (!xe->info.has_mem_copy_instr &&
(!IS_ALIGNED(len, 4) ||
!IS_ALIGNED(page_offset, XE_CACHELINE_BYTES) ||
!IS_ALIGNED(offset, XE_CACHELINE_BYTES))) {
int buf_offset = 0;
void *bounce;
int err;
@@ -2166,6 +2247,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
u64 vram_addr = vram_region_gpu_offset(bo->ttm.resource) +
cursor.start;
int current_bytes;
u32 pitch;
if (cursor.size > MAX_PREEMPTDISABLE_TRANSFER)
current_bytes = min_t(int, bytes_left,
@@ -2173,13 +2255,13 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
else
current_bytes = min_t(int, bytes_left, cursor.size);
if (current_bytes & ~PAGE_MASK) {
int pitch = 4;
pitch = xe_migrate_copy_pitch(xe, current_bytes);
if (xe->info.has_mem_copy_instr)
current_bytes = min_t(int, current_bytes, U16_MAX * pitch);
else
current_bytes = min_t(int, current_bytes,
round_down(S16_MAX * pitch,
XE_CACHELINE_BYTES));
}
__fence = xe_migrate_vram(m, current_bytes,
(unsigned long)buf & ~PAGE_MASK,

View File

@@ -9,7 +9,7 @@
/**
* DOC: Migrate Layer
*
* The XE migrate layer is used generate jobs which can copy memory (eviction),
* The Xe migrate layer is used generate jobs which can copy memory (eviction),
* clear memory, or program tables (binds). This layer exists in every GT, has
* a migrate engine, and uses a special VM for all generated jobs.
*

View File

@@ -379,3 +379,32 @@ int xe_mmio_wait32_not(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 va
{
return __xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, false);
}
#ifdef CONFIG_PCI_IOV
static size_t vf_regs_stride(struct xe_device *xe)
{
return GRAPHICS_VERx100(xe) > 1200 ? 0x400 : 0x1000;
}
/**
* xe_mmio_init_vf_view() - Initialize an MMIO instance for accesses like the VF
* @mmio: the target &xe_mmio to initialize as VF's view
* @base: the source &xe_mmio to initialize from
* @vfid: the VF identifier
*/
void xe_mmio_init_vf_view(struct xe_mmio *mmio, const struct xe_mmio *base, unsigned int vfid)
{
struct xe_tile *tile = base->tile;
struct xe_device *xe = tile->xe;
size_t offset = vf_regs_stride(xe) * vfid;
xe_assert(xe, IS_SRIOV_PF(xe));
xe_assert(xe, vfid);
xe_assert(xe, !base->sriov_vf_gt);
xe_assert(xe, base->regs_size > offset);
*mmio = *base;
mmio->regs += offset;
mmio->regs_size -= offset;
}
#endif

View File

@@ -42,4 +42,8 @@ static inline struct xe_mmio *xe_root_tile_mmio(struct xe_device *xe)
return &xe->tiles[0].mmio;
}
#ifdef CONFIG_PCI_IOV
void xe_mmio_init_vf_view(struct xe_mmio *mmio, const struct xe_mmio *base, unsigned int vfid);
#endif
#endif

View File

@@ -568,6 +568,23 @@ static const struct xe_mocs_ops xe2_mocs_ops = {
.dump = xe2_mocs_dump,
};
/*
* Note that the "L3" and "L4" register fields actually control the L2 and L3
* caches respectively on this platform.
*/
static const struct xe_mocs_entry xe3p_xpc_mocs_table[] = {
/* Defer to PAT */
MOCS_ENTRY(0, XE2_L3_0_WB | L4_3_UC, 0),
/* UC */
MOCS_ENTRY(1, IG_PAT | XE2_L3_3_UC | L4_3_UC, 0),
/* L2 */
MOCS_ENTRY(2, IG_PAT | XE2_L3_0_WB | L4_3_UC, 0),
/* L3 */
MOCS_ENTRY(3, IG_PAT | XE2_L3_3_UC | L4_0_WB, 0),
/* L2 + L3 */
MOCS_ENTRY(4, IG_PAT | XE2_L3_0_WB | L4_0_WB, 0),
};
static unsigned int get_mocs_settings(struct xe_device *xe,
struct xe_mocs_info *info)
{
@@ -576,6 +593,15 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
memset(info, 0, sizeof(struct xe_mocs_info));
switch (xe->info.platform) {
case XE_CRESCENTISLAND:
info->ops = &xe2_mocs_ops;
info->table_size = ARRAY_SIZE(xe3p_xpc_mocs_table);
info->table = xe3p_xpc_mocs_table;
info->num_mocs_regs = XE2_NUM_MOCS_ENTRIES;
info->uc_index = 1;
info->wb_index = 4;
info->unused_entries_index = 4;
break;
case XE_NOVALAKE_S:
case XE_PANTHERLAKE:
case XE_LUNARLAKE:

View File

@@ -342,6 +342,7 @@ static const struct xe_device_desc lnl_desc = {
.has_display = true,
.has_flat_ccs = 1,
.has_pxp = true,
.has_mem_copy_instr = true,
.max_gt_per_tile = 2,
.needs_scratch = true,
.va_bits = 48,
@@ -362,6 +363,7 @@ static const struct xe_device_desc bmg_desc = {
.has_heci_cscfi = 1,
.has_late_bind = true,
.has_sriov = true,
.has_mem_copy_instr = true,
.max_gt_per_tile = 2,
.needs_scratch = true,
.subplatforms = (const struct xe_subplatform_desc[]) {
@@ -378,6 +380,7 @@ static const struct xe_device_desc ptl_desc = {
.has_display = true,
.has_flat_ccs = 1,
.has_sriov = true,
.has_mem_copy_instr = true,
.max_gt_per_tile = 2,
.needs_scratch = true,
.needs_shared_vf_gt_wq = true,
@@ -390,12 +393,27 @@ static const struct xe_device_desc nvls_desc = {
.dma_mask_size = 46,
.has_display = true,
.has_flat_ccs = 1,
.has_mem_copy_instr = true,
.max_gt_per_tile = 2,
.require_force_probe = true,
.va_bits = 48,
.vm_max_level = 4,
};
static const struct xe_device_desc cri_desc = {
DGFX_FEATURES,
PLATFORM(CRESCENTISLAND),
.dma_mask_size = 52,
.has_display = false,
.has_flat_ccs = false,
.has_mbx_power_limits = true,
.has_sriov = true,
.max_gt_per_tile = 2,
.require_force_probe = true,
.va_bits = 57,
.vm_max_level = 4,
};
#undef PLATFORM
__diag_pop();
@@ -423,6 +441,7 @@ static const struct pci_device_id pciidlist[] = {
INTEL_BMG_IDS(INTEL_VGA_DEVICE, &bmg_desc),
INTEL_PTL_IDS(INTEL_VGA_DEVICE, &ptl_desc),
INTEL_NVLS_IDS(INTEL_VGA_DEVICE, &nvls_desc),
INTEL_CRI_IDS(INTEL_PCI_DEVICE, &cri_desc),
{ }
};
MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -655,6 +674,7 @@ static int xe_info_init_early(struct xe_device *xe,
xe->info.has_pxp = desc->has_pxp;
xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) &&
desc->has_sriov;
xe->info.has_mem_copy_instr = desc->has_mem_copy_instr;
xe->info.skip_guc_pc = desc->skip_guc_pc;
xe->info.skip_mtcfg = desc->skip_mtcfg;
xe->info.skip_pcode = desc->skip_pcode;

View File

@@ -46,6 +46,7 @@ struct xe_device_desc {
u8 has_late_bind:1;
u8 has_llc:1;
u8 has_mbx_power_limits:1;
u8 has_mem_copy_instr:1;
u8 has_pxp:1;
u8 has_sriov:1;
u8 needs_scratch:1;

View File

@@ -25,6 +25,7 @@ enum xe_platform {
XE_BATTLEMAGE,
XE_PANTHERLAKE,
XE_NOVALAKE_S,
XE_CRESCENTISLAND,
};
enum xe_subplatform {

View File

@@ -102,7 +102,7 @@ static void xe_pm_block_end_signalling(void)
/**
* xe_pm_might_block_on_suspend() - Annotate that the code might block on suspend
*
* Annotation to use where the code might block or sieze to make
* Annotation to use where the code might block or seize to make
* progress pending resume completion.
*/
void xe_pm_might_block_on_suspend(void)

View File

@@ -12,7 +12,7 @@
struct xe_exec_queue;
/**
* struct xe_preempt_fence - XE preempt fence
* struct xe_preempt_fence - Xe preempt fence
*
* hardware and triggers a callback once the xe_engine is complete.
*/

View File

@@ -715,7 +715,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
.vm = vm,
.tile = tile,
.curs = &curs,
.va_curs_start = range ? range->base.itree.start :
.va_curs_start = range ? xe_svm_range_start(range) :
xe_vma_start(vma),
.vma = vma,
.wupd.entries = entries,
@@ -734,7 +734,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
}
if (xe_svm_range_has_dma_mapping(range)) {
xe_res_first_dma(range->base.pages.dma_addr, 0,
range->base.itree.last + 1 - range->base.itree.start,
xe_svm_range_size(range),
&curs);
xe_svm_range_debug(range, "BIND PREPARE - MIXED");
} else {
@@ -778,8 +778,8 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
walk_pt:
ret = xe_pt_walk_range(&pt->base, pt->level,
range ? range->base.itree.start : xe_vma_start(vma),
range ? range->base.itree.last + 1 : xe_vma_end(vma),
range ? xe_svm_range_start(range) : xe_vma_start(vma),
range ? xe_svm_range_end(range) : xe_vma_end(vma),
&xe_walk.base);
*num_entries = xe_walk.wupd.num_used_entries;
@@ -975,8 +975,8 @@ bool xe_pt_zap_ptes_range(struct xe_tile *tile, struct xe_vm *vm,
if (!(pt_mask & BIT(tile->id)))
return false;
(void)xe_pt_walk_shared(&pt->base, pt->level, range->base.itree.start,
range->base.itree.last + 1, &xe_walk.base);
(void)xe_pt_walk_shared(&pt->base, pt->level, xe_svm_range_start(range),
xe_svm_range_end(range), &xe_walk.base);
return xe_walk.needs_invalidate;
}
@@ -1661,8 +1661,8 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
struct xe_svm_range *range,
struct xe_vm_pgtable_update *entries)
{
u64 start = range ? range->base.itree.start : xe_vma_start(vma);
u64 end = range ? range->base.itree.last + 1 : xe_vma_end(vma);
u64 start = range ? xe_svm_range_start(range) : xe_vma_start(vma);
u64 end = range ? xe_svm_range_end(range) : xe_vma_end(vma);
struct xe_pt_stage_unbind_walk xe_walk = {
.base = {
.ops = &xe_pt_stage_unbind_ops,
@@ -1872,7 +1872,7 @@ static int bind_range_prepare(struct xe_vm *vm, struct xe_tile *tile,
vm_dbg(&xe_vma_vm(vma)->xe->drm,
"Preparing bind, with range [%lx...%lx)\n",
range->base.itree.start, range->base.itree.last);
xe_svm_range_start(range), xe_svm_range_end(range) - 1);
pt_op->vma = NULL;
pt_op->bind = true;
@@ -1887,8 +1887,8 @@ static int bind_range_prepare(struct xe_vm *vm, struct xe_tile *tile,
pt_op->num_entries, true);
xe_pt_update_ops_rfence_interval(pt_update_ops,
range->base.itree.start,
range->base.itree.last + 1);
xe_svm_range_start(range),
xe_svm_range_end(range));
++pt_update_ops->current_op;
pt_update_ops->needs_svm_lock = true;
@@ -1983,7 +1983,7 @@ static int unbind_range_prepare(struct xe_vm *vm,
vm_dbg(&vm->xe->drm,
"Preparing unbind, with range [%lx...%lx)\n",
range->base.itree.start, range->base.itree.last);
xe_svm_range_start(range), xe_svm_range_end(range) - 1);
pt_op->vma = XE_INVALID_VMA;
pt_op->bind = false;
@@ -1994,8 +1994,8 @@ static int unbind_range_prepare(struct xe_vm *vm,
xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
pt_op->num_entries, false);
xe_pt_update_ops_rfence_interval(pt_update_ops, range->base.itree.start,
range->base.itree.last + 1);
xe_pt_update_ops_rfence_interval(pt_update_ops, xe_svm_range_start(range),
xe_svm_range_end(range));
++pt_update_ops->current_op;
pt_update_ops->needs_svm_lock = true;
pt_update_ops->needs_invalidation |= xe_vm_has_scratch(vm) ||

View File

@@ -13,13 +13,13 @@
struct xe_range_fence_tree;
struct xe_range_fence;
/** struct xe_range_fence_ops - XE range fence ops */
/** struct xe_range_fence_ops - Xe range fence ops */
struct xe_range_fence_ops {
/** @free: free range fence op */
void (*free)(struct xe_range_fence *rfence);
};
/** struct xe_range_fence - XE range fence (address conflict tracking) */
/** struct xe_range_fence - Xe range fence (address conflict tracking) */
struct xe_range_fence {
/** @rb: RB tree node inserted into interval tree */
struct rb_node rb;

View File

@@ -160,11 +160,11 @@ err_free:
}
/**
* xe_sched_job_destroy - Destroy XE schedule job
* @ref: reference to XE schedule job
* xe_sched_job_destroy - Destroy Xe schedule job
* @ref: reference to Xe schedule job
*
* Called when ref == 0, drop a reference to job's xe_engine + fence, cleanup
* base DRM schedule job, and free memory for XE schedule job.
* base DRM schedule job, and free memory for Xe schedule job.
*/
void xe_sched_job_destroy(struct kref *ref)
{

View File

@@ -23,10 +23,10 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
void xe_sched_job_destroy(struct kref *ref);
/**
* xe_sched_job_get - get reference to XE schedule job
* @job: XE schedule job object
* xe_sched_job_get - get reference to Xe schedule job
* @job: Xe schedule job object
*
* Increment XE schedule job's reference count
* Increment Xe schedule job's reference count
*/
static inline struct xe_sched_job *xe_sched_job_get(struct xe_sched_job *job)
{
@@ -35,10 +35,10 @@ static inline struct xe_sched_job *xe_sched_job_get(struct xe_sched_job *job)
}
/**
* xe_sched_job_put - put reference to XE schedule job
* @job: XE schedule job object
* xe_sched_job_put - put reference to Xe schedule job
* @job: Xe schedule job object
*
* Decrement XE schedule job's reference count, call xe_sched_job_destroy when
* Decrement Xe schedule job's reference count, call xe_sched_job_destroy when
* reference count == 0.
*/
static inline void xe_sched_job_put(struct xe_sched_job *job)

View File

@@ -32,7 +32,7 @@ struct xe_job_ptrs {
};
/**
* struct xe_sched_job - XE schedule job (batch buffer tracking)
* struct xe_sched_job - Xe schedule job (batch buffer tracking)
*/
struct xe_sched_job {
/** @drm: base DRM scheduler job */

View File

@@ -130,10 +130,15 @@
bool xe_sriov_vf_migration_supported(struct xe_device *xe)
{
xe_assert(xe, IS_SRIOV_VF(xe));
return xe->sriov.vf.migration.enabled;
return !xe->sriov.vf.migration.disabled;
}
static void vf_disable_migration(struct xe_device *xe, const char *fmt, ...)
/**
* xe_sriov_vf_migration_disable - Turn off VF migration with given log message.
* @xe: the &xe_device instance.
* @fmt: format string for the log message, to be combined with following VAs.
*/
void xe_sriov_vf_migration_disable(struct xe_device *xe, const char *fmt, ...)
{
struct va_format vaf;
va_list va_args;
@@ -146,7 +151,7 @@ static void vf_disable_migration(struct xe_device *xe, const char *fmt, ...)
xe_sriov_notice(xe, "migration disabled: %pV\n", &vaf);
va_end(va_args);
xe->sriov.vf.migration.enabled = false;
xe->sriov.vf.migration.disabled = true;
}
static void vf_migration_init_early(struct xe_device *xe)
@@ -156,25 +161,12 @@ static void vf_migration_init_early(struct xe_device *xe)
* supported at production quality.
*/
if (!IS_ENABLED(CONFIG_DRM_XE_DEBUG))
return vf_disable_migration(xe,
"experimental feature not available on production builds");
return xe_sriov_vf_migration_disable(xe,
"experimental feature not available on production builds");
if (GRAPHICS_VER(xe) < 20)
return vf_disable_migration(xe, "requires gfx version >= 20, but only %u found",
GRAPHICS_VER(xe));
if (!xe_device_has_memirq(xe))
return xe_sriov_vf_migration_disable(xe, "requires memory-based IRQ support");
if (!IS_DGFX(xe)) {
struct xe_uc_fw_version guc_version;
xe_gt_sriov_vf_guc_versions(xe_device_get_gt(xe, 0), NULL, &guc_version);
if (MAKE_GUC_VER_STRUCT(guc_version) < MAKE_GUC_VER(1, 23, 0))
return vf_disable_migration(xe,
"CCS migration requires GuC ABI >= 1.23 but only %u.%u found",
guc_version.major, guc_version.minor);
}
xe->sriov.vf.migration.enabled = true;
xe_sriov_dbg(xe, "migration support enabled\n");
}
/**
@@ -196,12 +188,7 @@ void xe_sriov_vf_init_early(struct xe_device *xe)
*/
int xe_sriov_vf_init_late(struct xe_device *xe)
{
int err = 0;
if (xe_sriov_vf_migration_supported(xe))
err = xe_sriov_vf_ccs_init(xe);
return err;
return xe_sriov_vf_ccs_init(xe);
}
static int sa_info_vf_ccs(struct seq_file *m, void *data)

View File

@@ -14,6 +14,7 @@ struct xe_device;
void xe_sriov_vf_init_early(struct xe_device *xe);
int xe_sriov_vf_init_late(struct xe_device *xe);
bool xe_sriov_vf_migration_supported(struct xe_device *xe);
void xe_sriov_vf_migration_disable(struct xe_device *xe, const char *fmt, ...);
void xe_sriov_vf_debugfs_register(struct xe_device *xe, struct dentry *root);
#endif

View File

@@ -10,6 +10,8 @@
#include "xe_device.h"
#include "xe_exec_queue.h"
#include "xe_exec_queue_types.h"
#include "xe_gt_sriov_vf.h"
#include "xe_guc.h"
#include "xe_guc_submit.h"
#include "xe_lrc.h"
#include "xe_migrate.h"
@@ -260,6 +262,45 @@ int xe_sriov_vf_ccs_register_context(struct xe_device *xe)
return err;
}
/*
* Whether GuC requires CCS copy BBs for VF migration.
* @xe: the &xe_device instance.
*
* Only selected platforms require VF KMD to maintain CCS copy BBs and linked LRCAs.
*
* Return: true if VF driver must participate in the CCS migration, false otherwise.
*/
static bool vf_migration_ccs_bb_needed(struct xe_device *xe)
{
xe_assert(xe, IS_SRIOV_VF(xe));
return !IS_DGFX(xe) && xe_device_has_flat_ccs(xe);
}
/*
* Check for disable migration due to no CCS BBs support in GuC FW.
* @xe: the &xe_device instance.
*
* Performs late disable of VF migration feature in case GuC FW cannot support it.
*
* Returns: True if VF migration with CCS BBs is supported, false otherwise.
*/
static bool vf_migration_ccs_bb_support_check(struct xe_device *xe)
{
struct xe_gt *gt = xe_root_mmio_gt(xe);
struct xe_uc_fw_version guc_version;
xe_gt_sriov_vf_guc_versions(gt, NULL, &guc_version);
if (MAKE_GUC_VER_STRUCT(guc_version) < MAKE_GUC_VER(1, 23, 0)) {
xe_sriov_vf_migration_disable(xe,
"CCS migration requires GuC ABI >= 1.23 but only %u.%u found",
guc_version.major, guc_version.minor);
return false;
}
return true;
}
static void xe_sriov_vf_ccs_fini(void *arg)
{
struct xe_sriov_vf_ccs_ctx *ctx = arg;
@@ -292,9 +333,10 @@ int xe_sriov_vf_ccs_init(struct xe_device *xe)
int err;
xe_assert(xe, IS_SRIOV_VF(xe));
xe_assert(xe, xe_sriov_vf_migration_supported(xe));
if (IS_DGFX(xe) || !xe_device_has_flat_ccs(xe))
if (!xe_sriov_vf_migration_supported(xe) ||
!vf_migration_ccs_bb_needed(xe) ||
!vf_migration_ccs_bb_support_check(xe))
return 0;
for_each_ccs_rw_ctx(ctx_id) {

View File

@@ -34,10 +34,10 @@ struct xe_device_vf {
/** @migration: VF Migration state data */
struct {
/**
* @migration.enabled: flag indicating if migration support
* was enabled or not due to missing prerequisites
* @migration.disabled: flag indicating if migration support
* was turned off due to missing prerequisites
*/
bool enabled;
bool disabled;
} migration;
/** @ccs: VF CCS state data */

View File

@@ -633,7 +633,7 @@ err_out:
/*
* XXX: We can't derive the GT here (or anywhere in this functions, but
* compute always uses the primary GT so accumlate stats on the likely
* compute always uses the primary GT so accumulate stats on the likely
* GT of the fault.
*/
if (gt)

View File

@@ -33,7 +33,7 @@ void xe_tlb_inval_fence_init(struct xe_tlb_inval *tlb_inval,
* xe_tlb_inval_fence_wait() - TLB invalidiation fence wait
* @fence: TLB invalidation fence to wait on
*
* Wait on a TLB invalidiation fence until it signals, non interruptable
* Wait on a TLB invalidiation fence until it signals, non interruptible
*/
static inline void
xe_tlb_inval_fence_wait(struct xe_tlb_inval_fence *fence)

View File

@@ -106,7 +106,7 @@ static u64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr)
stolen_size = tile_size - mgr->stolen_base;
xe_assert(xe, stolen_size > wopcm_size);
xe_assert(xe, stolen_size >= wopcm_size);
stolen_size -= wopcm_size;
/* Verify usage fits in the actual resource available */

View File

@@ -10,7 +10,7 @@
#include <drm/ttm/ttm_device.h>
/**
* struct xe_ttm_vram_mgr - XE TTM VRAM manager
* struct xe_ttm_vram_mgr - Xe TTM VRAM manager
*
* Manages placement of TTM resource in VRAM.
*/
@@ -32,7 +32,7 @@ struct xe_ttm_vram_mgr {
};
/**
* struct xe_ttm_vram_mgr_resource - XE TTM VRAM resource
* struct xe_ttm_vram_mgr_resource - Xe TTM VRAM resource
*/
struct xe_ttm_vram_mgr_resource {
/** @base: Base TTM resource */

View File

@@ -62,7 +62,7 @@ enum xe_uc_fw_type {
};
/**
* struct xe_uc_fw_version - Version for XE micro controller firmware
* struct xe_uc_fw_version - Version for Xe micro controller firmware
*/
struct xe_uc_fw_version {
/** @branch: branch version of the FW (not always available) */
@@ -84,7 +84,7 @@ enum xe_uc_fw_version_types {
};
/**
* struct xe_uc_fw - XE micro controller firmware
* struct xe_uc_fw - Xe micro controller firmware
*/
struct xe_uc_fw {
/** @type: type uC firmware */
@@ -112,7 +112,7 @@ struct xe_uc_fw {
/** @size: size of uC firmware including css header */
size_t size;
/** @bo: XE BO for uC firmware */
/** @bo: Xe BO for uC firmware */
struct xe_bo *bo;
/** @has_gsc_headers: whether the FW image starts with GSC headers */

View File

@@ -12,7 +12,7 @@
#include "xe_wopcm_types.h"
/**
* struct xe_uc - XE micro controllers
* struct xe_uc - Xe micro controllers
*/
struct xe_uc {
/** @guc: Graphics micro controller */

View File

@@ -108,7 +108,7 @@ struct xe_val_flags {
* @request_exclusive: Whether to lock exclusively (write mode) the next time
* the domain lock is locked.
* @exec_flags: The drm_exec flags used for drm_exec (re-)initialization.
* @nr: The drm_exec nr parameter used for drm_exec (re-)initializaiton.
* @nr: The drm_exec nr parameter used for drm_exec (re-)initialization.
*/
struct xe_validation_ctx {
struct drm_exec *exec;
@@ -137,7 +137,7 @@ bool xe_validation_should_retry(struct xe_validation_ctx *ctx, int *ret);
* @_ret: The current error value possibly holding -ENOMEM
*
* Use this in way similar to drm_exec_retry_on_contention().
* If @_ret contains -ENOMEM the tranaction is restarted once in a way that
* If @_ret contains -ENOMEM the transaction is restarted once in a way that
* blocks other transactions and allows exhastive eviction. If the transaction
* was already restarted once, Just return the -ENOMEM. May also set
* _ret to -EINTR if not retrying and waits are interruptible.
@@ -180,7 +180,7 @@ static inline void *class_xe_validation_lock_ptr(class_xe_validation_t *_T)
* @_val: The xe_validation_device.
* @_exec: The struct drm_exec object
* @_flags: Flags for the xe_validation_ctx initialization.
* @_ret: Return in / out parameter. May be set by this macro. Typicall 0 when called.
* @_ret: Return in / out parameter. May be set by this macro. Typically 0 when called.
*
* This macro is will initiate a drm_exec transaction with additional support for
* exhaustive eviction.

View File

@@ -824,7 +824,7 @@ xe_vm_ops_add_range_rebind(struct xe_vma_ops *vops,
*
* (re)bind SVM range setting up GPU page tables for the range.
*
* Return: dma fence for rebind to signal completion on succees, ERR_PTR on
* Return: dma fence for rebind to signal completion on success, ERR_PTR on
* failure
*/
struct dma_fence *xe_vm_range_rebind(struct xe_vm *vm,
@@ -907,7 +907,7 @@ xe_vm_ops_add_range_unbind(struct xe_vma_ops *vops,
*
* Unbind SVM range removing the GPU page tables for the range.
*
* Return: dma fence for unbind to signal completion on succees, ERR_PTR on
* Return: dma fence for unbind to signal completion on success, ERR_PTR on
* failure
*/
struct dma_fence *xe_vm_range_unbind(struct xe_vm *vm,
@@ -1291,7 +1291,7 @@ static u16 pde_pat_index(struct xe_bo *bo)
* selection of options. The user PAT index is only for encoding leaf
* nodes, where we have use of more bits to do the encoding. The
* non-leaf nodes are instead under driver control so the chosen index
* here should be distict from the user PAT index. Also the
* here should be distinct from the user PAT index. Also the
* corresponding coherency of the PAT index should be tied to the
* allocation type of the page table (or at least we should pick
* something which is always safe).
@@ -4172,7 +4172,7 @@ void xe_vm_snapshot_free(struct xe_vm_snapshot *snap)
/**
* xe_vma_need_vram_for_atomic - Check if VMA needs VRAM migration for atomic operations
* @xe: Pointer to the XE device structure
* @xe: Pointer to the Xe device structure
* @vma: Pointer to the virtual memory area (VMA) structure
* @is_atomic: In pagefault path and atomic operation
*
@@ -4319,7 +4319,7 @@ static int xe_vm_alloc_vma(struct xe_vm *vm,
xe_vma_destroy(gpuva_to_vma(op->base.remap.unmap->va), NULL);
} else if (__op->op == DRM_GPUVA_OP_MAP) {
vma = op->map.vma;
/* In case of madvise call, MAP will always be follwed by REMAP.
/* In case of madvise call, MAP will always be followed by REMAP.
* Therefore temp_attr will always have sane values, making it safe to
* copy them to new vma.
*/

View File

@@ -7,7 +7,7 @@
#define _XE_VM_DOC_H_
/**
* DOC: XE VM (user address space)
* DOC: Xe VM (user address space)
*
* VM creation
* ===========
@@ -202,13 +202,13 @@
* User pointers are user allocated memory (malloc'd, mmap'd, etc..) for which the
* user wants to create a GPU mapping. Typically in other DRM drivers a dummy BO
* was created and then a binding was created. We bypass creating a dummy BO in
* XE and simply create a binding directly from the userptr.
* Xe and simply create a binding directly from the userptr.
*
* Invalidation
* ------------
*
* Since this a core kernel managed memory the kernel can move this memory
* whenever it wants. We register an invalidation MMU notifier to alert XE when
* whenever it wants. We register an invalidation MMU notifier to alert Xe when
* a user pointer is about to move. The invalidation notifier needs to block
* until all pending users (jobs or compute mode engines) of the userptr are
* idle to ensure no faults. This done by waiting on all of VM's dma-resv slots.
@@ -419,7 +419,7 @@
* =======
*
* VM locking protects all of the core data paths (bind operations, execs,
* evictions, and compute mode rebind worker) in XE.
* evictions, and compute mode rebind worker) in Xe.
*
* Locks
* -----

View File

@@ -52,7 +52,7 @@ struct xe_vm_pgtable_update_op;
* struct xe_vma_mem_attr - memory attributes associated with vma
*/
struct xe_vma_mem_attr {
/** @preferred_loc: perferred memory_location */
/** @preferred_loc: preferred memory_location */
struct {
/** @preferred_loc.migration_policy: Pages migration policy */
u32 migration_policy;
@@ -338,7 +338,7 @@ struct xe_vm {
u64 tlb_flush_seqno;
/** @batch_invalidate_tlb: Always invalidate TLB before batch start */
bool batch_invalidate_tlb;
/** @xef: XE file handle for tracking this VM's drm client */
/** @xef: Xe file handle for tracking this VM's drm client */
struct xe_file *xef;
};

View File

@@ -916,6 +916,10 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE))
},
{ XE_RTP_NAME("14024681466"),
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)),
XE_RTP_ACTIONS(SET(XEHP_SLICE_COMMON_ECO_CHICKEN1, FAST_CLEAR_VALIGN_FIX))
},
};
static __maybe_unused const struct xe_rtp_entry oob_was[] = {

View File

@@ -893,4 +893,8 @@
MACRO__(0xD744, ## __VA_ARGS__), \
MACRO__(0xD745, ## __VA_ARGS__)
/* CRI */
#define INTEL_CRI_IDS(MACRO__, ...) \
MACRO__(0x674C, ## __VA_ARGS__)
#endif /* __PCIIDS_H__ */