diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-01-16 13:39:15 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-01-16 13:39:44 +1000 |
| commit | 971c2b68bddb87f4929e66cd4563fca78b722210 (patch) | |
| tree | 3bc70fe3059e143f0f0f9425f39b83ae02da4617 | |
| parent | 9d10cd526111a989eb353c3a4df9d4c79695ea8d (diff) | |
| parent | 83675851547e835c15252c601f41acf269c351d9 (diff) | |
Merge tag 'drm-xe-next-2026-01-15' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next
UAPI Changes:
- Remove unused KEEP_ACTIVE flag in the new multi queue uAPI (Niranjana)
- Expose new temperature attributes in HWMON (Karthik)
Driver Changes:
- Force i2c into polling mode when in survivability (Raag)
- Validate preferred system memory placement in xe_svm_range_validate (Brost)
- Adjust page count tracepoints in shrinker (Brost)
- Fix a couple drm_pagemap issues with multi-GPU (Brost)
- Define GuC firmware for NVL-S (Roper)
- Handle GT resume failure (Raag)
- Improve wedged mode handling (Lukasz)
- Add missing newlines to drm_warn messages (Osama)
- Fix WQ_MEM_RECLAIM passed as max_active to alloc_workqueue (Marco)
- Page-reclaim fixes and PRL stats addition (Brian)
- Fix struct guc_lfd_file_header kernel-doc (Jani)
- Allow compressible surfaces to be 1-way coherent (Xin)
- Fix DRM scheduler layering violations in Xe (Brost)
- Minor improvements to MERT code (Michal)
- Privatize struct xe_ggtt_node (Maarten)
- Convert wait for lmem init into an assert (Bala)
- Enable GSC loading and PXP for PTL (Daniele)
- Replace use of system_wq with tlb_inval->timeout_wq (Marco)
- VRAM addr range bit expansion (Fei)
- Cleanup unused header includes (Roper)
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patch.msgid.link/aWkSxRQK7VhTlP32@intel.com
134 files changed, 1391 insertions, 973 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon index d9e2b17c6872..55ab45f669ac 100644 --- a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon +++ b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon @@ -109,6 +109,22 @@ Description: RO. Package current voltage in millivolt. Only supported for particular Intel Xe graphics platforms. +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_crit +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Package critical temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_emergency +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Package shutdown temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_input Date: March 2025 KernelVersion: 6.15 @@ -117,6 +133,30 @@ Description: RO. Package temperature in millidegree Celsius. Only supported for particular Intel Xe graphics platforms. +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_max +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Package maximum temperature limit in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_crit +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. VRAM critical temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_emergency +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. VRAM shutdown temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_input Date: March 2025 KernelVersion: 6.15 @@ -125,6 +165,76 @@ Description: RO. VRAM temperature in millidegree Celsius. Only supported for particular Intel Xe graphics platforms. +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp4_crit +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Memory controller critical temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp4_emergency +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Memory controller shutdown temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp4_input +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. Memory controller average temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp5_crit +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. GPU PCIe critical temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp5_emergency +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. GPU PCIe shutdown temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp5_input +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. GPU PCIe temperature in millidegree Celsius. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp[6-21]_crit +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. VRAM channel critical temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp[6-21]_emergency +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. VRAM channel shutdown temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp[6-21]_input +Date: January 2026 +KernelVersion: 7.0 +Contact: intel-xe@lists.freedesktop.org +Description: RO. VRAM channel temperature in millidegree Celsius. + + Only supported for particular Intel Xe graphics platforms. + What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan1_input Date: March 2025 KernelVersion: 6.16 diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c index ba099aa7c52f..03ee39a761a4 100644 --- a/drivers/gpu/drm/drm_pagemap.c +++ b/drivers/gpu/drm/drm_pagemap.c @@ -480,8 +480,18 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation, .start = start, .end = end, .pgmap_owner = pagemap->owner, - .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT | - MIGRATE_VMA_SELECT_DEVICE_PRIVATE, + /* + * FIXME: MIGRATE_VMA_SELECT_DEVICE_PRIVATE intermittently + * causes 'xe_exec_system_allocator --r *race*no*' to trigger aa + * engine reset and a hard hang due to getting stuck on a folio + * lock. This should work and needs to be root-caused. The only + * downside of not selecting MIGRATE_VMA_SELECT_DEVICE_PRIVATE + * is that device-to-device migrations won’t work; instead, + * memory will bounce through system memory. This path should be + * rare and only occur when the madvise attributes of memory are + * changed or atomics are being used. + */ + .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT, }; unsigned long i, npages = npages_in_range(start, end); unsigned long own_pages = 0, migrated_pages = 0; @@ -582,7 +592,7 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation, err = ops->populate_devmem_pfn(devmem_allocation, npages, migrate.dst); if (err) - goto err_finalize; + goto err_aborted_migration; own_pages = 0; @@ -621,8 +631,10 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation, err = drm_pagemap_migrate_range(devmem_allocation, migrate.src, migrate.dst, pages, pagemap_addr, &last, &cur, mdetails); - if (err) + if (err) { + npages = i + 1; goto err_finalize; + } } cur.start = npages; cur.ops = NULL; /* Force migration */ @@ -646,7 +658,7 @@ err_finalize: err_aborted_migration: migrate_vma_pages(&migrate); - for (i = 0; i < npages;) { + for (i = 0; !err && i < npages;) { struct page *page = migrate_pfn_to_page(migrate.src[i]); unsigned long nr_pages = page ? NR_PAGES(folio_order(page_folio(page))) : 1; diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 2b20c79d7ec9..b39cbb756232 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -370,7 +370,8 @@ always-$(CONFIG_DRM_XE_WERROR) += \ $(patsubst %.h,%.hdrtest, $(shell cd $(src) && find * -name '*.h' $(hdrtest_find_args))) quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) - cmd_hdrtest = $(CC) -DHDRTEST $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@ + cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $< -include $<; \ + $(srctree)/scripts/kernel-doc -none -Werror $<; touch $@ $(obj)/%.hdrtest: $(src)/%.h FORCE $(call if_changed_dep,hdrtest) diff --git a/drivers/gpu/drm/xe/abi/guc_lfd_abi.h b/drivers/gpu/drm/xe/abi/guc_lfd_abi.h index b6ed20d5b508..5c48459f365f 100644 --- a/drivers/gpu/drm/xe/abi/guc_lfd_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_lfd_abi.h @@ -148,7 +148,7 @@ struct guc_lfd_data_os_info { } __packed; /** - * struct guc_logfile_header - Header of GuC Log Streaming-LFD-File Format. + * struct guc_lfd_file_header - Header of GuC Log Streaming-LFD-File Format. * This structure encapsulates the layout of the guc-log-file format */ struct guc_lfd_file_header { @@ -163,8 +163,7 @@ struct guc_lfd_file_header { #define GUC_LFD_FILE_HEADER_VERSION_MASK_MAJOR GENMASK(31, 16) #define GUC_LFD_FILE_HEADER_VERSION_MASK_MINOR GENMASK(15, 0) - /** @stream: A stream of one or more guc_lfd_data LFD blocks - */ + /** @stream: A stream of one or more guc_lfd_data LFD blocks */ u32 stream[]; } __packed; diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h index b17e3bab23d5..c4b5adaaa99a 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h @@ -8,7 +8,7 @@ #include <uapi/drm/i915_drm.h> -#include "xe_ggtt_types.h" +#include "xe_ggtt.h" #include <linux/refcount.h> @@ -30,7 +30,7 @@ struct i915_vma { static inline u32 i915_ggtt_offset(const struct i915_vma *vma) { - return vma->node->base.start; + return xe_ggtt_node_addr(vma->node); } #endif diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index a22a9182dadb..d2c4e94180fa 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -171,12 +171,13 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, } static void -write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo_ofs, +write_ggtt_rotated(struct xe_ggtt *ggtt, u32 *ggtt_ofs, + u64 pte_flags, + xe_ggtt_set_pte_fn write_pte, + struct xe_bo *bo, u32 bo_ofs, u32 width, u32 height, u32 src_stride, u32 dst_stride) { - struct xe_device *xe = xe_bo_device(bo); u32 column, row; - u64 pte = ggtt->pt_ops->pte_encode_flags(bo, xe->pat.idx[XE_CACHE_NONE]); for (column = 0; column < width; column++) { u32 src_idx = src_stride * (height - 1) + column + bo_ofs; @@ -184,7 +185,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo for (row = 0; row < height; row++) { u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, XE_PAGE_SIZE); - ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte | addr); + write_pte(ggtt, *ggtt_ofs, pte_flags | addr); *ggtt_ofs += XE_PAGE_SIZE; src_idx -= src_stride; } @@ -194,6 +195,28 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo } } +struct fb_rotate_args { + const struct i915_gtt_view *view; + struct xe_bo *bo; +}; + +static void write_ggtt_rotated_node(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, + u64 pte_flags, xe_ggtt_set_pte_fn write_pte, void *data) +{ + struct fb_rotate_args *args = data; + struct xe_bo *bo = args->bo; + const struct intel_rotation_info *rot_info = &args->view->rotated; + u32 ggtt_ofs = xe_ggtt_node_addr(node); + + for (u32 i = 0; i < ARRAY_SIZE(rot_info->plane); i++) + write_ggtt_rotated(ggtt, &ggtt_ofs, pte_flags, write_pte, + bo, rot_info->plane[i].offset, + rot_info->plane[i].width, + rot_info->plane[i].height, + rot_info->plane[i].src_stride, + rot_info->plane[i].dst_stride); +} + static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, const struct i915_gtt_view *view, struct i915_vma *vma, @@ -204,66 +227,43 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, struct xe_device *xe = to_xe_device(fb->base.dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); struct xe_ggtt *ggtt = tile0->mem.ggtt; + u64 pte, size; u32 align; - int ret; + int ret = 0; /* TODO: Consider sharing framebuffer mapping? * embed i915_vma inside intel_framebuffer */ guard(xe_pm_runtime_noresume)(xe); - ACQUIRE(mutex_intr, lock)(&ggtt->lock); - ret = ACQUIRE_ERR(mutex_intr, &lock); - if (ret) - return ret; align = XE_PAGE_SIZE; - if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) - align = max_t(u32, align, SZ_64K); + if (xe_bo_is_vram(bo) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) + align = max(align, SZ_64K); + /* Fast case, preallocated GGTT view? */ if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) { vma->node = bo->ggtt_node[tile0->id]; - } else if (view->type == I915_GTT_VIEW_NORMAL) { - vma->node = xe_ggtt_node_init(ggtt); - if (IS_ERR(vma->node)) - return PTR_ERR(vma->node); - - ret = xe_ggtt_node_insert_locked(vma->node, xe_bo_size(bo), align, 0); - if (ret) { - xe_ggtt_node_fini(vma->node); - return ret; - } - - xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]); - } else { - u32 i, ggtt_ofs; - const struct intel_rotation_info *rot_info = &view->rotated; - - /* display seems to use tiles instead of bytes here, so convert it back.. */ - u32 size = intel_rotation_info_size(rot_info) * XE_PAGE_SIZE; - - vma->node = xe_ggtt_node_init(ggtt); - if (IS_ERR(vma->node)) { - ret = PTR_ERR(vma->node); - return ret; - } - - ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0); - if (ret) { - xe_ggtt_node_fini(vma->node); - return ret; - } - - ggtt_ofs = vma->node->base.start; - - for (i = 0; i < ARRAY_SIZE(rot_info->plane); i++) - write_ggtt_rotated(bo, ggtt, &ggtt_ofs, - rot_info->plane[i].offset, - rot_info->plane[i].width, - rot_info->plane[i].height, - rot_info->plane[i].src_stride, - rot_info->plane[i].dst_stride); + return 0; } + /* TODO: Consider sharing framebuffer mapping? + * embed i915_vma inside intel_framebuffer + */ + if (view->type == I915_GTT_VIEW_NORMAL) + size = xe_bo_size(bo); + else + /* display uses tiles instead of bytes here, so convert it back.. */ + size = intel_rotation_info_size(&view->rotated) * XE_PAGE_SIZE; + + pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + vma->node = xe_ggtt_node_insert_transform(ggtt, bo, pte, + ALIGN(size, align), align, + view->type == I915_GTT_VIEW_NORMAL ? + NULL : write_ggtt_rotated_node, + &(struct fb_rotate_args){view, bo}); + if (IS_ERR(vma->node)) + ret = PTR_ERR(vma->node); + return ret; } @@ -353,7 +353,7 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) if (vma->dpt) xe_bo_unpin_map_no_vm(vma->dpt); else if (!xe_ggtt_node_allocated(vma->bo->ggtt_node[tile_id]) || - vma->bo->ggtt_node[tile_id]->base.start != vma->node->base.start) + vma->bo->ggtt_node[tile_id] != vma->node) xe_ggtt_node_remove(vma->node, false); ttm_bo_reserve(&vma->bo->ttm, false, false, NULL); diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 07acae121aa7..ed1f65f5ef4d 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -39,7 +39,7 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm) struct xe_gt *gt = tile->media_gt; struct xe_gsc *gsc = >->uc.gsc; - if (!gsc || !xe_uc_fw_is_enabled(&gsc->fw)) { + if (!gsc || !xe_uc_fw_is_available(&gsc->fw)) { drm_dbg_kms(&xe->drm, "GSC Components not ready for HDCP2.x\n"); return false; diff --git a/drivers/gpu/drm/xe/display/xe_stolen.c b/drivers/gpu/drm/xe/display/xe_stolen.c index 12771709183a..8dc2f86ec602 100644 --- a/drivers/gpu/drm/xe/display/xe_stolen.c +++ b/drivers/gpu/drm/xe/display/xe_stolen.c @@ -78,7 +78,7 @@ static u64 xe_stolen_node_address(const struct intel_stolen_node *node) static u64 xe_stolen_node_size(const struct intel_stolen_node *node) { - return node->bo->ttm.base.size; + return xe_bo_size(node->bo); } static struct intel_stolen_node *xe_stolen_node_alloc(struct drm_device *drm) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 93643da57428..24fc64fc832e 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -89,6 +89,7 @@ #define UNIFIED_COMPRESSION_FORMAT REG_GENMASK(3, 0) #define XE2_GAMREQSTRM_CTRL XE_REG_MCR(0x4194) +#define EN_CMP_1WCOH REG_BIT(15) #define CG_DIS_CNTLBUS REG_BIT(6) #define CCS_AUX_INV XE_REG(0x4208) @@ -101,6 +102,11 @@ #define XE2_LMEM_CFG XE_REG(0x48b0) +#define XE2_GAMWALK_CTRL 0x47e4 +#define XE2_GAMWALK_CTRL_MEDIA XE_REG(XE2_GAMWALK_CTRL + MEDIA_GT_GSI_OFFSET) +#define XE2_GAMWALK_CTRL_3D XE_REG_MCR(XE2_GAMWALK_CTRL) +#define EN_CMP_1WCOH_GW REG_BIT(14) + #define XEHP_FLAT_CCS_BASE_ADDR XE_REG_MCR(0x4910) #define XEHP_FLAT_CCS_PTR REG_GENMASK(31, 8) diff --git a/drivers/gpu/drm/xe/regs/xe_mert_regs.h b/drivers/gpu/drm/xe/regs/xe_mert_regs.h index c345e11ceea8..99e5a26da657 100644 --- a/drivers/gpu/drm/xe/regs/xe_mert_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_mert_regs.h @@ -11,11 +11,13 @@ #define MERT_LMEM_CFG XE_REG(0x1448b0) #define MERT_TLB_CT_INTR_ERR_ID_PORT XE_REG(0x145190) -#define MERT_TLB_CT_VFID_MASK REG_GENMASK(16, 9) -#define MERT_TLB_CT_ERROR_MASK REG_GENMASK(5, 0) -#define MERT_TLB_CT_LMTT_FAULT 0x05 +#define CATERR_VFID REG_GENMASK(16, 9) +#define CATERR_CODES REG_GENMASK(5, 0) +#define CATERR_NO_ERROR 0x00 +#define CATERR_UNMAPPED_GGTT 0x01 +#define CATERR_LMTT_FAULT 0x05 #define MERT_TLB_INV_DESC_A XE_REG(0x14cf7c) #define MERT_TLB_INV_DESC_A_VALID REG_BIT(0) -#endif /* _XE_MERT_REGS_H_ */ +#endif diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h index fb097607b86c..4b3c46eb858f 100644 --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h @@ -21,7 +21,10 @@ #define BMG_FAN_1_SPEED XE_REG(0x138140) #define BMG_FAN_2_SPEED XE_REG(0x138170) #define BMG_FAN_3_SPEED XE_REG(0x1381a0) +#define BMG_VRAM_TEMPERATURE_N(n) XE_REG(0x138260 + ((n) * (sizeof(u32)))) #define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0) +#define TEMP_MASK_VRAM_N REG_GENMASK(30, 8) +#define TEMP_SIGN_MASK REG_BIT(31) #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) #endif /* _XE_PCODE_REGS_H_ */ diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c index 2278e589a493..b7d8e45804cf 100644 --- a/drivers/gpu/drm/xe/tests/xe_bo.c +++ b/drivers/gpu/drm/xe/tests/xe_bo.c @@ -18,6 +18,7 @@ #include "tests/xe_test.h" #include "xe_bo_evict.h" +#include "xe_gt.h" #include "xe_pci.h" #include "xe_pm.h" diff --git a/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c index d266882adc0e..acddbedcf17c 100644 --- a/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c +++ b/drivers/gpu/drm/xe/tests/xe_guc_buf_kunit.c @@ -67,7 +67,7 @@ static int guc_buf_test_init(struct kunit *test) KUNIT_ASSERT_EQ(test, 0, xe_ggtt_init_kunit(ggtt, DUT_GGTT_START, - DUT_GGTT_START + DUT_GGTT_SIZE)); + DUT_GGTT_SIZE)); kunit_activate_static_stub(test, xe_managed_bo_create_pin_map, replacement_xe_managed_bo_create_pin_map); diff --git a/drivers/gpu/drm/xe/xe_bb.c b/drivers/gpu/drm/xe/xe_bb.c index 6d20229c11de..8b678297aaa2 100644 --- a/drivers/gpu/drm/xe/xe_bb.c +++ b/drivers/gpu/drm/xe/xe_bb.c @@ -7,10 +7,9 @@ #include "instructions/xe_mi_commands.h" #include "xe_assert.h" -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_exec_queue_types.h" #include "xe_gt.h" -#include "xe_hw_fence.h" #include "xe_sa.h" #include "xe_sched_job.h" #include "xe_vm_types.h" diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 8b6474cd3eaf..e9180b01a4e4 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -26,9 +26,9 @@ #include "xe_dma_buf.h" #include "xe_drm_client.h" #include "xe_ggtt.h" -#include "xe_gt.h" #include "xe_map.h" #include "xe_migrate.h" +#include "xe_pat.h" #include "xe_pm.h" #include "xe_preempt_fence.h" #include "xe_pxp.h" @@ -1054,6 +1054,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, unsigned long *scanned) { struct xe_device *xe = ttm_to_xe_device(bo->bdev); + struct ttm_tt *tt = bo->ttm; long lret; /* Fake move to system, without copying data. */ @@ -1078,8 +1079,10 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, .writeback = false, .allow_move = false}); - if (lret > 0) + if (lret > 0) { xe_ttm_tt_account_subtract(xe, bo->ttm); + update_global_total_pages(bo->bdev, -(long)tt->num_pages); + } return lret; } @@ -1165,8 +1168,10 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, if (needs_rpm) xe_pm_runtime_put(xe); - if (lret > 0) + if (lret > 0) { xe_ttm_tt_account_subtract(xe, tt); + update_global_total_pages(bo->bdev, -(long)tt->num_pages); + } out_unref: xe_bo_put(xe_bo); @@ -1709,7 +1714,7 @@ static void xe_ttm_bo_destroy(struct ttm_buffer_object *ttm_bo) xe_assert(xe, list_empty(&ttm_bo->base.gpuva.list)); for_each_tile(tile, xe, id) - if (bo->ggtt_node[id] && bo->ggtt_node[id]->base.size) + if (bo->ggtt_node[id]) xe_ggtt_remove_bo(tile->mem.ggtt, bo); #ifdef CONFIG_PROC_FS @@ -3517,16 +3522,16 @@ bool xe_bo_needs_ccs_pages(struct xe_bo *bo) if (IS_DGFX(xe) && (bo->flags & XE_BO_FLAG_SYSTEM)) return false; + /* Check if userspace explicitly requested no compression */ + if (bo->flags & XE_BO_FLAG_NO_COMPRESSION) + return false; + /* - * Compression implies coh_none, therefore we know for sure that WB - * memory can't currently use compression, which is likely one of the - * common cases. - * Additionally, userspace may explicitly request no compression via the - * DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION flag, which should also disable - * CCS usage. + * For WB (Write-Back) CPU caching mode, check if the device + * supports WB compression with coherency. */ - if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB || - bo->flags & XE_BO_FLAG_NO_COMPRESSION) + if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB && + xe->pat.idx[XE_CACHE_WB_COMPRESSION] == XE_PAT_INVALID_IDX) return false; return true; @@ -3603,8 +3608,8 @@ void xe_bo_put(struct xe_bo *bo) might_lock(&bo->client->bos_lock); #endif for_each_tile(tile, xe_bo_device(bo), id) - if (bo->ggtt_node[id] && bo->ggtt_node[id]->ggtt) - xe_ggtt_might_lock(bo->ggtt_node[id]->ggtt); + if (bo->ggtt_node[id]) + xe_ggtt_might_lock(tile->mem.ggtt); drm_gem_object_put(&bo->ttm.base); } } diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h index 8ab4474129c3..c914ab719f20 100644 --- a/drivers/gpu/drm/xe/xe_bo.h +++ b/drivers/gpu/drm/xe/xe_bo.h @@ -9,6 +9,7 @@ #include <drm/ttm/ttm_tt.h> #include "xe_bo_types.h" +#include "xe_ggtt.h" #include "xe_macros.h" #include "xe_validation.h" #include "xe_vm_types.h" @@ -252,13 +253,14 @@ static inline u32 __xe_bo_ggtt_addr(struct xe_bo *bo, u8 tile_id) { struct xe_ggtt_node *ggtt_node = bo->ggtt_node[tile_id]; + u64 offset; if (XE_WARN_ON(!ggtt_node)) return 0; - XE_WARN_ON(ggtt_node->base.size > xe_bo_size(bo)); - XE_WARN_ON(ggtt_node->base.start + ggtt_node->base.size > (1ull << 32)); - return ggtt_node->base.start; + offset = xe_ggtt_node_addr(ggtt_node); + XE_WARN_ON(offset + xe_bo_size(bo) > (1ull << 32)); + return offset; } static inline u32 diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index 0907868b32d6..844cfafe1ec7 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -254,36 +254,81 @@ static ssize_t wedged_mode_show(struct file *f, char __user *ubuf, return simple_read_from_buffer(ubuf, size, pos, buf, len); } +static int __wedged_mode_set_reset_policy(struct xe_gt *gt, enum xe_wedged_mode mode) +{ + bool enable_engine_reset; + int ret; + + enable_engine_reset = (mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET); + ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads, + enable_engine_reset); + if (ret) + xe_gt_err(gt, "Failed to update GuC ADS scheduler policy (%pe)\n", ERR_PTR(ret)); + + return ret; +} + +static int wedged_mode_set_reset_policy(struct xe_device *xe, enum xe_wedged_mode mode) +{ + struct xe_gt *gt; + int ret; + u8 id; + + guard(xe_pm_runtime)(xe); + for_each_gt(gt, xe, id) { + ret = __wedged_mode_set_reset_policy(gt, mode); + if (ret) { + if (id > 0) { + xe->wedged.inconsistent_reset = true; + drm_err(&xe->drm, "Inconsistent reset policy state between GTs\n"); + } + return ret; + } + } + + xe->wedged.inconsistent_reset = false; + + return 0; +} + +static bool wedged_mode_needs_policy_update(struct xe_device *xe, enum xe_wedged_mode mode) +{ + if (xe->wedged.inconsistent_reset) + return true; + + if (xe->wedged.mode == mode) + return false; + + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET || + mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) + return true; + + return false; +} + static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, size_t size, loff_t *pos) { struct xe_device *xe = file_inode(f)->i_private; - struct xe_gt *gt; u32 wedged_mode; ssize_t ret; - u8 id; ret = kstrtouint_from_user(ubuf, size, 0, &wedged_mode); if (ret) return ret; - if (wedged_mode > 2) - return -EINVAL; + ret = xe_device_validate_wedged_mode(xe, wedged_mode); + if (ret) + return ret; - if (xe->wedged.mode == wedged_mode) - return size; + if (wedged_mode_needs_policy_update(xe, wedged_mode)) { + ret = wedged_mode_set_reset_policy(xe, wedged_mode); + if (ret) + return ret; + } xe->wedged.mode = wedged_mode; - guard(xe_pm_runtime)(xe); - for_each_gt(gt, xe, id) { - ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads); - if (ret) { - xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); - return -EIO; - } - } - return size; } diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index 7263c2a5f3a8..cf41bb6d2172 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -15,14 +15,13 @@ #include "xe_device.h" #include "xe_exec_queue.h" #include "xe_force_wake.h" -#include "xe_gt.h" #include "xe_gt_printk.h" +#include "xe_gt_types.h" #include "xe_guc_capture.h" #include "xe_guc_ct.h" #include "xe_guc_log.h" #include "xe_guc_submit.h" #include "xe_hw_engine.h" -#include "xe_module.h" #include "xe_pm.h" #include "xe_sched_job.h" #include "xe_vm.h" diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index e101d290b2a6..495310a624b5 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -8,7 +8,6 @@ #include <linux/aperture.h> #include <linux/delay.h> #include <linux/fault-inject.h> -#include <linux/iopoll.h> #include <linux/units.h> #include <drm/drm_atomic_helper.h> @@ -36,7 +35,6 @@ #include "xe_exec_queue.h" #include "xe_force_wake.h" #include "xe_ggtt.h" -#include "xe_gsc_proxy.h" #include "xe_gt.h" #include "xe_gt_mcr.h" #include "xe_gt_printk.h" @@ -180,12 +178,7 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) xa_for_each(&xef->exec_queue.xa, idx, q) { if (q->vm && q->hwe->hw_engine_group) xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); - - if (xe_exec_queue_is_multi_queue_primary(q)) - xe_exec_queue_group_kill_put(q->multi_queue.group); - else - xe_exec_queue_kill(q); - + xe_exec_queue_kill(q); xe_exec_queue_put(q); } xa_for_each(&xef->vm.xa, idx, vm) @@ -659,62 +652,14 @@ mask_err: return err; } -static int lmem_initializing(struct xe_device *xe) +static void assert_lmem_ready(struct xe_device *xe) { - if (xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & LMEM_INIT) - return 0; - - if (signal_pending(current)) - return -EINTR; - - return 1; -} - -static int wait_for_lmem_ready(struct xe_device *xe) -{ - const unsigned long TIMEOUT_SEC = 60; - unsigned long prev_jiffies; - int initializing; - - if (!IS_DGFX(xe)) - return 0; - - if (IS_SRIOV_VF(xe)) - return 0; - - if (!lmem_initializing(xe)) - return 0; - - drm_dbg(&xe->drm, "Waiting for lmem initialization\n"); - prev_jiffies = jiffies; - - /* - * The boot firmware initializes local memory and - * assesses its health. If memory training fails, - * the punit will have been instructed to keep the GT powered - * down.we won't be able to communicate with it - * - * If the status check is done before punit updates the register, - * it can lead to the system being unusable. - * use a timeout and defer the probe to prevent this. - */ - poll_timeout_us(initializing = lmem_initializing(xe), - initializing <= 0, - 20 * USEC_PER_MSEC, TIMEOUT_SEC * USEC_PER_SEC, true); - if (initializing < 0) - return initializing; - - if (initializing) { - drm_dbg(&xe->drm, "lmem not initialized by firmware\n"); - return -EPROBE_DEFER; - } - - drm_dbg(&xe->drm, "lmem ready after %ums", - jiffies_to_msecs(jiffies - prev_jiffies)); + if (!IS_DGFX(xe) || IS_SRIOV_VF(xe)) + return; - return 0; + xe_assert(xe, xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & + LMEM_INIT); } -ALLOW_ERROR_INJECTION(wait_for_lmem_ready, ERRNO); /* See xe_pci_probe() */ static void vf_update_device_info(struct xe_device *xe) { @@ -769,6 +714,11 @@ int xe_device_probe_early(struct xe_device *xe) if (IS_SRIOV_VF(xe)) vf_update_device_info(xe); + /* + * Check for pcode uncore_init status to confirm if the SoC + * initialization is complete. Until done, any MMIO or lmem access from + * the driver will be blocked + */ err = xe_pcode_probe_early(xe); if (err || xe_survivability_mode_is_requested(xe)) { int save_err = err; @@ -785,11 +735,17 @@ int xe_device_probe_early(struct xe_device *xe) return save_err; } - err = wait_for_lmem_ready(xe); - if (err) - return err; + /* + * Make sure the lmem is initialized and ready to use. xe_pcode_ready() + * is flagged after full initialization is complete. Assert if lmem is + * not initialized. + */ + assert_lmem_ready(xe); - xe->wedged.mode = xe_modparam.wedged_mode; + xe->wedged.mode = xe_device_validate_wedged_mode(xe, xe_modparam.wedged_mode) ? + XE_WEDGED_MODE_DEFAULT : xe_modparam.wedged_mode; + drm_dbg(&xe->drm, "wedged_mode: setting mode (%u) %s\n", + xe->wedged.mode, xe_wedged_mode_to_string(xe->wedged.mode)); err = xe_device_vram_alloc(xe); if (err) @@ -1272,10 +1228,10 @@ static void xe_device_wedged_fini(struct drm_device *drm, void *arg) * DOC: Xe Device Wedging * * Xe driver uses drm device wedged uevent as documented in Documentation/gpu/drm-uapi.rst. - * When device is in wedged state, every IOCTL will be blocked and GT cannot be - * used. Certain critical errors like gt reset failure, firmware failures can cause - * the device to be wedged. The default recovery method for a wedged state - * is rebind/bus-reset. + * When device is in wedged state, every IOCTL will be blocked and GT cannot + * be used. The conditions under which the driver declares the device wedged + * depend on the wedged mode configuration (see &enum xe_wedged_mode). The + * default recovery method for a wedged state is rebind/bus-reset. * * Another recovery method is vendor-specific. Below are the cases that send * ``WEDGED=vendor-specific`` recovery method in drm device wedged uevent. @@ -1340,7 +1296,7 @@ void xe_device_declare_wedged(struct xe_device *xe) struct xe_gt *gt; u8 id; - if (xe->wedged.mode == 0) { + if (xe->wedged.mode == XE_WEDGED_MODE_NEVER) { drm_dbg(&xe->drm, "Wedged mode is forcibly disabled\n"); return; } @@ -1374,3 +1330,48 @@ void xe_device_declare_wedged(struct xe_device *xe) drm_dev_wedged_event(&xe->drm, xe->wedged.method, NULL); } } + +/** + * xe_device_validate_wedged_mode - Check if given mode is supported + * @xe: the &xe_device + * @mode: requested mode to validate + * + * Check whether the provided wedged mode is supported. + * + * Return: 0 if mode is supported, error code otherwise. + */ +int xe_device_validate_wedged_mode(struct xe_device *xe, unsigned int mode) +{ + if (mode > XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) { + drm_dbg(&xe->drm, "wedged_mode: invalid value (%u)\n", mode); + return -EINVAL; + } else if (mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET && (IS_SRIOV_VF(xe) || + (IS_SRIOV_PF(xe) && !IS_ENABLED(CONFIG_DRM_XE_DEBUG)))) { + drm_dbg(&xe->drm, "wedged_mode: (%u) %s mode is not supported for %s\n", + mode, xe_wedged_mode_to_string(mode), + xe_sriov_mode_to_string(xe_device_sriov_mode(xe))); + return -EPERM; + } + + return 0; +} + +/** + * xe_wedged_mode_to_string - Convert enum value to string. + * @mode: the &xe_wedged_mode to convert + * + * Returns: wedged mode as a user friendly string. + */ +const char *xe_wedged_mode_to_string(enum xe_wedged_mode mode) +{ + switch (mode) { + case XE_WEDGED_MODE_NEVER: + return "never"; + case XE_WEDGED_MODE_UPON_CRITICAL_ERROR: + return "upon-critical-error"; + case XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET: + return "upon-any-hang-no-reset"; + default: + return "<invalid>"; + } +} diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index 3e72fa4609f8..3740143790db 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -194,6 +194,8 @@ static inline bool xe_device_wedged(struct xe_device *xe) void xe_device_set_wedged_method(struct xe_device *xe, unsigned long method); void xe_device_declare_wedged(struct xe_device *xe); +int xe_device_validate_wedged_mode(struct xe_device *xe, unsigned int mode); +const char *xe_wedged_mode_to_string(enum xe_wedged_mode mode); struct xe_file *xe_file_get(struct xe_file *xef); void xe_file_put(struct xe_file *xef); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index a85be9ba175e..f689766adcb1 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -46,6 +46,25 @@ struct xe_pat_ops; struct xe_pxp; struct xe_vram_region; +/** + * enum xe_wedged_mode - possible wedged modes + * @XE_WEDGED_MODE_NEVER: Device will never be declared wedged. + * @XE_WEDGED_MODE_UPON_CRITICAL_ERROR: Device will be declared wedged only + * when critical error occurs like GT reset failure or firmware failure. + * This is the default mode. + * @XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET: Device will be declared wedged on + * any hang. In this mode, engine resets are disabled to avoid automatic + * recovery attempts. This mode is primarily intended for debugging hangs. + */ +enum xe_wedged_mode { + XE_WEDGED_MODE_NEVER = 0, + XE_WEDGED_MODE_UPON_CRITICAL_ERROR = 1, + XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET = 2, +}; + +#define XE_WEDGED_MODE_DEFAULT XE_WEDGED_MODE_UPON_CRITICAL_ERROR +#define XE_WEDGED_MODE_DEFAULT_STR "upon-critical-error" + #define XE_BO_INVALID_OFFSET LONG_MAX #define GRAPHICS_VER(xe) ((xe)->info.graphics_verx100 / 100) @@ -322,6 +341,8 @@ struct xe_device { * pcode mailbox commands. */ u8 has_mbx_power_limits:1; + /** @info.has_mbx_thermal_info: Device supports thermal mailbox commands */ + u8 has_mbx_thermal_info:1; /** @info.has_mem_copy_instr: Device supports MEM_COPY instruction */ u8 has_mem_copy_instr:1; /** @info.has_mert: Device has standalone MERT */ @@ -626,9 +647,11 @@ struct xe_device { /** @wedged.flag: Xe device faced a critical error and is now blocked. */ atomic_t flag; /** @wedged.mode: Mode controlled by kernel parameter and debugfs */ - int mode; + enum xe_wedged_mode mode; /** @wedged.method: Recovery method to be sent in the drm device wedged uevent */ unsigned long method; + /** @wedged.inconsistent_reset: Inconsistent reset policy state between GTs */ + bool inconsistent_reset; } wedged; /** @bo_device: Struct to control async free of BOs */ diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c index 730a5c9c2637..a5485fe6e3f1 100644 --- a/drivers/gpu/drm/xe/xe_exec.c +++ b/drivers/gpu/drm/xe/xe_exec.c @@ -11,7 +11,6 @@ #include <uapi/drm/xe_drm.h> #include <linux/delay.h> -#include "xe_bo.h" #include "xe_device.h" #include "xe_exec_queue.h" #include "xe_hw_engine_group.h" diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 0b9e074b022f..a940849bb6c7 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -21,13 +21,11 @@ #include "xe_gt_sriov_vf.h" #include "xe_hw_engine_class_sysfs.h" #include "xe_hw_engine_group.h" -#include "xe_hw_fence.h" #include "xe_irq.h" #include "xe_lrc.h" #include "xe_macros.h" #include "xe_migrate.h" #include "xe_pm.h" -#include "xe_ring_ops_types.h" #include "xe_trace.h" #include "xe_vm.h" #include "xe_pxp.h" @@ -84,9 +82,8 @@ * group is destroyed. The secondary queues hold a reference to the primary * queue thus preventing the group from being destroyed when user destroys * the primary queue. Once the primary queue is destroyed, secondary queues - * can't be added to the queue group, but they can continue to submit the - * jobs if the DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag is set during the multi - * queue group creation. + * can't be added to the queue group and new job submissions on existing + * secondary queues are not allowed. * * The queues of a multi queue group can set their priority within the group * through the DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY property. @@ -467,26 +464,6 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe, } ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO); -static void xe_exec_queue_group_kill(struct kref *ref) -{ - struct xe_exec_queue_group *group = container_of(ref, struct xe_exec_queue_group, - kill_refcount); - xe_exec_queue_kill(group->primary); -} - -static inline void xe_exec_queue_group_kill_get(struct xe_exec_queue_group *group) -{ - kref_get(&group->kill_refcount); -} - -void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group) -{ - if (!group) - return; - - kref_put(&group->kill_refcount, xe_exec_queue_group_kill); -} - void xe_exec_queue_destroy(struct kref *ref) { struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount); @@ -716,7 +693,6 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue * group->primary = q; group->cgp_bo = bo; INIT_LIST_HEAD(&group->list); - kref_init(&group->kill_refcount); xa_init_flags(&group->xa, XA_FLAGS_ALLOC1); mutex_init(&group->list_lock); q->multi_queue.group = group; @@ -792,11 +768,6 @@ static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q q->multi_queue.pos = pos; - if (group->primary->multi_queue.keep_active) { - xe_exec_queue_group_kill_get(group); - q->multi_queue.keep_active = true; - } - return 0; } @@ -810,11 +781,6 @@ static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queu lrc = xa_erase(&group->xa, q->multi_queue.pos); xe_assert(xe, lrc); xe_lrc_put(lrc); - - if (q->multi_queue.keep_active) { - xe_exec_queue_group_kill_put(group); - q->multi_queue.keep_active = false; - } } static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q, @@ -836,24 +802,12 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue return -EINVAL; if (value & DRM_XE_MULTI_GROUP_CREATE) { - if (XE_IOCTL_DBG(xe, value & ~(DRM_XE_MULTI_GROUP_CREATE | - DRM_XE_MULTI_GROUP_KEEP_ACTIVE))) - return -EINVAL; - - /* - * KEEP_ACTIVE is not supported in preempt fence mode as in that mode, - * VM_DESTROY ioctl expects all exec queues of that VM are already killed. - */ - if (XE_IOCTL_DBG(xe, (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) && - xe_vm_in_preempt_fence_mode(q->vm))) + if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE)) return -EINVAL; q->multi_queue.valid = true; q->multi_queue.is_primary = true; q->multi_queue.pos = 0; - if (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) - q->multi_queue.keep_active = true; - return 0; } @@ -1419,11 +1373,6 @@ void xe_exec_queue_kill(struct xe_exec_queue *q) q->ops->kill(q); xe_vm_remove_compute_exec_queue(q->vm, q); - - if (!xe_exec_queue_is_multi_queue_primary(q) && q->multi_queue.keep_active) { - xe_exec_queue_group_kill_put(q->multi_queue.group); - q->multi_queue.keep_active = false; - } } int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data, @@ -1450,10 +1399,7 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data, if (q->vm && q->hwe->hw_engine_group) xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); - if (xe_exec_queue_is_multi_queue_primary(q)) - xe_exec_queue_group_kill_put(q->multi_queue.group); - else - xe_exec_queue_kill(q); + xe_exec_queue_kill(q); trace_xe_exec_queue_close(q); xe_exec_queue_put(q); diff --git a/drivers/gpu/drm/xe/xe_exec_queue.h b/drivers/gpu/drm/xe/xe_exec_queue.h index b5ad975d7e97..b1e51789128f 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.h +++ b/drivers/gpu/drm/xe/xe_exec_queue.h @@ -113,8 +113,6 @@ static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_ return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q; } -void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group); - bool xe_exec_queue_is_lr(struct xe_exec_queue *q); bool xe_exec_queue_is_idle(struct xe_exec_queue *q); diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 67ea5eebf70b..5fc516b0bb77 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -62,8 +62,6 @@ struct xe_exec_queue_group { struct list_head list; /** @list_lock: Secondary queue list lock */ struct mutex list_lock; - /** @kill_refcount: ref count to kill primary queue */ - struct kref kill_refcount; /** @sync_pending: CGP_SYNC_DONE g2h response pending */ bool sync_pending; /** @banned: Group banned */ @@ -163,8 +161,6 @@ struct xe_exec_queue { u8 valid:1; /** @multi_queue.is_primary: Is primary queue (Q0) of the group */ u8 is_primary:1; - /** @multi_queue.keep_active: Keep the group active after primary is destroyed */ - u8 keep_active:1; } multi_queue; /** @sched_props: scheduling properties */ diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 46c17a18a3f4..8bf330aeaec0 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -15,8 +15,7 @@ #include "xe_bo.h" #include "xe_device.h" #include "xe_exec_queue.h" -#include "xe_gt.h" -#include "xe_hw_fence.h" +#include "xe_gt_types.h" #include "xe_irq.h" #include "xe_lrc.h" #include "xe_macros.h" diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 48ab8b43fcd0..60665ad1415b 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -20,9 +20,8 @@ #include "regs/xe_regs.h" #include "xe_assert.h" #include "xe_bo.h" -#include "xe_device.h" -#include "xe_gt.h" #include "xe_gt_printk.h" +#include "xe_gt_types.h" #include "xe_map.h" #include "xe_mmio.h" #include "xe_pm.h" @@ -67,6 +66,24 @@ * give us the correct placement for free. */ +/** + * struct xe_ggtt_node - A node in GGTT. + * + * This struct needs to be initialized (only-once) with xe_ggtt_node_init() before any node + * insertion, reservation, or 'ballooning'. + * It will, then, be finalized by either xe_ggtt_node_remove() or xe_ggtt_node_deballoon(). + */ +struct xe_ggtt_node { + /** @ggtt: Back pointer to xe_ggtt where this region will be inserted at */ + struct xe_ggtt *ggtt; + /** @base: A drm_mm_node */ + struct drm_mm_node base; + /** @delayed_removal_work: The work struct for the delayed removal */ + struct work_struct delayed_removal_work; + /** @invalidate_on_remove: If it needs invalidation upon removal */ + bool invalidate_on_remove; +}; + static u64 xelp_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) { u64 pte = XE_PAGE_PRESENT; @@ -137,10 +154,32 @@ static void ggtt_update_access_counter(struct xe_ggtt *ggtt) } } +/** + * xe_ggtt_start - Get starting offset of GGTT. + * @ggtt: &xe_ggtt + * + * Returns: Starting offset for this &xe_ggtt. + */ +u64 xe_ggtt_start(struct xe_ggtt *ggtt) +{ + return ggtt->start; +} + +/** + * xe_ggtt_size - Get size of GGTT. + * @ggtt: &xe_ggtt + * + * Returns: Total usable size of this &xe_ggtt. + */ +u64 xe_ggtt_size(struct xe_ggtt *ggtt) +{ + return ggtt->size; +} + static void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte) { xe_tile_assert(ggtt->tile, !(addr & XE_PTE_MASK)); - xe_tile_assert(ggtt->tile, addr < ggtt->size); + xe_tile_assert(ggtt->tile, addr < ggtt->start + ggtt->size); writeq(pte, &ggtt->gsm[addr >> XE_PTE_SHIFT]); } @@ -256,16 +295,16 @@ static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { .ggtt_get_pte = xe_ggtt_get_pte, }; -static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u32 reserved) +static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u64 start, u64 size) { - drm_mm_init(&ggtt->mm, reserved, - ggtt->size - reserved); + ggtt->start = start; + ggtt->size = size; + drm_mm_init(&ggtt->mm, start, size); } -int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 reserved, u32 size) +int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 start, u32 size) { - ggtt->size = size; - __xe_ggtt_init_early(ggtt, reserved); + __xe_ggtt_init_early(ggtt, start, size); return 0; } EXPORT_SYMBOL_IF_KUNIT(xe_ggtt_init_kunit); @@ -293,26 +332,32 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) struct xe_device *xe = tile_to_xe(ggtt->tile); struct pci_dev *pdev = to_pci_dev(xe->drm.dev); unsigned int gsm_size; + u64 ggtt_start, wopcm = xe_wopcm_size(xe), ggtt_size; int err; - if (IS_SRIOV_VF(xe) || GRAPHICS_VERx100(xe) >= 1250) - gsm_size = SZ_8M; /* GGTT is expected to be 4GiB */ - else - gsm_size = probe_gsm_size(pdev); - - if (gsm_size == 0) { - xe_tile_err(ggtt->tile, "Hardware reported no preallocated GSM\n"); - return -ENOMEM; + if (!IS_SRIOV_VF(xe)) { + if (GRAPHICS_VERx100(xe) >= 1250) + gsm_size = SZ_8M; /* GGTT is expected to be 4GiB */ + else + gsm_size = probe_gsm_size(pdev); + if (gsm_size == 0) { + xe_tile_err(ggtt->tile, "Hardware reported no preallocated GSM\n"); + return -ENOMEM; + } + ggtt_start = wopcm; + ggtt_size = (gsm_size / 8) * (u64)XE_PAGE_SIZE - ggtt_start; + } else { + /* GGTT is expected to be 4GiB */ + ggtt_start = wopcm; + ggtt_size = SZ_4G - ggtt_start; } ggtt->gsm = ggtt->tile->mmio.regs + SZ_8M; - ggtt->size = (gsm_size / 8) * (u64) XE_PAGE_SIZE; - if (IS_DGFX(xe) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) ggtt->flags |= XE_GGTT_FLAGS_64K; - if (ggtt->size > GUC_GGTT_TOP) - ggtt->size = GUC_GGTT_TOP; + if (ggtt_size + ggtt_start > GUC_GGTT_TOP) + ggtt_size = GUC_GGTT_TOP - ggtt_start; if (GRAPHICS_VERx100(xe) >= 1270) ggtt->pt_ops = @@ -322,11 +367,11 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) else ggtt->pt_ops = &xelp_pt_ops; - ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM); + ggtt->wq = alloc_workqueue("xe-ggtt-wq", WQ_MEM_RECLAIM, 0); if (!ggtt->wq) return -ENOMEM; - __xe_ggtt_init_early(ggtt, xe_wopcm_size(xe)); + __xe_ggtt_init_early(ggtt, ggtt_start, ggtt_size); err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); if (err) @@ -563,11 +608,9 @@ void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size) { struct xe_tile *tile = ggtt->tile; - struct xe_device *xe = tile_to_xe(tile); - u64 __maybe_unused wopcm = xe_wopcm_size(xe); - xe_tile_assert(tile, start >= wopcm); - xe_tile_assert(tile, start + size < ggtt->size - wopcm); + xe_tile_assert(tile, start >= ggtt->start); + xe_tile_assert(tile, start + size <= ggtt->start + ggtt->size); } /** @@ -610,20 +653,8 @@ void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift) } } -/** - * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT - * @node: the &xe_ggtt_node to be inserted - * @size: size of the node - * @align: alignment constrain of the node - * @mm_flags: flags to control the node behavior - * - * It cannot be called without first having called xe_ggtt_init() once. - * To be used in cases where ggtt->lock is already taken. - * - * Return: 0 on success or a negative error code on failure. - */ -int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, - u32 size, u32 align, u32 mm_flags) +static int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, + u32 size, u32 align, u32 mm_flags) { return drm_mm_insert_node_generic(&node->ggtt->mm, &node->base, size, align, 0, mm_flags); @@ -661,9 +692,11 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align) * This function will allocate the struct %xe_ggtt_node and return its pointer. * This struct will then be freed after the node removal upon xe_ggtt_node_remove() * or xe_ggtt_node_remove_balloon_locked(). - * Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated - * in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), - * xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved in GGTT. + * + * Having %xe_ggtt_node struct allocated doesn't mean that the node is already + * allocated in GGTT. Only xe_ggtt_node_insert(), allocation through + * xe_ggtt_node_insert_transform(), or xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved + * in GGTT. * * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. **/ @@ -726,13 +759,12 @@ size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node) * @ggtt: the &xe_ggtt where node will be mapped * @node: the &xe_ggtt_node where this BO is mapped * @bo: the &xe_bo to be mapped - * @pat_index: Which pat_index to use. + * @pte: The pte flags to append. */ -void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, - struct xe_bo *bo, u16 pat_index) +static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, + struct xe_bo *bo, u64 pte) { - - u64 start, pte, end; + u64 start, end; struct xe_res_cursor cur; if (XE_WARN_ON(!node)) @@ -741,7 +773,6 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, start = node->base.start; end = start + xe_bo_size(bo); - pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); if (!xe_bo_is_vram(bo) && !xe_bo_is_stolen(bo)) { xe_assert(xe_bo_device(bo), bo->ttm.ttm); @@ -771,12 +802,65 @@ void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo) { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + u64 pte; mutex_lock(&ggtt->lock); - xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pat_index); + pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); + xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pte); mutex_unlock(&ggtt->lock); } +/** + * xe_ggtt_node_insert_transform - Insert a newly allocated &xe_ggtt_node into the GGTT + * @ggtt: the &xe_ggtt where the node will inserted/reserved. + * @bo: The bo to be transformed + * @pte_flags: The extra GGTT flags to add to mapping. + * @size: size of the node + * @align: required alignment for node + * @transform: transformation function that will populate the GGTT node, or NULL for linear mapping. + * @arg: Extra argument to pass to the transformation function. + * + * This function allows inserting a GGTT node with a custom transformation function. + * This is useful for display to allow inserting rotated framebuffers to GGTT. + * + * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. + */ +struct xe_ggtt_node *xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt, + struct xe_bo *bo, u64 pte_flags, + u64 size, u32 align, + xe_ggtt_transform_cb transform, void *arg) +{ + struct xe_ggtt_node *node; + int ret; + + node = xe_ggtt_node_init(ggtt); + if (IS_ERR(node)) + return ERR_CAST(node); + + if (mutex_lock_interruptible(&ggtt->lock) < 0) { + ret = -ERESTARTSYS; + goto err; + } + + ret = xe_ggtt_node_insert_locked(node, size, align, 0); + if (ret) + goto err_unlock; + + if (transform) + transform(ggtt, node, pte_flags, ggtt->pt_ops->ggtt_set_pte, arg); + else + xe_ggtt_map_bo(ggtt, node, bo, pte_flags); + + mutex_unlock(&ggtt->lock); + return node; + +err_unlock: + mutex_unlock(&ggtt->lock); +err: + xe_ggtt_node_fini(node); + return ERR_PTR(ret); +} + static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, u64 start, u64 end, struct drm_exec *exec) { @@ -815,8 +899,9 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, } else { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); - xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pat_index); + xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte); } mutex_unlock(&ggtt->lock); @@ -890,14 +975,12 @@ u64 xe_ggtt_largest_hole(struct xe_ggtt *ggtt, u64 alignment, u64 *spare) { const struct drm_mm *mm = &ggtt->mm; const struct drm_mm_node *entry; - u64 hole_min_start = xe_wopcm_size(tile_to_xe(ggtt->tile)); u64 hole_start, hole_end, hole_size; u64 max_hole = 0; mutex_lock(&ggtt->lock); - drm_mm_for_each_hole(entry, mm, hole_start, hole_end) { - hole_start = max(hole_start, hole_min_start); + hole_start = max(hole_start, ggtt->start); hole_start = ALIGN(hole_start, alignment); hole_end = ALIGN_DOWN(hole_end, alignment); if (hole_start >= hole_end) @@ -1069,15 +1152,13 @@ u64 xe_ggtt_print_holes(struct xe_ggtt *ggtt, u64 alignment, struct drm_printer { const struct drm_mm *mm = &ggtt->mm; const struct drm_mm_node *entry; - u64 hole_min_start = xe_wopcm_size(tile_to_xe(ggtt->tile)); u64 hole_start, hole_end, hole_size; u64 total = 0; char buf[10]; mutex_lock(&ggtt->lock); - drm_mm_for_each_hole(entry, mm, hole_start, hole_end) { - hole_start = max(hole_start, hole_min_start); + hole_start = max(hole_start, ggtt->start); hole_start = ALIGN(hole_start, alignment); hole_end = ALIGN_DOWN(hole_end, alignment); if (hole_start >= hole_end) @@ -1121,3 +1202,25 @@ u64 xe_ggtt_read_pte(struct xe_ggtt *ggtt, u64 offset) { return ioread64(ggtt->gsm + (offset / XE_PAGE_SIZE)); } + +/** + * xe_ggtt_node_addr - Get @node offset in GGTT. + * @node: &xe_ggtt_node + * + * Get the GGTT offset for allocated node. + */ +u64 xe_ggtt_node_addr(const struct xe_ggtt_node *node) +{ + return node->base.start; +} + +/** + * xe_ggtt_node_size - Get @node allocation size. + * @node: &xe_ggtt_node + * + * Get the allocated node's size. + */ +u64 xe_ggtt_node_size(const struct xe_ggtt_node *node) +{ + return node->base.size; +} diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index 93fea4b6079c..70d5e07ac4b6 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -23,15 +23,18 @@ int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 size); void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift); +u64 xe_ggtt_start(struct xe_ggtt *ggtt); +u64 xe_ggtt_size(struct xe_ggtt *ggtt); int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); -int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, - u32 size, u32 align, u32 mm_flags); +struct xe_ggtt_node * +xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt, + struct xe_bo *bo, u64 pte, + u64 size, u32 align, + xe_ggtt_transform_cb transform, void *arg); void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node); size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node); -void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, - struct xe_bo *bo, u16 pat_index); void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo); int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo, struct drm_exec *exec); int xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, @@ -58,4 +61,7 @@ void xe_ggtt_might_lock(struct xe_ggtt *ggtt); u64 xe_ggtt_encode_pte_flags(struct xe_ggtt *ggtt, struct xe_bo *bo, u16 pat_index); u64 xe_ggtt_read_pte(struct xe_ggtt *ggtt, u64 offset); +u64 xe_ggtt_node_addr(const struct xe_ggtt_node *node); +u64 xe_ggtt_node_size(const struct xe_ggtt_node *node); + #endif diff --git a/drivers/gpu/drm/xe/xe_ggtt_types.h b/drivers/gpu/drm/xe/xe_ggtt_types.h index dacd796f8184..d82b71a198bc 100644 --- a/drivers/gpu/drm/xe/xe_ggtt_types.h +++ b/drivers/gpu/drm/xe/xe_ggtt_types.h @@ -11,6 +11,7 @@ #include "xe_pt_types.h" struct xe_bo; +struct xe_ggtt_node; struct xe_gt; /** @@ -22,7 +23,9 @@ struct xe_gt; struct xe_ggtt { /** @tile: Back pointer to tile where this GGTT belongs */ struct xe_tile *tile; - /** @size: Total size of this GGTT */ + /** @start: Start offset of GGTT */ + u64 start; + /** @size: Total usable size of this GGTT */ u64 size; #define XE_GGTT_FLAGS_64K BIT(0) @@ -51,24 +54,11 @@ struct xe_ggtt { struct workqueue_struct *wq; }; -/** - * struct xe_ggtt_node - A node in GGTT. - * - * This struct needs to be initialized (only-once) with xe_ggtt_node_init() before any node - * insertion, reservation, or 'ballooning'. - * It will, then, be finalized by either xe_ggtt_node_remove() or xe_ggtt_node_deballoon(). - */ -struct xe_ggtt_node { - /** @ggtt: Back pointer to xe_ggtt where this region will be inserted at */ - struct xe_ggtt *ggtt; - /** @base: A drm_mm_node */ - struct drm_mm_node base; - /** @delayed_removal_work: The work struct for the delayed removal */ - struct work_struct delayed_removal_work; - /** @invalidate_on_remove: If it needs invalidation upon removal */ - bool invalidate_on_remove; -}; - +typedef void (*xe_ggtt_set_pte_fn)(struct xe_ggtt *ggtt, u64 addr, u64 pte); +typedef void (*xe_ggtt_transform_cb)(struct xe_ggtt *ggtt, + struct xe_ggtt_node *node, + u64 pte_flags, + xe_ggtt_set_pte_fn set_pte, void *arg); /** * struct xe_ggtt_pt_ops - GGTT Page table operations * Which can vary from platform to platform. @@ -76,8 +66,10 @@ struct xe_ggtt_node { struct xe_ggtt_pt_ops { /** @pte_encode_flags: Encode PTE flags for a given BO */ u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index); + /** @ggtt_set_pte: Directly write into GGTT's PTE */ - void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte); + xe_ggtt_set_pte_fn ggtt_set_pte; + /** @ggtt_get_pte: Directly read from GGTT's PTE */ u64 (*ggtt_get_pte)(struct xe_ggtt *ggtt, u64 addr); }; diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c b/drivers/gpu/drm/xe/xe_gpu_scheduler.c index f91e06d03511..9c8004d5dd91 100644 --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c @@ -7,7 +7,7 @@ static void xe_sched_process_msg_queue(struct xe_gpu_scheduler *sched) { - if (!READ_ONCE(sched->base.pause_submit)) + if (!drm_sched_is_stopped(&sched->base)) queue_work(sched->base.submit_wq, &sched->work_process_msg); } @@ -43,7 +43,7 @@ static void xe_sched_process_msg_work(struct work_struct *w) container_of(w, struct xe_gpu_scheduler, work_process_msg); struct xe_sched_msg *msg; - if (READ_ONCE(sched->base.pause_submit)) + if (drm_sched_is_stopped(&sched->base)) return; msg = xe_sched_get_msg(sched); @@ -77,6 +77,7 @@ int xe_sched_init(struct xe_gpu_scheduler *sched, }; sched->ops = xe_ops; + spin_lock_init(&sched->msg_lock); INIT_LIST_HEAD(&sched->msgs); INIT_WORK(&sched->work_process_msg, xe_sched_process_msg_work); @@ -117,7 +118,7 @@ void xe_sched_add_msg(struct xe_gpu_scheduler *sched, void xe_sched_add_msg_locked(struct xe_gpu_scheduler *sched, struct xe_sched_msg *msg) { - lockdep_assert_held(&sched->base.job_list_lock); + lockdep_assert_held(&sched->msg_lock); list_add_tail(&msg->link, &sched->msgs); xe_sched_process_msg_queue(sched); @@ -131,7 +132,7 @@ void xe_sched_add_msg_locked(struct xe_gpu_scheduler *sched, void xe_sched_add_msg_head(struct xe_gpu_scheduler *sched, struct xe_sched_msg *msg) { - lockdep_assert_held(&sched->base.job_list_lock); + lockdep_assert_held(&sched->msg_lock); list_add(&msg->link, &sched->msgs); xe_sched_process_msg_queue(sched); diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.h b/drivers/gpu/drm/xe/xe_gpu_scheduler.h index c7a77a3a9681..664c2db56af3 100644 --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.h +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.h @@ -33,12 +33,12 @@ void xe_sched_add_msg_head(struct xe_gpu_scheduler *sched, static inline void xe_sched_msg_lock(struct xe_gpu_scheduler *sched) { - spin_lock(&sched->base.job_list_lock); + spin_lock(&sched->msg_lock); } static inline void xe_sched_msg_unlock(struct xe_gpu_scheduler *sched) { - spin_unlock(&sched->base.job_list_lock); + spin_unlock(&sched->msg_lock); } static inline void xe_sched_stop(struct xe_gpu_scheduler *sched) @@ -56,12 +56,9 @@ static inline void xe_sched_resubmit_jobs(struct xe_gpu_scheduler *sched) struct drm_sched_job *s_job; bool restore_replay = false; - list_for_each_entry(s_job, &sched->base.pending_list, list) { - struct drm_sched_fence *s_fence = s_job->s_fence; - struct dma_fence *hw_fence = s_fence->parent; - + drm_sched_for_each_pending_job(s_job, &sched->base, NULL) { restore_replay |= to_xe_sched_job(s_job)->restore_replay; - if (restore_replay || (hw_fence && !dma_fence_is_signaled(hw_fence))) + if (restore_replay || !drm_sched_job_is_signaled(s_job)) sched->base.ops->run_job(s_job); } } @@ -72,14 +69,6 @@ xe_sched_invalidate_job(struct xe_sched_job *job, int threshold) return drm_sched_invalidate_job(&job->drm, threshold); } -static inline void xe_sched_add_pending_job(struct xe_gpu_scheduler *sched, - struct xe_sched_job *job) -{ - spin_lock(&sched->base.job_list_lock); - list_add(&job->drm.list, &sched->base.pending_list); - spin_unlock(&sched->base.job_list_lock); -} - /** * xe_sched_first_pending_job() - Find first pending job which is unsignaled * @sched: Xe GPU scheduler @@ -89,21 +78,13 @@ static inline void xe_sched_add_pending_job(struct xe_gpu_scheduler *sched, static inline struct xe_sched_job *xe_sched_first_pending_job(struct xe_gpu_scheduler *sched) { - struct xe_sched_job *job, *r_job = NULL; - - spin_lock(&sched->base.job_list_lock); - list_for_each_entry(job, &sched->base.pending_list, drm.list) { - struct drm_sched_fence *s_fence = job->drm.s_fence; - struct dma_fence *hw_fence = s_fence->parent; + struct drm_sched_job *job; - if (hw_fence && !dma_fence_is_signaled(hw_fence)) { - r_job = job; - break; - } - } - spin_unlock(&sched->base.job_list_lock); + drm_sched_for_each_pending_job(job, &sched->base, NULL) + if (!drm_sched_job_is_signaled(job)) + return to_xe_sched_job(job); - return r_job; + return NULL; } static inline int diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler_types.h b/drivers/gpu/drm/xe/xe_gpu_scheduler_types.h index 6731b13da8bb..63d9bf92583c 100644 --- a/drivers/gpu/drm/xe/xe_gpu_scheduler_types.h +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler_types.h @@ -47,6 +47,8 @@ struct xe_gpu_scheduler { const struct xe_sched_backend_ops *ops; /** @msgs: list of messages to be processed in @work_process_msg */ struct list_head msgs; + /** @msg_lock: Message lock */ + spinlock_t msg_lock; /** @work_process_msg: processes messages */ struct work_struct work_process_msg; }; diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c index a3157b0fe791..e5c234f3d795 100644 --- a/drivers/gpu/drm/xe/xe_gsc.c +++ b/drivers/gpu/drm/xe/xe_gsc.c @@ -414,15 +414,16 @@ int xe_gsc_init(struct xe_gsc *gsc) } /* - * Some platforms can have GuC but not GSC. That would cause - * xe_uc_fw_init(gsc) to return a "not supported" failure code and abort - * all firmware loading. So check for GSC being enabled before - * propagating the failure back up. That way the higher level will keep - * going and load GuC as appropriate. + * Starting from BMG the GSC is no longer needed for MC6 entry, so the + * only missing features if the FW is lacking would be the content + * protection ones. This is acceptable, so we allow the driver load to + * continue if the GSC FW is missing. */ ret = xe_uc_fw_init(&gsc->fw); if (!xe_uc_fw_is_enabled(&gsc->fw)) return 0; + else if (gt_to_xe(gt)->info.platform >= XE_BATTLEMAGE && !xe_uc_fw_is_available(&gsc->fw)) + return 0; else if (ret) goto out; @@ -614,7 +615,7 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) drm_printf(p, "\tfound security version %u\n", gsc->security_version); - if (!xe_uc_fw_is_enabled(&gsc->fw)) + if (!xe_uc_fw_is_available(&gsc->fw)) return; CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC); diff --git a/drivers/gpu/drm/xe/xe_gsc_debugfs.c b/drivers/gpu/drm/xe/xe_gsc_debugfs.c index b13928b50eb9..d4977e666946 100644 --- a/drivers/gpu/drm/xe/xe_gsc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gsc_debugfs.c @@ -7,11 +7,10 @@ #include <drm/drm_debugfs.h> #include <drm/drm_managed.h> +#include <drm/drm_print.h> -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_gsc.h" -#include "xe_macros.h" #include "xe_pm.h" static struct xe_gt * diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c index e7573a0c5e5d..42438b21f235 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.c +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c @@ -18,8 +18,8 @@ #include "xe_force_wake.h" #include "xe_gsc.h" #include "xe_gsc_submit.h" -#include "xe_gt.h" #include "xe_gt_printk.h" +#include "xe_gt_types.h" #include "xe_map.h" #include "xe_mmio.h" #include "xe_pm.h" diff --git a/drivers/gpu/drm/xe/xe_gsc_submit.c b/drivers/gpu/drm/xe/xe_gsc_submit.c index 9ede483d37ef..08082b596501 100644 --- a/drivers/gpu/drm/xe/xe_gsc_submit.c +++ b/drivers/gpu/drm/xe/xe_gsc_submit.c @@ -11,12 +11,10 @@ #include "xe_assert.h" #include "xe_bb.h" #include "xe_exec_queue.h" -#include "xe_gt_printk.h" #include "xe_gt_types.h" #include "xe_map.h" #include "xe_sched_job.h" #include "instructions/xe_gsc_commands.h" -#include "regs/xe_gsc_regs.h" #define GSC_HDR_SIZE (sizeof(struct intel_gsc_mtl_header)) /* shorthand define */ diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 313ce83ab0e5..9d090d0f2438 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -13,13 +13,11 @@ #include <generated/xe_wa_oob.h> #include "instructions/xe_alu_commands.h" -#include "instructions/xe_gfxpipe_commands.h" #include "instructions/xe_mi_commands.h" #include "regs/xe_engine_regs.h" #include "regs/xe_gt_regs.h" #include "xe_assert.h" #include "xe_bb.h" -#include "xe_bo.h" #include "xe_device.h" #include "xe_eu_stall.h" #include "xe_exec_queue.h" @@ -140,6 +138,36 @@ static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); } +static void xe_gt_enable_comp_1wcoh(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + unsigned int fw_ref; + u32 reg; + + if (IS_SRIOV_VF(xe)) + return; + + if (GRAPHICS_VER(xe) >= 30 && xe->info.has_flat_ccs) { + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref) + return; + + reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); + reg |= EN_CMP_1WCOH; + xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); + + if (xe_gt_is_media_type(gt)) { + xe_mmio_rmw32(>->mmio, XE2_GAMWALK_CTRL_MEDIA, 0, EN_CMP_1WCOH_GW); + } else { + reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMWALK_CTRL_3D); + reg |= EN_CMP_1WCOH_GW; + xe_gt_mcr_multicast_write(gt, XE2_GAMWALK_CTRL_3D, reg); + } + + xe_force_wake_put(gt_to_fw(gt), fw_ref); + } +} + static void gt_reset_worker(struct work_struct *w); static int emit_job_sync(struct xe_exec_queue *q, struct xe_bb *bb, @@ -466,6 +494,7 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) xe_gt_topology_init(gt); xe_gt_mcr_init(gt); xe_gt_enable_host_l2_vram(gt); + xe_gt_enable_comp_1wcoh(gt); if (xe_gt_is_main_type(gt)) { err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt); @@ -745,6 +774,7 @@ static int do_gt_restart(struct xe_gt *gt) xe_pat_init(gt); xe_gt_enable_host_l2_vram(gt); + xe_gt_enable_comp_1wcoh(gt); xe_gt_mcr_set_implicit_defaults(gt); xe_reg_sr_apply_mmio(>->reg_sr, gt); diff --git a/drivers/gpu/drm/xe/xe_gt_clock.c b/drivers/gpu/drm/xe/xe_gt_clock.c index bfc25c46f798..53b3835192da 100644 --- a/drivers/gpu/drm/xe/xe_gt_clock.c +++ b/drivers/gpu/drm/xe/xe_gt_clock.c @@ -8,12 +8,8 @@ #include "xe_gt_clock.h" #include "regs/xe_gt_regs.h" -#include "regs/xe_regs.h" -#include "xe_assert.h" -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_gt_printk.h" -#include "xe_macros.h" #include "xe_mmio.h" #define f19_2_mhz 19200000 diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c index e4f38b5150fc..4363bc9c3606 100644 --- a/drivers/gpu/drm/xe/xe_gt_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c @@ -22,7 +22,6 @@ #include "xe_guc_hwconfig.h" #include "xe_hw_engine.h" #include "xe_lrc.h" -#include "xe_macros.h" #include "xe_mocs.h" #include "xe_pat.h" #include "xe_pm.h" diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c index c1c9bec3c487..7a569e1730a4 100644 --- a/drivers/gpu/drm/xe/xe_gt_idle.c +++ b/drivers/gpu/drm/xe/xe_gt_idle.c @@ -13,7 +13,6 @@ #include "xe_gt_sysfs.h" #include "xe_guc_pc.h" #include "regs/xe_gt_regs.h" -#include "xe_macros.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_sriov.h" diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index 164010860664..7c1fe9ac120d 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -7,7 +7,6 @@ #include "regs/xe_gt_regs.h" #include "xe_assert.h" -#include "xe_gt.h" #include "xe_gt_printk.h" #include "xe_gt_topology.h" #include "xe_gt_types.h" diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 5a870914b102..23601ce79348 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -24,13 +24,11 @@ #include "xe_guc_buf.h" #include "xe_guc_ct.h" #include "xe_guc_db_mgr.h" -#include "xe_guc_fwif.h" #include "xe_guc_id_mgr.h" #include "xe_guc_klv_helpers.h" #include "xe_guc_klv_thresholds_set.h" #include "xe_guc_submit.h" #include "xe_lmtt.h" -#include "xe_map.h" #include "xe_migrate.h" #include "xe_sriov.h" #include "xe_ttm_vram_mgr.h" @@ -284,7 +282,7 @@ static u32 encode_config_ggtt(u32 *cfg, const struct xe_gt_sriov_config *config, if (!xe_ggtt_node_allocated(node)) return 0; - return encode_ggtt(cfg, node->base.start, node->base.size, details); + return encode_ggtt(cfg, xe_ggtt_node_addr(node), xe_ggtt_node_size(node), details); } static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n, @@ -393,8 +391,8 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) xe_gt_assert(gt, num_dwords <= max_cfg_dwords); if (vfid == PFID) { - u64 ggtt_start = xe_wopcm_size(gt_to_xe(gt)); - u64 ggtt_size = gt_to_tile(gt)->mem.ggtt->size - ggtt_start; + u64 ggtt_start = xe_ggtt_start(gt_to_tile(gt)->mem.ggtt); + u64 ggtt_size = xe_ggtt_size(gt_to_tile(gt)->mem.ggtt); /* plain PF config data will never include a real GGTT region */ xe_gt_assert(gt, !encode_config_ggtt(cfg + num_dwords, config, true)); @@ -545,9 +543,9 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size) xe_ggtt_assign(node, vfid); xe_gt_sriov_dbg_verbose(gt, "VF%u assigned GGTT %llx-%llx\n", - vfid, node->base.start, node->base.start + node->base.size - 1); + vfid, xe_ggtt_node_addr(node), xe_ggtt_node_addr(node) + size - 1); - err = pf_distribute_config_ggtt(gt->tile, vfid, node->base.start, node->base.size); + err = pf_distribute_config_ggtt(gt->tile, vfid, xe_ggtt_node_addr(node), size); if (unlikely(err)) goto err; @@ -564,7 +562,7 @@ static u64 pf_get_vf_config_ggtt(struct xe_gt *gt, unsigned int vfid) struct xe_ggtt_node *node = config->ggtt_region; xe_gt_assert(gt, xe_gt_is_main_type(gt)); - return xe_ggtt_node_allocated(node) ? node->base.size : 0; + return xe_ggtt_node_allocated(node) ? xe_ggtt_node_size(node) : 0; } /** @@ -3040,11 +3038,12 @@ int xe_gt_sriov_pf_config_print_ggtt(struct xe_gt *gt, struct drm_printer *p) if (!xe_ggtt_node_allocated(config->ggtt_region)) continue; - string_get_size(config->ggtt_region->base.size, 1, STRING_UNITS_2, + string_get_size(xe_ggtt_node_size(config->ggtt_region), 1, STRING_UNITS_2, buf, sizeof(buf)); drm_printf(p, "VF%u:\t%#0llx-%#llx\t(%s)\n", - n, config->ggtt_region->base.start, - config->ggtt_region->base.start + config->ggtt_region->base.size - 1, + n, xe_ggtt_node_addr(config->ggtt_region), + xe_ggtt_node_addr(config->ggtt_region) + + xe_ggtt_node_size(config->ggtt_region) - 1, buf); } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c index 47d288c53539..f97abb02aebd 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c @@ -8,7 +8,6 @@ #include <drm/drm_print.h> #include <drm/drm_debugfs.h> -#include "xe_bo.h" #include "xe_debugfs.h" #include "xe_device.h" #include "xe_gt.h" diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c index 7410e7b93256..87a164efcc33 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c @@ -14,7 +14,6 @@ #include "xe_gt_sriov_pf.h" #include "xe_gt_sriov_pf_config.h" #include "xe_gt_sriov_pf_control.h" -#include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_migration.h" #include "xe_gt_sriov_printk.h" #include "xe_guc.h" @@ -25,6 +24,7 @@ #include "xe_sriov.h" #include "xe_sriov_packet.h" #include "xe_sriov_packet_types.h" +#include "xe_sriov_pf_helpers.h" #include "xe_sriov_pf_migration.h" #define XE_GT_SRIOV_PF_MIGRATION_RING_SIZE 5 diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index c28606ca6623..848e24926ecd 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -7,7 +7,6 @@ #include "abi/guc_actions_sriov_abi.h" -#include "xe_bo.h" #include "xe_gt.h" #include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_policy.h" diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c index 2eb21610e5a0..b5e0a5b7723e 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_service.c @@ -5,20 +5,19 @@ #include <drm/drm_managed.h> -#include "abi/guc_actions_sriov_abi.h" #include "abi/guc_relay_actions_abi.h" #include "regs/xe_gt_regs.h" #include "regs/xe_guc_regs.h" -#include "regs/xe_regs.h" +#include "xe_assert.h" #include "xe_mmio.h" #include "xe_gt_sriov_printk.h" -#include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_service.h" #include "xe_gt_sriov_pf_service_types.h" #include "xe_guc_ct.h" #include "xe_guc_hxg_helpers.h" +#include "xe_sriov.h" #include "xe_sriov_pf_service.h" static const struct xe_reg tgl_runtime_regs[] = { diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index d91c65dc3496..30e8c2cf5f09 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -15,7 +15,6 @@ #include "abi/guc_klvs_abi.h" #include "abi/guc_relay_actions_abi.h" #include "regs/xe_gt_regs.h" -#include "regs/xe_gtt_defs.h" #include "xe_assert.h" #include "xe_device.h" diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h index 9a6b5672d569..4ef881b9b662 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h @@ -43,10 +43,10 @@ struct xe_gt_sriov_vf_runtime { }; /** - * xe_gt_sriov_vf_migration - VF migration data. + * struct xe_gt_sriov_vf_migration - VF migration data. */ struct xe_gt_sriov_vf_migration { - /** @migration: VF migration recovery worker */ + /** @worker: VF migration recovery worker */ struct work_struct worker; /** @lock: Protects recovery_queued, teardown */ spinlock_t lock; diff --git a/drivers/gpu/drm/xe/xe_gt_stats.c b/drivers/gpu/drm/xe/xe_gt_stats.c index fb2904bd0abd..37506434d7a3 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats.c +++ b/drivers/gpu/drm/xe/xe_gt_stats.c @@ -7,8 +7,8 @@ #include <drm/drm_print.h> -#include "xe_gt.h" #include "xe_gt_stats.h" +#include "xe_gt_types.h" /** * xe_gt_stats_incr - Increments the specified stats counter @@ -76,6 +76,11 @@ static const char *const stat_description[__XE_GT_STATS_NUM_IDS] = { "hw_engine_group_suspend_lr_queue_us"), DEF_STAT_STR(HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US, "hw_engine_group_wait_dma_queue_us"), + DEF_STAT_STR(PRL_4K_ENTRY_COUNT, "prl_4k_entry_count"), + DEF_STAT_STR(PRL_64K_ENTRY_COUNT, "prl_64k_entry_count"), + DEF_STAT_STR(PRL_2M_ENTRY_COUNT, "prl_2m_entry_count"), + DEF_STAT_STR(PRL_ISSUED_COUNT, "prl_issued_count"), + DEF_STAT_STR(PRL_ABORTED_COUNT, "prl_aborted_count"), }; /** diff --git a/drivers/gpu/drm/xe/xe_gt_stats_types.h b/drivers/gpu/drm/xe/xe_gt_stats_types.h index b92d013091d5..b8accdbc54eb 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats_types.h +++ b/drivers/gpu/drm/xe/xe_gt_stats_types.h @@ -49,6 +49,11 @@ enum xe_gt_stats_id { XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT, XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US, XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US, + XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, + XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, + XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, + XE_GT_STATS_ID_PRL_ISSUED_COUNT, + XE_GT_STATS_ID_PRL_ABORTED_COUNT, /* must be the last entry */ __XE_GT_STATS_NUM_IDS, }; diff --git a/drivers/gpu/drm/xe/xe_gt_sysfs.c b/drivers/gpu/drm/xe/xe_gt_sysfs.c index ec2b8246204b..1448be047b4a 100644 --- a/drivers/gpu/drm/xe/xe_gt_sysfs.c +++ b/drivers/gpu/drm/xe/xe_gt_sysfs.c @@ -10,7 +10,7 @@ #include <drm/drm_managed.h> -#include "xe_gt.h" +#include "xe_gt_types.h" static void xe_gt_sysfs_kobj_release(struct kobject *kobj) { diff --git a/drivers/gpu/drm/xe/xe_gt_throttle.c b/drivers/gpu/drm/xe/xe_gt_throttle.c index 570358310e97..1e7e3a31aa69 100644 --- a/drivers/gpu/drm/xe/xe_gt_throttle.c +++ b/drivers/gpu/drm/xe/xe_gt_throttle.c @@ -6,7 +6,7 @@ #include <drm/drm_managed.h> #include <regs/xe_gt_regs.h> -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_gt.h" #include "xe_gt_sysfs.h" #include "xe_gt_throttle.h" diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index 5feeb91426ee..f4cbc030f4c8 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -28,8 +28,6 @@ #include "xe_lrc.h" #include "xe_map.h" #include "xe_mmio.h" -#include "xe_platform_types.h" -#include "xe_uc_fw.h" #include "xe_wa.h" /* Slack of a few additional entries per engine */ @@ -451,7 +449,7 @@ static void guc_policies_init(struct xe_guc_ads *ads) ads_blob_write(ads, policies.max_num_work_items, GLOBAL_POLICY_MAX_NUM_WI); - if (xe->wedged.mode == 2) + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; ads_blob_write(ads, policies.global_flags, global_flags); @@ -983,16 +981,17 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off /** * xe_guc_ads_scheduler_policy_toggle_reset - Toggle reset policy * @ads: Additional data structures object + * @enable_engine_reset: true to enable engine resets, false otherwise * - * This function update the GuC's engine reset policy based on wedged.mode. + * This function update the GuC's engine reset policy. * * Return: 0 on success, and negative error code otherwise. */ -int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) +int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads, + bool enable_engine_reset) { struct guc_policies *policies; struct xe_guc *guc = ads_to_guc(ads); - struct xe_device *xe = ads_to_xe(ads); CLASS(xe_guc_buf, buf)(&guc->buf, sizeof(*policies)); if (!xe_guc_buf_is_valid(buf)) @@ -1004,10 +1003,11 @@ int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) policies->dpc_promote_time = ads_blob_read(ads, policies.dpc_promote_time); policies->max_num_work_items = ads_blob_read(ads, policies.max_num_work_items); policies->is_valid = 1; - if (xe->wedged.mode == 2) - policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; - else + + if (enable_engine_reset) policies->global_flags &= ~GLOBAL_POLICY_DISABLE_ENGINE_RESET; + else + policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; return guc_ads_action_update_policies(ads, xe_guc_buf_flush(buf)); } diff --git a/drivers/gpu/drm/xe/xe_guc_ads.h b/drivers/gpu/drm/xe/xe_guc_ads.h index 2e6674c760ff..7a39f361cb17 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.h +++ b/drivers/gpu/drm/xe/xe_guc_ads.h @@ -6,6 +6,8 @@ #ifndef _XE_GUC_ADS_H_ #define _XE_GUC_ADS_H_ +#include <linux/types.h> + struct xe_guc_ads; int xe_guc_ads_init(struct xe_guc_ads *ads); @@ -13,6 +15,7 @@ int xe_guc_ads_init_post_hwconfig(struct xe_guc_ads *ads); void xe_guc_ads_populate(struct xe_guc_ads *ads); void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads); void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads); -int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads); +int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads, + bool enable_engine_reset); #endif diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c index c36fc31e0438..11f77decd8d1 100644 --- a/drivers/gpu/drm/xe/xe_guc_buf.c +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -6,7 +6,6 @@ #include <linux/cleanup.h> #include <drm/drm_managed.h> -#include "xe_assert.h" #include "xe_bo.h" #include "xe_gt_printk.h" #include "xe_guc.h" diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c index 2cda92f7b323..2f5816c78fba 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture.c +++ b/drivers/gpu/drm/xe/xe_guc_capture.c @@ -13,17 +13,14 @@ #include "abi/guc_log_abi.h" #include "regs/xe_engine_regs.h" #include "regs/xe_gt_regs.h" -#include "regs/xe_guc_regs.h" -#include "regs/xe_regs.h" -#include "xe_bo.h" +#include "xe_bo_types.h" #include "xe_device.h" #include "xe_exec_queue_types.h" #include "xe_gt.h" #include "xe_gt_mcr.h" #include "xe_gt_printk.h" #include "xe_guc.h" -#include "xe_guc_ads.h" #include "xe_guc_capture.h" #include "xe_guc_capture_types.h" #include "xe_guc_ct.h" @@ -1889,7 +1886,14 @@ xe_guc_capture_get_matching_and_lock(struct xe_exec_queue *q) return NULL; xe = gt_to_xe(q->gt); - if (xe->wedged.mode >= 2 || !xe_device_uc_enabled(xe) || IS_SRIOV_VF(xe)) + + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) + return NULL; + + if (!xe_device_uc_enabled(xe)) + return NULL; + + if (IS_SRIOV_VF(xe)) return NULL; ss = &xe->devcoredump.snapshot; diff --git a/drivers/gpu/drm/xe/xe_guc_debugfs.c b/drivers/gpu/drm/xe/xe_guc_debugfs.c index 23827e87450f..2f23119686d4 100644 --- a/drivers/gpu/drm/xe/xe_guc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_guc_debugfs.c @@ -8,13 +8,12 @@ #include <drm/drm_debugfs.h> #include <drm/drm_managed.h> -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_device_types.h" +#include "xe_gt_types.h" #include "xe_guc.h" #include "xe_guc_ct.h" #include "xe_guc_log.h" #include "xe_guc_pc.h" -#include "xe_macros.h" #include "xe_pm.h" /* diff --git a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h index a3b034e4b205..fd0915ed8eb1 100644 --- a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h @@ -33,8 +33,6 @@ struct xe_guc_exec_queue { */ #define MAX_STATIC_MSG_TYPE 3 struct xe_sched_msg static_msgs[MAX_STATIC_MSG_TYPE]; - /** @lr_tdr: long running TDR worker */ - struct work_struct lr_tdr; /** @destroy_async: do final destroy async from this worker */ struct work_struct destroy_async; /** @resume_time: time of last resume */ diff --git a/drivers/gpu/drm/xe/xe_guc_hwconfig.c b/drivers/gpu/drm/xe/xe_guc_hwconfig.c index af2c817d552c..b300901dbb8e 100644 --- a/drivers/gpu/drm/xe/xe_guc_hwconfig.c +++ b/drivers/gpu/drm/xe/xe_guc_hwconfig.c @@ -10,8 +10,8 @@ #include "abi/guc_actions_abi.h" #include "xe_bo.h" -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_device_types.h" +#include "xe_gt_types.h" #include "xe_guc.h" #include "xe_map.h" diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c index d7473b9673bb..acac66a4eca7 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@ -15,8 +15,8 @@ #include "xe_bo.h" #include "xe_devcoredump.h" #include "xe_force_wake.h" -#include "xe_gt.h" #include "xe_gt_printk.h" +#include "xe_gt_types.h" #include "xe_map.h" #include "xe_mmio.h" #include "xe_module.h" diff --git a/drivers/gpu/drm/xe/xe_guc_relay.c b/drivers/gpu/drm/xe/xe_guc_relay.c index 0c0ff24ba62a..577a315854af 100644 --- a/drivers/gpu/drm/xe/xe_guc_relay.c +++ b/drivers/gpu/drm/xe/xe_guc_relay.c @@ -17,8 +17,7 @@ #include "abi/guc_relay_communication_abi.h" #include "xe_assert.h" -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_device_types.h" #include "xe_gt_sriov_printk.h" #include "xe_gt_sriov_pf_service.h" #include "xe_guc.h" diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 7a4218f76024..a27ea931b956 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -17,7 +17,6 @@ #include "abi/guc_actions_abi.h" #include "abi/guc_actions_slpc_abi.h" #include "abi/guc_klvs_abi.h" -#include "regs/xe_lrc_layout.h" #include "xe_assert.h" #include "xe_bo.h" #include "xe_devcoredump.h" @@ -36,7 +35,6 @@ #include "xe_guc_klv_helpers.h" #include "xe_guc_submit_types.h" #include "xe_hw_engine.h" -#include "xe_hw_fence.h" #include "xe_lrc.h" #include "xe_macros.h" #include "xe_map.h" @@ -71,11 +69,8 @@ exec_queue_to_guc(struct xe_exec_queue *q) #define EXEC_QUEUE_STATE_KILLED (1 << 7) #define EXEC_QUEUE_STATE_WEDGED (1 << 8) #define EXEC_QUEUE_STATE_BANNED (1 << 9) -#define EXEC_QUEUE_STATE_CHECK_TIMEOUT (1 << 10) -#define EXEC_QUEUE_STATE_EXTRA_REF (1 << 11) -#define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 12) -#define EXEC_QUEUE_STATE_PENDING_TDR_EXIT (1 << 13) -#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 14) +#define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 10) +#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 11) static bool exec_queue_registered(struct xe_exec_queue *q) { @@ -207,36 +202,6 @@ static void set_exec_queue_wedged(struct xe_exec_queue *q) atomic_or(EXEC_QUEUE_STATE_WEDGED, &q->guc->state); } -static bool exec_queue_check_timeout(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_CHECK_TIMEOUT; -} - -static void set_exec_queue_check_timeout(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state); -} - -static void clear_exec_queue_check_timeout(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state); -} - -static bool exec_queue_extra_ref(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_EXTRA_REF; -} - -static void set_exec_queue_extra_ref(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); -} - -static void clear_exec_queue_extra_ref(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); -} - static bool exec_queue_pending_resume(struct xe_exec_queue *q) { return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_RESUME; @@ -252,21 +217,6 @@ static void clear_exec_queue_pending_resume(struct xe_exec_queue *q) atomic_and(~EXEC_QUEUE_STATE_PENDING_RESUME, &q->guc->state); } -static bool exec_queue_pending_tdr_exit(struct xe_exec_queue *q) -{ - return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_TDR_EXIT; -} - -static void set_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) -{ - atomic_or(EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); -} - -static void clear_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) -{ - atomic_and(~EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); -} - static bool exec_queue_idle_skip_suspend(struct xe_exec_queue *q) { return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND; @@ -603,10 +553,7 @@ static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q) /** to wakeup xe_wait_user_fence ioctl if exec queue is reset */ wake_up_all(&xe->ufence_wq); - if (xe_exec_queue_is_lr(q)) - queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr); - else - xe_sched_tdr_queue_imm(&q->guc->sched); + xe_sched_tdr_queue_imm(&q->guc->sched); } static void xe_guc_exec_queue_group_trigger_cleanup(struct xe_exec_queue *q) @@ -639,19 +586,19 @@ static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q) WRITE_ONCE(group->banned, true); set_exec_queue_reset(primary); - if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary)) + if (!exec_queue_banned(primary)) xe_guc_exec_queue_trigger_cleanup(primary); mutex_lock(&group->list_lock); list_for_each_entry(eq, &group->list, multi_queue.link) { set_exec_queue_reset(eq); - if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq)) + if (!exec_queue_banned(eq)) xe_guc_exec_queue_trigger_cleanup(eq); } mutex_unlock(&group->list_lock); } else { set_exec_queue_reset(q); - if (!exec_queue_banned(q) && !exec_queue_check_timeout(q)) + if (!exec_queue_banned(q)) xe_guc_exec_queue_trigger_cleanup(q); } } @@ -994,14 +941,6 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type) parallel_write(xe, map, wq_desc.wq_status, WQ_STATUS_ACTIVE); } - /* - * We must keep a reference for LR engines if engine is registered with - * the GuC as jobs signal immediately and can't destroy an engine if the - * GuC has a reference to it. - */ - if (xe_exec_queue_is_lr(q)) - xe_exec_queue_get(q); - set_exec_queue_registered(q); trace_xe_exec_queue_register(q); if (xe_exec_queue_is_multi_queue_primary(q)) @@ -1202,7 +1141,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) struct xe_sched_job *job = to_xe_sched_job(drm_job); struct xe_exec_queue *q = job->q; struct xe_guc *guc = exec_queue_to_guc(q); - bool lr = xe_exec_queue_is_lr(q), killed_or_banned_or_wedged = + bool killed_or_banned_or_wedged = exec_queue_killed_or_banned_or_wedged(q); xe_gt_assert(guc_to_gt(guc), !(exec_queue_destroyed(q) || exec_queue_pending_disable(q)) || @@ -1232,14 +1171,6 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) } run_job_out: - /* - * We don't care about job-fence ordering in LR VMs because these fences - * are never exported; they are used solely to keep jobs on the pending - * list. Once a queue enters an error state, there's no need to track - * them. - */ - if (killed_or_banned_or_wedged && lr) - xe_sched_job_set_error(job, -ECANCELED); return job->fence; } @@ -1291,8 +1222,7 @@ static void disable_scheduling_deregister(struct xe_guc *guc, xe_gt_warn(q->gt, "Pending enable/disable failed to respond\n"); xe_sched_submission_start(sched); xe_gt_reset_async(q->gt); - if (!xe_exec_queue_is_lr(q)) - xe_sched_tdr_queue_imm(sched); + xe_sched_tdr_queue_imm(sched); return; } @@ -1339,8 +1269,9 @@ void xe_guc_submit_wedge(struct xe_guc *guc) err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, guc_submit_wedged_fini, guc); if (err) { - xe_gt_err(gt, "Failed to register clean-up on wedged.mode=2; " - "Although device is wedged.\n"); + xe_gt_err(gt, "Failed to register clean-up in wedged.mode=%s; " + "Although device is wedged.\n", + xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)); return; } @@ -1355,7 +1286,7 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc) { struct xe_device *xe = guc_to_xe(guc); - if (xe->wedged.mode != 2) + if (xe->wedged.mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) return false; if (xe_device_wedged(xe)) @@ -1366,84 +1297,6 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc) return true; } -static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w) -{ - struct xe_guc_exec_queue *ge = - container_of(w, struct xe_guc_exec_queue, lr_tdr); - struct xe_exec_queue *q = ge->q; - struct xe_guc *guc = exec_queue_to_guc(q); - struct xe_gpu_scheduler *sched = &ge->sched; - struct xe_sched_job *job; - bool wedged = false; - - xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_lr(q)); - - if (vf_recovery(guc)) - return; - - trace_xe_exec_queue_lr_cleanup(q); - - if (!exec_queue_killed(q)) - wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); - - /* Kill the run_job / process_msg entry points */ - xe_sched_submission_stop(sched); - - /* - * Engine state now mostly stable, disable scheduling / deregister if - * needed. This cleanup routine might be called multiple times, where - * the actual async engine deregister drops the final engine ref. - * Calling disable_scheduling_deregister will mark the engine as - * destroyed and fire off the CT requests to disable scheduling / - * deregister, which we only want to do once. We also don't want to mark - * the engine as pending_disable again as this may race with the - * xe_guc_deregister_done_handler() which treats it as an unexpected - * state. - */ - if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) { - struct xe_guc *guc = exec_queue_to_guc(q); - int ret; - - set_exec_queue_banned(q); - disable_scheduling_deregister(guc, q); - - /* - * Must wait for scheduling to be disabled before signalling - * any fences, if GT broken the GT reset code should signal us. - */ - ret = wait_event_timeout(guc->ct.wq, - !exec_queue_pending_disable(q) || - xe_guc_read_stopped(guc) || - vf_recovery(guc), HZ * 5); - if (vf_recovery(guc)) - return; - - if (!ret) { - xe_gt_warn(q->gt, "Schedule disable failed to respond, guc_id=%d\n", - q->guc->id); - xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n", - q->guc->id); - xe_sched_submission_start(sched); - xe_gt_reset_async(q->gt); - return; - } - } - - if (!exec_queue_killed(q) && !xe_lrc_ring_is_idle(q->lrc[0])) - xe_devcoredump(q, NULL, "LR job cleanup, guc_id=%d", q->guc->id); - - xe_hw_fence_irq_stop(q->fence_irq); - - xe_sched_submission_start(sched); - - spin_lock(&sched->base.job_list_lock); - list_for_each_entry(job, &sched->base.pending_list, drm.list) - xe_sched_job_set_error(job, -ECANCELED); - spin_unlock(&sched->base.job_list_lock); - - xe_hw_fence_irq_start(q->fence_irq); -} - #define ADJUST_FIVE_PERCENT(__t) mul_u64_u32_div(__t, 105, 100) static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) @@ -1462,7 +1315,16 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) return xe_sched_invalidate_job(job, 2); } - ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0])); + ctx_timestamp = lower_32_bits(xe_lrc_timestamp(q->lrc[0])); + if (ctx_timestamp == job->sample_timestamp) { + xe_gt_warn(gt, "Check job timeout: seqno=%u, lrc_seqno=%u, guc_id=%d, timestamp stuck", + xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job), + q->guc->id); + + return xe_sched_invalidate_job(job, 0); + } + + job->sample_timestamp = ctx_timestamp; ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); /* @@ -1516,8 +1378,7 @@ static void enable_scheduling(struct xe_exec_queue *q) xe_gt_warn(guc_to_gt(guc), "Schedule enable failed to respond"); set_exec_queue_banned(q); xe_gt_reset_async(q->gt); - if (!xe_exec_queue_is_lr(q)) - xe_sched_tdr_queue_imm(&q->guc->sched); + xe_sched_tdr_queue_imm(&q->guc->sched); } } @@ -1543,33 +1404,11 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate) G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1); } -static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q) -{ - u32 action[] = { - XE_GUC_ACTION_DEREGISTER_CONTEXT, - q->guc->id, - }; - - xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); - xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q)); - xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_enable(q)); - xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q)); - - set_exec_queue_destroyed(q); - trace_xe_exec_queue_deregister(q); - - if (xe_exec_queue_is_multi_queue_secondary(q)) - handle_deregister_done(guc, q); - else - xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), - G2H_LEN_DW_DEREGISTER_CONTEXT, 1); -} - static enum drm_gpu_sched_stat guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) { struct xe_sched_job *job = to_xe_sched_job(drm_job); - struct xe_sched_job *tmp_job; + struct drm_sched_job *tmp_job; struct xe_exec_queue *q = job->q; struct xe_gpu_scheduler *sched = &q->guc->sched; struct xe_guc *guc = exec_queue_to_guc(q); @@ -1577,10 +1416,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) struct xe_device *xe = guc_to_xe(guc); int err = -ETIME; pid_t pid = -1; - int i = 0; bool wedged = false, skip_timeout_check; - xe_gt_assert(guc_to_gt(guc), !xe_exec_queue_is_lr(q)); + xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); /* * TDR has fired before free job worker. Common if exec queue @@ -1597,14 +1435,17 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) /* Must check all state after stopping scheduler */ skip_timeout_check = exec_queue_reset(q) || - exec_queue_killed_or_banned_or_wedged(q) || - exec_queue_destroyed(q); + exec_queue_killed_or_banned_or_wedged(q); /* Skip timeout check if multi-queue group is banned */ if (xe_exec_queue_is_multi_queue(q) && READ_ONCE(q->multi_queue.group->banned)) skip_timeout_check = true; + /* LR jobs can only get here if queue has been killed or hit an error */ + if (xe_exec_queue_is_lr(q)) + xe_gt_assert(guc_to_gt(guc), skip_timeout_check); + /* * FIXME: In multi-queue scenario, the TDR must ensure that the whole * multi-queue group is off the HW before signaling the fences to avoid @@ -1628,23 +1469,24 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) } /* - * XXX: Sampling timeout doesn't work in wedged mode as we have to - * modify scheduling state to read timestamp. We could read the - * timestamp from a register to accumulate current running time but this - * doesn't work for SRIOV. For now assuming timeouts in wedged mode are - * genuine timeouts. + * Check if job is actually timed out, if so restart job execution and TDR */ + if (!skip_timeout_check && !check_timeout(q, job)) + goto rearm; + if (!exec_queue_killed(q)) wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); - /* Engine state now stable, disable scheduling to check timestamp */ - if (!wedged && exec_queue_registered(q)) { + set_exec_queue_banned(q); + + /* Kick job / queue off hardware */ + if (!wedged && (exec_queue_enabled(q) || exec_queue_pending_disable(q))) { int ret; if (exec_queue_reset(q)) err = -EIO; - if (!exec_queue_destroyed(q)) { + if (xe_uc_fw_is_running(&guc->fw)) { /* * Wait for any pending G2H to flush out before * modifying state @@ -1659,13 +1501,6 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) if (!ret || xe_guc_read_stopped(guc)) goto trigger_reset; - /* - * Flag communicates to G2H handler that schedule - * disable originated from a timeout check. The G2H then - * avoid triggering cleanup or deregistering the exec - * queue. - */ - set_exec_queue_check_timeout(q); disable_scheduling(q, skip_timeout_check); } @@ -1679,6 +1514,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) */ smp_rmb(); ret = wait_event_timeout(guc->ct.wq, + !xe_uc_fw_is_running(&guc->fw) || !exec_queue_pending_disable(q) || xe_guc_read_stopped(guc) || vf_recovery(guc), HZ * 5); @@ -1693,24 +1529,12 @@ trigger_reset: xe_devcoredump(q, job, "Schedule disable failed to respond, guc_id=%d, ret=%d, guc_read=%d", q->guc->id, ret, xe_guc_read_stopped(guc)); - set_exec_queue_extra_ref(q); - xe_exec_queue_get(q); /* GT reset owns this */ - set_exec_queue_banned(q); xe_gt_reset_async(q->gt); xe_sched_tdr_queue_imm(sched); goto rearm; } } - /* - * Check if job is actually timed out, if so restart job execution and TDR - */ - if (!wedged && !skip_timeout_check && !check_timeout(q, job) && - !exec_queue_reset(q) && exec_queue_registered(q)) { - clear_exec_queue_check_timeout(q); - goto sched_enable; - } - if (q->vm && q->vm->xef) { process_name = q->vm->xef->process_name; pid = q->vm->xef->pid; @@ -1741,28 +1565,16 @@ trigger_reset: if (!wedged && (q->flags & EXEC_QUEUE_FLAG_KERNEL || (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)))) { if (!xe_sched_invalidate_job(job, 2)) { - clear_exec_queue_check_timeout(q); xe_gt_reset_async(q->gt); goto rearm; } } - /* Finish cleaning up exec queue via deregister */ - set_exec_queue_banned(q); - if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) { - set_exec_queue_extra_ref(q); - xe_exec_queue_get(q); - __deregister_exec_queue(guc, q); - } - - /* Stop fence signaling */ - xe_hw_fence_irq_stop(q->fence_irq); + /* Mark all outstanding jobs as bad, thus completing them */ + xe_sched_job_set_error(job, err); + drm_sched_for_each_pending_job(tmp_job, &sched->base, NULL) + xe_sched_job_set_error(to_xe_sched_job(tmp_job), -ECANCELED); - /* - * Fence state now stable, stop / start scheduler which cleans up any - * fences that are complete - */ - xe_sched_add_pending_job(sched, job); xe_sched_submission_start(sched); if (xe_exec_queue_is_multi_queue(q)) @@ -1770,20 +1582,12 @@ trigger_reset: else xe_guc_exec_queue_trigger_cleanup(q); - /* Mark all outstanding jobs as bad, thus completing them */ - spin_lock(&sched->base.job_list_lock); - list_for_each_entry(tmp_job, &sched->base.pending_list, drm.list) - xe_sched_job_set_error(tmp_job, !i++ ? err : -ECANCELED); - spin_unlock(&sched->base.job_list_lock); - - /* Start fence signaling */ - xe_hw_fence_irq_start(q->fence_irq); - - return DRM_GPU_SCHED_STAT_RESET; + /* + * We want the job added back to the pending list so it gets freed; this + * is what DRM_GPU_SCHED_STAT_NO_HANG does. + */ + return DRM_GPU_SCHED_STAT_NO_HANG; -sched_enable: - set_exec_queue_pending_tdr_exit(q); - enable_scheduling(q); rearm: /* * XXX: Ideally want to adjust timeout based on current execution time @@ -1829,8 +1633,6 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) mutex_unlock(&group->list_lock); } - if (xe_exec_queue_is_lr(q)) - cancel_work_sync(&ge->lr_tdr); /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&ge->sched.base.work_tdr); @@ -2134,9 +1936,6 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) if (err) goto err_sched; - if (xe_exec_queue_is_lr(q)) - INIT_WORK(&q->guc->lr_tdr, xe_guc_exec_queue_lr_cleanup); - mutex_lock(&guc->submission_state.lock); err = alloc_guc_id(guc, q); @@ -2432,9 +2231,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) /* Clean up lost G2H + reset engine state */ if (exec_queue_registered(q)) { - if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); - else if (exec_queue_destroyed(q)) + if (exec_queue_destroyed(q)) __guc_exec_queue_destroy(guc, q); } if (q->guc->suspend_pending) { @@ -2464,9 +2261,6 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) trace_xe_sched_job_ban(job); ban = true; } - } else if (xe_exec_queue_is_lr(q) && - !xe_lrc_ring_is_idle(q->lrc[0])) { - ban = true; } if (ban) { @@ -2546,11 +2340,8 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, q->guc->id); } - if (pending_enable && !pending_resume && - !exec_queue_pending_tdr_exit(q)) { + if (pending_enable && !pending_resume) { clear_exec_queue_registered(q); - if (xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); xe_gt_dbg(guc_to_gt(guc), "Replay REGISTER - guc_id=%d", q->guc->id); } @@ -2558,7 +2349,6 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, if (pending_enable) { clear_exec_queue_enabled(q); clear_exec_queue_pending_resume(q); - clear_exec_queue_pending_tdr_exit(q); clear_exec_queue_pending_enable(q); xe_gt_dbg(guc_to_gt(guc), "Replay ENABLE - guc_id=%d", q->guc->id); @@ -2566,11 +2356,7 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, if (exec_queue_destroyed(q) && exec_queue_registered(q)) { clear_exec_queue_destroyed(q); - if (exec_queue_extra_ref(q)) - xe_exec_queue_put(q); - else - q->guc->needs_cleanup = true; - clear_exec_queue_extra_ref(q); + q->guc->needs_cleanup = true; xe_gt_dbg(guc_to_gt(guc), "Replay CLEANUP - guc_id=%d", q->guc->id); } @@ -2588,7 +2374,6 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, if (!pending_enable) set_exec_queue_enabled(q); clear_exec_queue_pending_disable(q); - clear_exec_queue_check_timeout(q); xe_gt_dbg(guc_to_gt(guc), "Replay DISABLE - guc_id=%d", q->guc->id); } @@ -2623,10 +2408,7 @@ static void guc_exec_queue_pause(struct xe_guc *guc, struct xe_exec_queue *q) /* Stop scheduling + flush any DRM scheduler operations */ xe_sched_submission_stop(sched); - if (xe_exec_queue_is_lr(q)) - cancel_work_sync(&q->guc->lr_tdr); - else - cancel_delayed_work_sync(&sched->base.work_tdr); + cancel_delayed_work_sync(&sched->base.work_tdr); guc_exec_queue_revert_pending_state_change(guc, q); @@ -2753,11 +2535,12 @@ static void guc_exec_queue_unpause_prepare(struct xe_guc *guc, struct xe_exec_queue *q) { struct xe_gpu_scheduler *sched = &q->guc->sched; - struct xe_sched_job *job = NULL, *__job; + struct xe_sched_job *job = NULL; + struct drm_sched_job *s_job; bool restore_replay = false; - list_for_each_entry(__job, &sched->base.pending_list, drm.list) { - job = __job; + drm_sched_for_each_pending_job(s_job, &sched->base, NULL) { + job = to_xe_sched_job(s_job); restore_replay |= job->restore_replay; if (restore_replay) { xe_gt_dbg(guc_to_gt(guc), "Replay JOB - guc_id=%d, seqno=%d", @@ -2881,7 +2664,7 @@ void xe_guc_submit_unpause_vf(struct xe_guc *guc) * created after resfix done. */ if (q->guc->id != index || - !READ_ONCE(q->guc->sched.base.pause_submit)) + !drm_sched_is_stopped(&q->guc->sched.base)) continue; guc_exec_queue_unpause(guc, q); @@ -2967,13 +2750,10 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, q->guc->resume_time = ktime_get(); clear_exec_queue_pending_resume(q); - clear_exec_queue_pending_tdr_exit(q); clear_exec_queue_pending_enable(q); smp_wmb(); wake_up_all(&guc->ct.wq); } else { - bool check_timeout = exec_queue_check_timeout(q); - xe_gt_assert(guc_to_gt(guc), runnable_state == 0); xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q)); @@ -2981,11 +2761,11 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, suspend_fence_signal(q); clear_exec_queue_pending_disable(q); } else { - if (exec_queue_banned(q) || check_timeout) { + if (exec_queue_banned(q)) { smp_wmb(); wake_up_all(&guc->ct.wq); } - if (!check_timeout && exec_queue_destroyed(q)) { + if (exec_queue_destroyed(q)) { /* * Make sure to clear the pending_disable only * after sampling the destroyed state. We want @@ -3048,11 +2828,7 @@ static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q) trace_xe_exec_queue_deregister_done(q); clear_exec_queue_registered(q); - - if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); - else - __guc_exec_queue_destroy(guc, q); + __guc_exec_queue_destroy(guc, q); } int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len) @@ -3386,29 +3162,6 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q) snapshot->multi_queue.primary = xe_exec_queue_multi_queue_primary(q)->guc->id; snapshot->multi_queue.pos = q->multi_queue.pos; } - spin_lock(&sched->base.job_list_lock); - snapshot->pending_list_size = list_count_nodes(&sched->base.pending_list); - snapshot->pending_list = kmalloc_array(snapshot->pending_list_size, - sizeof(struct pending_list_snapshot), - GFP_ATOMIC); - - if (snapshot->pending_list) { - struct xe_sched_job *job_iter; - - i = 0; - list_for_each_entry(job_iter, &sched->base.pending_list, drm.list) { - snapshot->pending_list[i].seqno = - xe_sched_job_seqno(job_iter); - snapshot->pending_list[i].fence = - dma_fence_is_signaled(job_iter->fence) ? 1 : 0; - snapshot->pending_list[i].finished = - dma_fence_is_signaled(&job_iter->drm.s_fence->finished) - ? 1 : 0; - i++; - } - } - - spin_unlock(&sched->base.job_list_lock); return snapshot; } @@ -3472,13 +3225,6 @@ xe_guc_exec_queue_snapshot_print(struct xe_guc_submit_exec_queue_snapshot *snaps drm_printf(p, "\tMulti queue primary GuC ID: %d\n", snapshot->multi_queue.primary); drm_printf(p, "\tMulti queue position: %d\n", snapshot->multi_queue.pos); } - - for (i = 0; snapshot->pending_list && i < snapshot->pending_list_size; - i++) - drm_printf(p, "\tJob: seqno=%d, fence=%d, finished=%d\n", - snapshot->pending_list[i].seqno, - snapshot->pending_list[i].fence, - snapshot->pending_list[i].finished); } /** @@ -3501,7 +3247,6 @@ void xe_guc_exec_queue_snapshot_free(struct xe_guc_submit_exec_queue_snapshot *s xe_lrc_snapshot_free(snapshot->lrc[i]); kfree(snapshot->lrc); } - kfree(snapshot->pending_list); kfree(snapshot); } diff --git a/drivers/gpu/drm/xe/xe_guc_submit_types.h b/drivers/gpu/drm/xe/xe_guc_submit_types.h index 25e29e85502c..5ccc5f959bb3 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit_types.h +++ b/drivers/gpu/drm/xe/xe_guc_submit_types.h @@ -61,12 +61,6 @@ struct guc_submit_parallel_scratch { u32 wq[WQ_SIZE / sizeof(u32)]; }; -struct pending_list_snapshot { - u32 seqno; - bool fence; - bool finished; -}; - /** * struct xe_guc_submit_exec_queue_snapshot - Snapshot for devcoredump */ @@ -147,11 +141,6 @@ struct xe_guc_submit_exec_queue_snapshot { /** @valid: The exec queue is part of a multi queue group */ bool valid; } multi_queue; - - /** @pending_list_size: Size of the pending list snapshot array */ - int pending_list_size; - /** @pending_list: snapshot of the pending list info */ - struct pending_list_snapshot *pending_list; }; #endif diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c index 6532a88d51e2..774467befbb9 100644 --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c @@ -97,6 +97,7 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) static int send_page_reclaim(struct xe_guc *guc, u32 seqno, u64 gpu_addr) { + struct xe_gt *gt = guc_to_gt(guc); u32 action[] = { XE_GUC_ACTION_PAGE_RECLAMATION, seqno, @@ -104,6 +105,8 @@ static int send_page_reclaim(struct xe_guc *guc, u32 seqno, upper_32_bits(gpu_addr), }; + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_ISSUED_COUNT, 1); + return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), G2H_LEN_DW_PAGE_RECLAMATION, 1); } diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.c b/drivers/gpu/drm/xe/xe_heci_gsc.c index 495cdd4f948d..c1f15313f92e 100644 --- a/drivers/gpu/drm/xe/xe_heci_gsc.c +++ b/drivers/gpu/drm/xe/xe_heci_gsc.c @@ -11,7 +11,6 @@ #include <drm/drm_print.h> #include "xe_device_types.h" -#include "xe_drv.h" #include "xe_heci_gsc.h" #include "regs/xe_gsc_regs.h" #include "xe_platform_types.h" diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c index 4212162913af..57afe21444b1 100644 --- a/drivers/gpu/drm/xe/xe_huc.c +++ b/drivers/gpu/drm/xe/xe_huc.c @@ -12,7 +12,6 @@ #include "abi/gsc_pxp_commands_abi.h" #include "regs/xe_gsc_regs.h" #include "regs/xe_guc_regs.h" -#include "xe_assert.h" #include "xe_bo.h" #include "xe_device.h" #include "xe_force_wake.h" diff --git a/drivers/gpu/drm/xe/xe_huc_debugfs.c b/drivers/gpu/drm/xe/xe_huc_debugfs.c index df9c4d79b710..80829967b3d7 100644 --- a/drivers/gpu/drm/xe/xe_huc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_huc_debugfs.c @@ -7,11 +7,10 @@ #include <drm/drm_debugfs.h> #include <drm/drm_managed.h> +#include <drm/drm_print.h> -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_huc.h" -#include "xe_macros.h" #include "xe_pm.h" static struct xe_gt * diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 6a9e2a4272dd..4d3ee5226e3a 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -33,7 +33,6 @@ #include "xe_hw_fence.h" #include "xe_irq.h" #include "xe_lrc.h" -#include "xe_macros.h" #include "xe_mmio.h" #include "xe_reg_sr.h" #include "xe_reg_whitelist.h" diff --git a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c index cb45cdceef67..3c65becb39ad 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c +++ b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c @@ -7,7 +7,7 @@ #include <linux/kobject.h> #include <linux/sysfs.h> -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_gt.h" #include "xe_hw_engine_class_sysfs.h" #include "xe_pm.h" diff --git a/drivers/gpu/drm/xe/xe_hw_engine_group.c b/drivers/gpu/drm/xe/xe_hw_engine_group.c index f69a32c27458..2ef33dfbe3a2 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_group.c +++ b/drivers/gpu/drm/xe/xe_hw_engine_group.c @@ -6,7 +6,7 @@ #include <drm/drm_managed.h> #include "xe_assert.h" -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_exec_queue.h" #include "xe_gt.h" #include "xe_gt_stats.h" diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c index f6057456e460..ae8ed15b64c5 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.c +++ b/drivers/gpu/drm/xe/xe_hw_fence.c @@ -8,9 +8,7 @@ #include <linux/device.h> #include <linux/slab.h> -#include "xe_bo.h" -#include "xe_device.h" -#include "xe_gt.h" +#include "xe_device_types.h" #include "xe_hw_engine.h" #include "xe_macros.h" #include "xe_map.h" @@ -108,22 +106,6 @@ void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq) irq_work_queue(&irq->work); } -void xe_hw_fence_irq_stop(struct xe_hw_fence_irq *irq) -{ - spin_lock_irq(&irq->lock); - irq->enabled = false; - spin_unlock_irq(&irq->lock); -} - -void xe_hw_fence_irq_start(struct xe_hw_fence_irq *irq) -{ - spin_lock_irq(&irq->lock); - irq->enabled = true; - spin_unlock_irq(&irq->lock); - - irq_work_queue(&irq->work); -} - void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt, struct xe_hw_fence_irq *irq, const char *name) { diff --git a/drivers/gpu/drm/xe/xe_hw_fence.h b/drivers/gpu/drm/xe/xe_hw_fence.h index f13a1c4982c7..599492c13f80 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.h +++ b/drivers/gpu/drm/xe/xe_hw_fence.h @@ -17,8 +17,6 @@ void xe_hw_fence_module_exit(void); void xe_hw_fence_irq_init(struct xe_hw_fence_irq *irq); void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq); void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq); -void xe_hw_fence_irq_stop(struct xe_hw_fence_irq *irq); -void xe_hw_fence_irq_start(struct xe_hw_fence_irq *irq); void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt, struct xe_hw_fence_irq *irq, const char *name); diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index ff2aea52ef75..baf277955b33 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -39,10 +39,16 @@ enum xe_hwmon_reg_operation { REG_READ64, }; +#define MAX_VRAM_CHANNELS (16) + enum xe_hwmon_channel { CHANNEL_CARD, CHANNEL_PKG, CHANNEL_VRAM, + CHANNEL_MCTRL, + CHANNEL_PCIE, + CHANNEL_VRAM_N, + CHANNEL_VRAM_N_MAX = CHANNEL_VRAM_N + MAX_VRAM_CHANNELS, CHANNEL_MAX, }; @@ -53,6 +59,15 @@ enum xe_fan_channel { FAN_MAX, }; +enum xe_temp_limit { + TEMP_LIMIT_PKG_SHUTDOWN, + TEMP_LIMIT_PKG_CRIT, + TEMP_LIMIT_MEM_SHUTDOWN, + TEMP_LIMIT_PKG_MAX, + TEMP_LIMIT_MEM_CRIT, + TEMP_LIMIT_MAX +}; + /* Attribute index for powerX_xxx_interval sysfs entries */ enum sensor_attr_power { SENSOR_INDEX_PSYS_PL1, @@ -91,6 +106,12 @@ enum sensor_attr_power { */ #define PL_WRITE_MBX_TIMEOUT_MS (1) +/* Index of memory controller in READ_THERMAL_DATA output */ +#define TEMP_INDEX_MCTRL 2 + +/* Maximum characters in hwmon label name */ +#define MAX_LABEL_SIZE 16 + /** * struct xe_hwmon_energy_info - to accumulate energy */ @@ -112,6 +133,24 @@ struct xe_hwmon_fan_info { }; /** + * struct xe_hwmon_thermal_info - to store temperature data + */ +struct xe_hwmon_thermal_info { + union { + /** @limit: temperatures limits */ + u8 limit[TEMP_LIMIT_MAX]; + /** @data: temperature limits in dwords */ + u32 data[DIV_ROUND_UP(TEMP_LIMIT_MAX, sizeof(u32))]; + }; + /** @count: no of temperature sensors available for the platform */ + u8 count; + /** @value: signed value from each sensor */ + s8 value[U8_MAX]; + /** @vram_label: vram label names */ + char vram_label[MAX_VRAM_CHANNELS][MAX_LABEL_SIZE]; +}; + +/** * struct xe_hwmon - xe hwmon data structure */ struct xe_hwmon { @@ -137,7 +176,8 @@ struct xe_hwmon { u32 pl1_on_boot[CHANNEL_MAX]; /** @pl2_on_boot: power limit PL2 on boot */ u32 pl2_on_boot[CHANNEL_MAX]; - + /** @temp: Temperature info */ + struct xe_hwmon_thermal_info temp; }; static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 attr, int channel, @@ -224,6 +264,8 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg return BMG_PACKAGE_TEMPERATURE; else if (channel == CHANNEL_VRAM) return BMG_VRAM_TEMPERATURE; + else if (in_range(channel, CHANNEL_VRAM_N, CHANNEL_VRAM_N_MAX)) + return BMG_VRAM_TEMPERATURE_N(channel - CHANNEL_VRAM_N); } else if (xe->info.platform == XE_DG2) { if (channel == CHANNEL_PKG) return PCU_CR_PACKAGE_TEMPERATURE; @@ -677,8 +719,29 @@ static const struct attribute_group *hwmon_groups[] = { }; static const struct hwmon_channel_info * const hwmon_info[] = { - HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(temp, + HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL | + HWMON_T_MAX, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL), HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CRIT | HWMON_P_CAP, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CAP), @@ -689,6 +752,75 @@ static const struct hwmon_channel_info * const hwmon_info[] = { NULL }; +static int xe_hwmon_pcode_read_thermal_info(struct xe_hwmon *hwmon) +{ + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); + u32 config = 0; + int ret; + + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_LIMITS, 0), + &hwmon->temp.data[0], &hwmon->temp.data[1]); + if (ret) + return ret; + + drm_dbg(&hwmon->xe->drm, "thermal info read val 0x%x val1 0x%x\n", + hwmon->temp.data[0], hwmon->temp.data[1]); + + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_CONFIG, 0), + &config, NULL); + if (ret) + return ret; + + drm_dbg(&hwmon->xe->drm, "thermal config count 0x%x\n", config); + hwmon->temp.count = REG_FIELD_GET(TEMP_MASK, config); + + return ret; +} + +static int get_mc_temp(struct xe_hwmon *hwmon, long *val) +{ + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); + u32 *dword = (u32 *)hwmon->temp.value; + s32 average = 0; + int ret, i; + + for (i = 0; i < DIV_ROUND_UP(TEMP_LIMIT_MAX, sizeof(u32)); i++) { + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_DATA, i), + (dword + i), NULL); + if (ret) + return ret; + drm_dbg(&hwmon->xe->drm, "thermal data for group %d val 0x%x\n", i, dword[i]); + } + + for (i = TEMP_INDEX_MCTRL; i < hwmon->temp.count - 1; i++) + average += hwmon->temp.value[i]; + + average /= (hwmon->temp.count - TEMP_INDEX_MCTRL - 1); + *val = average * MILLIDEGREE_PER_DEGREE; + return 0; +} + +static int get_pcie_temp(struct xe_hwmon *hwmon, long *val) +{ + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); + u32 data = 0; + int ret; + + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_DATA, + PCIE_SENSOR_GROUP_ID), &data, NULL); + if (ret) + return ret; + + /* Sensor offset is different for G21 */ + if (hwmon->xe->info.subplatform != XE_SUBPLATFORM_BATTLEMAGE_G21) + data = REG_FIELD_GET(PCIE_SENSOR_MASK, data); + + data = REG_FIELD_GET(TEMP_MASK, data); + *val = (s8)data * MILLIDEGREE_PER_DEGREE; + + return 0; +} + /* I1 is exposed as power_crit or as curr_crit depending on bit 31 */ static int xe_hwmon_pcode_read_i1(const struct xe_hwmon *hwmon, u32 *uval) { @@ -783,13 +915,77 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu *value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE); } +static inline bool is_vram_ch_available(struct xe_hwmon *hwmon, int channel) +{ + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); + int vram_id = channel - CHANNEL_VRAM_N; + struct xe_reg vram_reg; + + vram_reg = xe_hwmon_get_reg(hwmon, REG_TEMP, channel); + if (!xe_reg_is_valid(vram_reg) || !xe_mmio_read32(mmio, vram_reg)) + return false; + + /* Create label only for available vram channel */ + sprintf(hwmon->temp.vram_label[vram_id], "vram_ch_%d", vram_id); + return true; +} + static umode_t xe_hwmon_temp_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) { switch (attr) { + case hwmon_temp_emergency: + switch (channel) { + case CHANNEL_PKG: + return hwmon->temp.limit[TEMP_LIMIT_PKG_SHUTDOWN] ? 0444 : 0; + case CHANNEL_VRAM: + return hwmon->temp.limit[TEMP_LIMIT_MEM_SHUTDOWN] ? 0444 : 0; + case CHANNEL_MCTRL: + case CHANNEL_PCIE: + return hwmon->temp.count ? 0444 : 0; + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: + return (is_vram_ch_available(hwmon, channel) && + hwmon->temp.limit[TEMP_LIMIT_MEM_SHUTDOWN]) ? 0444 : 0; + default: + return 0; + } + case hwmon_temp_crit: + switch (channel) { + case CHANNEL_PKG: + return hwmon->temp.limit[TEMP_LIMIT_PKG_CRIT] ? 0444 : 0; + case CHANNEL_VRAM: + return hwmon->temp.limit[TEMP_LIMIT_MEM_CRIT] ? 0444 : 0; + case CHANNEL_MCTRL: + case CHANNEL_PCIE: + return hwmon->temp.count ? 0444 : 0; + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: + return (is_vram_ch_available(hwmon, channel) && + hwmon->temp.limit[TEMP_LIMIT_MEM_CRIT]) ? 0444 : 0; + default: + return 0; + } + case hwmon_temp_max: + switch (channel) { + case CHANNEL_PKG: + return hwmon->temp.limit[TEMP_LIMIT_PKG_MAX] ? 0444 : 0; + default: + return 0; + } case hwmon_temp_input: case hwmon_temp_label: - return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_TEMP, channel)) ? 0444 : 0; + switch (channel) { + case CHANNEL_PKG: + case CHANNEL_VRAM: + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_TEMP, + channel)) ? 0444 : 0; + case CHANNEL_MCTRL: + case CHANNEL_PCIE: + return hwmon->temp.count ? 0444 : 0; + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: + return is_vram_ch_available(hwmon, channel) ? 0444 : 0; + default: + return 0; + } default: return 0; } @@ -803,11 +999,67 @@ xe_hwmon_temp_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) switch (attr) { case hwmon_temp_input: - reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); + switch (channel) { + case CHANNEL_PKG: + case CHANNEL_VRAM: + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); - /* HW register value is in degrees Celsius, convert to millidegrees. */ - *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; - return 0; + /* HW register value is in degrees Celsius, convert to millidegrees. */ + *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; + return 0; + case CHANNEL_MCTRL: + return get_mc_temp(hwmon, val); + case CHANNEL_PCIE: + return get_pcie_temp(hwmon, val); + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); + /* + * This temperature format is 24 bit [31:8] signed integer and 8 bit + * [7:0] fraction. + */ + *val = (s32)(REG_FIELD_GET(TEMP_MASK_VRAM_N, reg_val)) * + (REG_FIELD_GET(TEMP_SIGN_MASK, reg_val) ? -1 : 1) * + MILLIDEGREE_PER_DEGREE; + return 0; + default: + return -EOPNOTSUPP; + } + case hwmon_temp_emergency: + switch (channel) { + case CHANNEL_PKG: + case CHANNEL_MCTRL: + case CHANNEL_PCIE: + *val = hwmon->temp.limit[TEMP_LIMIT_PKG_SHUTDOWN] * MILLIDEGREE_PER_DEGREE; + return 0; + case CHANNEL_VRAM: + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: + *val = hwmon->temp.limit[TEMP_LIMIT_MEM_SHUTDOWN] * MILLIDEGREE_PER_DEGREE; + return 0; + default: + return -EOPNOTSUPP; + } + case hwmon_temp_crit: + switch (channel) { + case CHANNEL_PKG: + case CHANNEL_MCTRL: + case CHANNEL_PCIE: + *val = hwmon->temp.limit[TEMP_LIMIT_PKG_CRIT] * MILLIDEGREE_PER_DEGREE; + return 0; + case CHANNEL_VRAM: + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: + *val = hwmon->temp.limit[TEMP_LIMIT_MEM_CRIT] * MILLIDEGREE_PER_DEGREE; + return 0; + default: + return -EOPNOTSUPP; + } + case hwmon_temp_max: + switch (channel) { + case CHANNEL_PKG: + *val = hwmon->temp.limit[TEMP_LIMIT_PKG_MAX] * MILLIDEGREE_PER_DEGREE; + return 0; + default: + return -EOPNOTSUPP; + } default: return -EOPNOTSUPP; } @@ -1163,12 +1415,20 @@ static int xe_hwmon_read_label(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, const char **str) { + struct xe_hwmon *hwmon = dev_get_drvdata(dev); + switch (type) { case hwmon_temp: if (channel == CHANNEL_PKG) *str = "pkg"; else if (channel == CHANNEL_VRAM) *str = "vram"; + else if (channel == CHANNEL_MCTRL) + *str = "mctrl"; + else if (channel == CHANNEL_PCIE) + *str = "pcie"; + else if (in_range(channel, CHANNEL_VRAM_N, CHANNEL_VRAM_N_MAX)) + *str = hwmon->temp.vram_label[channel - CHANNEL_VRAM_N]; return 0; case hwmon_power: case hwmon_energy: @@ -1263,6 +1523,9 @@ xe_hwmon_get_preregistration_info(struct xe_hwmon *hwmon) for (channel = 0; channel < FAN_MAX; channel++) if (xe_hwmon_is_visible(hwmon, hwmon_fan, hwmon_fan_input, channel)) xe_hwmon_fan_input_read(hwmon, channel, &fan_speed); + + if (hwmon->xe->info.has_mbx_thermal_info && xe_hwmon_pcode_read_thermal_info(hwmon)) + drm_warn(&hwmon->xe->drm, "Thermal mailbox not supported by card firmware\n"); } int xe_hwmon_register(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_i2c.c b/drivers/gpu/drm/xe/xe_i2c.c index 8eccbae05705..1e1fb72e49bf 100644 --- a/drivers/gpu/drm/xe/xe_i2c.c +++ b/drivers/gpu/drm/xe/xe_i2c.c @@ -5,6 +5,7 @@ * Copyright (C) 2025 Intel Corporation. */ +#include <drm/drm_print.h> #include <linux/array_size.h> #include <linux/container_of.h> #include <linux/device.h> @@ -26,11 +27,11 @@ #include "regs/xe_i2c_regs.h" #include "regs/xe_irq_regs.h" -#include "xe_device.h" #include "xe_device_types.h" #include "xe_i2c.h" #include "xe_mmio.h" -#include "xe_platform_types.h" +#include "xe_sriov.h" +#include "xe_survivability_mode.h" /** * DOC: Xe I2C devices @@ -213,11 +214,13 @@ static const struct irq_domain_ops xe_i2c_irq_ops = { .map = xe_i2c_irq_map, }; -static int xe_i2c_create_irq(struct xe_i2c *i2c) +static int xe_i2c_create_irq(struct xe_device *xe) { + struct xe_i2c *i2c = xe->i2c; struct irq_domain *domain; - if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ)) + if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ) || + xe_survivability_mode_is_boot_enabled(xe)) return 0; domain = irq_domain_create_linear(dev_fwnode(i2c->drm_dev), 1, &xe_i2c_irq_ops, NULL); @@ -351,7 +354,7 @@ int xe_i2c_probe(struct xe_device *xe) if (ret) return ret; - ret = xe_i2c_create_irq(i2c); + ret = xe_i2c_create_irq(xe); if (ret) goto err_unregister_notifier; diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c index baf5d2c6e802..7560a45f7f64 100644 --- a/drivers/gpu/drm/xe/xe_irq.c +++ b/drivers/gpu/drm/xe/xe_irq.c @@ -10,7 +10,6 @@ #include <drm/drm_managed.h> #include "display/xe_display.h" -#include "regs/xe_guc_regs.h" #include "regs/xe_irq_regs.h" #include "xe_device.h" #include "xe_drv.h" diff --git a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h index 0f5da89ce98b..2a8a985c37e7 100644 --- a/drivers/gpu/drm/xe/xe_late_bind_fw_types.h +++ b/drivers/gpu/drm/xe/xe_late_bind_fw_types.h @@ -15,10 +15,12 @@ #define XE_LB_MAX_PAYLOAD_SIZE SZ_4K /** - * xe_late_bind_fw_id - enum to determine late binding fw index + * enum xe_late_bind_fw_id - enum to determine late binding fw index */ enum xe_late_bind_fw_id { + /** @XE_LB_FW_FAN_CONTROL: Fan control */ XE_LB_FW_FAN_CONTROL = 0, + /** @XE_LB_FW_MAX_ID: Number of IDs */ XE_LB_FW_MAX_ID }; diff --git a/drivers/gpu/drm/xe/xe_lmtt.c b/drivers/gpu/drm/xe/xe_lmtt.c index 3059ea6525bc..2077e1ef8b43 100644 --- a/drivers/gpu/drm/xe/xe_lmtt.c +++ b/drivers/gpu/drm/xe/xe_lmtt.c @@ -289,7 +289,7 @@ void xe_lmtt_invalidate_hw(struct xe_lmtt *lmtt) ERR_PTR(err)); if (xe_device_has_mert(xe) && xe_tile_is_root(tile)) { - err = xe_mert_invalidate_lmtt(tile); + err = xe_mert_invalidate_lmtt(xe); if (err) xe_tile_sriov_err(tile, "MERT LMTT invalidation failed (%pe)", ERR_PTR(err)); diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 70eae7d03a27..f4f31bc240d9 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -857,7 +857,7 @@ u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc) * * Returns: ctx timestamp value */ -u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) +static u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) { struct xe_device *xe = lrc_to_xe(lrc); struct iosys_map map; @@ -1068,6 +1068,9 @@ static ssize_t setup_utilization_wa(struct xe_lrc *lrc, { u32 *cmd = batch; + if (IS_SRIOV_VF(gt_to_xe(lrc->gt))) + return 0; + if (xe_gt_WARN_ON(lrc->gt, max_len < 12)) return -ENOSPC; @@ -2406,35 +2409,31 @@ static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts) } /** - * xe_lrc_update_timestamp() - Update ctx timestamp + * xe_lrc_timestamp() - Current ctx timestamp * @lrc: Pointer to the lrc. - * @old_ts: Old timestamp value * - * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and - * update saved value. With support for active contexts, the calculation may be - * slightly racy, so follow a read-again logic to ensure that the context is - * still active before returning the right timestamp. + * Return latest ctx timestamp. With support for active contexts, the + * calculation may bb slightly racy, so follow a read-again logic to ensure that + * the context is still active before returning the right timestamp. * * Returns: New ctx timestamp value */ -u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) +u64 xe_lrc_timestamp(struct xe_lrc *lrc) { - u64 lrc_ts, reg_ts; + u64 lrc_ts, reg_ts, new_ts; u32 engine_id; - *old_ts = lrc->ctx_timestamp; - lrc_ts = xe_lrc_ctx_timestamp(lrc); /* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */ if (IS_SRIOV_VF(lrc_to_xe(lrc))) { - lrc->ctx_timestamp = lrc_ts; + new_ts = lrc_ts; goto done; } if (lrc_ts == CONTEXT_ACTIVE) { engine_id = xe_lrc_engine_id(lrc); if (!get_ctx_timestamp(lrc, engine_id, ®_ts)) - lrc->ctx_timestamp = reg_ts; + new_ts = reg_ts; /* read lrc again to ensure context is still active */ lrc_ts = xe_lrc_ctx_timestamp(lrc); @@ -2445,9 +2444,27 @@ u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) * be a separate if condition. */ if (lrc_ts != CONTEXT_ACTIVE) - lrc->ctx_timestamp = lrc_ts; + new_ts = lrc_ts; done: + return new_ts; +} + +/** + * xe_lrc_update_timestamp() - Update ctx timestamp + * @lrc: Pointer to the lrc. + * @old_ts: Old timestamp value + * + * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and + * update saved value. + * + * Returns: New ctx timestamp value + */ +u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) +{ + *old_ts = lrc->ctx_timestamp; + lrc->ctx_timestamp = xe_lrc_timestamp(lrc); + trace_xe_lrc_update_timestamp(lrc, *old_ts); return lrc->ctx_timestamp; diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h index 8acf85273c1a..c307a3fd9ea2 100644 --- a/drivers/gpu/drm/xe/xe_lrc.h +++ b/drivers/gpu/drm/xe/xe_lrc.h @@ -145,7 +145,6 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc); u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc); -u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); int xe_lrc_setup_wa_bb_with_scratch(struct xe_lrc *lrc, struct xe_hw_engine *hwe, @@ -165,4 +164,6 @@ int xe_lrc_setup_wa_bb_with_scratch(struct xe_lrc *lrc, struct xe_hw_engine *hwe */ u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts); +u64 xe_lrc_timestamp(struct xe_lrc *lrc); + #endif diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index b0c7ce0a5d1e..811e07136efb 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -7,7 +7,6 @@ #include "regs/xe_guc_regs.h" #include "regs/xe_irq_regs.h" -#include "regs/xe_regs.h" #include "xe_assert.h" #include "xe_bo.h" @@ -16,7 +15,6 @@ #include "xe_gt.h" #include "xe_guc.h" #include "xe_hw_engine.h" -#include "xe_map.h" #include "xe_memirq.h" #include "xe_tile_printk.h" diff --git a/drivers/gpu/drm/xe/xe_mert.c b/drivers/gpu/drm/xe/xe_mert.c index f7689e922953..f637df95418b 100644 --- a/drivers/gpu/drm/xe/xe_mert.c +++ b/drivers/gpu/drm/xe/xe_mert.c @@ -9,25 +9,38 @@ #include "xe_device.h" #include "xe_mert.h" #include "xe_mmio.h" +#include "xe_sriov_printk.h" #include "xe_tile.h" /** - * xe_mert_invalidate_lmtt - Invalidate MERT LMTT - * @tile: the &xe_tile + * xe_mert_init_early() - Initialize MERT data + * @xe: the &xe_device with MERT to init + */ +void xe_mert_init_early(struct xe_device *xe) +{ + struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_mert *mert = &tile->mert; + + spin_lock_init(&mert->lock); + init_completion(&mert->tlb_inv_done); +} + +/** + * xe_mert_invalidate_lmtt() - Invalidate MERT LMTT + * @xe: the &xe_device with MERT * * Trigger invalidation of the MERT LMTT and wait for completion. * * Return: 0 on success or -ETIMEDOUT in case of a timeout. */ -int xe_mert_invalidate_lmtt(struct xe_tile *tile) +int xe_mert_invalidate_lmtt(struct xe_device *xe) { - struct xe_device *xe = tile_to_xe(tile); + struct xe_tile *tile = xe_device_get_root_tile(xe); struct xe_mert *mert = &tile->mert; const long timeout = HZ / 4; unsigned long flags; xe_assert(xe, xe_device_has_mert(xe)); - xe_assert(xe, xe_tile_is_root(tile)); spin_lock_irqsave(&mert->lock, flags); if (!mert->tlb_inv_triggered) { @@ -43,6 +56,37 @@ int xe_mert_invalidate_lmtt(struct xe_tile *tile) return 0; } +static void mert_handle_cat_error(struct xe_device *xe) +{ + struct xe_tile *tile = xe_device_get_root_tile(xe); + u32 reg_val, vfid, code; + + reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT); + if (!reg_val) + return; + xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0); + + vfid = FIELD_GET(CATERR_VFID, reg_val); + code = FIELD_GET(CATERR_CODES, reg_val); + + switch (code) { + case CATERR_NO_ERROR: + break; + case CATERR_UNMAPPED_GGTT: + xe_sriov_err(xe, "MERT: CAT_ERR: Access to an unmapped GGTT!\n"); + xe_device_declare_wedged(xe); + break; + case CATERR_LMTT_FAULT: + xe_sriov_dbg(xe, "MERT: CAT_ERR: VF%u LMTT fault!\n", vfid); + /* XXX: track/report malicious VF activity */ + break; + default: + xe_sriov_err(xe, "MERT: Unexpected CAT_ERR code=%#x!\n", code); + xe_device_declare_wedged(xe); + break; + } +} + /** * xe_mert_irq_handler - Handler for MERT interrupts * @xe: the &xe_device @@ -53,30 +97,22 @@ int xe_mert_invalidate_lmtt(struct xe_tile *tile) void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl) { struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_mert *mert = &tile->mert; unsigned long flags; u32 reg_val; - u8 err; if (!(master_ctl & SOC_H2DMEMINT_IRQ)) return; - reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT); - xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0); - - err = FIELD_GET(MERT_TLB_CT_ERROR_MASK, reg_val); - if (err == MERT_TLB_CT_LMTT_FAULT) - drm_dbg(&xe->drm, "MERT catastrophic error: LMTT fault (VF%u)\n", - FIELD_GET(MERT_TLB_CT_VFID_MASK, reg_val)); - else if (err) - drm_dbg(&xe->drm, "MERT catastrophic error: Unexpected fault (0x%x)\n", err); + mert_handle_cat_error(xe); - spin_lock_irqsave(&tile->mert.lock, flags); - if (tile->mert.tlb_inv_triggered) { + spin_lock_irqsave(&mert->lock, flags); + if (mert->tlb_inv_triggered) { reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_INV_DESC_A); if (!(reg_val & MERT_TLB_INV_DESC_A_VALID)) { - tile->mert.tlb_inv_triggered = false; - complete_all(&tile->mert.tlb_inv_done); + mert->tlb_inv_triggered = false; + complete_all(&mert->tlb_inv_done); } } - spin_unlock_irqrestore(&tile->mert.lock, flags); + spin_unlock_irqrestore(&mert->lock, flags); } diff --git a/drivers/gpu/drm/xe/xe_mert.h b/drivers/gpu/drm/xe/xe_mert.h index 2e14c5dec008..fc977203692d 100644 --- a/drivers/gpu/drm/xe/xe_mert.h +++ b/drivers/gpu/drm/xe/xe_mert.h @@ -3,30 +3,33 @@ * Copyright(c) 2025, Intel Corporation. All rights reserved. */ -#ifndef __XE_MERT_H__ -#define __XE_MERT_H__ +#ifndef _XE_MERT_H_ +#define _XE_MERT_H_ #include <linux/completion.h> #include <linux/spinlock.h> #include <linux/types.h> struct xe_device; -struct xe_tile; +/** + * struct xe_mert - MERT related data + */ struct xe_mert { /** @lock: protects the TLB invalidation status */ spinlock_t lock; /** @tlb_inv_triggered: indicates if TLB invalidation was triggered */ bool tlb_inv_triggered; - /** @mert.tlb_inv_done: completion of TLB invalidation */ + /** @tlb_inv_done: completion of TLB invalidation */ struct completion tlb_inv_done; }; #ifdef CONFIG_PCI_IOV -int xe_mert_invalidate_lmtt(struct xe_tile *tile); +void xe_mert_init_early(struct xe_device *xe); +int xe_mert_invalidate_lmtt(struct xe_device *xe); void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl); #else static inline void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl) { } #endif -#endif /* __XE_MERT_H__ */ +#endif diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index 350dca1f0925..bcb6674b7dac 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -14,12 +14,8 @@ #include <drm/drm_print.h> #include "regs/xe_bars.h" -#include "regs/xe_regs.h" #include "xe_device.h" -#include "xe_gt.h" -#include "xe_gt_printk.h" #include "xe_gt_sriov_vf.h" -#include "xe_macros.h" #include "xe_sriov.h" #include "xe_trace.h" #include "xe_wa.h" diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c index 0b7225bd77e0..54822497c21e 100644 --- a/drivers/gpu/drm/xe/xe_mocs.c +++ b/drivers/gpu/drm/xe/xe_mocs.c @@ -6,7 +6,6 @@ #include "xe_mocs.h" #include "regs/xe_gt_regs.h" -#include "xe_bo.h" #include "xe_device.h" #include "xe_exec_queue.h" #include "xe_force_wake.h" @@ -17,7 +16,6 @@ #include "xe_platform_types.h" #include "xe_pm.h" #include "xe_sriov.h" -#include "xe_step_types.h" #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) #define mocs_dbg xe_gt_dbg diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c index d08338fc3bc1..a0048f64ed12 100644 --- a/drivers/gpu/drm/xe/xe_module.c +++ b/drivers/gpu/drm/xe/xe_module.c @@ -10,6 +10,7 @@ #include <drm/drm_module.h> +#include "xe_device_types.h" #include "xe_drv.h" #include "xe_configfs.h" #include "xe_hw_fence.h" @@ -29,7 +30,8 @@ #define DEFAULT_FORCE_PROBE CONFIG_DRM_XE_FORCE_PROBE #define DEFAULT_MAX_VFS ~0 #define DEFAULT_MAX_VFS_STR "unlimited" -#define DEFAULT_WEDGED_MODE 1 +#define DEFAULT_WEDGED_MODE XE_WEDGED_MODE_DEFAULT +#define DEFAULT_WEDGED_MODE_STR XE_WEDGED_MODE_DEFAULT_STR #define DEFAULT_SVM_NOTIFIER_SIZE 512 struct xe_modparam xe_modparam = { @@ -88,10 +90,10 @@ MODULE_PARM_DESC(max_vfs, "[default=" DEFAULT_MAX_VFS_STR "])"); #endif -module_param_named_unsafe(wedged_mode, xe_modparam.wedged_mode, int, 0600); +module_param_named_unsafe(wedged_mode, xe_modparam.wedged_mode, uint, 0600); MODULE_PARM_DESC(wedged_mode, - "Module's default policy for the wedged mode (0=never, 1=upon-critical-errors, 2=upon-any-hang " - "[default=" __stringify(DEFAULT_WEDGED_MODE) "])"); + "Module's default policy for the wedged mode (0=never, 1=upon-critical-error, 2=upon-any-hang-no-reset " + "[default=" DEFAULT_WEDGED_MODE_STR "])"); static int xe_check_nomodeset(void) { diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h index 5a3bfea8b7b4..1c75f38ca393 100644 --- a/drivers/gpu/drm/xe/xe_module.h +++ b/drivers/gpu/drm/xe/xe_module.h @@ -21,7 +21,7 @@ struct xe_modparam { #ifdef CONFIG_PCI_IOV unsigned int max_vfs; #endif - int wedged_mode; + unsigned int wedged_mode; u32 svm_notifier_size; }; diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c index 01510061d4d4..437375046517 100644 --- a/drivers/gpu/drm/xe/xe_nvm.c +++ b/drivers/gpu/drm/xe/xe_nvm.c @@ -6,7 +6,6 @@ #include <linux/intel_dg_nvm_aux.h> #include <linux/pci.h> -#include "xe_device.h" #include "xe_device_types.h" #include "xe_mmio.h" #include "xe_nvm.h" diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c index fd8c33761127..e13c71a89da2 100644 --- a/drivers/gpu/drm/xe/xe_page_reclaim.c +++ b/drivers/gpu/drm/xe/xe_page_reclaim.c @@ -10,14 +10,11 @@ #include "xe_page_reclaim.h" -#include "regs/xe_gt_regs.h" -#include "xe_assert.h" +#include "xe_gt_stats.h" #include "xe_macros.h" -#include "xe_mmio.h" #include "xe_pat.h" #include "xe_sa.h" #include "xe_tlb_inval_types.h" -#include "xe_vm.h" /** * xe_page_reclaim_skip() - Decide whether PRL should be skipped for a VMA @@ -108,7 +105,6 @@ void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl) */ void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl) { - // xe_page_reclaim_list_invalidate(prl); prl->entries = NULL; prl->num_entries = 0; } diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h index a4f58e0ce9b4..3dd103e37beb 100644 --- a/drivers/gpu/drm/xe/xe_page_reclaim.h +++ b/drivers/gpu/drm/xe/xe_page_reclaim.h @@ -19,6 +19,7 @@ struct xe_tlb_inval; struct xe_tlb_inval_fence; struct xe_tile; +struct xe_gt; struct xe_vma; struct xe_guc_page_reclaim_entry { @@ -75,6 +76,25 @@ struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inva struct xe_page_reclaim_list *prl, struct xe_tlb_inval_fence *fence); void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl); + +/** + * xe_page_reclaim_list_abort() - Invalidate a PRL and log an abort reason + * @gt: GT owning the page reclaim request + * @prl: Page reclaim list to invalidate + * @fmt: format string for the log message with args + * + * Abort page reclaim process by invalidating PRL and doing any relevant logging. + */ +#define xe_page_reclaim_list_abort(gt, prl, fmt, ...) \ + do { \ + struct xe_gt *__gt = (gt); \ + struct xe_page_reclaim_list *__prl = (prl); \ + \ + xe_page_reclaim_list_invalidate(__prl); \ + xe_gt_stats_incr(__gt, XE_GT_STATS_ID_PRL_ABORTED_COUNT, 1); \ + vm_dbg(>_to_xe(__gt)->drm, "PRL aborted: " fmt, ##__VA_ARGS__); \ + } while (0) + void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl); int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl); /** diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 2c3375e0250b..14d0dce5190a 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -132,9 +132,10 @@ static const struct xe_pat_table_entry xelpg_pat_table[] = { * in the table. * * Note: There is an implicit assumption in the driver that compression and - * coh_1way+ are mutually exclusive. If this is ever not true then userptr - * and imported dma-buf from external device will have uncleared ccs state. See - * also xe_bo_needs_ccs_pages(). + * coh_1way+ are mutually exclusive for platforms prior to Xe3. Starting + * with Xe3, compression can be combined with coherency. If using compression + * with coherency, userptr and imported dma-buf from external device will + * have uncleared ccs state. See also xe_bo_needs_ccs_pages(). */ #define XE2_PAT(no_promote, comp_en, l3clos, l3_policy, l4_policy, __coh_mode) \ { \ @@ -144,8 +145,7 @@ static const struct xe_pat_table_entry xelpg_pat_table[] = { REG_FIELD_PREP(XE2_L3_POLICY, l3_policy) | \ REG_FIELD_PREP(XE2_L4_POLICY, l4_policy) | \ REG_FIELD_PREP(XE2_COH_MODE, __coh_mode), \ - .coh_mode = (BUILD_BUG_ON_ZERO(__coh_mode && comp_en) || __coh_mode) ? \ - XE_COH_AT_LEAST_1WAY : XE_COH_NONE, \ + .coh_mode = __coh_mode ? XE_COH_AT_LEAST_1WAY : XE_COH_NONE, \ .valid = 1 \ } @@ -181,6 +181,38 @@ static const struct xe_pat_table_entry xe2_pat_table[] = { [31] = XE2_PAT( 0, 0, 3, 0, 3, 3 ), }; +static const struct xe_pat_table_entry xe3_lpg_pat_table[] = { + [ 0] = XE2_PAT( 0, 0, 0, 0, 3, 0 ), + [ 1] = XE2_PAT( 0, 0, 0, 0, 3, 2 ), + [ 2] = XE2_PAT( 0, 0, 0, 0, 3, 3 ), + [ 3] = XE2_PAT( 0, 0, 0, 3, 3, 0 ), + [ 4] = XE2_PAT( 0, 0, 0, 3, 0, 2 ), + [ 5] = XE2_PAT( 0, 0, 0, 3, 3, 2 ), + [ 6] = XE2_PAT( 1, 0, 0, 1, 3, 0 ), + [ 7] = XE2_PAT( 0, 0, 0, 3, 0, 3 ), + [ 8] = XE2_PAT( 0, 0, 0, 3, 0, 0 ), + [ 9] = XE2_PAT( 0, 1, 0, 0, 3, 0 ), + [10] = XE2_PAT( 0, 1, 0, 3, 0, 0 ), + [11] = XE2_PAT( 1, 1, 0, 1, 3, 0 ), + [12] = XE2_PAT( 0, 1, 0, 3, 3, 0 ), + [13] = XE2_PAT( 0, 0, 0, 0, 0, 0 ), + [14] = XE2_PAT( 0, 1, 0, 0, 0, 0 ), + [15] = XE2_PAT( 1, 1, 0, 1, 1, 0 ), + [16] = XE2_PAT( 0, 1, 0, 0, 3, 2 ), + /* 17..19 are reserved; leave set to all 0's */ + [20] = XE2_PAT( 0, 0, 1, 0, 3, 0 ), + [21] = XE2_PAT( 0, 1, 1, 0, 3, 0 ), + [22] = XE2_PAT( 0, 0, 1, 0, 3, 2 ), + [23] = XE2_PAT( 0, 0, 1, 0, 3, 3 ), + [24] = XE2_PAT( 0, 0, 2, 0, 3, 0 ), + [25] = XE2_PAT( 0, 1, 2, 0, 3, 0 ), + [26] = XE2_PAT( 0, 0, 2, 0, 3, 2 ), + [27] = XE2_PAT( 0, 0, 2, 0, 3, 3 ), + [28] = XE2_PAT( 0, 0, 3, 0, 3, 0 ), + [29] = XE2_PAT( 0, 1, 3, 0, 3, 0 ), + [30] = XE2_PAT( 0, 0, 3, 0, 3, 2 ), + [31] = XE2_PAT( 0, 0, 3, 0, 3, 3 ), +}; /* Special PAT values programmed outside the main table */ static const struct xe_pat_table_entry xe2_pat_ats = XE2_PAT( 0, 0, 0, 0, 3, 3 ); static const struct xe_pat_table_entry xe2_pat_pta = XE2_PAT( 0, 0, 0, 0, 3, 0 ); @@ -490,6 +522,7 @@ static const struct xe_pat_ops xe3p_xpc_pat_ops = { void xe_pat_init_early(struct xe_device *xe) { + xe->pat.idx[XE_CACHE_WB_COMPRESSION] = XE_PAT_INVALID_IDX; if (GRAPHICS_VERx100(xe) == 3511) { xe->pat.ops = &xe3p_xpc_pat_ops; xe->pat.table = xe3p_xpc_pat_table; @@ -501,7 +534,12 @@ void xe_pat_init_early(struct xe_device *xe) xe->pat.idx[XE_CACHE_WB] = 2; } else if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) { xe->pat.ops = &xe2_pat_ops; - xe->pat.table = xe2_pat_table; + if (GRAPHICS_VER(xe) == 30) { + xe->pat.table = xe3_lpg_pat_table; + xe->pat.idx[XE_CACHE_WB_COMPRESSION] = 16; + } else { + xe->pat.table = xe2_pat_table; + } xe->pat.pat_ats = &xe2_pat_ats; if (IS_DGFX(xe)) xe->pat.pat_pta = &xe2_pat_pta; @@ -658,6 +696,8 @@ int xe_pat_dump_sw_config(struct xe_gt *gt, struct drm_printer *p) if (GRAPHICS_VER(xe) >= 20) { drm_printf(p, "IDX[XE_CACHE_NONE_COMPRESSION] = %d\n", xe->pat.idx[XE_CACHE_NONE_COMPRESSION]); + drm_printf(p, "IDX[XE_CACHE_WB_COMPRESSION] = %d\n", + xe->pat.idx[XE_CACHE_WB_COMPRESSION]); } return 0; diff --git a/drivers/gpu/drm/xe/xe_pat.h b/drivers/gpu/drm/xe/xe_pat.h index d5dadfb7f924..c7e2a53d8cee 100644 --- a/drivers/gpu/drm/xe/xe_pat.h +++ b/drivers/gpu/drm/xe/xe_pat.h @@ -12,6 +12,8 @@ struct drm_printer; struct xe_device; struct xe_gt; +#define XE_PAT_INVALID_IDX U16_MAX + /** * struct xe_pat_table_entry - The pat_index encoding and other meta information. */ diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index a1fdca451ce0..09189ff3da44 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -24,7 +24,6 @@ #include "xe_gt.h" #include "xe_gt_sriov_vf.h" #include "xe_guc.h" -#include "xe_macros.h" #include "xe_mmio.h" #include "xe_module.h" #include "xe_pci_rebar.h" @@ -366,6 +365,7 @@ static const struct xe_device_desc bmg_desc = { .has_fan_control = true, .has_flat_ccs = 1, .has_mbx_power_limits = true, + .has_mbx_thermal_info = true, .has_gsc_nvm = 1, .has_heci_cscfi = 1, .has_i2c = true, @@ -392,6 +392,7 @@ static const struct xe_device_desc ptl_desc = { .has_sriov = true, .has_mem_copy_instr = true, .has_pre_prod_wa = 1, + .has_pxp = true, .max_gt_per_tile = 2, .needs_scratch = true, .needs_shared_vf_gt_wq = true, @@ -421,6 +422,7 @@ static const struct xe_device_desc cri_desc = { .has_gsc_nvm = 1, .has_i2c = true, .has_mbx_power_limits = true, + .has_mbx_thermal_info = true, .has_mert = true, .has_pre_prod_wa = 1, .has_soc_remapper_sysctrl = true, @@ -686,6 +688,7 @@ static int xe_info_init_early(struct xe_device *xe, /* runtime fusing may force flat_ccs to disabled later */ xe->info.has_flat_ccs = desc->has_flat_ccs; xe->info.has_mbx_power_limits = desc->has_mbx_power_limits; + xe->info.has_mbx_thermal_info = desc->has_mbx_thermal_info; xe->info.has_gsc_nvm = desc->has_gsc_nvm; xe->info.has_heci_gscfi = desc->has_heci_gscfi; xe->info.has_heci_cscfi = desc->has_heci_cscfi; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 5f20f56571d1..20acc5349ee6 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -48,6 +48,7 @@ struct xe_device_desc { u8 has_late_bind:1; u8 has_llc:1; u8 has_mbx_power_limits:1; + u8 has_mbx_thermal_info:1; u8 has_mem_copy_instr:1; u8 has_mert:1; u8 has_pre_prod_wa:1; diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h index 975892d6b230..85cc7478b787 100644 --- a/drivers/gpu/drm/xe/xe_pcode_api.h +++ b/drivers/gpu/drm/xe/xe_pcode_api.h @@ -50,6 +50,13 @@ #define READ_PL_FROM_FW 0x1 #define READ_PL_FROM_PCODE 0x0 +#define PCODE_THERMAL_INFO 0x25 +#define READ_THERMAL_LIMITS 0x0 +#define READ_THERMAL_CONFIG 0x1 +#define READ_THERMAL_DATA 0x2 +#define PCIE_SENSOR_GROUP_ID 0x2 +#define PCIE_SENSOR_MASK REG_GENMASK(31, 16) + #define PCODE_LATE_BINDING 0x5C #define GET_CAPABILITY_STATUS 0x0 #define V1_FAN_SUPPORTED REG_BIT(0) diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index 4390ba69610d..559cf5490ac0 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -260,10 +260,19 @@ int xe_pm_resume(struct xe_device *xe) xe_irq_resume(xe); - for_each_gt(gt, xe, id) - xe_gt_resume(gt); + for_each_gt(gt, xe, id) { + err = xe_gt_resume(gt); + if (err) + break; + } + /* + * Try to bring up display before bailing from GT resume failure, + * so we don't leave the user clueless with a blank screen. + */ xe_display_pm_resume(xe); + if (err) + goto err; err = xe_bo_restore_late(xe); if (err) @@ -656,10 +665,19 @@ int xe_pm_runtime_resume(struct xe_device *xe) xe_irq_resume(xe); - for_each_gt(gt, xe, id) - xe->d3cold.allowed ? xe_gt_resume(gt) : xe_gt_runtime_resume(gt); + for_each_gt(gt, xe, id) { + err = xe->d3cold.allowed ? xe_gt_resume(gt) : xe_gt_runtime_resume(gt); + if (err) + break; + } + /* + * Try to bring up display before bailing from GT resume failure, + * so we don't leave the user clueless with a blank screen. + */ xe_display_pm_runtime_resume(xe); + if (err) + goto out; if (xe->d3cold.allowed) { err = xe_bo_restore_late(xe); diff --git a/drivers/gpu/drm/xe/xe_psmi.c b/drivers/gpu/drm/xe/xe_psmi.c index 6a54e38b81ba..899b01f72ba3 100644 --- a/drivers/gpu/drm/xe/xe_psmi.c +++ b/drivers/gpu/drm/xe/xe_psmi.c @@ -6,7 +6,7 @@ #include <linux/debugfs.h> #include "xe_bo.h" -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_configfs.h" #include "xe_psmi.h" diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 6cd78bb2b652..6703a7049227 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -11,6 +11,7 @@ #include "xe_drm_client.h" #include "xe_exec_queue.h" #include "xe_gt.h" +#include "xe_gt_stats.h" #include "xe_migrate.h" #include "xe_page_reclaim.h" #include "xe_pt_types.h" @@ -1576,12 +1577,6 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level, return false; } -/* Huge 2MB leaf lives directly in a level-1 table and has no children */ -static bool is_2m_pte(struct xe_pt *pte) -{ - return pte->level == 1 && !pte->base.children; -} - /* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */ #define COMPUTE_RECLAIM_ADDRESS_MASK(page_size) \ ({ \ @@ -1593,8 +1588,10 @@ static int generate_reclaim_entry(struct xe_tile *tile, struct xe_page_reclaim_list *prl, u64 pte, struct xe_pt *xe_child) { + struct xe_gt *gt = tile->primary_gt; struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries; - u64 phys_page = (pte & XE_PTE_ADDR_MASK) >> XE_PTE_SHIFT; + u64 phys_addr = pte & XE_PTE_ADDR_MASK; + u64 phys_page = phys_addr >> XE_PTE_SHIFT; int num_entries = prl->num_entries; u32 reclamation_size; @@ -1612,16 +1609,21 @@ static int generate_reclaim_entry(struct xe_tile *tile, * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim */ if (xe_child->level == 0 && !(pte & XE_PTE_PS64)) { + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1); reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K); /* reclamation_size = 0 */ + xe_tile_assert(tile, phys_addr % SZ_4K == 0); } else if (xe_child->level == 0) { + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1); reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */ - } else if (is_2m_pte(xe_child)) { + xe_tile_assert(tile, phys_addr % SZ_64K == 0); + } else if (xe_child->level == 1 && pte & XE_PDE_PS_2M) { + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, 1); reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M); /* reclamation_size = 9 */ + xe_tile_assert(tile, phys_addr % SZ_2M == 0); } else { - xe_page_reclaim_list_invalidate(prl); - vm_dbg(&tile_to_xe(tile)->drm, - "PRL invalidate: unsupported PTE level=%u pte=%#llx\n", - xe_child->level, pte); + xe_page_reclaim_list_abort(tile->primary_gt, prl, + "unsupported PTE level=%u pte=%#llx", + xe_child->level, pte); return -EINVAL; } @@ -1648,20 +1650,40 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, struct xe_pt_stage_unbind_walk *xe_walk = container_of(walk, typeof(*xe_walk), base); struct xe_device *xe = tile_to_xe(xe_walk->tile); + pgoff_t first = xe_pt_offset(addr, xe_child->level, walk); + bool killed; XE_WARN_ON(!*child); XE_WARN_ON(!level); /* Check for leaf node */ if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && - !xe_child->base.children) { + (!xe_child->base.children || !xe_child->base.children[first])) { struct iosys_map *leaf_map = &xe_child->bo->vmap; - pgoff_t first = xe_pt_offset(addr, 0, walk); - pgoff_t count = xe_pt_num_entries(addr, next, 0, walk); + pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk); for (pgoff_t i = 0; i < count; i++) { u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64); int ret; + /* + * In rare scenarios, pte may not be written yet due to racy conditions. + * In such cases, invalidate the PRL and fallback to full PPC invalidation. + */ + if (!pte) { + xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, + "found zero pte at addr=%#llx", addr); + break; + } + + /* Ensure it is a defined page */ + xe_tile_assert(xe_walk->tile, + xe_child->level == 0 || + (pte & (XE_PTE_PS64 | XE_PDE_PS_2M | XE_PDPE_PS_1G))); + + /* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */ + if (pte & XE_PTE_PS64) + i += 15; /* Skip other 15 consecutive 4K pages in the 64K page */ + /* Account for NULL terminated entry on end (-1) */ if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) { ret = generate_reclaim_entry(xe_walk->tile, xe_walk->prl, @@ -1670,22 +1692,32 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, break; } else { /* overflow, mark as invalid */ - xe_page_reclaim_list_invalidate(xe_walk->prl); - vm_dbg(&xe->drm, - "PRL invalidate: overflow while adding pte=%#llx", - pte); + xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, + "overflow while adding pte=%#llx", + pte); break; } } } - /* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */ - if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) && - xe_walk->prl && level > 1 && xe_child->base.children && xe_child->num_live != 0) { - xe_page_reclaim_list_invalidate(xe_walk->prl); - vm_dbg(&xe->drm, - "PRL invalidate: kill at level=%u addr=%#llx next=%#llx num_live=%u\n", - level, addr, next, xe_child->num_live); + killed = xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk); + + /* + * Verify PRL is active and if entry is not a leaf pte (base.children conditions), + * there is a potential need to invalidate the PRL if any PTE (num_live) are dropped. + */ + if (xe_walk->prl && level > 1 && xe_child->num_live && + xe_child->base.children && xe_child->base.children[first]) { + bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base); + + /* + * If aborting page walk early (kill) or page walk completes the full range + * we need to invalidate the PRL. + */ + if (killed || covered) + xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, + "kill at level=%u addr=%#llx next=%#llx num_live=%u", + level, addr, next, xe_child->num_live); } return 0; diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h index 88fabf8e2655..84b51d3762a4 100644 --- a/drivers/gpu/drm/xe/xe_pt_types.h +++ b/drivers/gpu/drm/xe/xe_pt_types.h @@ -20,6 +20,7 @@ enum xe_cache_level { XE_CACHE_WT, XE_CACHE_WB, XE_CACHE_NONE_COMPRESSION, /*UC + COH_NONE + COMPRESSION */ + XE_CACHE_WB_COMPRESSION, __XE_CACHE_LEVEL_COUNT, }; diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 508f4c128a48..d61446bf9c19 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -15,7 +15,6 @@ #include "xe_force_wake.h" #include "xe_guc_submit.h" #include "xe_gsc_proxy.h" -#include "xe_gt.h" #include "xe_gt_types.h" #include "xe_huc.h" #include "xe_mmio.h" diff --git a/drivers/gpu/drm/xe/xe_pxp_debugfs.c b/drivers/gpu/drm/xe/xe_pxp_debugfs.c index 525a2f6bb076..d6e2e41bc88c 100644 --- a/drivers/gpu/drm/xe/xe_pxp_debugfs.c +++ b/drivers/gpu/drm/xe/xe_pxp_debugfs.c @@ -11,7 +11,7 @@ #include <drm/drm_managed.h> #include <drm/drm_print.h> -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_pxp.h" #include "xe_pxp_types.h" #include "regs/xe_irq_regs.h" diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c index 1a465385f909..d3e13ea33123 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr.c +++ b/drivers/gpu/drm/xe/xe_reg_sr.c @@ -13,16 +13,13 @@ #include <drm/drm_managed.h> #include <drm/drm_print.h> -#include "regs/xe_engine_regs.h" -#include "regs/xe_gt_regs.h" #include "xe_device.h" #include "xe_device_types.h" #include "xe_force_wake.h" -#include "xe_gt.h" #include "xe_gt_mcr.h" #include "xe_gt_printk.h" +#include "xe_gt_types.h" #include "xe_hw_engine_types.h" -#include "xe_macros.h" #include "xe_mmio.h" #include "xe_rtp_types.h" diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c index 1391cb6ec9c6..1d36c09681aa 100644 --- a/drivers/gpu/drm/xe/xe_reg_whitelist.c +++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c @@ -8,7 +8,6 @@ #include "regs/xe_engine_regs.h" #include "regs/xe_gt_regs.h" #include "regs/xe_oa_regs.h" -#include "regs/xe_regs.h" #include "xe_device.h" #include "xe_gt_types.h" #include "xe_gt_printk.h" diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c index 957b9e2fd138..248620b0901d 100644 --- a/drivers/gpu/drm/xe/xe_ring_ops.c +++ b/drivers/gpu/drm/xe/xe_ring_ops.c @@ -11,11 +11,9 @@ #include "instructions/xe_mi_commands.h" #include "regs/xe_engine_regs.h" #include "regs/xe_gt_regs.h" -#include "regs/xe_lrc_layout.h" #include "xe_exec_queue.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_lrc.h" -#include "xe_macros.h" #include "xe_sched_job.h" #include "xe_sriov.h" #include "xe_vm_types.h" @@ -235,13 +233,26 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job) return 0; } -static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i) +static int emit_copy_timestamp(struct xe_device *xe, struct xe_lrc *lrc, + u32 *dw, int i) { dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; dw[i++] = RING_CTX_TIMESTAMP(0).addr; dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); dw[i++] = 0; + /* + * Ensure CTX timestamp >= Job timestamp during VF sampling to avoid + * arithmetic wraparound in TDR. + */ + if (IS_SRIOV_VF(xe)) { + dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | + MI_SRM_ADD_CS_OFFSET; + dw[i++] = RING_CTX_TIMESTAMP(0).addr; + dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc); + dw[i++] = 0; + } + return i; } @@ -255,7 +266,7 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc *head = lrc->ring.tail; - i = emit_copy_timestamp(lrc, dw, i); + i = emit_copy_timestamp(gt_to_xe(gt), lrc, dw, i); if (job->ring_ops_flush_tlb) { dw[i++] = preparser_disable(true); @@ -310,7 +321,7 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc, *head = lrc->ring.tail; - i = emit_copy_timestamp(lrc, dw, i); + i = emit_copy_timestamp(xe, lrc, dw, i); dw[i++] = preparser_disable(true); @@ -364,7 +375,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job, *head = lrc->ring.tail; - i = emit_copy_timestamp(lrc, dw, i); + i = emit_copy_timestamp(xe, lrc, dw, i); dw[i++] = preparser_disable(true); if (lacks_render) @@ -406,12 +417,14 @@ static void emit_migration_job_gen12(struct xe_sched_job *job, struct xe_lrc *lrc, u32 *head, u32 seqno) { + struct xe_gt *gt = job->q->gt; + struct xe_device *xe = gt_to_xe(gt); u32 saddr = xe_lrc_start_seqno_ggtt_addr(lrc); u32 dw[MAX_JOB_SIZE_DW], i = 0; *head = lrc->ring.tail; - i = emit_copy_timestamp(lrc, dw, i); + i = emit_copy_timestamp(xe, lrc, dw, i); i = emit_store_imm_ggtt(saddr, seqno, dw, i); diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index ed509b1c8cfc..b7c26e2fb411 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -12,7 +12,6 @@ #include "xe_configfs.h" #include "xe_gt.h" #include "xe_gt_topology.h" -#include "xe_macros.h" #include "xe_reg_sr.h" #include "xe_sriov.h" diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index a87c1436c7c1..b738102575d4 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -10,7 +10,7 @@ #include <drm/drm_managed.h> #include "xe_bo.h" -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_map.h" static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c index cb674a322113..3927666fe556 100644 --- a/drivers/gpu/drm/xe/xe_sched_job.c +++ b/drivers/gpu/drm/xe/xe_sched_job.c @@ -11,7 +11,7 @@ #include "xe_device.h" #include "xe_exec_queue.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_hw_engine_types.h" #include "xe_hw_fence.h" #include "xe_lrc.h" @@ -110,6 +110,7 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, return ERR_PTR(-ENOMEM); job->q = q; + job->sample_timestamp = U64_MAX; kref_init(&job->refcount); xe_exec_queue_get(job->q); diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h index 7c4c54fe920a..13c2970e81a8 100644 --- a/drivers/gpu/drm/xe/xe_sched_job_types.h +++ b/drivers/gpu/drm/xe/xe_sched_job_types.h @@ -59,6 +59,8 @@ struct xe_sched_job { u32 lrc_seqno; /** @migrate_flush_flags: Additional flush flags for migration jobs */ u32 migrate_flush_flags; + /** @sample_timestamp: Sampling of job timestamp in TDR */ + u64 sample_timestamp; /** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */ bool ring_ops_flush_tlb; /** @ggtt: mapped in ggtt. */ diff --git a/drivers/gpu/drm/xe/xe_sriov_packet.c b/drivers/gpu/drm/xe/xe_sriov_packet.c index 2cefefaed9ba..7a4c3de662e5 100644 --- a/drivers/gpu/drm/xe/xe_sriov_packet.c +++ b/drivers/gpu/drm/xe/xe_sriov_packet.c @@ -6,7 +6,6 @@ #include "xe_bo.h" #include "xe_device.h" #include "xe_guc_klv_helpers.h" -#include "xe_printk.h" #include "xe_sriov_packet.h" #include "xe_sriov_packet_types.h" #include "xe_sriov_pf_helpers.h" diff --git a/drivers/gpu/drm/xe/xe_sriov_pf.c b/drivers/gpu/drm/xe/xe_sriov_pf.c index 72423bb17e6f..6ce3c58e003c 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf.c @@ -90,7 +90,6 @@ bool xe_sriov_pf_readiness(struct xe_device *xe) */ int xe_sriov_pf_init_early(struct xe_device *xe) { - struct xe_mert *mert = &xe_device_get_root_tile(xe)->mert; int err; xe_assert(xe, IS_SRIOV_PF(xe)); @@ -112,8 +111,7 @@ int xe_sriov_pf_init_early(struct xe_device *xe) xe_sriov_pf_service_init(xe); - spin_lock_init(&mert->lock); - init_completion(&mert->tlb_inv_done); + xe_mert_init_early(xe); return 0; } diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c index e84bdde9bc80..81b377830d6d 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c @@ -16,7 +16,6 @@ #include "xe_sriov_pf_migration.h" #include "xe_sriov_pf_provision.h" #include "xe_sriov_pf_service.h" -#include "xe_sriov_printk.h" #include "xe_tile_sriov_pf_debugfs.h" /* diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index 1b75405b8d02..29894bd081c0 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -6,7 +6,6 @@ #include <drm/drm_debugfs.h> #include <drm/drm_managed.h> -#include "xe_gt.h" #include "xe_gt_sriov_vf.h" #include "xe_guc.h" #include "xe_sriov_printk.h" diff --git a/drivers/gpu/drm/xe/xe_step.c b/drivers/gpu/drm/xe/xe_step.c index 10e88f2c9615..2860986f82f7 100644 --- a/drivers/gpu/drm/xe/xe_step.c +++ b/drivers/gpu/drm/xe/xe_step.c @@ -5,10 +5,11 @@ #include "xe_step.h" +#include <drm/drm_print.h> #include <kunit/visibility.h> #include <linux/bitfield.h> -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_platform_types.h" /* diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c b/drivers/gpu/drm/xe/xe_survivability_mode.c index 4c716182ad3b..6578ffc77bd5 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.c +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c @@ -12,7 +12,6 @@ #include "xe_configfs.h" #include "xe_device.h" -#include "xe_gt.h" #include "xe_heci_gsc.h" #include "xe_i2c.h" #include "xe_mmio.h" @@ -321,7 +320,7 @@ static int enable_boot_survivability_mode(struct pci_dev *pdev) if (ret) return ret; - /* Make sure xe_heci_gsc_init() knows about survivability mode */ + /* Make sure xe_heci_gsc_init() and xe_i2c_probe() are aware of survivability */ survivability->mode = true; xe_heci_gsc_init(xe); diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index fa2ee2c08f31..213f0334518a 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -988,6 +988,8 @@ bool xe_svm_range_validate(struct xe_vm *vm, ret = (range->tile_present & ~range->tile_invalidated & tile_mask) == tile_mask; if (dpagemap) ret = ret && xe_svm_range_has_pagemap_locked(range, dpagemap); + else + ret = ret && !range->base.pages.dpagemap; xe_svm_notifier_unlock(vm); diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c index eb262aad11da..c465aae7883c 100644 --- a/drivers/gpu/drm/xe/xe_tile.c +++ b/drivers/gpu/drm/xe/xe_tile.c @@ -9,9 +9,8 @@ #include <drm/drm_pagemap_util.h> #include "xe_bo.h" -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_ggtt.h" -#include "xe_gt.h" #include "xe_memirq.h" #include "xe_migrate.h" #include "xe_pcode.h" diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c index dec042248164..e837888367c4 100644 --- a/drivers/gpu/drm/xe/xe_tlb_inval.c +++ b/drivers/gpu/drm/xe/xe_tlb_inval.c @@ -5,13 +5,10 @@ #include <drm/drm_managed.h> -#include "abi/guc_actions_abi.h" -#include "xe_device.h" +#include "xe_device_types.h" #include "xe_force_wake.h" -#include "xe_gt.h" -#include "xe_gt_printk.h" #include "xe_gt_stats.h" -#include "xe_guc.h" +#include "xe_gt_types.h" #include "xe_guc_ct.h" #include "xe_guc_tlb_inval.h" #include "xe_mmio.h" @@ -94,7 +91,7 @@ static void xe_tlb_inval_fence_timeout(struct work_struct *work) xe_tlb_inval_fence_signal(fence); } if (!list_empty(&tlb_inval->pending_fences)) - queue_delayed_work(system_wq, &tlb_inval->fence_tdr, + queue_delayed_work(tlb_inval->timeout_wq, &tlb_inval->fence_tdr, timeout_delay); spin_unlock_irq(&tlb_inval->pending_lock); } @@ -146,6 +143,10 @@ int xe_gt_tlb_inval_init_early(struct xe_gt *gt) if (IS_ERR(tlb_inval->job_wq)) return PTR_ERR(tlb_inval->job_wq); + tlb_inval->timeout_wq = gt->ordered_wq; + if (IS_ERR(tlb_inval->timeout_wq)) + return PTR_ERR(tlb_inval->timeout_wq); + /* XXX: Blindly setting up backend to GuC */ xe_guc_tlb_inval_init_early(>->uc.guc, tlb_inval); @@ -240,7 +241,7 @@ static void xe_tlb_inval_fence_prep(struct xe_tlb_inval_fence *fence) list_add_tail(&fence->link, &tlb_inval->pending_fences); if (list_is_singular(&tlb_inval->pending_fences)) - queue_delayed_work(system_wq, &tlb_inval->fence_tdr, + queue_delayed_work(tlb_inval->timeout_wq, &tlb_inval->fence_tdr, tlb_inval->ops->timeout_delay(tlb_inval)); spin_unlock_irq(&tlb_inval->pending_lock); @@ -399,7 +400,7 @@ void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno) } if (!list_empty(&tlb_inval->pending_fences)) - mod_delayed_work(system_wq, + mod_delayed_work(tlb_inval->timeout_wq, &tlb_inval->fence_tdr, tlb_inval->ops->timeout_delay(tlb_inval)); else diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_types.h b/drivers/gpu/drm/xe/xe_tlb_inval_types.h index 48d1503e8460..3b089f90f002 100644 --- a/drivers/gpu/drm/xe/xe_tlb_inval_types.h +++ b/drivers/gpu/drm/xe/xe_tlb_inval_types.h @@ -109,6 +109,8 @@ struct xe_tlb_inval { struct workqueue_struct *job_wq; /** @tlb_inval.lock: protects TLB invalidation fences */ spinlock_t lock; + /** @timeout_wq: schedules TLB invalidation fence timeouts */ + struct workqueue_struct *timeout_wq; }; /** diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h index 6d12fcc13f43..750fa32c13b2 100644 --- a/drivers/gpu/drm/xe/xe_trace.h +++ b/drivers/gpu/drm/xe/xe_trace.h @@ -228,11 +228,6 @@ DEFINE_EVENT(xe_exec_queue, xe_exec_queue_resubmit, TP_ARGS(q) ); -DEFINE_EVENT(xe_exec_queue, xe_exec_queue_lr_cleanup, - TP_PROTO(struct xe_exec_queue *q), - TP_ARGS(q) -); - DECLARE_EVENT_CLASS(xe_sched_job, TP_PROTO(struct xe_sched_job *job), TP_ARGS(job), diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c index 1bddecfb723a..27c9d72222cf 100644 --- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c @@ -17,7 +17,6 @@ #include "regs/xe_regs.h" #include "xe_bo.h" #include "xe_device.h" -#include "xe_gt.h" #include "xe_gt_printk.h" #include "xe_mmio.h" #include "xe_res_cursor.h" diff --git a/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c b/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c index 3e404eb8d098..99fb7e99eb7f 100644 --- a/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c @@ -13,7 +13,6 @@ #include <drm/ttm/ttm_tt.h> #include "xe_bo.h" -#include "xe_gt.h" struct xe_ttm_sys_node { struct ttm_buffer_object *tbo; diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c index 9f70802fce92..6553a19f7cf2 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -12,7 +12,6 @@ #include "xe_bo.h" #include "xe_device.h" -#include "xe_gt.h" #include "xe_res_cursor.h" #include "xe_ttm_vram_mgr.h" #include "xe_vram_types.h" diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c index 157520ea1783..3f63c2a7e86d 100644 --- a/drivers/gpu/drm/xe/xe_uc.c +++ b/drivers/gpu/drm/xe/xe_uc.c @@ -8,7 +8,6 @@ #include "xe_assert.h" #include "xe_device.h" #include "xe_gsc.h" -#include "xe_gsc_proxy.h" #include "xe_gt.h" #include "xe_gt_printk.h" #include "xe_gt_sriov_vf.h" @@ -17,7 +16,6 @@ #include "xe_guc_engine_activity.h" #include "xe_huc.h" #include "xe_sriov.h" -#include "xe_uc_fw.h" #include "xe_wopcm.h" static struct xe_gt * diff --git a/drivers/gpu/drm/xe/xe_uc_debugfs.c b/drivers/gpu/drm/xe/xe_uc_debugfs.c index 24a4209051ee..45119993f5cb 100644 --- a/drivers/gpu/drm/xe/xe_uc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_uc_debugfs.c @@ -7,12 +7,12 @@ #include <drm/drm_debugfs.h> -#include "xe_gt.h" #include "xe_gsc_debugfs.h" #include "xe_guc_debugfs.h" #include "xe_huc_debugfs.h" #include "xe_macros.h" #include "xe_uc_debugfs.h" +#include "xe_uc_types.h" void xe_uc_debugfs_register(struct xe_uc *uc, struct dentry *parent) { diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c index dcb4a32e7a64..d35bc4989144 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.c +++ b/drivers/gpu/drm/xe/xe_uc_fw.c @@ -14,9 +14,9 @@ #include "xe_device_types.h" #include "xe_force_wake.h" #include "xe_gsc.h" -#include "xe_gt.h" #include "xe_gt_printk.h" #include "xe_gt_sriov_vf.h" +#include "xe_gt_types.h" #include "xe_guc.h" #include "xe_map.h" #include "xe_mmio.h" @@ -115,6 +115,7 @@ struct fw_blobs_by_type { #define XE_GT_TYPE_ANY XE_GT_TYPE_UNINITIALIZED #define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver) \ + fw_def(NOVALAKE_S, GT_TYPE_ANY, mmp_ver(xe, guc, nvl, 70, 55, 4)) \ fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, guc, ptl, 70, 54, 0)) \ fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 54, 0)) \ fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 53, 0)) \ @@ -140,6 +141,7 @@ struct fw_blobs_by_type { /* for the GSC FW we match the compatibility version and not the release one */ #define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver) \ + fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, gsc, ptl, 105, 1, 0)) \ fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, gsc, lnl, 104, 1, 0)) \ fw_def(METEORLAKE, GT_TYPE_ANY, major_ver(i915, gsc, mtl, 102, 1, 0)) @@ -738,7 +740,7 @@ static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmwar return 0; } - err = request_firmware(&fw, uc_fw->path, dev); + err = firmware_request_nowarn(&fw, uc_fw->path, dev); if (err) goto fail; @@ -767,8 +769,12 @@ fail: XE_UC_FIRMWARE_MISSING : XE_UC_FIRMWARE_ERROR); - xe_gt_notice(gt, "%s firmware %s: fetch failed with error %pe\n", - xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, ERR_PTR(err)); + if (err == -ENOENT) + xe_gt_info(gt, "%s firmware %s not found\n", + xe_uc_fw_type_repr(uc_fw->type), uc_fw->path); + else + xe_gt_notice(gt, "%s firmware %s: fetch failed with error %pe\n", + xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, ERR_PTR(err)); xe_gt_info(gt, "%s firmware(s) can be downloaded from %s\n", xe_uc_fw_type_repr(uc_fw->type), XE_UC_FIRMWARE_URL); diff --git a/drivers/gpu/drm/xe/xe_validation.c b/drivers/gpu/drm/xe/xe_validation.c index 826cd09966ef..a611438eaafe 100644 --- a/drivers/gpu/drm/xe/xe_validation.c +++ b/drivers/gpu/drm/xe/xe_validation.c @@ -2,7 +2,6 @@ /* * Copyright © 2024 Intel Corporation */ -#include "xe_bo.h" #include <drm/drm_exec.h> #include <drm/drm_gem.h> #include <drm/drm_gpuvm.h> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 02df403a5b28..4a316bd49135 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -33,7 +33,6 @@ #include "xe_preempt_fence.h" #include "xe_pt.h" #include "xe_pxp.h" -#include "xe_res_cursor.h" #include "xe_sriov_vf.h" #include "xe_svm.h" #include "xe_sync.h" @@ -2209,7 +2208,7 @@ static void print_op(struct xe_device *xe, struct drm_gpuva_op *op) (ULL)xe_vma_start(vma), (ULL)xe_vma_size(vma)); break; default: - drm_warn(&xe->drm, "NOT POSSIBLE"); + drm_warn(&xe->drm, "NOT POSSIBLE\n"); } } #else @@ -2312,7 +2311,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, xe_bo_unlock(bo); break; default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); ops = ERR_PTR(-EINVAL); } if (IS_ERR(ops)) @@ -2584,7 +2583,7 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct xe_vma_op *op) op->flags |= XE_VMA_OP_COMMITTED; break; default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); } return err; @@ -2783,7 +2782,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, break; default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); } err = xe_vma_op_commit(vm, op); @@ -2845,7 +2844,7 @@ static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op, /* Nothing to do */ break; default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); } } @@ -3029,7 +3028,7 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, break; } default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); } return err; @@ -3268,7 +3267,7 @@ static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op, vma_add_ufence(gpuva_to_vma(op->base.prefetch.va), ufence); break; default: - drm_warn(&vm->xe->drm, "NOT POSSIBLE"); + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); } } @@ -3405,6 +3404,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR; u16 pat_index = (*bind_ops)[i].pat_index; u16 coh_mode; + bool comp_en; if (XE_IOCTL_DBG(xe, is_cpu_addr_mirror && (!xe_vm_in_fault_mode(vm) || @@ -3421,6 +3421,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, pat_index = array_index_nospec(pat_index, xe->pat.n_entries); (*bind_ops)[i].pat_index = pat_index; coh_mode = xe_pat_index_get_coh_mode(xe, pat_index); + comp_en = xe_pat_index_get_comp_en(xe, pat_index); if (XE_IOCTL_DBG(xe, !coh_mode)) { /* hw reserved */ err = -EINVAL; goto free_bind_ops; @@ -3451,6 +3452,8 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || XE_IOCTL_DBG(xe, coh_mode == XE_COH_NONE && op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || + XE_IOCTL_DBG(xe, comp_en && + op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || XE_IOCTL_DBG(xe, op == DRM_XE_VM_BIND_OP_MAP_USERPTR && !IS_ENABLED(CONFIG_DRM_GPUSVM)) || XE_IOCTL_DBG(xe, obj && @@ -3529,6 +3532,7 @@ static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, u16 pat_index, u32 op, u32 bind_flags) { u16 coh_mode; + bool comp_en; if (XE_IOCTL_DBG(xe, (bo->flags & XE_BO_FLAG_NO_COMPRESSION) && xe_pat_index_get_comp_en(xe, pat_index))) @@ -3574,6 +3578,14 @@ static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, return -EINVAL; } + /* + * Ensures that imported buffer objects (dma-bufs) are not mapped + * with a PAT index that enables compression. + */ + comp_en = xe_pat_index_get_comp_en(xe, pat_index); + if (XE_IOCTL_DBG(xe, bo->ttm.base.import_attach && comp_en)) + return -EINVAL; + /* If a BO is protected it can only be mapped if the key is still valid */ if ((bind_flags & DRM_XE_VM_BIND_FLAG_CHECK_PXP) && xe_bo_is_protected(bo) && op != DRM_XE_VM_BIND_OP_UNMAP && op != DRM_XE_VM_BIND_OP_UNMAP_ALL) diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 7d11ca47d73e..6cc98df47291 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -382,7 +382,7 @@ static inline void xe_vm_set_validation_exec(struct xe_vm *vm, struct drm_exec * } /** - * xe_vm_set_validation_exec() - Accessor to read the drm_exec object + * xe_vm_validation_exec() - Accessor to read the drm_exec object * @vm: The vm we want to register a drm_exec object with. * * Return: The drm_exec object used to lock the vm's resv. The value diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c index c64d98bf1723..0538dcb8b18c 100644 --- a/drivers/gpu/drm/xe/xe_vram.c +++ b/drivers/gpu/drm/xe/xe_vram.c @@ -13,12 +13,10 @@ #include "regs/xe_gt_regs.h" #include "regs/xe_regs.h" #include "xe_assert.h" -#include "xe_bo.h" #include "xe_device.h" #include "xe_force_wake.h" #include "xe_gt_mcr.h" #include "xe_mmio.h" -#include "xe_module.h" #include "xe_sriov.h" #include "xe_tile_sriov_vf.h" #include "xe_ttm_vram_mgr.h" @@ -155,7 +153,7 @@ static int tile_vram_size(struct xe_tile *tile, u64 *vram_size, *tile_offset = 0; } else { reg = xe_mmio_read32(&tile->mmio, SG_TILE_ADDR_RANGE(tile->id)); - *tile_size = (u64)REG_FIELD_GET(GENMASK(14, 8), reg) * SZ_1G; + *tile_size = (u64)REG_FIELD_GET(GENMASK(17, 8), reg) * SZ_1G; *tile_offset = (u64)REG_FIELD_GET(GENMASK(7, 1), reg) * SZ_1G; } diff --git a/drivers/gpu/drm/xe/xe_vram_freq.c b/drivers/gpu/drm/xe/xe_vram_freq.c index 17bc84da4cdc..6f8281e0b96a 100644 --- a/drivers/gpu/drm/xe/xe_vram_freq.c +++ b/drivers/gpu/drm/xe/xe_vram_freq.c @@ -5,7 +5,6 @@ #include <linux/sysfs.h> #include <drm/drm_managed.h> -#include "xe_gt_types.h" #include "xe_pcode.h" #include "xe_pcode_api.h" #include "xe_tile.h" diff --git a/drivers/gpu/drm/xe/xe_vsec.c b/drivers/gpu/drm/xe/xe_vsec.c index c83ea3d48fae..4ebb4dbe1c9b 100644 --- a/drivers/gpu/drm/xe/xe_vsec.c +++ b/drivers/gpu/drm/xe/xe_vsec.c @@ -12,7 +12,6 @@ #include "xe_device.h" #include "xe_device_types.h" -#include "xe_drv.h" #include "xe_mmio.h" #include "xe_platform_types.h" #include "xe_pm.h" diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index a93717e77da0..a991ee2b8781 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -19,7 +19,7 @@ #include "regs/xe_regs.h" #include "xe_device_types.h" #include "xe_force_wake.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_hw_engine_types.h" #include "xe_mmio.h" #include "xe_platform_types.h" diff --git a/drivers/gpu/drm/xe/xe_wait_user_fence.c b/drivers/gpu/drm/xe/xe_wait_user_fence.c index 5b4264ea38bd..51eb940ceb4e 100644 --- a/drivers/gpu/drm/xe/xe_wait_user_fence.c +++ b/drivers/gpu/drm/xe/xe_wait_user_fence.c @@ -11,7 +11,6 @@ #include <uapi/drm/xe_drm.h> #include "xe_device.h" -#include "xe_gt.h" #include "xe_macros.h" #include "xe_exec_queue.h" diff --git a/drivers/gpu/drm/xe/xe_wopcm.c b/drivers/gpu/drm/xe/xe_wopcm.c index ada0d0aa6b74..dde4f4967ca3 100644 --- a/drivers/gpu/drm/xe/xe_wopcm.c +++ b/drivers/gpu/drm/xe/xe_wopcm.c @@ -10,7 +10,7 @@ #include "regs/xe_guc_regs.h" #include "xe_device.h" #include "xe_force_wake.h" -#include "xe_gt.h" +#include "xe_gt_types.h" #include "xe_mmio.h" #include "xe_uc_fw.h" diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index bb69f9b30c7d..077e66a682e2 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -1280,9 +1280,6 @@ struct drm_xe_vm_bind { * then a new multi-queue group is created with this queue as the primary queue * (Q0). Otherwise, the queue gets added to the multi-queue group whose primary * queue's exec_queue_id is specified in the lower 32 bits of the 'value' field. - * If the extension's 'value' field has %DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag - * set, then the multi-queue group is kept active after the primary queue is - * destroyed. * All the other non-relevant bits of extension's 'value' field while adding the * primary or the secondary queues of the group must be set to 0. * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue @@ -1331,7 +1328,6 @@ struct drm_xe_exec_queue_create { #define DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE 3 #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP 4 #define DRM_XE_MULTI_GROUP_CREATE (1ull << 63) -#define DRM_XE_MULTI_GROUP_KEEP_ACTIVE (1ull << 62) #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY 5 /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; |
