mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 02:31:27 +02:00
Driver Changes:
- drm/xe/oa: Fix exec_queue leak on width check in stream open (Shuicheng Lin) - drm/xe/memirq: Drop cached iosys_map for MEMIRQ status (Michal Wajdeczko) - drm/xe/memirq: Drop cached iosys_map for MEMIRQ mask (Michal Wajdeczko) - drm/xe/memirq: Dump all source pages if MSI-X (Michal Wajdeczko) - drm/xe/memirq: Update diagnostic message (Michal Wajdeczko) - drm/xe/memirq: Reduce buffer size (Michal Wajdeczko) - drm/xe/memirq: Use IRQ page from HW engine definition (Michal Wajdeczko) - drm/xe/memirq: Update GuC initialization and IRQ handler (Michal Wajdeczko) - drm/xe/memirq: Make page layout macros private (Michal Wajdeczko) - drm/xe: Add IRQ page to HW engine definition (Michal Wajdeczko) - drm/xe/guc: Use xe_device_is_l2_flush_optimized() (Gustavo Sousa) - drm/xe/multi_queue: Fix secondary queue error case (Niranjana Vishwanathapura) - drm/xe/reg_sr: Do sanity check for MCR vs non-MCR (Gustavo Sousa) - drm/xe/mcr: Extract reg_in_steering_type_ranges() (Gustavo Sousa) - drm/xe/kunit: Use KUNIT_EXPECT_EQ() in xe_wa_gt() (Gustavo Sousa) - drm/xe: Extract xe_hw_engine_setup_reg_lrc() (Gustavo Sousa) - drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN4 (Gustavo Sousa) - drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN1 (Gustavo Sousa) - drm/xe: Define CACHE_MODE_1 as MCR register (Gustavo Sousa) - drm/xe/pf: Fix CFI failure in debugfs access (Mohanram Meenakshisundaram) - drm/xe/vf: Fix signature of print functions (Michal Wajdeczko) - drm/xe: Make drm_driver const (Michal Wajdeczko) - drm/xe/display: Drop xe_display_driver_set_hooks() (Michal Wajdeczko) - drm/xe/display: Add macro with display driver features (Michal Wajdeczko) - drm/xe/display: Add macro with display driver ops (Michal Wajdeczko) - drm/xe/display: Prefer forward declarations (Michal Wajdeczko) - drm/xe/display: Drop xe_display_driver_remove() stub (Michal Wajdeczko) - drm/xe: Drop unused drm/drm_atomic_helper.h include (Michal Wajdeczko) - drm/xe/sriov: Mark NVL as SR-IOV capable (Jakub Kolakowski) - drm/xe/gt_idle: Use NSEC_PER_MSEC instead of float literal (Shuicheng Lin) - drm/xe/gsc: Fix double-free of managed BO in error path (Shuicheng Lin) -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRskUM7w1oG5rx2IZO4FpNVCsYGvwUCag9PtAAKCRC4FpNVCsYG v6jqAQDZuKtO+Zihz29VR9xD2xqm1C0AoC5IrT1Q4yxl5HXAUwD+LnHLl4dhvHuV zQ+NjGWmaWV3fdOKcZGowUdlR3/j9go= =bUe0 -----END PGP SIGNATURE----- Merge tag 'drm-xe-next-2026-05-21' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next Driver Changes: - drm/xe/oa: Fix exec_queue leak on width check in stream open (Shuicheng Lin) - drm/xe/memirq: Drop cached iosys_map for MEMIRQ status (Michal Wajdeczko) - drm/xe/memirq: Drop cached iosys_map for MEMIRQ mask (Michal Wajdeczko) - drm/xe/memirq: Dump all source pages if MSI-X (Michal Wajdeczko) - drm/xe/memirq: Update diagnostic message (Michal Wajdeczko) - drm/xe/memirq: Reduce buffer size (Michal Wajdeczko) - drm/xe/memirq: Use IRQ page from HW engine definition (Michal Wajdeczko) - drm/xe/memirq: Update GuC initialization and IRQ handler (Michal Wajdeczko) - drm/xe/memirq: Make page layout macros private (Michal Wajdeczko) - drm/xe: Add IRQ page to HW engine definition (Michal Wajdeczko) - drm/xe/guc: Use xe_device_is_l2_flush_optimized() (Gustavo Sousa) - drm/xe/multi_queue: Fix secondary queue error case (Niranjana Vishwanathapura) - drm/xe/reg_sr: Do sanity check for MCR vs non-MCR (Gustavo Sousa) - drm/xe/mcr: Extract reg_in_steering_type_ranges() (Gustavo Sousa) - drm/xe/kunit: Use KUNIT_EXPECT_EQ() in xe_wa_gt() (Gustavo Sousa) - drm/xe: Extract xe_hw_engine_setup_reg_lrc() (Gustavo Sousa) - drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN4 (Gustavo Sousa) - drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN1 (Gustavo Sousa) - drm/xe: Define CACHE_MODE_1 as MCR register (Gustavo Sousa) - drm/xe/pf: Fix CFI failure in debugfs access (Mohanram Meenakshisundaram) - drm/xe/vf: Fix signature of print functions (Michal Wajdeczko) - drm/xe: Make drm_driver const (Michal Wajdeczko) - drm/xe/display: Drop xe_display_driver_set_hooks() (Michal Wajdeczko) - drm/xe/display: Add macro with display driver features (Michal Wajdeczko) - drm/xe/display: Add macro with display driver ops (Michal Wajdeczko) - drm/xe/display: Prefer forward declarations (Michal Wajdeczko) - drm/xe/display: Drop xe_display_driver_remove() stub (Michal Wajdeczko) - drm/xe: Drop unused drm/drm_atomic_helper.h include (Michal Wajdeczko) - drm/xe/sriov: Mark NVL as SR-IOV capable (Jakub Kolakowski) - drm/xe/gt_idle: Use NSEC_PER_MSEC instead of float literal (Shuicheng Lin) - drm/xe/gsc: Fix double-free of managed BO in error path (Shuicheng Lin) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com> Link: https://patch.msgid.link/ag9RLujZiYYnSc_F@fedora
This commit is contained in:
commit
57b5fd7cb2
|
|
@ -36,6 +36,7 @@
|
|||
#include "intel_hotplug.h"
|
||||
#include "intel_opregion.h"
|
||||
#include "skl_watermark.h"
|
||||
#include "xe_device.h"
|
||||
#include "xe_display_bo.h"
|
||||
#include "xe_display_pcode.h"
|
||||
#include "xe_display_rpm.h"
|
||||
|
|
@ -70,31 +71,9 @@ bool xe_display_driver_probe_defer(struct pci_dev *pdev)
|
|||
return intel_display_driver_probe_defer(pdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_display_driver_set_hooks - Add driver flags and hooks for display
|
||||
* @driver: DRM device driver
|
||||
*
|
||||
* Set features and function hooks in @driver that are needed for driving the
|
||||
* display IP. This sets the driver's capability of driving display, regardless
|
||||
* if the device has it enabled
|
||||
*
|
||||
* Note: This is called before xe or display device creation.
|
||||
*/
|
||||
void xe_display_driver_set_hooks(struct drm_driver *driver)
|
||||
{
|
||||
if (!xe_modparam.probe_display)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
driver->fbdev_probe = intel_fbdev_driver_fbdev_probe;
|
||||
#endif
|
||||
|
||||
driver->driver_features |= DRIVER_MODESET | DRIVER_ATOMIC;
|
||||
}
|
||||
|
||||
static void unset_display_features(struct xe_device *xe)
|
||||
{
|
||||
xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
|
||||
xe->drm.driver_features &= ~XE_DISPLAY_DRIVER_FEATURES;
|
||||
}
|
||||
|
||||
static void xe_display_fini_early(void *arg)
|
||||
|
|
@ -604,3 +583,11 @@ int xe_display_probe(struct xe_device *xe)
|
|||
unset_display_features(xe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
int xe_display_driver_fbdev_probe(struct drm_fb_helper *fbh,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
return intel_fbdev_driver_fbdev_probe(fbh, sizes);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,14 +6,20 @@
|
|||
#ifndef _XE_DISPLAY_H_
|
||||
#define _XE_DISPLAY_H_
|
||||
|
||||
#include "xe_device.h"
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_driver;
|
||||
struct drm_fb_helper;
|
||||
struct drm_fb_helper_surface_size;
|
||||
struct pci_dev;
|
||||
struct xe_device;
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
|
||||
|
||||
bool xe_display_driver_probe_defer(struct pci_dev *pdev);
|
||||
void xe_display_driver_set_hooks(struct drm_driver *driver);
|
||||
|
||||
int xe_display_driver_fbdev_probe(struct drm_fb_helper *fbh,
|
||||
struct drm_fb_helper_surface_size *sizes);
|
||||
|
||||
int xe_display_probe(struct xe_device *xe);
|
||||
|
||||
|
|
@ -38,11 +44,18 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe);
|
|||
void xe_display_pm_runtime_suspend_late(struct xe_device *xe);
|
||||
void xe_display_pm_runtime_resume(struct xe_device *xe);
|
||||
|
||||
#define XE_DISPLAY_DRIVER_FEATURES (DRIVER_MODESET | DRIVER_ATOMIC)
|
||||
#define XE_DISPLAY_DRIVER_OPS \
|
||||
.fbdev_probe = PTR_IF(IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION), \
|
||||
xe_display_driver_fbdev_probe)
|
||||
|
||||
#else
|
||||
|
||||
#define XE_DISPLAY_DRIVER_FEATURES 0
|
||||
#define XE_DISPLAY_DRIVER_OPS \
|
||||
.fbdev_probe = NULL
|
||||
|
||||
static inline int xe_display_driver_probe_defer(struct pci_dev *pdev) { return 0; }
|
||||
static inline void xe_display_driver_set_hooks(struct drm_driver *driver) { }
|
||||
static inline void xe_display_driver_remove(struct xe_device *xe) {}
|
||||
|
||||
static inline int xe_display_probe(struct xe_device *xe) { return 0; }
|
||||
|
||||
|
|
|
|||
|
|
@ -152,10 +152,11 @@
|
|||
|
||||
#define XEHPG_INSTDONE_GEOM_SVGUNIT XE_REG_MCR(0x666c)
|
||||
|
||||
#define CACHE_MODE_1 XE_REG(0x7004, XE_REG_OPTION_MASKED)
|
||||
#define CACHE_MODE_1 XE_REG_MCR(0x7004, XE_REG_OPTION_MASKED)
|
||||
#define MSAA_OPTIMIZATION_REDUC_DISABLE REG_BIT(11)
|
||||
|
||||
#define COMMON_SLICE_CHICKEN1 XE_REG(0x7010, XE_REG_OPTION_MASKED)
|
||||
#define XEHP_COMMON_SLICE_CHICKEN1 XE_REG_MCR(0x7010, XE_REG_OPTION_MASKED)
|
||||
#define DISABLE_BOTTOM_CLIP_RECTANGLE_TEST REG_BIT(14)
|
||||
|
||||
#define HIZ_CHICKEN XE_REG(0x7018, XE_REG_OPTION_MASKED)
|
||||
|
|
@ -178,6 +179,7 @@
|
|||
#define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108)
|
||||
|
||||
#define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED)
|
||||
#define XEHP_COMMON_SLICE_CHICKEN4 XE_REG_MCR(0x7300, XE_REG_OPTION_MASKED)
|
||||
#define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12)
|
||||
#define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6)
|
||||
#define HW_FILTERING REG_BIT(5)
|
||||
|
|
|
|||
|
|
@ -9,24 +9,30 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_kunit_helpers.h>
|
||||
|
||||
#include <kunit/static_stub.h>
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include "regs/xe_gt_regs.h"
|
||||
#include "regs/xe_reg_defs.h"
|
||||
#include "xe_device.h"
|
||||
#include "xe_device_types.h"
|
||||
#include "xe_gt_mcr.h"
|
||||
#include "xe_kunit_helpers.h"
|
||||
#include "xe_pci_test.h"
|
||||
#include "xe_reg_sr.h"
|
||||
#include "xe_rtp.h"
|
||||
|
||||
#define REGULAR_REG1 XE_REG(1)
|
||||
#define REGULAR_REG2 XE_REG(2)
|
||||
#define REGULAR_REG3 XE_REG(3)
|
||||
#define MCR_REG1 XE_REG_MCR(1)
|
||||
#define MCR_REG2 XE_REG_MCR(2)
|
||||
#define MCR_REG3 XE_REG_MCR(3)
|
||||
#define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED)
|
||||
#define REGULAR_REG1 XE_REG(1)
|
||||
#define REGULAR_REG2 XE_REG(2)
|
||||
#define REGULAR_REG3 XE_REG(3)
|
||||
#define REGULAR_REG4 XE_REG(4)
|
||||
#define BAD_REGULAR_REG5 XE_REG(5)
|
||||
#define MCR_REG1 XE_REG_MCR(1)
|
||||
#define MCR_REG2 XE_REG_MCR(2)
|
||||
#define MCR_REG3 XE_REG_MCR(3)
|
||||
#define BAD_MCR_REG4 XE_REG_MCR(4)
|
||||
#define MCR_REG5 XE_REG_MCR(5)
|
||||
#define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED)
|
||||
|
||||
#undef XE_REG_MCR
|
||||
#define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1)
|
||||
|
|
@ -48,6 +54,23 @@ struct rtp_test_case {
|
|||
const struct xe_rtp_entry *entries;
|
||||
};
|
||||
|
||||
static bool fake_xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
|
||||
{
|
||||
/*
|
||||
* All supported platforms in this imaginary setup will always have REG4
|
||||
* as a non-MCR register and REG5 as MCR, meaning that BAD_MCR_REG4 and
|
||||
* BAD_REGULAR_REG5 represent programming errors to be captured by our
|
||||
* tests.
|
||||
*/
|
||||
if (reg.raw == BAD_REGULAR_REG5.raw)
|
||||
return true;
|
||||
|
||||
if (reg.raw == BAD_MCR_REG4.raw)
|
||||
return false;
|
||||
|
||||
return reg.mcr;
|
||||
}
|
||||
|
||||
static bool match_yes(const struct xe_device *xe, const struct xe_gt *gt,
|
||||
const struct xe_hw_engine *hwe)
|
||||
{
|
||||
|
|
@ -304,6 +327,38 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
|
|||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "bad-mcr-reg-forced-to-regular",
|
||||
.expected_reg = REGULAR_REG4,
|
||||
.expected_set_bits = REG_BIT(0),
|
||||
.expected_clr_bits = REG_BIT(0),
|
||||
.expected_active = BIT(0),
|
||||
.expected_count_sr_entries = 1,
|
||||
.expected_sr_errors = 1,
|
||||
.entries = (const struct xe_rtp_entry_sr[]) {
|
||||
{ XE_RTP_NAME("bad-mcr-regular-reg"),
|
||||
XE_RTP_RULES(FUNC(match_yes)),
|
||||
XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0)))
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "bad-regular-reg-forced-to-mcr",
|
||||
.expected_reg = MCR_REG5,
|
||||
.expected_set_bits = REG_BIT(0),
|
||||
.expected_clr_bits = REG_BIT(0),
|
||||
.expected_active = BIT(0),
|
||||
.expected_count_sr_entries = 1,
|
||||
.expected_sr_errors = 1,
|
||||
.entries = (const struct xe_rtp_entry_sr[]) {
|
||||
{ XE_RTP_NAME("bad-regular-reg"),
|
||||
XE_RTP_RULES(FUNC(match_yes)),
|
||||
XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0)))
|
||||
},
|
||||
{}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static void xe_rtp_process_to_sr_tests(struct kunit *test)
|
||||
|
|
@ -523,6 +578,8 @@ static int xe_rtp_test_init(struct kunit *test)
|
|||
xe->drm.dev = dev;
|
||||
test->priv = xe;
|
||||
|
||||
kunit_activate_static_stub(test, xe_gt_mcr_check_reg, fake_xe_gt_mcr_check_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include <kunit/test.h>
|
||||
|
||||
#include "xe_device.h"
|
||||
#include "xe_gt.h"
|
||||
#include "xe_gt_mcr.h"
|
||||
#include "xe_kunit_helpers.h"
|
||||
#include "xe_pci_test.h"
|
||||
#include "xe_reg_sr.h"
|
||||
|
|
@ -19,8 +21,10 @@ static int xe_wa_test_init(struct kunit *test)
|
|||
{
|
||||
const struct xe_pci_fake_data *param = test->param_value;
|
||||
struct xe_pci_fake_data data = *param;
|
||||
struct xe_device *xe;
|
||||
struct device *dev;
|
||||
struct xe_device *xe;
|
||||
struct xe_gt *gt;
|
||||
int id;
|
||||
int ret;
|
||||
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
|
|
@ -33,6 +37,12 @@ static int xe_wa_test_init(struct kunit *test)
|
|||
ret = xe_pci_fake_device_init(xe);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Needed for sanitize_mcr(). */
|
||||
for_each_gt(gt, xe, id) {
|
||||
xe_gt_mcr_init_early(gt);
|
||||
xe_gt_mmio_init(gt);
|
||||
}
|
||||
|
||||
if (!param->graphics_verx100)
|
||||
xe->info.step = param->step;
|
||||
|
||||
|
|
@ -55,7 +65,7 @@ static void xe_wa_gt(struct kunit *test)
|
|||
xe_wa_process_gt(gt);
|
||||
xe_tuning_process_gt(gt);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, gt->reg_sr.errors, 0);
|
||||
KUNIT_EXPECT_EQ(test, gt->reg_sr.errors, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#include <linux/fault-inject.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_gem_ttm_helper.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
|
|
@ -392,8 +391,9 @@ bool xe_is_xe_file(const struct file *file)
|
|||
return file->f_op == &xe_driver_fops;
|
||||
}
|
||||
|
||||
static struct drm_driver regular_driver = {
|
||||
static const struct drm_driver regular_driver = {
|
||||
.driver_features =
|
||||
XE_DISPLAY_DRIVER_FEATURES |
|
||||
DRIVER_GEM |
|
||||
DRIVER_RENDER | DRIVER_SYNCOBJ |
|
||||
DRIVER_SYNCOBJ_TIMELINE | DRIVER_GEM_GPUVA,
|
||||
|
|
@ -415,6 +415,7 @@ static struct drm_driver regular_driver = {
|
|||
.major = DRIVER_MAJOR,
|
||||
.minor = DRIVER_MINOR,
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
XE_DISPLAY_DRIVER_OPS,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
|
|
@ -423,8 +424,9 @@ static const struct drm_ioctl_desc xe_ioctls_admin_only[] = {
|
|||
DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static struct drm_driver admin_only_driver = {
|
||||
static const struct drm_driver admin_only_driver = {
|
||||
.driver_features =
|
||||
XE_DISPLAY_DRIVER_FEATURES |
|
||||
DRIVER_GEM | DRIVER_RENDER | DRIVER_GEM_GPUVA,
|
||||
.open = xe_file_open,
|
||||
.postclose = xe_file_close,
|
||||
|
|
@ -436,6 +438,7 @@ static struct drm_driver admin_only_driver = {
|
|||
.major = DRIVER_MAJOR,
|
||||
.minor = DRIVER_MINOR,
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
XE_DISPLAY_DRIVER_OPS,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -475,7 +478,7 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy)
|
|||
struct xe_device *xe_device_create(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct drm_driver *driver = ®ular_driver;
|
||||
const struct drm_driver *driver = ®ular_driver;
|
||||
struct xe_device *xe;
|
||||
int err;
|
||||
|
||||
|
|
@ -488,8 +491,6 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
|
|||
driver = &admin_only_driver;
|
||||
#endif
|
||||
|
||||
xe_display_driver_set_hooks(driver);
|
||||
|
||||
err = aperture_remove_conflicting_pci_devices(pdev, driver->name);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
|
|
|||
|
|
@ -482,8 +482,7 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
|
|||
EXEC_QUEUE_FLAG_PERMANENT, 0);
|
||||
if (IS_ERR(q)) {
|
||||
xe_gt_err(gt, "Failed to create queue for GSC submission\n");
|
||||
err = PTR_ERR(q);
|
||||
goto out_bo;
|
||||
return PTR_ERR(q);
|
||||
}
|
||||
|
||||
wq = alloc_ordered_workqueue("gsc-ordered-wq", 0);
|
||||
|
|
@ -506,8 +505,6 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
|
|||
|
||||
out_q:
|
||||
xe_exec_queue_put(q);
|
||||
out_bo:
|
||||
xe_bo_unpin_map_no_vm(bo);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <linux/minmax.h>
|
||||
|
||||
#include <kunit/visibility.h>
|
||||
|
||||
#include <drm/drm_managed.h>
|
||||
#include <uapi/drm/xe_drm.h>
|
||||
|
||||
|
|
@ -393,10 +395,7 @@ int xe_gt_record_default_lrcs(struct xe_gt *gt)
|
|||
if (gt->default_lrc[hwe->class])
|
||||
continue;
|
||||
|
||||
xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe);
|
||||
xe_wa_process_lrc(hwe);
|
||||
xe_hw_engine_setup_default_lrc_state(hwe);
|
||||
xe_tuning_process_lrc(hwe);
|
||||
xe_hw_engine_setup_reg_lrc(hwe);
|
||||
|
||||
default_lrc = drmm_kzalloc(&xe->drm,
|
||||
xe_gt_lrc_size(gt, hwe->class),
|
||||
|
|
@ -788,6 +787,7 @@ void xe_gt_mmio_init(struct xe_gt *gt)
|
|||
if (IS_SRIOV_VF(xe))
|
||||
gt->mmio.sriov_vf_gt = gt;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(xe_gt_mmio_init);
|
||||
|
||||
void xe_gt_record_user_engines(struct xe_gt *gt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/time64.h>
|
||||
|
||||
#include <drm/drm_managed.h>
|
||||
|
||||
#include <generated/xe_wa_oob.h>
|
||||
|
|
@ -93,7 +95,7 @@ static u64 get_residency_ms(struct xe_gt_idle *gtidle, u64 cur_residency)
|
|||
gtidle->cur_residency = cur_residency;
|
||||
|
||||
/* residency multiplier in ns, convert to ms */
|
||||
cur_residency = mul_u64_u32_div(cur_residency, gtidle->residency_multiplier, 1e6);
|
||||
cur_residency = mul_u64_u32_div(cur_residency, gtidle->residency_multiplier, NSEC_PER_MSEC);
|
||||
|
||||
return cur_residency;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
* Copyright © 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <kunit/static_stub.h>
|
||||
#include <kunit/visibility.h>
|
||||
|
||||
#include "xe_gt_mcr.h"
|
||||
|
||||
#include "regs/xe_gt_regs.h"
|
||||
|
|
@ -553,6 +556,7 @@ void xe_gt_mcr_init_early(struct xe_gt *gt)
|
|||
/* Mark instance 0 as initialized, we need this early for VRAM and CCS probe. */
|
||||
gt->steering[INSTANCE0].initialized = true;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(xe_gt_mcr_init_early);
|
||||
|
||||
/**
|
||||
* xe_gt_mcr_init - Normal initialization of the MCR support
|
||||
|
|
@ -600,6 +604,40 @@ void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt)
|
|||
}
|
||||
}
|
||||
|
||||
static bool reg_in_steering_type_ranges(struct xe_gt *gt,
|
||||
struct xe_reg reg,
|
||||
int type)
|
||||
{
|
||||
if (!gt->steering[type].ranges)
|
||||
return false;
|
||||
|
||||
for (int i = 0; gt->steering[type].ranges[i].end > 0; i++)
|
||||
if (xe_mmio_in_range(>->mmio, >->steering[type].ranges[i], reg))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* xe_gt_mcr_check_reg - check if a register is recognized by this GT as MCR
|
||||
* @gt: GT structure
|
||||
* @reg: The register to check
|
||||
*
|
||||
* Returns true if the register offset falls within one of the MMIO ranges
|
||||
* classified as MCR for the GT.
|
||||
*/
|
||||
bool xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
|
||||
{
|
||||
KUNIT_STATIC_STUB_REDIRECT(xe_gt_mcr_check_reg, gt, reg);
|
||||
|
||||
for (int type = 0; type <= IMPLICIT_STEERING; type++)
|
||||
if (reg_in_steering_type_ranges(gt, reg, type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(xe_gt_mcr_check_reg);
|
||||
|
||||
/*
|
||||
* xe_gt_mcr_get_nonterminated_steering - find group/instance values that
|
||||
* will steer a register to a non-terminated instance
|
||||
|
|
@ -621,30 +659,21 @@ bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
|
|||
u8 *group, u8 *instance)
|
||||
{
|
||||
const struct xe_reg reg = to_xe_reg(reg_mcr);
|
||||
const struct xe_mmio_range *implicit_ranges;
|
||||
|
||||
for (int type = 0; type < IMPLICIT_STEERING; type++) {
|
||||
if (!gt->steering[type].ranges)
|
||||
continue;
|
||||
if (reg_in_steering_type_ranges(gt, reg, type)) {
|
||||
drm_WARN(>_to_xe(gt)->drm, !gt->steering[type].initialized,
|
||||
"Uninitialized usage of MCR register %s/%#x\n",
|
||||
xe_steering_types[type].name, reg.addr);
|
||||
|
||||
for (int i = 0; gt->steering[type].ranges[i].end > 0; i++) {
|
||||
if (xe_mmio_in_range(>->mmio, >->steering[type].ranges[i], reg)) {
|
||||
drm_WARN(>_to_xe(gt)->drm, !gt->steering[type].initialized,
|
||||
"Uninitialized usage of MCR register %s/%#x\n",
|
||||
xe_steering_types[type].name, reg.addr);
|
||||
|
||||
*group = gt->steering[type].group_target;
|
||||
*instance = gt->steering[type].instance_target;
|
||||
return true;
|
||||
}
|
||||
*group = gt->steering[type].group_target;
|
||||
*instance = gt->steering[type].instance_target;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
implicit_ranges = gt->steering[IMPLICIT_STEERING].ranges;
|
||||
if (implicit_ranges)
|
||||
for (int i = 0; implicit_ranges[i].end > 0; i++)
|
||||
if (xe_mmio_in_range(>->mmio, &implicit_ranges[i], reg))
|
||||
return false;
|
||||
if (reg_in_steering_type_ranges(gt, reg, IMPLICIT_STEERING))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Not found in a steering table and not a register with implicit
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
|
|||
void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
|
||||
u32 value);
|
||||
|
||||
bool xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg);
|
||||
bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
|
||||
struct xe_reg_mcr reg_mcr,
|
||||
u8 *group, u8 *instance);
|
||||
|
|
|
|||
|
|
@ -114,8 +114,10 @@ int xe_gt_sriov_pf_monitor_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32
|
|||
* VFs with no events are not printed.
|
||||
*
|
||||
* This function can only be called on PF.
|
||||
*
|
||||
* Return: always 0
|
||||
*/
|
||||
void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p)
|
||||
int xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p)
|
||||
{
|
||||
unsigned int n, total_vfs = xe_gt_sriov_pf_get_totalvfs(gt);
|
||||
const struct xe_gt_sriov_monitor *data;
|
||||
|
|
@ -144,4 +146,6 @@ void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p
|
|||
#undef __format
|
||||
#undef __value
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ struct drm_printer;
|
|||
struct xe_gt;
|
||||
|
||||
void xe_gt_sriov_pf_monitor_flr(struct xe_gt *gt, u32 vfid);
|
||||
void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p);
|
||||
int xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p);
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
int xe_gt_sriov_pf_monitor_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32 len);
|
||||
|
|
|
|||
|
|
@ -1137,13 +1137,15 @@ void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val)
|
|||
}
|
||||
|
||||
/**
|
||||
* xe_gt_sriov_vf_print_config - Print VF self config.
|
||||
* xe_gt_sriov_vf_print_config() - Print VF self config.
|
||||
* @gt: the &xe_gt
|
||||
* @p: the &drm_printer
|
||||
*
|
||||
* This function is for VF use only.
|
||||
*
|
||||
* Return: always 0.
|
||||
*/
|
||||
void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p)
|
||||
int xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p)
|
||||
{
|
||||
struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config;
|
||||
struct xe_device *xe = gt_to_xe(gt);
|
||||
|
|
@ -1170,16 +1172,20 @@ void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p)
|
|||
|
||||
drm_printf(p, "GuC contexts:\t%u\n", config->num_ctxs);
|
||||
drm_printf(p, "GuC doorbells:\t%u\n", config->num_dbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_gt_sriov_vf_print_runtime - Print VF's runtime regs received from PF.
|
||||
* xe_gt_sriov_vf_print_runtime() - Print VF's runtime regs received from PF.
|
||||
* @gt: the &xe_gt
|
||||
* @p: the &drm_printer
|
||||
*
|
||||
* This function is for VF use only.
|
||||
*
|
||||
* Return: always 0.
|
||||
*/
|
||||
void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p)
|
||||
int xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p)
|
||||
{
|
||||
struct vf_runtime_reg *vf_regs = gt->sriov.vf.runtime.regs;
|
||||
unsigned int size = gt->sriov.vf.runtime.num_regs;
|
||||
|
|
@ -1188,16 +1194,20 @@ void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p)
|
|||
|
||||
for (; size--; vf_regs++)
|
||||
drm_printf(p, "%#x = %#x\n", vf_regs->offset, vf_regs->value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_gt_sriov_vf_print_version - Print VF ABI versions.
|
||||
* xe_gt_sriov_vf_print_version() - Print VF ABI versions.
|
||||
* @gt: the &xe_gt
|
||||
* @p: the &drm_printer
|
||||
*
|
||||
* This function is for VF use only.
|
||||
*
|
||||
* Return: always 0.
|
||||
*/
|
||||
void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p)
|
||||
int xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p)
|
||||
{
|
||||
struct xe_device *xe = gt_to_xe(gt);
|
||||
struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version;
|
||||
|
|
@ -1227,6 +1237,8 @@ void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p)
|
|||
GUC_RELAY_VERSION_LATEST_MAJOR, GUC_RELAY_VERSION_LATEST_MINOR);
|
||||
drm_printf(p, "\thandshake:\t%u.%u\n",
|
||||
pf_version->major, pf_version->minor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vf_post_migration_shutdown(struct xe_gt *gt)
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ bool xe_gt_sriov_vf_sched_groups_enabled(struct xe_gt *gt);
|
|||
u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg);
|
||||
void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val);
|
||||
|
||||
void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p);
|
||||
void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p);
|
||||
void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p);
|
||||
int xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p);
|
||||
int xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p);
|
||||
int xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p);
|
||||
|
||||
int xe_gt_sriov_vf_wait_valid_ggtt(struct xe_gt *gt);
|
||||
int xe_vf_migration_fixups_complete_count(struct xe_gt *gt);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static u32 guc_ctl_feature_flags(struct xe_guc *guc)
|
|||
if (xe_guc_using_main_gamctrl_queues(guc))
|
||||
flags |= GUC_CTL_MAIN_GAMCTRL_QUEUES;
|
||||
|
||||
if (GRAPHICS_VER(xe) >= 35 && !IS_DGFX(xe) && xe_gt_is_media_type(guc_to_gt(guc)))
|
||||
if (xe_device_is_l2_flush_optimized(xe) && xe_gt_is_media_type(guc_to_gt(guc)))
|
||||
flags |= GUC_CTL_ENABLE_L2FLUSH_OPT;
|
||||
|
||||
return flags;
|
||||
|
|
|
|||
|
|
@ -1665,6 +1665,14 @@ static void guc_exec_queue_fini(struct xe_exec_queue *q)
|
|||
struct xe_guc_exec_queue *ge = q->guc;
|
||||
struct xe_guc *guc = exec_queue_to_guc(q);
|
||||
|
||||
if (xe_exec_queue_is_multi_queue_secondary(q)) {
|
||||
struct xe_exec_queue_group *group = q->multi_queue.group;
|
||||
|
||||
mutex_lock(&group->list_lock);
|
||||
list_del(&q->multi_queue.link);
|
||||
mutex_unlock(&group->list_lock);
|
||||
}
|
||||
|
||||
release_guc_id(guc, q);
|
||||
xe_sched_entity_fini(&ge->entity);
|
||||
xe_sched_fini(&ge->sched);
|
||||
|
|
@ -1686,14 +1694,6 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w)
|
|||
guard(xe_pm_runtime)(guc_to_xe(guc));
|
||||
trace_xe_exec_queue_destroy(q);
|
||||
|
||||
if (xe_exec_queue_is_multi_queue_secondary(q)) {
|
||||
struct xe_exec_queue_group *group = q->multi_queue.group;
|
||||
|
||||
mutex_lock(&group->list_lock);
|
||||
list_del(&q->multi_queue.link);
|
||||
mutex_unlock(&group->list_lock);
|
||||
}
|
||||
|
||||
/* Confirm no work left behind accessing device structures */
|
||||
cancel_delayed_work_sync(&ge->sched.base.work_tdr);
|
||||
|
||||
|
|
|
|||
|
|
@ -337,8 +337,8 @@ static bool xe_rtp_cfeg_wmtp_disabled(const struct xe_device *xe,
|
|||
return xe_mmio_read32(&hwe->gt->mmio, XEHP_FUSE4) & CFEG_WMTP_DISABLE;
|
||||
}
|
||||
|
||||
void
|
||||
xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
|
||||
static void
|
||||
hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
|
||||
{
|
||||
struct xe_gt *gt = hwe->gt;
|
||||
const u8 mocs_write_idx = gt->mocs.uc_index;
|
||||
|
|
@ -375,6 +375,17 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
|
|||
&hwe->reg_lrc, true);
|
||||
}
|
||||
|
||||
void xe_hw_engine_setup_reg_lrc(struct xe_hw_engine *hwe)
|
||||
{
|
||||
struct xe_gt *gt = hwe->gt;
|
||||
struct xe_device *xe = gt_to_xe(gt);
|
||||
|
||||
xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe);
|
||||
xe_wa_process_lrc(hwe);
|
||||
hw_engine_setup_default_lrc_state(hwe);
|
||||
xe_tuning_process_lrc(hwe);
|
||||
}
|
||||
|
||||
static void
|
||||
hw_engine_setup_default_state(struct xe_hw_engine *hwe)
|
||||
{
|
||||
|
|
@ -503,9 +514,14 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
|
|||
hwe->class = info->class;
|
||||
hwe->instance = info->instance;
|
||||
hwe->mmio_base = info->mmio_base;
|
||||
hwe->irq_offset = xe_device_has_msix(gt_to_xe(gt)) ?
|
||||
get_msix_irq_offset(gt, info->class) :
|
||||
info->irq_offset;
|
||||
if (xe_device_has_msix(gt_to_xe(gt))) {
|
||||
hwe->irq_offset = get_msix_irq_offset(gt, info->class);
|
||||
hwe->irq_page = info->instance;
|
||||
|
||||
} else {
|
||||
hwe->irq_offset = info->irq_offset;
|
||||
hwe->irq_page = 0;
|
||||
}
|
||||
hwe->domain = info->domain;
|
||||
hwe->name = info->name;
|
||||
hwe->fence_irq = >->fence_irq[info->class];
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ struct xe_hw_engine_snapshot *
|
|||
xe_hw_engine_snapshot_capture(struct xe_hw_engine *hwe, struct xe_exec_queue *q);
|
||||
void xe_hw_engine_snapshot_free(struct xe_hw_engine_snapshot *snapshot);
|
||||
void xe_hw_engine_print(struct xe_hw_engine *hwe, struct drm_printer *p);
|
||||
void xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe);
|
||||
void xe_hw_engine_setup_reg_lrc(struct xe_hw_engine *hwe);
|
||||
|
||||
bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe);
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ struct xe_hw_engine {
|
|||
u16 logical_instance;
|
||||
/** @irq_offset: IRQ offset of this hw engine */
|
||||
u16 irq_offset;
|
||||
/** @irq_page: MEMIRQ page used by this HW engine */
|
||||
u16 irq_page;
|
||||
/** @mmio_base: MMIO base address of this hw engine*/
|
||||
u32 mmio_base;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -152,6 +152,16 @@ static const char *guc_name(struct xe_guc *guc)
|
|||
*
|
||||
*/
|
||||
|
||||
/* ISR */
|
||||
#define XE_MEMIRQ_STATUS_OFFSET(inst) ((inst) * SZ_4K + 0x0)
|
||||
/* IIR */
|
||||
#define XE_MEMIRQ_SOURCE_OFFSET(inst) ((inst) * SZ_4K + 0x400)
|
||||
/* IMR */
|
||||
#define XE_MEMIRQ_ENABLE_OFFSET 0x440
|
||||
|
||||
/* engine ISR vector offset */
|
||||
#define XE_MEMIRQ_VECTOR_OFFSET(page, source) (XE_MEMIRQ_STATUS_OFFSET(page) + (source) * SZ_16)
|
||||
|
||||
static inline bool hw_reports_to_instance_zero(struct xe_memirq *memirq)
|
||||
{
|
||||
/*
|
||||
|
|
@ -162,18 +172,35 @@ static inline bool hw_reports_to_instance_zero(struct xe_memirq *memirq)
|
|||
return xe_device_has_msix(memirq_to_xe(memirq));
|
||||
}
|
||||
|
||||
static unsigned int hwe_max_count(struct xe_tile *tile)
|
||||
{
|
||||
unsigned int max_instance = 0;
|
||||
unsigned int gtid, hweid;
|
||||
struct xe_hw_engine *hwe;
|
||||
struct xe_gt *gt;
|
||||
|
||||
for_each_gt_on_tile(gt, tile, gtid)
|
||||
for_each_hw_engine(hwe, gt, hweid)
|
||||
max_instance = max(max_instance, hwe->instance);
|
||||
|
||||
return max_instance + 1;
|
||||
}
|
||||
|
||||
static int memirq_alloc_pages(struct xe_memirq *memirq)
|
||||
{
|
||||
struct xe_device *xe = memirq_to_xe(memirq);
|
||||
struct xe_tile *tile = memirq_to_tile(memirq);
|
||||
size_t bo_size = hw_reports_to_instance_zero(memirq) ?
|
||||
XE_HW_ENGINE_MAX_INSTANCE * SZ_4K : SZ_4K;
|
||||
unsigned int num_pages;
|
||||
struct xe_bo *bo;
|
||||
size_t bo_size;
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(!IS_ALIGNED(XE_MEMIRQ_SOURCE_OFFSET(0), SZ_64));
|
||||
BUILD_BUG_ON(!IS_ALIGNED(XE_MEMIRQ_STATUS_OFFSET(0), SZ_4K));
|
||||
|
||||
num_pages = hw_reports_to_instance_zero(memirq) ? hwe_max_count(tile) : 1;
|
||||
bo_size = num_pages * SZ_4K;
|
||||
|
||||
bo = xe_managed_bo_create_pin_map(xe, tile, bo_size,
|
||||
XE_BO_FLAG_SYSTEM |
|
||||
XE_BO_FLAG_GGTT |
|
||||
|
|
@ -192,16 +219,15 @@ static int memirq_alloc_pages(struct xe_memirq *memirq)
|
|||
|
||||
memirq->bo = bo;
|
||||
memirq->source = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_SOURCE_OFFSET(0));
|
||||
memirq->status = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_STATUS_OFFSET(0));
|
||||
memirq->mask = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_ENABLE_OFFSET);
|
||||
memirq->num_pages = num_pages;
|
||||
|
||||
memirq_assert(memirq, !memirq->source.is_iomem);
|
||||
memirq_assert(memirq, !memirq->status.is_iomem);
|
||||
memirq_assert(memirq, !memirq->mask.is_iomem);
|
||||
|
||||
memirq_debug(memirq, "page offsets: bo %#x bo_size %zu source %#x status %#x\n",
|
||||
xe_bo_ggtt_addr(bo), bo_size, XE_MEMIRQ_SOURCE_OFFSET(0),
|
||||
XE_MEMIRQ_STATUS_OFFSET(0));
|
||||
memirq_debug(memirq, "pages: count %u size %zu\n", num_pages, bo_size);
|
||||
memirq_debug(memirq, "page0: source %#x status %#x mask %#x\n",
|
||||
xe_bo_ggtt_addr(bo) + XE_MEMIRQ_SOURCE_OFFSET(0),
|
||||
xe_bo_ggtt_addr(bo) + XE_MEMIRQ_STATUS_OFFSET(0),
|
||||
xe_bo_ggtt_addr(bo) + XE_MEMIRQ_ENABLE_OFFSET);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -216,7 +242,8 @@ static void memirq_set_enable(struct xe_memirq *memirq, bool enable)
|
|||
* We only care about the GT_MI_USER_INTERRUPT from the engines and
|
||||
* the GuC does not look at the ENABLE mask at all.
|
||||
*/
|
||||
iosys_map_wr(&memirq->mask, 0, u32, enable ? GT_MI_USER_INTERRUPT : 0);
|
||||
iosys_map_wr(&memirq->bo->vmap, XE_MEMIRQ_ENABLE_OFFSET, u32,
|
||||
enable ? GT_MI_USER_INTERRUPT : 0);
|
||||
|
||||
memirq->enabled = enable;
|
||||
}
|
||||
|
|
@ -253,15 +280,6 @@ int xe_memirq_init(struct xe_memirq *memirq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 __memirq_source_page(struct xe_memirq *memirq, u16 instance)
|
||||
{
|
||||
memirq_assert(memirq, instance <= XE_HW_ENGINE_MAX_INSTANCE);
|
||||
memirq_assert(memirq, memirq->bo);
|
||||
|
||||
instance = hw_reports_to_instance_zero(memirq) ? instance : 0;
|
||||
return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_SOURCE_OFFSET(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_memirq_source_ptr - Get GGTT's offset of the `Interrupt Source Report Page`_.
|
||||
* @memirq: the &xe_memirq to query
|
||||
|
|
@ -276,16 +294,7 @@ u32 xe_memirq_source_ptr(struct xe_memirq *memirq, struct xe_hw_engine *hwe)
|
|||
{
|
||||
memirq_assert(memirq, xe_device_uses_memirq(memirq_to_xe(memirq)));
|
||||
|
||||
return __memirq_source_page(memirq, hwe->instance);
|
||||
}
|
||||
|
||||
static u32 __memirq_status_page(struct xe_memirq *memirq, u16 instance)
|
||||
{
|
||||
memirq_assert(memirq, instance <= XE_HW_ENGINE_MAX_INSTANCE);
|
||||
memirq_assert(memirq, memirq->bo);
|
||||
|
||||
instance = hw_reports_to_instance_zero(memirq) ? instance : 0;
|
||||
return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_STATUS_OFFSET(instance);
|
||||
return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_SOURCE_OFFSET(hwe->irq_page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -302,7 +311,7 @@ u32 xe_memirq_status_ptr(struct xe_memirq *memirq, struct xe_hw_engine *hwe)
|
|||
{
|
||||
memirq_assert(memirq, xe_device_uses_memirq(memirq_to_xe(memirq)));
|
||||
|
||||
return __memirq_status_page(memirq, hwe->instance);
|
||||
return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_STATUS_OFFSET(hwe->irq_page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -339,13 +348,14 @@ int xe_memirq_init_guc(struct xe_memirq *memirq, struct xe_guc *guc)
|
|||
{
|
||||
bool is_media = xe_gt_is_media_type(guc_to_gt(guc));
|
||||
u32 offset = is_media ? ilog2(INTR_MGUC) : ilog2(INTR_GUC);
|
||||
u32 source, status;
|
||||
u64 source, status;
|
||||
int err;
|
||||
|
||||
memirq_assert(memirq, xe_device_uses_memirq(memirq_to_xe(memirq)));
|
||||
|
||||
source = __memirq_source_page(memirq, 0) + offset;
|
||||
status = __memirq_status_page(memirq, 0) + offset * SZ_16;
|
||||
/* GuC expects exact locations, it doesn't add anything on its own */
|
||||
source = xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_SOURCE_OFFSET(0) + offset;
|
||||
status = xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_VECTOR_OFFSET(0, offset);
|
||||
|
||||
err = xe_guc_self_cfg64(guc, GUC_KLV_SELF_CFG_MEMIRQ_SOURCE_ADDR_KEY,
|
||||
source);
|
||||
|
|
@ -489,16 +499,16 @@ static void memirq_dispatch_guc(struct xe_memirq *memirq, struct iosys_map *stat
|
|||
*/
|
||||
void xe_memirq_hwe_handler(struct xe_memirq *memirq, struct xe_hw_engine *hwe)
|
||||
{
|
||||
u16 offset = hwe->irq_offset;
|
||||
u16 instance = hw_reports_to_instance_zero(memirq) ? hwe->instance : 0;
|
||||
struct iosys_map src_offset = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap,
|
||||
XE_MEMIRQ_SOURCE_OFFSET(instance));
|
||||
struct iosys_map source =
|
||||
IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap,
|
||||
XE_MEMIRQ_SOURCE_OFFSET(hwe->irq_page));
|
||||
|
||||
if (memirq_received(memirq, &src_offset, offset, "SRC")) {
|
||||
struct iosys_map status_offset =
|
||||
if (memirq_received(memirq, &source, hwe->irq_offset, "SRC")) {
|
||||
struct iosys_map status =
|
||||
IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap,
|
||||
XE_MEMIRQ_STATUS_OFFSET(instance) + offset * SZ_16);
|
||||
memirq_dispatch_engine(memirq, &status_offset, hwe);
|
||||
XE_MEMIRQ_VECTOR_OFFSET(hwe->irq_page,
|
||||
hwe->irq_offset));
|
||||
memirq_dispatch_engine(memirq, &status, hwe);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -513,12 +523,25 @@ bool xe_memirq_guc_sw_int_0_irq_pending(struct xe_memirq *memirq, struct xe_guc
|
|||
{
|
||||
struct xe_gt *gt = guc_to_gt(guc);
|
||||
u32 offset = xe_gt_is_media_type(gt) ? ilog2(INTR_MGUC) : ilog2(INTR_GUC);
|
||||
struct iosys_map map = IOSYS_MAP_INIT_OFFSET(&memirq->status, offset * SZ_16);
|
||||
struct iosys_map map = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap,
|
||||
XE_MEMIRQ_VECTOR_OFFSET(0, offset));
|
||||
|
||||
return memirq_received_noclear(memirq, &map, ilog2(GUC_INTR_SW_INT_0),
|
||||
guc_name(guc));
|
||||
}
|
||||
|
||||
static void memirq_dump_source_pages(struct xe_memirq *memirq)
|
||||
{
|
||||
memirq_assert(memirq, !memirq->bo->vmap.is_iomem);
|
||||
|
||||
for (int n = 0; n < memirq->num_pages; n++) {
|
||||
memirq_debug(memirq, "SOURCE %*ph\n", 32,
|
||||
memirq->bo->vmap.vaddr + XE_MEMIRQ_SOURCE_OFFSET(n));
|
||||
memirq_debug(memirq, "SOURCE %*ph\n", 32,
|
||||
memirq->bo->vmap.vaddr + XE_MEMIRQ_SOURCE_OFFSET(n) + 32);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_memirq_handler - The `Memory Based Interrupts`_ Handler.
|
||||
* @memirq: the &xe_memirq
|
||||
|
|
@ -538,9 +561,8 @@ void xe_memirq_handler(struct xe_memirq *memirq)
|
|||
if (!memirq->bo)
|
||||
return;
|
||||
|
||||
memirq_assert(memirq, !memirq->source.is_iomem);
|
||||
memirq_debug(memirq, "SOURCE %*ph\n", 32, memirq->source.vaddr);
|
||||
memirq_debug(memirq, "SOURCE %*ph\n", 32, memirq->source.vaddr + 32);
|
||||
if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEMIRQ))
|
||||
memirq_dump_source_pages(memirq);
|
||||
|
||||
for_each_gt(gt, xe, gtid) {
|
||||
if (gt->tile != tile)
|
||||
|
|
@ -553,7 +575,8 @@ void xe_memirq_handler(struct xe_memirq *memirq)
|
|||
/* GuC and media GuC (if present) must be checked separately */
|
||||
|
||||
if (memirq_received(memirq, &memirq->source, ilog2(INTR_GUC), "SRC")) {
|
||||
map = IOSYS_MAP_INIT_OFFSET(&memirq->status, ilog2(INTR_GUC) * SZ_16);
|
||||
map = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap,
|
||||
XE_MEMIRQ_VECTOR_OFFSET(0, ilog2(INTR_GUC)));
|
||||
memirq_dispatch_guc(memirq, &map, &tile->primary_gt->uc.guc);
|
||||
}
|
||||
|
||||
|
|
@ -561,7 +584,8 @@ void xe_memirq_handler(struct xe_memirq *memirq)
|
|||
return;
|
||||
|
||||
if (memirq_received(memirq, &memirq->source, ilog2(INTR_MGUC), "SRC")) {
|
||||
map = IOSYS_MAP_INIT_OFFSET(&memirq->status, ilog2(INTR_MGUC) * SZ_16);
|
||||
map = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap,
|
||||
XE_MEMIRQ_VECTOR_OFFSET(0, ilog2(INTR_MGUC)));
|
||||
memirq_dispatch_guc(memirq, &map, &tile->media_gt->uc.guc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,27 +10,18 @@
|
|||
|
||||
struct xe_bo;
|
||||
|
||||
/* ISR */
|
||||
#define XE_MEMIRQ_STATUS_OFFSET(inst) ((inst) * SZ_4K + 0x0)
|
||||
/* IIR */
|
||||
#define XE_MEMIRQ_SOURCE_OFFSET(inst) ((inst) * SZ_4K + 0x400)
|
||||
/* IMR */
|
||||
#define XE_MEMIRQ_ENABLE_OFFSET 0x440
|
||||
|
||||
/**
|
||||
* struct xe_memirq - Data used by the `Memory Based Interrupts`_.
|
||||
*
|
||||
* @bo: buffer object with `Memory Based Interrupts Page Layout`_.
|
||||
* @num_pages: number of per-instance source/status pages.
|
||||
* @source: iosys pointer to `Interrupt Source Report Page`_.
|
||||
* @status: iosys pointer to `Interrupt Status Report Page`_.
|
||||
* @mask: iosys pointer to Interrupt Enable Mask.
|
||||
* @enabled: internal flag used to control processing of the interrupts.
|
||||
*/
|
||||
struct xe_memirq {
|
||||
struct xe_bo *bo;
|
||||
unsigned int num_pages;
|
||||
struct iosys_map source;
|
||||
struct iosys_map status;
|
||||
struct iosys_map mask;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2051,8 +2051,10 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
|
|||
if (XE_IOCTL_DBG(oa->xe, !param.exec_q))
|
||||
return -ENOENT;
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, param.exec_q->width > 1))
|
||||
return -EOPNOTSUPP;
|
||||
if (XE_IOCTL_DBG(oa->xe, param.exec_q->width > 1)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_exec_q;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -444,6 +444,7 @@ static const struct xe_device_desc nvls_desc = {
|
|||
.has_display = true,
|
||||
.has_flat_ccs = 1,
|
||||
.has_pre_prod_wa = 1,
|
||||
.has_sriov = true,
|
||||
.max_gt_per_tile = 2,
|
||||
MULTI_LRC_MASK,
|
||||
.require_force_probe = true,
|
||||
|
|
@ -482,6 +483,7 @@ static const struct xe_device_desc nvlp_desc = {
|
|||
.has_flat_ccs = 1,
|
||||
.has_page_reclaim_hw_assist = true,
|
||||
.has_pre_prod_wa = true,
|
||||
.has_sriov = true,
|
||||
.max_gt_per_tile = 2,
|
||||
MULTI_LRC_MASK,
|
||||
.require_force_probe = true,
|
||||
|
|
|
|||
|
|
@ -70,14 +70,49 @@ static void reg_sr_inc_error(struct xe_reg_sr *sr)
|
|||
#endif
|
||||
}
|
||||
|
||||
static struct xe_reg sanitize_mcr(struct xe_reg_sr *sr,
|
||||
const struct xe_reg_sr_entry *e,
|
||||
struct xe_gt *gt)
|
||||
{
|
||||
struct xe_reg reg = e->reg;
|
||||
bool is_mcr;
|
||||
|
||||
/*
|
||||
* We need the gt structure to check MCR ranges.
|
||||
*/
|
||||
if (!gt)
|
||||
return reg;
|
||||
|
||||
is_mcr = xe_gt_mcr_check_reg(gt, reg);
|
||||
|
||||
if (is_mcr && !reg.mcr) {
|
||||
reg.mcr = 1;
|
||||
xe_gt_notice(gt, "xe_reg_sr_entry using non-MCR register for address 0x%x, forcing MCR\n",
|
||||
reg.addr);
|
||||
reg_sr_inc_error(sr);
|
||||
}
|
||||
|
||||
if (!is_mcr && reg.mcr) {
|
||||
reg.mcr = 0;
|
||||
xe_gt_notice(gt, "xe_reg_sr_entry using MCR register for address 0x%x, forcing non-MCR\n",
|
||||
reg.addr);
|
||||
reg_sr_inc_error(sr);
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
int xe_reg_sr_add(struct xe_reg_sr *sr,
|
||||
const struct xe_reg_sr_entry *e,
|
||||
struct xe_gt *gt)
|
||||
{
|
||||
unsigned long idx = e->reg.addr;
|
||||
struct xe_reg_sr_entry *pentry = xa_load(&sr->xa, idx);
|
||||
struct xe_reg reg;
|
||||
int ret;
|
||||
|
||||
reg = sanitize_mcr(sr, e, gt);
|
||||
|
||||
if (pentry) {
|
||||
if (!compatible_entries(pentry, e)) {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -98,6 +133,7 @@ int xe_reg_sr_add(struct xe_reg_sr *sr,
|
|||
}
|
||||
|
||||
*pentry = *e;
|
||||
pentry->reg = reg;
|
||||
ret = xa_err(xa_store(&sr->xa, idx, pentry, GFP_KERNEL));
|
||||
if (ret)
|
||||
goto fail_free;
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ static const struct xe_rtp_entry_sr engine_tunings[] = {
|
|||
static const struct xe_rtp_entry_sr lrc_tunings[] = {
|
||||
{ XE_RTP_NAME("Tuning: Windower HW Filtering"),
|
||||
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3599), ENGINE_CLASS(RENDER)),
|
||||
XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, HW_FILTERING))
|
||||
XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN4, HW_FILTERING))
|
||||
},
|
||||
|
||||
/* DG2 */
|
||||
|
|
|
|||
|
|
@ -664,7 +664,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
|
|||
},
|
||||
{ XE_RTP_NAME("18033852989"),
|
||||
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)),
|
||||
XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST))
|
||||
XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST))
|
||||
},
|
||||
{ XE_RTP_NAME("15016589081"),
|
||||
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)),
|
||||
|
|
@ -767,7 +767,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
|
|||
},
|
||||
{ XE_RTP_NAME("22021007897"),
|
||||
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)),
|
||||
XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE))
|
||||
XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE))
|
||||
},
|
||||
|
||||
/* Xe3_LPG */
|
||||
|
|
@ -783,7 +783,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
|
|||
},
|
||||
{ XE_RTP_NAME("22021007897"),
|
||||
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_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE))
|
||||
},
|
||||
{ XE_RTP_NAME("14024681466"),
|
||||
XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user