Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Highlights:

UAPI Changes:
Loosen used tracking restriction (Matthew Auld)
New SR-IOV debugfs structure and debugfs updates (Michal Wajdeczko)
Hide the GPU madvise flag behind a VM_BIND flag (Thomas Hellström)
Always expose VRAM provisioning data on discrete GPUs (Lukasz Laguna)

Cross-subsystem Changes:
Allow VRAM mappings for userptr when used with SVM (Matthew Brost)

Driver Changes:
Allow pinning of p2p dma-buf (Thomas Hellstrom)
Use per-tile debugfs where appropriate (Michal Wajdeczko)
Add documentation for Execution Queues (Niranjana Vishwanathapura)
PF improvements (Michal Wajdeczko)
VF migration recovery redesign work (Matthew Brost)
User / Kernel VRAM partitioning (Piotr Piórkowski)
Update Tile-based messages (Michal Wajdeczko)
Allow configfs to disable specific GT types (Matt Roper)
VF provisioning improvements (Michal Wajdeczko)
Initial Xe3P support (Various people)

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

From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com>
Link: https://lore.kernel.org/r/aPXzbOb7eGbkgMrr@fedora

+4710 -2108
+1
Documentation/gpu/xe/index.rst
··· 14 14 xe_mm 15 15 xe_map 16 16 xe_migrate 17 + xe_exec_queue 17 18 xe_cs 18 19 xe_pm 19 20 xe_gt_freq
+20
Documentation/gpu/xe/xe_exec_queue.rst
··· 1 + .. SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2 + 3 + =============== 4 + Execution Queue 5 + =============== 6 + 7 + .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c 8 + :doc: Execution Queue 9 + 10 + Internal API 11 + ============ 12 + 13 + .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue_types.h 14 + :internal: 15 + 16 + .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.h 17 + :internal: 18 + 19 + .. kernel-doc:: drivers/gpu/drm/xe/xe_exec_queue.c 20 + :internal:
+4 -2
drivers/gpu/drm/drm_gpusvm.c
··· 1363 1363 order = drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages); 1364 1364 if (is_device_private_page(page) || 1365 1365 is_device_coherent_page(page)) { 1366 - if (zdd != page->zone_device_data && i > 0) { 1366 + if (!ctx->allow_mixed && 1367 + zdd != page->zone_device_data && i > 0) { 1367 1368 err = -EOPNOTSUPP; 1368 1369 goto err_unmap; 1369 1370 } ··· 1400 1399 } else { 1401 1400 dma_addr_t addr; 1402 1401 1403 - if (is_zone_device_page(page) || pagemap) { 1402 + if (is_zone_device_page(page) || 1403 + (pagemap && !ctx->allow_mixed)) { 1404 1404 err = -EOPNOTSUPP; 1405 1405 goto err_unmap; 1406 1406 }
+11 -11
drivers/gpu/drm/xe/Kconfig.debug
··· 40 40 41 41 If in doubt, say "N". 42 42 43 + config DRM_XE_DEBUG_SRIOV 44 + bool "Enable extra SR-IOV debugging" 45 + default n 46 + imply DRM_XE_DEBUG_MEMIRQ 47 + help 48 + Enable extra SR-IOV debugging info. 49 + 50 + Recommended for driver developers only. 51 + 52 + If in doubt, say "N". 53 + 43 54 config DRM_XE_DEBUG_MEMIRQ 44 55 bool "Enable extra memirq debugging" 45 56 default n 46 57 help 47 58 Choose this option to enable additional debugging info for 48 59 memory based interrupts. 49 - 50 - Recommended for driver developers only. 51 - 52 - If in doubt, say "N". 53 - 54 - config DRM_XE_DEBUG_SRIOV 55 - bool "Enable extra SR-IOV debugging" 56 - default n 57 - select DRM_XE_DEBUG_MEMIRQ 58 - help 59 - Enable extra SR-IOV debugging info. 60 60 61 61 Recommended for driver developers only. 62 62
+5 -1
drivers/gpu/drm/xe/Makefile
··· 174 174 xe_lmtt_ml.o \ 175 175 xe_pci_sriov.o \ 176 176 xe_sriov_pf.o \ 177 - xe_sriov_pf_service.o 177 + xe_sriov_pf_control.o \ 178 + xe_sriov_pf_debugfs.o \ 179 + xe_sriov_pf_provision.o \ 180 + xe_sriov_pf_service.o \ 181 + xe_tile_sriov_pf_debugfs.o 178 182 179 183 # include helpers for tests even when XE is built-in 180 184 ifdef CONFIG_DRM_XE_KUNIT_TEST
-8
drivers/gpu/drm/xe/abi/guc_actions_abi.h
··· 196 196 XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN = 11, 197 197 }; 198 198 199 - enum xe_guc_context_wq_item_offsets { 200 - XE_GUC_CONTEXT_WQ_HEADER_DATA_0_TYPE_LEN = 0, 201 - XE_GUC_CONTEXT_WQ_EL_INFO_DATA_1_CTX_DESC_LOW, 202 - XE_GUC_CONTEXT_WQ_EL_INFO_DATA_2_GUCCTX_RINGTAIL_FREEZEPOCS, 203 - XE_GUC_CONTEXT_WQ_EL_INFO_DATA_3_WI_FENCE_ID, 204 - XE_GUC_CONTEXT_WQ_EL_CHILD_LIST_DATA_4_RINGTAIL, 205 - }; 206 - 207 199 enum xe_guc_report_status { 208 200 XE_GUC_REPORT_STATUS_UNKNOWN = 0x0, 209 201 XE_GUC_REPORT_STATUS_ACKED = 0x1,
+2 -2
drivers/gpu/drm/xe/display/intel_fbdev_fb.c
··· 13 13 #include "xe_ttm_stolen_mgr.h" 14 14 #include "xe_wa.h" 15 15 16 - #include <generated/xe_wa_oob.h> 16 + #include <generated/xe_device_wa_oob.h> 17 17 18 18 struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, 19 19 struct drm_fb_helper_surface_size *sizes) ··· 41 41 size = PAGE_ALIGN(size); 42 42 obj = ERR_PTR(-ENODEV); 43 43 44 - if (!IS_DGFX(xe) && !XE_GT_WA(xe_root_mmio_gt(xe), 22019338487_display)) { 44 + if (!IS_DGFX(xe) && !XE_DEVICE_WA(xe, 22019338487_display)) { 45 45 obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), 46 46 size, 47 47 ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT |
+2 -3
drivers/gpu/drm/xe/display/xe_display.c
··· 223 223 gen11_display_irq_reset(display); 224 224 } 225 225 226 - void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) 226 + void xe_display_irq_postinstall(struct xe_device *xe) 227 227 { 228 228 struct intel_display *display = xe->display; 229 229 230 230 if (!xe->info.probe_display) 231 231 return; 232 232 233 - if (gt->info.id == XE_GT0) 234 - gen11_de_irq_postinstall(display); 233 + gen11_de_irq_postinstall(display); 235 234 } 236 235 237 236 static bool suspend_to_idle(void)
+2 -2
drivers/gpu/drm/xe/display/xe_display.h
··· 26 26 void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl); 27 27 void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir); 28 28 void xe_display_irq_reset(struct xe_device *xe); 29 - void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt); 29 + void xe_display_irq_postinstall(struct xe_device *xe); 30 30 31 31 void xe_display_pm_suspend(struct xe_device *xe); 32 32 void xe_display_pm_shutdown(struct xe_device *xe); ··· 55 55 static inline void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) {} 56 56 static inline void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) {} 57 57 static inline void xe_display_irq_reset(struct xe_device *xe) {} 58 - static inline void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) {} 58 + static inline void xe_display_irq_postinstall(struct xe_device *xe) {} 59 59 60 60 static inline void xe_display_pm_suspend(struct xe_device *xe) {} 61 61 static inline void xe_display_pm_shutdown(struct xe_device *xe) {}
+2 -1
drivers/gpu/drm/xe/display/xe_display_wa.c
··· 13 13 bool intel_display_needs_wa_16023588340(struct intel_display *display) 14 14 { 15 15 struct xe_device *xe = to_xe_device(display->drm); 16 + struct xe_gt *wa_gt = xe_root_mmio_gt(xe); 16 17 17 - return XE_GT_WA(xe_root_mmio_gt(xe), 16023588340); 18 + return wa_gt && XE_GT_WA(wa_gt, 16023588340); 18 19 }
+2 -2
drivers/gpu/drm/xe/display/xe_plane_initial.c
··· 25 25 #include "xe_vram_types.h" 26 26 #include "xe_wa.h" 27 27 28 - #include <generated/xe_wa_oob.h> 28 + #include <generated/xe_device_wa_oob.h> 29 29 30 30 void intel_plane_initial_vblank_wait(struct intel_crtc *crtc) 31 31 { ··· 123 123 phys_base = base; 124 124 flags |= XE_BO_FLAG_STOLEN; 125 125 126 - if (XE_GT_WA(xe_root_mmio_gt(xe), 22019338487_display)) 126 + if (XE_DEVICE_WA(xe, 22019338487_display)) 127 127 return NULL; 128 128 129 129 /*
+4
drivers/gpu/drm/xe/regs/xe_engine_regs.h
··· 141 141 #define INHIBIT_SWITCH_UNTIL_PREEMPTED REG_BIT(31) 142 142 #define IDLE_DELAY REG_GENMASK(20, 0) 143 143 144 + #define RING_CURRENT_LRCA(base) XE_REG((base) + 0x240) 145 + 144 146 #define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED) 145 147 #define CTX_CTRL_PXP_ENABLE REG_BIT(10) 146 148 #define CTX_CTRL_OAC_CONTEXT_ENABLE REG_BIT(8) ··· 154 152 #define RING_MODE(base) XE_REG((base) + 0x29c) 155 153 #define GFX_DISABLE_LEGACY_MODE REG_BIT(3) 156 154 #define GFX_MSIX_INTERRUPT_ENABLE REG_BIT(13) 155 + 156 + #define RING_CSMQDEBUG(base) XE_REG((base) + 0x2b0) 157 157 158 158 #define RING_TIMESTAMP(base) XE_REG((base) + 0x358) 159 159
+3 -4
drivers/gpu/drm/xe/regs/xe_gt_regs.h
··· 239 239 #define XE2_GT_GEOMETRY_DSS_1 XE_REG(0x9150) 240 240 #define XE2_GT_GEOMETRY_DSS_2 XE_REG(0x9154) 241 241 242 + #define SERVICE_COPY_ENABLE XE_REG(0x9170) 243 + #define FUSE_SERVICE_COPY_ENABLE_MASK REG_GENMASK(7, 0) 244 + 242 245 #define GDRST XE_REG(0x941c) 243 246 #define GRDOM_GUC REG_BIT(3) 244 247 #define GRDOM_FULL REG_BIT(0) ··· 348 345 #define MEDIA_SAMPLERS_POWERGATE_ENABLE REG_BIT(2) 349 346 #define VDN_HCP_POWERGATE_ENABLE(n) REG_BIT(3 + 2 * (n)) 350 347 #define VDN_MFXVDENC_POWERGATE_ENABLE(n) REG_BIT(4 + 2 * (n)) 351 - 352 - #define CTC_MODE XE_REG(0xa26c) 353 - #define CTC_SHIFT_PARAMETER_MASK REG_GENMASK(2, 1) 354 - #define CTC_SOURCE_DIVIDE_LOGIC REG_BIT(0) 355 348 356 349 #define FORCEWAKE_RENDER XE_REG(0xa278) 357 350
+3
drivers/gpu/drm/xe/regs/xe_i2c_regs.h
··· 14 14 #define REG_SG_REMAP_ADDR_PREFIX XE_REG(SOC_BASE + 0x0164) 15 15 #define REG_SG_REMAP_ADDR_POSTFIX XE_REG(SOC_BASE + 0x0168) 16 16 17 + #define I2C_BRIDGE_PCICFGCTL XE_REG(I2C_BRIDGE_OFFSET + 0x200) 18 + #define ACPI_INTR_EN REG_BIT(1) 19 + 17 20 #define I2C_CONFIG_CMD XE_REG(I2C_CONFIG_SPACE_OFFSET + PCI_COMMAND) 18 21 #define I2C_CONFIG_PMCSR XE_REG(I2C_CONFIG_SPACE_OFFSET + 0x84) 19 22
+6 -2
drivers/gpu/drm/xe/regs/xe_irq_regs.h
··· 65 65 #define BCS_RSVD_INTR_MASK XE_REG(0x1900a0, XE_REG_OPTION_VF) 66 66 #define VCS0_VCS1_INTR_MASK XE_REG(0x1900a8, XE_REG_OPTION_VF) 67 67 #define VCS2_VCS3_INTR_MASK XE_REG(0x1900ac, XE_REG_OPTION_VF) 68 + #define VCS4_VCS5_INTR_MASK XE_REG(0x1900b0, XE_REG_OPTION_VF) 69 + #define VCS6_VCS7_INTR_MASK XE_REG(0x1900b4, XE_REG_OPTION_VF) 68 70 #define VECS0_VECS1_INTR_MASK XE_REG(0x1900d0, XE_REG_OPTION_VF) 71 + #define VECS2_VECS3_INTR_MASK XE_REG(0x1900d4, XE_REG_OPTION_VF) 69 72 #define HECI2_RSVD_INTR_MASK XE_REG(0x1900e4) 70 73 #define GUC_SG_INTR_MASK XE_REG(0x1900e8, XE_REG_OPTION_VF) 71 74 #define GPM_WGBOXPERF_INTR_MASK XE_REG(0x1900ec, XE_REG_OPTION_VF) ··· 83 80 #define GT_WAIT_SEMAPHORE_INTERRUPT REG_BIT(11) 84 81 #define GT_CONTEXT_SWITCH_INTERRUPT REG_BIT(8) 85 82 #define GSC_ER_COMPLETE REG_BIT(5) 86 - #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT REG_BIT(4) 83 + #define GT_FLUSH_COMPLETE_INTERRUPT REG_BIT(4) 87 84 #define GT_CS_MASTER_ERROR_INTERRUPT REG_BIT(3) 88 - #define GT_RENDER_USER_INTERRUPT REG_BIT(0) 85 + #define GT_COMPUTE_WALKER_INTERRUPT REG_BIT(2) 86 + #define GT_MI_USER_INTERRUPT REG_BIT(0) 89 87 90 88 /* irqs for OTHER_KCR_INSTANCE */ 91 89 #define KCR_PXP_STATE_TERMINATED_INTERRUPT REG_BIT(1)
+15 -2
drivers/gpu/drm/xe/tests/xe_dma_buf.c
··· 31 31 struct drm_exec *exec) 32 32 { 33 33 struct dma_buf_test_params *params = to_dma_buf_test_params(test->priv); 34 + struct dma_buf_attachment *attach; 34 35 u32 mem_type; 35 36 int ret; 36 37 ··· 47 46 mem_type = XE_PL_TT; 48 47 else if (params->force_different_devices && !is_dynamic(params) && 49 48 (params->mem_mask & XE_BO_FLAG_SYSTEM)) 50 - /* Pin migrated to TT */ 49 + /* Pin migrated to TT on non-dynamic attachments. */ 51 50 mem_type = XE_PL_TT; 52 51 53 52 if (!xe_bo_is_mem_type(exported, mem_type)) { ··· 88 87 } 89 88 90 89 KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type)); 90 + 91 + /* Check that we can pin without migrating. */ 92 + attach = list_first_entry_or_null(&dmabuf->attachments, typeof(*attach), node); 93 + if (attach) { 94 + int err = dma_buf_pin(attach); 95 + 96 + if (!err) { 97 + KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type)); 98 + dma_buf_unpin(attach); 99 + } 100 + KUNIT_EXPECT_EQ(test, err, 0); 101 + } 91 102 92 103 if (params->force_different_devices) 93 104 KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(imported, XE_PL_TT)); ··· 163 150 xe_bo_lock(import_bo, false); 164 151 err = xe_bo_validate(import_bo, NULL, false, exec); 165 152 166 - /* Pinning in VRAM is not allowed. */ 153 + /* Pinning in VRAM is not allowed for non-dynamic attachments */ 167 154 if (!is_dynamic(params) && 168 155 params->force_different_devices && 169 156 !(params->mem_mask & XE_BO_FLAG_SYSTEM))
+4 -2
drivers/gpu/drm/xe/tests/xe_pci.c
··· 311 311 } 312 312 EXPORT_SYMBOL_IF_KUNIT(xe_pci_id_gen_param); 313 313 314 - static void fake_read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, 315 - u32 *ver, u32 *revid) 314 + static int fake_read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, 315 + u32 *ver, u32 *revid) 316 316 { 317 317 struct kunit *test = kunit_get_current_test(); 318 318 struct xe_pci_fake_data *data = test->priv; ··· 324 324 *ver = data->graphics_verx100; 325 325 *revid = xe_step_to_gmdid(data->step.graphics); 326 326 } 327 + 328 + return 0; 327 329 } 328 330 329 331 static void fake_xe_info_probe_tile_count(struct xe_device *xe)
+4 -2
drivers/gpu/drm/xe/tests/xe_rtp_test.c
··· 48 48 const struct xe_rtp_entry *entries; 49 49 }; 50 50 51 - static bool match_yes(const struct xe_gt *gt, const struct xe_hw_engine *hwe) 51 + static bool match_yes(const struct xe_device *xe, const struct xe_gt *gt, 52 + const struct xe_hw_engine *hwe) 52 53 { 53 54 return true; 54 55 } 55 56 56 - static bool match_no(const struct xe_gt *gt, const struct xe_hw_engine *hwe) 57 + static bool match_no(const struct xe_device *xe, const struct xe_gt *gt, 58 + const struct xe_hw_engine *hwe) 57 59 { 58 60 return false; 59 61 }
+52 -26
drivers/gpu/drm/xe/xe_bo.c
··· 34 34 #include "xe_res_cursor.h" 35 35 #include "xe_shrinker.h" 36 36 #include "xe_sriov_vf_ccs.h" 37 + #include "xe_tile.h" 37 38 #include "xe_trace_bo.h" 38 39 #include "xe_ttm_stolen_mgr.h" 39 40 #include "xe_vm.h" ··· 81 80 .num_placement = 2, 82 81 .placement = tt_placement_flags, 83 82 }; 83 + 84 + #define for_each_set_bo_vram_flag(bit__, bo_flags__) \ 85 + for (unsigned int __bit_tmp = BIT(0); __bit_tmp <= XE_BO_FLAG_VRAM_MASK; __bit_tmp <<= 1) \ 86 + for_each_if(((bit__) = __bit_tmp) & (bo_flags__) & XE_BO_FLAG_VRAM_MASK) 84 87 85 88 bool mem_type_is_vram(u32 mem_type) 86 89 { ··· 218 213 bo_flags & XE_BO_FLAG_PINNED; 219 214 } 220 215 216 + static u8 vram_bo_flag_to_tile_id(struct xe_device *xe, u32 vram_bo_flag) 217 + { 218 + xe_assert(xe, vram_bo_flag & XE_BO_FLAG_VRAM_MASK); 219 + xe_assert(xe, (vram_bo_flag & (vram_bo_flag - 1)) == 0); 220 + 221 + return __ffs(vram_bo_flag >> (__ffs(XE_BO_FLAG_VRAM0) - 1)) - 1; 222 + } 223 + 224 + static u32 bo_vram_flags_to_vram_placement(struct xe_device *xe, u32 bo_flags, u32 vram_flag, 225 + enum ttm_bo_type type) 226 + { 227 + u8 tile_id = vram_bo_flag_to_tile_id(xe, vram_flag); 228 + 229 + xe_assert(xe, tile_id < xe->info.tile_count); 230 + 231 + if (type == ttm_bo_type_kernel && !(bo_flags & XE_BO_FLAG_FORCE_USER_VRAM)) 232 + return xe->tiles[tile_id].mem.kernel_vram->placement; 233 + else 234 + return xe->tiles[tile_id].mem.vram->placement; 235 + } 236 + 221 237 static void add_vram(struct xe_device *xe, struct xe_bo *bo, 222 238 struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c) 223 239 { ··· 271 245 } 272 246 273 247 static void try_add_vram(struct xe_device *xe, struct xe_bo *bo, 274 - u32 bo_flags, u32 *c) 248 + u32 bo_flags, enum ttm_bo_type type, u32 *c) 275 249 { 276 - if (bo_flags & XE_BO_FLAG_VRAM0) 277 - add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM0, c); 278 - if (bo_flags & XE_BO_FLAG_VRAM1) 279 - add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM1, c); 250 + u32 vram_flag; 251 + 252 + for_each_set_bo_vram_flag(vram_flag, bo_flags) { 253 + u32 pl = bo_vram_flags_to_vram_placement(xe, bo_flags, vram_flag, type); 254 + 255 + add_vram(xe, bo, bo->placements, bo_flags, pl, c); 256 + } 280 257 } 281 258 282 259 static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo, ··· 298 269 } 299 270 300 271 static int __xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo, 301 - u32 bo_flags) 272 + u32 bo_flags, enum ttm_bo_type type) 302 273 { 303 274 u32 c = 0; 304 275 305 - try_add_vram(xe, bo, bo_flags, &c); 276 + try_add_vram(xe, bo, bo_flags, type, &c); 306 277 try_add_system(xe, bo, bo_flags, &c); 307 278 try_add_stolen(xe, bo, bo_flags, &c); 308 279 ··· 318 289 } 319 290 320 291 int xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo, 321 - u32 bo_flags) 292 + u32 bo_flags, enum ttm_bo_type type) 322 293 { 323 294 xe_bo_assert_held(bo); 324 - return __xe_bo_placement_for_flags(xe, bo, bo_flags); 295 + return __xe_bo_placement_for_flags(xe, bo, bo_flags, type); 325 296 } 326 297 327 298 static void xe_evict_flags(struct ttm_buffer_object *tbo, ··· 2193 2164 2194 2165 xe_validation_assert_exec(xe, exec, &bo->ttm.base); 2195 2166 if (!(flags & XE_BO_FLAG_FIXED_PLACEMENT)) { 2196 - err = __xe_bo_placement_for_flags(xe, bo, bo->flags); 2167 + err = __xe_bo_placement_for_flags(xe, bo, bo->flags, type); 2197 2168 if (WARN_ON(err)) { 2198 2169 xe_ttm_bo_destroy(&bo->ttm); 2199 2170 return ERR_PTR(err); ··· 2251 2222 } 2252 2223 2253 2224 static int __xe_bo_fixed_placement(struct xe_device *xe, 2254 - struct xe_bo *bo, 2225 + struct xe_bo *bo, enum ttm_bo_type type, 2255 2226 u32 flags, 2256 2227 u64 start, u64 end, u64 size) 2257 2228 { 2258 2229 struct ttm_place *place = bo->placements; 2230 + u32 vram_flag, vram_stolen_flags; 2259 2231 2260 2232 if (flags & (XE_BO_FLAG_USER | XE_BO_FLAG_SYSTEM)) 2233 + return -EINVAL; 2234 + 2235 + vram_flag = flags & XE_BO_FLAG_VRAM_MASK; 2236 + vram_stolen_flags = (flags & (XE_BO_FLAG_STOLEN)) | vram_flag; 2237 + 2238 + /* check if more than one VRAM/STOLEN flag is set */ 2239 + if (hweight32(vram_stolen_flags) > 1) 2261 2240 return -EINVAL; 2262 2241 2263 2242 place->flags = TTM_PL_FLAG_CONTIGUOUS; 2264 2243 place->fpfn = start >> PAGE_SHIFT; 2265 2244 place->lpfn = end >> PAGE_SHIFT; 2266 2245 2267 - switch (flags & (XE_BO_FLAG_STOLEN | XE_BO_FLAG_VRAM_MASK)) { 2268 - case XE_BO_FLAG_VRAM0: 2269 - place->mem_type = XE_PL_VRAM0; 2270 - break; 2271 - case XE_BO_FLAG_VRAM1: 2272 - place->mem_type = XE_PL_VRAM1; 2273 - break; 2274 - case XE_BO_FLAG_STOLEN: 2246 + if (flags & XE_BO_FLAG_STOLEN) 2275 2247 place->mem_type = XE_PL_STOLEN; 2276 - break; 2277 - 2278 - default: 2279 - /* 0 or multiple of the above set */ 2280 - return -EINVAL; 2281 - } 2248 + else 2249 + place->mem_type = bo_vram_flags_to_vram_placement(xe, flags, vram_flag, type); 2282 2250 2283 2251 bo->placement = (struct ttm_placement) { 2284 2252 .num_placement = 1, ··· 2304 2278 return bo; 2305 2279 2306 2280 flags |= XE_BO_FLAG_FIXED_PLACEMENT; 2307 - err = __xe_bo_fixed_placement(xe, bo, flags, start, end, size); 2281 + err = __xe_bo_fixed_placement(xe, bo, type, flags, start, end, size); 2308 2282 if (err) { 2309 2283 xe_bo_free(bo); 2310 2284 return ERR_PTR(err);
+2 -1
drivers/gpu/drm/xe/xe_bo.h
··· 49 49 #define XE_BO_FLAG_GGTT2 BIT(22) 50 50 #define XE_BO_FLAG_GGTT3 BIT(23) 51 51 #define XE_BO_FLAG_CPU_ADDR_MIRROR BIT(24) 52 + #define XE_BO_FLAG_FORCE_USER_VRAM BIT(25) 52 53 53 54 /* this one is trigger internally only */ 54 55 #define XE_BO_FLAG_INTERNAL_TEST BIT(30) ··· 123 122 int xe_managed_bo_reinit_in_vram(struct xe_device *xe, struct xe_tile *tile, struct xe_bo **src); 124 123 125 124 int xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo, 126 - u32 bo_flags); 125 + u32 bo_flags, enum ttm_bo_type type); 127 126 128 127 static inline struct xe_bo *ttm_to_xe_bo(const struct ttm_buffer_object *bo) 129 128 {
+9
drivers/gpu/drm/xe/xe_bo_evict.c
··· 73 73 &xe->pinned.late.kernel_bo_present, 74 74 xe_bo_notifier_prepare_pinned); 75 75 76 + if (!ret) 77 + ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.external, 78 + &xe->pinned.late.external, 79 + xe_bo_notifier_prepare_pinned); 80 + 76 81 return ret; 77 82 } 78 83 ··· 97 92 98 93 (void)xe_bo_apply_to_pinned(xe, &xe->pinned.late.kernel_bo_present, 99 94 &xe->pinned.late.kernel_bo_present, 95 + xe_bo_notifier_unprepare_pinned); 96 + 97 + (void)xe_bo_apply_to_pinned(xe, &xe->pinned.late.external, 98 + &xe->pinned.late.external, 100 99 xe_bo_notifier_unprepare_pinned); 101 100 } 102 101
+282
drivers/gpu/drm/xe/xe_configfs.c
··· 15 15 16 16 #include "instructions/xe_mi_commands.h" 17 17 #include "xe_configfs.h" 18 + #include "xe_gt_types.h" 18 19 #include "xe_hw_engine_types.h" 19 20 #include "xe_module.h" 20 21 #include "xe_pci_types.h" 22 + #include "xe_sriov_types.h" 21 23 22 24 /** 23 25 * DOC: Xe Configfs ··· 58 56 * : 59 57 * └── 0000:03:00.0 60 58 * ├── survivability_mode 59 + * ├── gt_types_allowed 61 60 * ├── engines_allowed 62 61 * └── enable_psmi 63 62 * ··· 81 78 * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode 82 79 * 83 80 * This attribute can only be set before binding to the device. 81 + * 82 + * Allowed GT types: 83 + * ----------------- 84 + * 85 + * Allow only specific types of GTs to be detected and initialized by the 86 + * driver. Any combination of GT types can be enabled/disabled, although 87 + * some settings will cause the device to fail to probe. 88 + * 89 + * Writes support both comma- and newline-separated input format. Reads 90 + * will always return one GT type per line. "primary" and "media" are the 91 + * GT type names supported by this interface. 92 + * 93 + * This attribute can only be set before binding to the device. 94 + * 95 + * Examples: 96 + * 97 + * Allow both primary and media GTs to be initialized and used. This matches 98 + * the driver's default behavior:: 99 + * 100 + * # echo 'primary,media' > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed 101 + * 102 + * Allow only the primary GT of each tile to be initialized and used, 103 + * effectively disabling the media GT if it exists on the platform:: 104 + * 105 + * # echo 'primary' > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed 106 + * 107 + * Allow only the media GT of each tile to be initialized and used, 108 + * effectively disabling the primary GT. **This configuration will cause 109 + * device probe failure on all current platforms, but may be allowed on 110 + * igpu platforms in the future**:: 111 + * 112 + * # echo 'media' > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed 113 + * 114 + * Disable all GTs. Only other GPU IP (such as display) is potentially usable. 115 + * **This configuration will cause device probe failure on all current 116 + * platforms, but may be allowed on igpu platforms in the future**:: 117 + * 118 + * # echo '' > /sys/kernel/config/xe/0000:03:00.0/gt_types_allowed 84 119 * 85 120 * Allowed engines: 86 121 * ---------------- ··· 210 169 * Currently this is implemented only for post and mid context restore and 211 170 * these attributes can only be set before binding to the device. 212 171 * 172 + * Max SR-IOV Virtual Functions 173 + * ---------------------------- 174 + * 175 + * This config allows to limit number of the Virtual Functions (VFs) that can 176 + * be managed by the Physical Function (PF) driver, where value 0 disables the 177 + * PF mode (no VFs). 178 + * 179 + * The default max_vfs config value is taken from the max_vfs modparam. 180 + * 181 + * How to enable PF with support with unlimited (up to HW limit) number of VFs:: 182 + * 183 + * # echo unlimited > /sys/kernel/config/xe/0000:00:02.0/sriov/max_vfs 184 + * # echo 0000:00:02.0 > /sys/bus/pci/drivers/xe/bind 185 + * 186 + * How to enable PF with support up to 3 VFs:: 187 + * 188 + * # echo 3 > /sys/kernel/config/xe/0000:00:02.0/sriov/max_vfs 189 + * # echo 0000:00:02.0 > /sys/bus/pci/drivers/xe/bind 190 + * 191 + * How to disable PF mode and always run as native:: 192 + * 193 + * # echo 0 > /sys/kernel/config/xe/0000:00:02.0/sriov/max_vfs 194 + * # echo 0000:00:02.0 > /sys/bus/pci/drivers/xe/bind 195 + * 196 + * This setting only takes effect when probing the device. 197 + * 213 198 * Remove devices 214 199 * ============== 215 200 * ··· 252 185 253 186 struct xe_config_group_device { 254 187 struct config_group group; 188 + struct config_group sriov; 255 189 256 190 struct xe_config_device { 191 + u64 gt_types_allowed; 257 192 u64 engines_allowed; 258 193 struct wa_bb ctx_restore_post_bb[XE_ENGINE_CLASS_MAX]; 259 194 struct wa_bb ctx_restore_mid_bb[XE_ENGINE_CLASS_MAX]; 260 195 bool survivability_mode; 261 196 bool enable_psmi; 197 + struct { 198 + unsigned int max_vfs; 199 + } sriov; 262 200 } config; 263 201 264 202 /* protects attributes */ 265 203 struct mutex lock; 266 204 /* matching descriptor */ 267 205 const struct xe_device_desc *desc; 206 + /* tentative SR-IOV mode */ 207 + enum xe_sriov_mode mode; 268 208 }; 269 209 270 210 static const struct xe_config_device device_defaults = { 211 + .gt_types_allowed = U64_MAX, 271 212 .engines_allowed = U64_MAX, 272 213 .survivability_mode = false, 273 214 .enable_psmi = false, 215 + .sriov = { 216 + .max_vfs = UINT_MAX, 217 + }, 274 218 }; 275 219 276 220 static void set_device_defaults(struct xe_config_device *config) 277 221 { 278 222 *config = device_defaults; 223 + #ifdef CONFIG_PCI_IOV 224 + config->sriov.max_vfs = xe_modparam.max_vfs; 225 + #endif 279 226 } 280 227 281 228 struct engine_info { ··· 301 220 /* Some helpful macros to aid on the sizing of buffer allocation when parsing */ 302 221 #define MAX_ENGINE_CLASS_CHARS 5 303 222 #define MAX_ENGINE_INSTANCE_CHARS 2 223 + #define MAX_GT_TYPE_CHARS 7 304 224 305 225 static const struct engine_info engine_info[] = { 306 226 { .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK, .engine_class = XE_ENGINE_CLASS_RENDER }, ··· 310 228 { .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK, .engine_class = XE_ENGINE_CLASS_VIDEO_ENHANCE }, 311 229 { .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK, .engine_class = XE_ENGINE_CLASS_COMPUTE }, 312 230 { .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK, .engine_class = XE_ENGINE_CLASS_OTHER }, 231 + }; 232 + 233 + static const struct { 234 + const char name[MAX_GT_TYPE_CHARS + 1]; 235 + enum xe_gt_type type; 236 + } gt_types[] = { 237 + { .name = "primary", .type = XE_GT_TYPE_MAIN }, 238 + { .name = "media", .type = XE_GT_TYPE_MEDIA }, 313 239 }; 314 240 315 241 static struct xe_config_group_device *to_xe_config_group_device(struct config_item *item) ··· 378 288 return -EBUSY; 379 289 380 290 dev->config.survivability_mode = survivability_mode; 291 + 292 + return len; 293 + } 294 + 295 + static ssize_t gt_types_allowed_show(struct config_item *item, char *page) 296 + { 297 + struct xe_config_device *dev = to_xe_config_device(item); 298 + char *p = page; 299 + 300 + for (size_t i = 0; i < ARRAY_SIZE(gt_types); i++) 301 + if (dev->gt_types_allowed & BIT_ULL(gt_types[i].type)) 302 + p += sprintf(p, "%s\n", gt_types[i].name); 303 + 304 + return p - page; 305 + } 306 + 307 + static ssize_t gt_types_allowed_store(struct config_item *item, const char *page, 308 + size_t len) 309 + { 310 + struct xe_config_group_device *dev = to_xe_config_group_device(item); 311 + char *buf __free(kfree) = kstrdup(page, GFP_KERNEL); 312 + char *p = buf; 313 + u64 typemask = 0; 314 + 315 + if (!buf) 316 + return -ENOMEM; 317 + 318 + while (p) { 319 + char *typename = strsep(&p, ",\n"); 320 + bool matched = false; 321 + 322 + if (typename[0] == '\0') 323 + continue; 324 + 325 + for (size_t i = 0; i < ARRAY_SIZE(gt_types); i++) { 326 + if (strcmp(typename, gt_types[i].name) == 0) { 327 + typemask |= BIT(gt_types[i].type); 328 + matched = true; 329 + break; 330 + } 331 + } 332 + 333 + if (!matched) 334 + return -EINVAL; 335 + } 336 + 337 + guard(mutex)(&dev->lock); 338 + if (is_bound(dev)) 339 + return -EBUSY; 340 + 341 + dev->config.gt_types_allowed = typemask; 381 342 382 343 return len; 383 344 } ··· 813 672 CONFIGFS_ATTR(, ctx_restore_post_bb); 814 673 CONFIGFS_ATTR(, enable_psmi); 815 674 CONFIGFS_ATTR(, engines_allowed); 675 + CONFIGFS_ATTR(, gt_types_allowed); 816 676 CONFIGFS_ATTR(, survivability_mode); 817 677 818 678 static struct configfs_attribute *xe_config_device_attrs[] = { ··· 821 679 &attr_ctx_restore_post_bb, 822 680 &attr_enable_psmi, 823 681 &attr_engines_allowed, 682 + &attr_gt_types_allowed, 824 683 &attr_survivability_mode, 825 684 NULL, 826 685 }; ··· 864 721 .ct_owner = THIS_MODULE, 865 722 }; 866 723 724 + static ssize_t sriov_max_vfs_show(struct config_item *item, char *page) 725 + { 726 + struct xe_config_group_device *dev = to_xe_config_group_device(item->ci_parent); 727 + 728 + guard(mutex)(&dev->lock); 729 + 730 + if (dev->config.sriov.max_vfs == UINT_MAX) 731 + return sprintf(page, "%s\n", "unlimited"); 732 + else 733 + return sprintf(page, "%u\n", dev->config.sriov.max_vfs); 734 + } 735 + 736 + static ssize_t sriov_max_vfs_store(struct config_item *item, const char *page, size_t len) 737 + { 738 + struct xe_config_group_device *dev = to_xe_config_group_device(item->ci_parent); 739 + unsigned int max_vfs; 740 + int ret; 741 + 742 + guard(mutex)(&dev->lock); 743 + 744 + if (is_bound(dev)) 745 + return -EBUSY; 746 + 747 + ret = kstrtouint(page, 0, &max_vfs); 748 + if (ret) { 749 + if (!sysfs_streq(page, "unlimited")) 750 + return ret; 751 + max_vfs = UINT_MAX; 752 + } 753 + 754 + dev->config.sriov.max_vfs = max_vfs; 755 + return len; 756 + } 757 + 758 + CONFIGFS_ATTR(sriov_, max_vfs); 759 + 760 + static struct configfs_attribute *xe_config_sriov_attrs[] = { 761 + &sriov_attr_max_vfs, 762 + NULL, 763 + }; 764 + 765 + static bool xe_config_sriov_is_visible(struct config_item *item, 766 + struct configfs_attribute *attr, int n) 767 + { 768 + struct xe_config_group_device *dev = to_xe_config_group_device(item->ci_parent); 769 + 770 + if (attr == &sriov_attr_max_vfs && dev->mode != XE_SRIOV_MODE_PF) 771 + return false; 772 + 773 + return true; 774 + } 775 + 776 + static struct configfs_group_operations xe_config_sriov_group_ops = { 777 + .is_visible = xe_config_sriov_is_visible, 778 + }; 779 + 780 + static const struct config_item_type xe_config_sriov_type = { 781 + .ct_owner = THIS_MODULE, 782 + .ct_group_ops = &xe_config_sriov_group_ops, 783 + .ct_attrs = xe_config_sriov_attrs, 784 + }; 785 + 867 786 static const struct xe_device_desc *xe_match_desc(struct pci_dev *pdev) 868 787 { 869 788 struct device_driver *driver = driver_find("xe", &pci_bus_type); ··· 951 746 unsigned int domain, bus, slot, function; 952 747 struct xe_config_group_device *dev; 953 748 const struct xe_device_desc *match; 749 + enum xe_sriov_mode mode; 954 750 struct pci_dev *pdev; 955 751 char canonical[16]; 956 752 int vfnumber = 0; ··· 968 762 return ERR_PTR(-EINVAL); 969 763 970 764 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); 765 + mode = pdev ? dev_is_pf(&pdev->dev) ? 766 + XE_SRIOV_MODE_PF : XE_SRIOV_MODE_NONE : XE_SRIOV_MODE_VF; 767 + 971 768 if (!pdev && function) 972 769 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, 0)); 973 770 if (!pdev && slot) ··· 1005 796 return ERR_PTR(-ENOMEM); 1006 797 1007 798 dev->desc = match; 799 + dev->mode = match->has_sriov ? mode : XE_SRIOV_MODE_NONE; 800 + 1008 801 set_device_defaults(&dev->config); 1009 802 1010 803 config_group_init_type_name(&dev->group, name, &xe_config_device_type); 804 + if (dev->mode != XE_SRIOV_MODE_NONE) { 805 + config_group_init_type_name(&dev->sriov, "sriov", &xe_config_sriov_type); 806 + configfs_add_default_group(&dev->sriov, &dev->group); 807 + } 1011 808 1012 809 mutex_init(&dev->lock); 1013 810 ··· 1061 846 dev->config.attr_); \ 1062 847 } while (0) 1063 848 849 + PRI_CUSTOM_ATTR("%llx", gt_types_allowed); 1064 850 PRI_CUSTOM_ATTR("%llx", engines_allowed); 1065 851 PRI_CUSTOM_ATTR("%d", enable_psmi); 1066 852 PRI_CUSTOM_ATTR("%d", survivability_mode); ··· 1110 894 config_group_put(&dev->group); 1111 895 1112 896 return mode; 897 + } 898 + 899 + static u64 get_gt_types_allowed(struct pci_dev *pdev) 900 + { 901 + struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 902 + u64 mask; 903 + 904 + if (!dev) 905 + return device_defaults.gt_types_allowed; 906 + 907 + mask = dev->config.gt_types_allowed; 908 + config_group_put(&dev->group); 909 + 910 + return mask; 911 + } 912 + 913 + /** 914 + * xe_configfs_primary_gt_allowed - determine whether primary GTs are supported 915 + * @pdev: pci device 916 + * 917 + * Return: True if primary GTs are enabled, false if they have been disabled via 918 + * configfs. 919 + */ 920 + bool xe_configfs_primary_gt_allowed(struct pci_dev *pdev) 921 + { 922 + return get_gt_types_allowed(pdev) & BIT_ULL(XE_GT_TYPE_MAIN); 923 + } 924 + 925 + /** 926 + * xe_configfs_media_gt_allowed - determine whether media GTs are supported 927 + * @pdev: pci device 928 + * 929 + * Return: True if the media GTs are enabled, false if they have been disabled 930 + * via configfs. 931 + */ 932 + bool xe_configfs_media_gt_allowed(struct pci_dev *pdev) 933 + { 934 + return get_gt_types_allowed(pdev) & BIT_ULL(XE_GT_TYPE_MEDIA); 1113 935 } 1114 936 1115 937 /** ··· 1241 987 1242 988 return len; 1243 989 } 990 + 991 + #ifdef CONFIG_PCI_IOV 992 + /** 993 + * xe_configfs_get_max_vfs() - Get number of VFs that could be managed 994 + * @pdev: the &pci_dev device 995 + * 996 + * Find the configfs group that belongs to the PCI device and return maximum 997 + * number of Virtual Functions (VFs) that could be managed by this device. 998 + * If configfs group is not present, use value of max_vfs module parameter. 999 + * 1000 + * Return: maximum number of VFs that could be managed. 1001 + */ 1002 + unsigned int xe_configfs_get_max_vfs(struct pci_dev *pdev) 1003 + { 1004 + struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 1005 + unsigned int max_vfs; 1006 + 1007 + if (!dev) 1008 + return xe_modparam.max_vfs; 1009 + 1010 + scoped_guard(mutex, &dev->lock) 1011 + max_vfs = dev->config.sriov.max_vfs; 1012 + 1013 + config_group_put(&dev->group); 1014 + 1015 + return max_vfs; 1016 + } 1017 + #endif 1244 1018 1245 1019 int __init xe_configfs_init(void) 1246 1020 {
+8
drivers/gpu/drm/xe/xe_configfs.h
··· 17 17 void xe_configfs_exit(void); 18 18 void xe_configfs_check_device(struct pci_dev *pdev); 19 19 bool xe_configfs_get_survivability_mode(struct pci_dev *pdev); 20 + bool xe_configfs_primary_gt_allowed(struct pci_dev *pdev); 21 + bool xe_configfs_media_gt_allowed(struct pci_dev *pdev); 20 22 u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev); 21 23 bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev); 22 24 u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev *pdev, enum xe_engine_class, 23 25 const u32 **cs); 24 26 u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev *pdev, enum xe_engine_class, 25 27 const u32 **cs); 28 + #ifdef CONFIG_PCI_IOV 29 + unsigned int xe_configfs_get_max_vfs(struct pci_dev *pdev); 30 + #endif 26 31 #else 27 32 static inline int xe_configfs_init(void) { return 0; } 28 33 static inline void xe_configfs_exit(void) { } 29 34 static inline void xe_configfs_check_device(struct pci_dev *pdev) { } 30 35 static inline bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) { return false; } 36 + static inline bool xe_configfs_primary_gt_allowed(struct pci_dev *pdev) { return true; } 37 + static inline bool xe_configfs_media_gt_allowed(struct pci_dev *pdev) { return true; } 31 38 static inline u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) { return U64_MAX; } 32 39 static inline bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev) { return false; } 33 40 static inline u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev *pdev, enum xe_engine_class, 34 41 const u32 **cs) { return 0; } 35 42 static inline u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev *pdev, enum xe_engine_class, 36 43 const u32 **cs) { return 0; } 44 + static inline unsigned int xe_configfs_get_max_vfs(struct pci_dev *pdev) { return UINT_MAX; } 37 45 #endif 38 46 39 47 #endif
+6 -9
drivers/gpu/drm/xe/xe_debugfs.c
··· 23 23 #include "xe_psmi.h" 24 24 #include "xe_pxp_debugfs.h" 25 25 #include "xe_sriov.h" 26 - #include "xe_sriov_pf.h" 26 + #include "xe_sriov_pf_debugfs.h" 27 27 #include "xe_sriov_vf.h" 28 28 #include "xe_step.h" 29 29 #include "xe_tile_debugfs.h" 30 - #include "xe_wa.h" 31 30 #include "xe_vsec.h" 31 + #include "xe_wa.h" 32 32 33 33 #ifdef CONFIG_DRM_XE_DEBUG 34 34 #include "xe_bo_evict.h" ··· 349 349 { 350 350 struct xe_device *xe = file_inode(f)->i_private; 351 351 struct xe_late_bind *late_bind = &xe->late_bind; 352 - u32 uval; 353 - ssize_t ret; 352 + bool val; 353 + int ret; 354 354 355 - ret = kstrtouint_from_user(ubuf, size, sizeof(uval), &uval); 355 + ret = kstrtobool_from_user(ubuf, size, &val); 356 356 if (ret) 357 357 return ret; 358 358 359 - if (uval > 1) 360 - return -EINVAL; 361 - 362 - late_bind->disable = !!uval; 359 + late_bind->disable = val; 363 360 return size; 364 361 } 365 362
+43 -33
drivers/gpu/drm/xe/xe_device.c
··· 8 8 #include <linux/aperture.h> 9 9 #include <linux/delay.h> 10 10 #include <linux/fault-inject.h> 11 + #include <linux/iopoll.h> 11 12 #include <linux/units.h> 12 13 13 14 #include <drm/drm_atomic_helper.h> ··· 631 630 return err; 632 631 } 633 632 634 - static bool verify_lmem_ready(struct xe_device *xe) 633 + static int lmem_initializing(struct xe_device *xe) 635 634 { 636 - u32 val = xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & LMEM_INIT; 635 + if (xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & LMEM_INIT) 636 + return 0; 637 637 638 - return !!val; 638 + if (signal_pending(current)) 639 + return -EINTR; 640 + 641 + return 1; 639 642 } 640 643 641 644 static int wait_for_lmem_ready(struct xe_device *xe) 642 645 { 643 - unsigned long timeout, start; 646 + const unsigned long TIMEOUT_SEC = 60; 647 + unsigned long prev_jiffies; 648 + int initializing; 644 649 645 650 if (!IS_DGFX(xe)) 646 651 return 0; ··· 654 647 if (IS_SRIOV_VF(xe)) 655 648 return 0; 656 649 657 - if (verify_lmem_ready(xe)) 650 + if (!lmem_initializing(xe)) 658 651 return 0; 659 652 660 653 drm_dbg(&xe->drm, "Waiting for lmem initialization\n"); 654 + prev_jiffies = jiffies; 661 655 662 - start = jiffies; 663 - timeout = start + secs_to_jiffies(60); /* 60 sec! */ 656 + /* 657 + * The boot firmware initializes local memory and 658 + * assesses its health. If memory training fails, 659 + * the punit will have been instructed to keep the GT powered 660 + * down.we won't be able to communicate with it 661 + * 662 + * If the status check is done before punit updates the register, 663 + * it can lead to the system being unusable. 664 + * use a timeout and defer the probe to prevent this. 665 + */ 666 + poll_timeout_us(initializing = lmem_initializing(xe), 667 + initializing <= 0, 668 + 20 * USEC_PER_MSEC, TIMEOUT_SEC * USEC_PER_SEC, true); 669 + if (initializing < 0) 670 + return initializing; 664 671 665 - do { 666 - if (signal_pending(current)) 667 - return -EINTR; 668 - 669 - /* 670 - * The boot firmware initializes local memory and 671 - * assesses its health. If memory training fails, 672 - * the punit will have been instructed to keep the GT powered 673 - * down.we won't be able to communicate with it 674 - * 675 - * If the status check is done before punit updates the register, 676 - * it can lead to the system being unusable. 677 - * use a timeout and defer the probe to prevent this. 678 - */ 679 - if (time_after(jiffies, timeout)) { 680 - drm_dbg(&xe->drm, "lmem not initialized by firmware\n"); 681 - return -EPROBE_DEFER; 682 - } 683 - 684 - msleep(20); 685 - 686 - } while (!verify_lmem_ready(xe)); 672 + if (initializing) { 673 + drm_dbg(&xe->drm, "lmem not initialized by firmware\n"); 674 + return -EPROBE_DEFER; 675 + } 687 676 688 677 drm_dbg(&xe->drm, "lmem ready after %ums", 689 - jiffies_to_msecs(jiffies - start)); 678 + jiffies_to_msecs(jiffies - prev_jiffies)); 690 679 691 680 return 0; 692 681 } ··· 782 779 return 0; 783 780 784 781 gt = xe_root_mmio_gt(xe); 782 + if (!gt) 783 + return 0; 785 784 786 785 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 787 786 if (!fw_ref) ··· 988 983 989 984 void xe_device_shutdown(struct xe_device *xe) 990 985 { 991 - struct xe_gt *gt; 992 - u8 id; 993 - 994 986 drm_dbg(&xe->drm, "Shutting down device\n"); 995 987 996 988 if (xe_driver_flr_disabled(xe)) { 989 + struct xe_gt *gt; 990 + u8 id; 991 + 997 992 xe_display_pm_shutdown(xe); 998 993 999 994 xe_irq_suspend(xe); ··· 1064 1059 unsigned int fw_ref; 1065 1060 1066 1061 gt = xe_root_mmio_gt(xe); 1062 + if (!gt) 1063 + return; 1067 1064 1068 1065 if (!XE_GT_WA(gt, 16023588340)) 1069 1066 return; ··· 1111 1104 return; 1112 1105 1113 1106 root_gt = xe_root_mmio_gt(xe); 1107 + if (!root_gt) 1108 + return; 1109 + 1114 1110 if (XE_GT_WA(root_gt, 16023588340)) { 1115 1111 /* A transient flush is not sufficient: flush the L2 */ 1116 1112 xe_device_l2_flush(xe);
+1 -9
drivers/gpu/drm/xe/xe_device_sysfs.c
··· 38 38 { 39 39 struct pci_dev *pdev = to_pci_dev(dev); 40 40 struct xe_device *xe = pdev_to_xe_device(pdev); 41 - int ret; 42 41 43 - xe_pm_runtime_get(xe); 44 - ret = sysfs_emit(buf, "%d\n", xe->d3cold.vram_threshold); 45 - xe_pm_runtime_put(xe); 46 - 47 - return ret; 42 + return sysfs_emit(buf, "%d\n", xe->d3cold.vram_threshold); 48 43 } 49 44 50 45 static ssize_t ··· 168 173 u32 cap = 0; 169 174 int ret; 170 175 171 - xe_pm_runtime_get(xe); 172 - 173 176 ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_CAPABILITY_STATUS, 0), 174 177 &cap, NULL); 175 - xe_pm_runtime_put(xe); 176 178 if (ret) 177 179 return 0; 178 180
+14 -1
drivers/gpu/drm/xe/xe_device_types.h
··· 27 27 #include "xe_sriov_vf_ccs_types.h" 28 28 #include "xe_step_types.h" 29 29 #include "xe_survivability_mode_types.h" 30 + #include "xe_tile_sriov_vf_types.h" 30 31 #include "xe_validation.h" 31 32 32 33 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) ··· 159 158 /** @mem: memory management info for tile */ 160 159 struct { 161 160 /** 162 - * @mem.vram: VRAM info for tile. 161 + * @mem.kernel_vram: kernel-dedicated VRAM info for tile. 162 + * 163 + * Although VRAM is associated with a specific tile, it can 164 + * still be accessed by all tiles' GTs. 165 + */ 166 + struct xe_vram_region *kernel_vram; 167 + 168 + /** 169 + * @mem.vram: general purpose VRAM info for tile. 163 170 * 164 171 * Although VRAM is associated with a specific tile, it can 165 172 * still be accessed by all tiles' GTs. ··· 194 185 struct { 195 186 /** @sriov.vf.ggtt_balloon: GGTT regions excluded from use. */ 196 187 struct xe_ggtt_node *ggtt_balloon[2]; 188 + /** @sriov.vf.self_config: VF configuration data */ 189 + struct xe_tile_sriov_vf_selfconfig self_config; 197 190 } vf; 198 191 } sriov; 199 192 ··· 329 318 u8 skip_mtcfg:1; 330 319 /** @info.skip_pcode: skip access to PCODE uC */ 331 320 u8 skip_pcode:1; 321 + /** @info.needs_shared_vf_gt_wq: needs shared GT WQ on VF */ 322 + u8 needs_shared_vf_gt_wq:1; 332 323 } info; 333 324 334 325 /** @wa_active: keep track of active workarounds */
+3
drivers/gpu/drm/xe/xe_device_wa_oob.rules
··· 1 + 22010954014 PLATFORM(DG2) 1 2 15015404425 PLATFORM(LUNARLAKE) 2 3 PLATFORM(PANTHERLAKE) 4 + 22019338487_display PLATFORM(LUNARLAKE) 5 + 14022085890 SUBPLATFORM(BATTLEMAGE, G21)
+26 -15
drivers/gpu/drm/xe/xe_dma_buf.c
··· 48 48 49 49 static int xe_dma_buf_pin(struct dma_buf_attachment *attach) 50 50 { 51 - struct drm_gem_object *obj = attach->dmabuf->priv; 51 + struct dma_buf *dmabuf = attach->dmabuf; 52 + struct drm_gem_object *obj = dmabuf->priv; 52 53 struct xe_bo *bo = gem_to_xe_bo(obj); 53 54 struct xe_device *xe = xe_bo_device(bo); 54 55 struct drm_exec *exec = XE_VALIDATION_UNSUPPORTED; 56 + bool allow_vram = true; 55 57 int ret; 56 58 57 - /* 58 - * For now only support pinning in TT memory, for two reasons: 59 - * 1) Avoid pinning in a placement not accessible to some importers. 60 - * 2) Pinning in VRAM requires PIN accounting which is a to-do. 61 - */ 62 - if (xe_bo_is_pinned(bo) && !xe_bo_is_mem_type(bo, XE_PL_TT)) { 59 + if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) { 60 + allow_vram = false; 61 + } else { 62 + list_for_each_entry(attach, &dmabuf->attachments, node) { 63 + if (!attach->peer2peer) { 64 + allow_vram = false; 65 + break; 66 + } 67 + } 68 + } 69 + 70 + if (xe_bo_is_pinned(bo) && !xe_bo_is_mem_type(bo, XE_PL_TT) && 71 + !(xe_bo_is_vram(bo) && allow_vram)) { 63 72 drm_dbg(&xe->drm, "Can't migrate pinned bo for dma-buf pin.\n"); 64 73 return -EINVAL; 65 74 } 66 75 67 - ret = xe_bo_migrate(bo, XE_PL_TT, NULL, exec); 68 - if (ret) { 69 - if (ret != -EINTR && ret != -ERESTARTSYS) 70 - drm_dbg(&xe->drm, 71 - "Failed migrating dma-buf to TT memory: %pe\n", 72 - ERR_PTR(ret)); 73 - return ret; 76 + if (!allow_vram) { 77 + ret = xe_bo_migrate(bo, XE_PL_TT, NULL, exec); 78 + if (ret) { 79 + if (ret != -EINTR && ret != -ERESTARTSYS) 80 + drm_dbg(&xe->drm, 81 + "Failed migrating dma-buf to TT memory: %pe\n", 82 + ERR_PTR(ret)); 83 + return ret; 84 + } 74 85 } 75 86 76 - ret = xe_bo_pin_external(bo, true, exec); 87 + ret = xe_bo_pin_external(bo, !allow_vram, exec); 77 88 xe_assert(xe, !ret); 78 89 79 90 return 0;
+26 -2
drivers/gpu/drm/xe/xe_eu_stall.c
··· 124 124 __u64 unused[6]; 125 125 } __packed; 126 126 127 + /* 128 + * EU stall data format for Xe3p arch GPUs. 129 + */ 130 + struct xe_eu_stall_data_xe3p { 131 + __u64 ip_addr:61; /* Bits 0 to 60 */ 132 + __u64 tdr_count:8; /* Bits 61 to 68 */ 133 + __u64 other_count:8; /* Bits 69 to 76 */ 134 + __u64 control_count:8; /* Bits 77 to 84 */ 135 + __u64 pipestall_count:8; /* Bits 85 to 92 */ 136 + __u64 send_count:8; /* Bits 93 to 100 */ 137 + __u64 dist_acc_count:8; /* Bits 101 to 108 */ 138 + __u64 sbid_count:8; /* Bits 109 to 116 */ 139 + __u64 sync_count:8; /* Bits 117 to 124 */ 140 + __u64 inst_fetch_count:8; /* Bits 125 to 132 */ 141 + __u64 active_count:8; /* Bits 133 to 140 */ 142 + __u64 ex_id:3; /* Bits 141 to 143 */ 143 + __u64 end_flag:1; /* Bit 144 */ 144 + __u64 unused_bits:47; 145 + __u64 unused[5]; 146 + } __packed; 147 + 127 148 const u64 eu_stall_sampling_rates[] = {251, 251 * 2, 251 * 3, 251 * 4, 251 * 5, 251 * 6, 251 * 7}; 128 149 129 150 /** ··· 188 167 { 189 168 size_t record_size = 0; 190 169 191 - if (xe->info.platform == XE_PVC) 192 - record_size = sizeof(struct xe_eu_stall_data_pvc); 170 + if (GRAPHICS_VER(xe) >= 35) 171 + record_size = sizeof(struct xe_eu_stall_data_xe3p); 193 172 else if (GRAPHICS_VER(xe) >= 20) 194 173 record_size = sizeof(struct xe_eu_stall_data_xe2); 174 + else if (xe->info.platform == XE_PVC) 175 + record_size = sizeof(struct xe_eu_stall_data_pvc); 176 + 195 177 196 178 xe_assert(xe, is_power_of_2(record_size)); 197 179
+4 -11
drivers/gpu/drm/xe/xe_exec.c
··· 16 16 #include "xe_exec_queue.h" 17 17 #include "xe_hw_engine_group.h" 18 18 #include "xe_macros.h" 19 + #include "xe_pm.h" 19 20 #include "xe_ring_ops_types.h" 20 21 #include "xe_sched_job.h" 21 22 #include "xe_sync.h" ··· 124 123 struct xe_validation_ctx ctx; 125 124 struct xe_sched_job *job; 126 125 struct xe_vm *vm; 127 - bool write_locked, skip_retry = false; 126 + bool write_locked; 128 127 int err = 0; 129 128 struct xe_hw_engine_group *group; 130 129 enum xe_hw_engine_group_execution_mode mode, previous_mode; ··· 248 247 * on task freezing during suspend / hibernate, the call will 249 248 * return -ERESTARTSYS and the IOCTL will be rerun. 250 249 */ 251 - err = wait_for_completion_interruptible(&xe->pm_block); 250 + err = xe_pm_block_on_suspend(xe); 252 251 if (err) 253 252 goto err_unlock_list; 254 253 ··· 263 262 if (xe_vm_is_closed_or_banned(q->vm)) { 264 263 drm_warn(&xe->drm, "Trying to schedule after vm is closed or banned\n"); 265 264 err = -ECANCELED; 266 - goto err_exec; 267 - } 268 - 269 - if (xe_exec_queue_is_lr(q) && xe_exec_queue_ring_full(q)) { 270 - err = -EWOULDBLOCK; /* Aliased to -EAGAIN */ 271 - skip_retry = true; 272 265 goto err_exec; 273 266 } 274 267 ··· 322 327 xe_sched_job_init_user_fence(job, &syncs[i]); 323 328 } 324 329 325 - if (xe_exec_queue_is_lr(q)) 326 - q->ring_ops->emit_job(job); 327 330 if (!xe_vm_in_lr_mode(vm)) 328 331 xe_exec_queue_last_fence_set(q, vm, &job->drm.s_fence->finished); 329 332 xe_sched_job_push(job); ··· 347 354 xe_validation_ctx_fini(&ctx); 348 355 err_unlock_list: 349 356 up_read(&vm->lock); 350 - if (err == -EAGAIN && !skip_retry) 357 + if (err == -EAGAIN) 351 358 goto retry; 352 359 err_hw_exec_mode: 353 360 if (mode == EXEC_MODE_DMA_FENCE)
+64 -56
drivers/gpu/drm/xe/xe_exec_queue.c
··· 15 15 #include "xe_dep_scheduler.h" 16 16 #include "xe_device.h" 17 17 #include "xe_gt.h" 18 + #include "xe_gt_sriov_vf.h" 18 19 #include "xe_hw_engine_class_sysfs.h" 19 20 #include "xe_hw_engine_group.h" 20 21 #include "xe_hw_fence.h" ··· 28 27 #include "xe_trace.h" 29 28 #include "xe_vm.h" 30 29 #include "xe_pxp.h" 30 + 31 + /** 32 + * DOC: Execution Queue 33 + * 34 + * An Execution queue is an interface for the HW context of execution. 35 + * The user creates an execution queue, submits the GPU jobs through those 36 + * queues and in the end destroys them. 37 + * 38 + * Execution queues can also be created by XeKMD itself for driver internal 39 + * operations like object migration etc. 40 + * 41 + * An execution queue is associated with a specified HW engine or a group of 42 + * engines (belonging to the same tile and engine class) and any GPU job 43 + * submitted on the queue will be run on one of these engines. 44 + * 45 + * An execution queue is tied to an address space (VM). It holds a reference 46 + * of the associated VM and the underlying Logical Ring Context/s (LRC/s) 47 + * until the queue is destroyed. 48 + * 49 + * The execution queue sits on top of the submission backend. It opaquely 50 + * handles the GuC and Execlist backends whichever the platform uses, and 51 + * the ring operations the different engine classes support. 52 + */ 31 53 32 54 enum xe_exec_queue_sched_prop { 33 55 XE_EXEC_QUEUE_JOB_TIMEOUT = 0, ··· 184 160 return q; 185 161 } 186 162 187 - static int __xe_exec_queue_init(struct xe_exec_queue *q) 163 + static int __xe_exec_queue_init(struct xe_exec_queue *q, u32 exec_queue_flags) 188 164 { 189 165 int i, err; 190 166 u32 flags = 0; ··· 203 179 flags |= XE_LRC_CREATE_RUNALONE; 204 180 } 205 181 206 - for (i = 0; i < q->width; ++i) { 207 - q->lrc[i] = xe_lrc_create(q->hwe, q->vm, SZ_16K, q->msix_vec, flags); 208 - if (IS_ERR(q->lrc[i])) { 209 - err = PTR_ERR(q->lrc[i]); 210 - goto err_lrc; 211 - } 212 - } 182 + if (!(exec_queue_flags & EXEC_QUEUE_FLAG_KERNEL)) 183 + flags |= XE_LRC_CREATE_USER_CTX; 213 184 214 185 err = q->ops->init(q); 215 186 if (err) 216 - goto err_lrc; 187 + return err; 188 + 189 + /* 190 + * This must occur after q->ops->init to avoid race conditions during VF 191 + * post-migration recovery, as the fixups for the LRC GGTT addresses 192 + * depend on the queue being present in the backend tracking structure. 193 + * 194 + * In addition to above, we must wait on inflight GGTT changes to avoid 195 + * writing out stale values here. Such wait provides a solid solution 196 + * (without a race) only if the function can detect migration instantly 197 + * from the moment vCPU resumes execution. 198 + */ 199 + for (i = 0; i < q->width; ++i) { 200 + struct xe_lrc *lrc; 201 + 202 + xe_gt_sriov_vf_wait_valid_ggtt(q->gt); 203 + lrc = xe_lrc_create(q->hwe, q->vm, xe_lrc_ring_size(), 204 + q->msix_vec, flags); 205 + if (IS_ERR(lrc)) { 206 + err = PTR_ERR(lrc); 207 + goto err_lrc; 208 + } 209 + 210 + /* Pairs with READ_ONCE to xe_exec_queue_contexts_hwsp_rebase */ 211 + WRITE_ONCE(q->lrc[i], lrc); 212 + } 217 213 218 214 return 0; 219 215 ··· 269 225 if (IS_ERR(q)) 270 226 return q; 271 227 272 - err = __xe_exec_queue_init(q); 228 + err = __xe_exec_queue_init(q, flags); 273 229 if (err) 274 230 goto err_post_alloc; 275 231 ··· 868 824 !(q->flags & EXEC_QUEUE_FLAG_VM); 869 825 } 870 826 871 - static s32 xe_exec_queue_num_job_inflight(struct xe_exec_queue *q) 872 - { 873 - return q->lrc[0]->fence_ctx.next_seqno - xe_lrc_seqno(q->lrc[0]) - 1; 874 - } 875 - 876 - /** 877 - * xe_exec_queue_ring_full() - Whether an exec_queue's ring is full 878 - * @q: The exec_queue 879 - * 880 - * Return: True if the exec_queue's ring is full, false otherwise. 881 - */ 882 - bool xe_exec_queue_ring_full(struct xe_exec_queue *q) 883 - { 884 - struct xe_lrc *lrc = q->lrc[0]; 885 - s32 max_job = lrc->ring.size / MAX_JOB_SIZE_BYTES; 886 - 887 - return xe_exec_queue_num_job_inflight(q) >= max_job; 888 - } 889 - 890 827 /** 891 828 * xe_exec_queue_is_idle() - Whether an exec_queue is idle. 892 829 * @q: The exec_queue ··· 1139 1114 int err = 0; 1140 1115 1141 1116 for (i = 0; i < q->width; ++i) { 1142 - xe_lrc_update_memirq_regs_with_address(q->lrc[i], q->hwe, scratch); 1143 - xe_lrc_update_hwctx_regs_with_address(q->lrc[i]); 1144 - err = xe_lrc_setup_wa_bb_with_scratch(q->lrc[i], q->hwe, scratch); 1117 + struct xe_lrc *lrc; 1118 + 1119 + /* Pairs with WRITE_ONCE in __xe_exec_queue_init */ 1120 + lrc = READ_ONCE(q->lrc[i]); 1121 + if (!lrc) 1122 + continue; 1123 + 1124 + xe_lrc_update_memirq_regs_with_address(lrc, q->hwe, scratch); 1125 + xe_lrc_update_hwctx_regs_with_address(lrc); 1126 + err = xe_lrc_setup_wa_bb_with_scratch(lrc, q->hwe, scratch); 1145 1127 if (err) 1146 1128 break; 1147 1129 } 1148 1130 1149 1131 return err; 1150 - } 1151 - 1152 - /** 1153 - * xe_exec_queue_jobs_ring_restore - Re-emit ring commands of requests pending on given queue. 1154 - * @q: the &xe_exec_queue struct instance 1155 - */ 1156 - void xe_exec_queue_jobs_ring_restore(struct xe_exec_queue *q) 1157 - { 1158 - struct xe_gpu_scheduler *sched = &q->guc->sched; 1159 - struct xe_sched_job *job; 1160 - 1161 - /* 1162 - * This routine is used within VF migration recovery. This means 1163 - * using the lock here introduces a restriction: we cannot wait 1164 - * for any GFX HW response while the lock is taken. 1165 - */ 1166 - spin_lock(&sched->base.job_list_lock); 1167 - list_for_each_entry(job, &sched->base.pending_list, drm.list) { 1168 - if (xe_sched_job_is_error(job)) 1169 - continue; 1170 - 1171 - q->ring_ops->emit_job(job); 1172 - } 1173 - spin_unlock(&sched->base.job_list_lock); 1174 1132 }
+1 -4
drivers/gpu/drm/xe/xe_exec_queue.h
··· 64 64 65 65 bool xe_exec_queue_is_lr(struct xe_exec_queue *q); 66 66 67 - bool xe_exec_queue_ring_full(struct xe_exec_queue *q); 68 - 69 67 bool xe_exec_queue_is_idle(struct xe_exec_queue *q); 70 68 71 69 void xe_exec_queue_kill(struct xe_exec_queue *q); ··· 90 92 91 93 int xe_exec_queue_contexts_hwsp_rebase(struct xe_exec_queue *q, void *scratch); 92 94 93 - void xe_exec_queue_jobs_ring_restore(struct xe_exec_queue *q); 94 - 95 95 struct xe_lrc *xe_exec_queue_lrc(struct xe_exec_queue *q); 96 + 96 97 #endif
+3
drivers/gpu/drm/xe/xe_exec_queue_types.h
··· 207 207 * call after suspend. In dma-fencing path thus must return within a 208 208 * reasonable amount of time. -ETIME return shall indicate an error 209 209 * waiting for suspend resulting in associated VM getting killed. 210 + * -EAGAIN return indicates the wait should be tried again, if the wait 211 + * is within a work item, the work item should be requeued as deadlock 212 + * avoidance mechanism. 210 213 */ 211 214 int (*suspend_wait)(struct xe_exec_queue *q); 212 215 /**
+1 -1
drivers/gpu/drm/xe/xe_execlist.c
··· 339 339 const struct drm_sched_init_args args = { 340 340 .ops = &drm_sched_ops, 341 341 .num_rqs = 1, 342 - .credit_limit = q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, 342 + .credit_limit = xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 343 343 .hang_limit = XE_SCHED_HANG_LIMIT, 344 344 .timeout = XE_SCHED_JOB_TIMEOUT, 345 345 .name = q->hwe->name,
+45 -25
drivers/gpu/drm/xe/xe_ggtt.c
··· 107 107 static void ggtt_update_access_counter(struct xe_ggtt *ggtt) 108 108 { 109 109 struct xe_tile *tile = ggtt->tile; 110 - struct xe_gt *affected_gt = XE_GT_WA(tile->primary_gt, 22019338487) ? 111 - tile->primary_gt : tile->media_gt; 112 - struct xe_mmio *mmio = &affected_gt->mmio; 113 - u32 max_gtt_writes = XE_GT_WA(ggtt->tile->primary_gt, 22019338487) ? 1100 : 63; 110 + struct xe_gt *affected_gt; 111 + u32 max_gtt_writes; 112 + 113 + if (tile->primary_gt && XE_GT_WA(tile->primary_gt, 22019338487)) { 114 + affected_gt = tile->primary_gt; 115 + max_gtt_writes = 1100; 116 + 117 + /* Only expected to apply to primary GT on dgpu platforms */ 118 + xe_tile_assert(tile, IS_DGFX(tile_to_xe(tile))); 119 + } else { 120 + affected_gt = tile->media_gt; 121 + max_gtt_writes = 63; 122 + 123 + /* Only expected to apply to media GT on igpu platforms */ 124 + xe_tile_assert(tile, !IS_DGFX(tile_to_xe(tile))); 125 + } 126 + 114 127 /* 115 128 * Wa_22019338487: GMD_ID is a RO register, a dummy write forces gunit 116 129 * to wait for completion of prior GTT writes before letting this through. ··· 132 119 lockdep_assert_held(&ggtt->lock); 133 120 134 121 if ((++ggtt->access_count % max_gtt_writes) == 0) { 135 - xe_mmio_write32(mmio, GMD_ID, 0x0); 122 + xe_mmio_write32(&affected_gt->mmio, GMD_ID, 0x0); 136 123 ggtt->access_count = 0; 137 124 } 138 125 } ··· 172 159 } 173 160 } 174 161 162 + static void primelockdep(struct xe_ggtt *ggtt) 163 + { 164 + if (!IS_ENABLED(CONFIG_LOCKDEP)) 165 + return; 166 + 167 + fs_reclaim_acquire(GFP_KERNEL); 168 + might_lock(&ggtt->lock); 169 + fs_reclaim_release(GFP_KERNEL); 170 + } 171 + 175 172 /** 176 173 * xe_ggtt_alloc - Allocate a GGTT for a given &xe_tile 177 174 * @tile: &xe_tile ··· 192 169 */ 193 170 struct xe_ggtt *xe_ggtt_alloc(struct xe_tile *tile) 194 171 { 195 - struct xe_ggtt *ggtt = drmm_kzalloc(&tile_to_xe(tile)->drm, sizeof(*ggtt), GFP_KERNEL); 196 - if (ggtt) 197 - ggtt->tile = tile; 172 + struct xe_device *xe = tile_to_xe(tile); 173 + struct xe_ggtt *ggtt; 174 + 175 + ggtt = drmm_kzalloc(&xe->drm, sizeof(*ggtt), GFP_KERNEL); 176 + if (!ggtt) 177 + return NULL; 178 + 179 + if (drmm_mutex_init(&xe->drm, &ggtt->lock)) 180 + return NULL; 181 + 182 + primelockdep(ggtt); 183 + ggtt->tile = tile; 184 + 198 185 return ggtt; 199 186 } 200 187 ··· 213 180 struct xe_ggtt *ggtt = arg; 214 181 215 182 destroy_workqueue(ggtt->wq); 216 - mutex_destroy(&ggtt->lock); 217 183 drm_mm_takedown(&ggtt->mm); 218 184 } 219 185 ··· 229 197 might_lock(&ggtt->lock); 230 198 } 231 199 #endif 232 - 233 - static void primelockdep(struct xe_ggtt *ggtt) 234 - { 235 - if (!IS_ENABLED(CONFIG_LOCKDEP)) 236 - return; 237 - 238 - fs_reclaim_acquire(GFP_KERNEL); 239 - might_lock(&ggtt->lock); 240 - fs_reclaim_release(GFP_KERNEL); 241 - } 242 200 243 201 static const struct xe_ggtt_pt_ops xelp_pt_ops = { 244 202 .pte_encode_flags = xelp_ggtt_pte_flags, ··· 249 227 { 250 228 drm_mm_init(&ggtt->mm, reserved, 251 229 ggtt->size - reserved); 252 - mutex_init(&ggtt->lock); 253 - primelockdep(ggtt); 254 230 } 255 231 256 232 int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 reserved, u32 size) ··· 304 284 ggtt->size = GUC_GGTT_TOP; 305 285 306 286 if (GRAPHICS_VERx100(xe) >= 1270) 307 - ggtt->pt_ops = (ggtt->tile->media_gt && 308 - XE_GT_WA(ggtt->tile->media_gt, 22019338487)) || 309 - XE_GT_WA(ggtt->tile->primary_gt, 22019338487) ? 310 - &xelpg_pt_wa_ops : &xelpg_pt_ops; 287 + ggtt->pt_ops = 288 + (ggtt->tile->media_gt && XE_GT_WA(ggtt->tile->media_gt, 22019338487)) || 289 + (ggtt->tile->primary_gt && XE_GT_WA(ggtt->tile->primary_gt, 22019338487)) ? 290 + &xelpg_pt_wa_ops : &xelpg_pt_ops; 311 291 else 312 292 ggtt->pt_ops = &xelp_pt_ops; 313 293
+14 -13
drivers/gpu/drm/xe/xe_gpu_scheduler.c
··· 101 101 cancel_work_sync(&sched->work_process_msg); 102 102 } 103 103 104 - /** 105 - * xe_sched_submission_stop_async - Stop further runs of submission tasks on a scheduler. 106 - * @sched: the &xe_gpu_scheduler struct instance 107 - * 108 - * This call disables further runs of scheduling work queue. It does not wait 109 - * for any in-progress runs to finish, only makes sure no further runs happen 110 - * afterwards. 111 - */ 112 - void xe_sched_submission_stop_async(struct xe_gpu_scheduler *sched) 113 - { 114 - drm_sched_wqueue_stop(&sched->base); 115 - } 116 - 117 104 void xe_sched_submission_resume_tdr(struct xe_gpu_scheduler *sched) 118 105 { 119 106 drm_sched_resume_timeout(&sched->base, sched->base.timeout); ··· 120 133 lockdep_assert_held(&sched->base.job_list_lock); 121 134 122 135 list_add_tail(&msg->link, &sched->msgs); 136 + xe_sched_process_msg_queue(sched); 137 + } 138 + 139 + /** 140 + * xe_sched_add_msg_head() - Xe GPU scheduler add message to head of list 141 + * @sched: Xe GPU scheduler 142 + * @msg: Message to add 143 + */ 144 + void xe_sched_add_msg_head(struct xe_gpu_scheduler *sched, 145 + struct xe_sched_msg *msg) 146 + { 147 + lockdep_assert_held(&sched->base.job_list_lock); 148 + 149 + list_add(&msg->link, &sched->msgs); 123 150 xe_sched_process_msg_queue(sched); 124 151 }
+22 -7
drivers/gpu/drm/xe/xe_gpu_scheduler.h
··· 7 7 #define _XE_GPU_SCHEDULER_H_ 8 8 9 9 #include "xe_gpu_scheduler_types.h" 10 - #include "xe_sched_job_types.h" 10 + #include "xe_sched_job.h" 11 11 12 12 int xe_sched_init(struct xe_gpu_scheduler *sched, 13 13 const struct drm_sched_backend_ops *ops, ··· 21 21 22 22 void xe_sched_submission_start(struct xe_gpu_scheduler *sched); 23 23 void xe_sched_submission_stop(struct xe_gpu_scheduler *sched); 24 - void xe_sched_submission_stop_async(struct xe_gpu_scheduler *sched); 25 24 26 25 void xe_sched_submission_resume_tdr(struct xe_gpu_scheduler *sched); 27 26 ··· 28 29 struct xe_sched_msg *msg); 29 30 void xe_sched_add_msg_locked(struct xe_gpu_scheduler *sched, 30 31 struct xe_sched_msg *msg); 32 + void xe_sched_add_msg_head(struct xe_gpu_scheduler *sched, 33 + struct xe_sched_msg *msg); 31 34 32 35 static inline void xe_sched_msg_lock(struct xe_gpu_scheduler *sched) 33 36 { ··· 59 58 struct drm_sched_fence *s_fence = s_job->s_fence; 60 59 struct dma_fence *hw_fence = s_fence->parent; 61 60 62 - if (hw_fence && !dma_fence_is_signaled(hw_fence)) 61 + if (to_xe_sched_job(s_job)->skip_emit || 62 + (hw_fence && !dma_fence_is_signaled(hw_fence))) 63 63 sched->base.ops->run_job(s_job); 64 64 } 65 65 } ··· 79 77 spin_unlock(&sched->base.job_list_lock); 80 78 } 81 79 80 + /** 81 + * xe_sched_first_pending_job() - Find first pending job which is unsignaled 82 + * @sched: Xe GPU scheduler 83 + * 84 + * Return first unsignaled job in pending list or NULL 85 + */ 82 86 static inline 83 87 struct xe_sched_job *xe_sched_first_pending_job(struct xe_gpu_scheduler *sched) 84 88 { 85 - struct xe_sched_job *job; 89 + struct xe_sched_job *job, *r_job = NULL; 86 90 87 91 spin_lock(&sched->base.job_list_lock); 88 - job = list_first_entry_or_null(&sched->base.pending_list, 89 - struct xe_sched_job, drm.list); 92 + list_for_each_entry(job, &sched->base.pending_list, drm.list) { 93 + struct drm_sched_fence *s_fence = job->drm.s_fence; 94 + struct dma_fence *hw_fence = s_fence->parent; 95 + 96 + if (hw_fence && !dma_fence_is_signaled(hw_fence)) { 97 + r_job = job; 98 + break; 99 + } 100 + } 90 101 spin_unlock(&sched->base.job_list_lock); 91 102 92 - return job; 103 + return r_job; 93 104 } 94 105 95 106 static inline int
+2 -2
drivers/gpu/drm/xe/xe_gsc.c
··· 266 266 unsigned int fw_ref; 267 267 int ret; 268 268 269 - if (XE_GT_WA(tile->primary_gt, 14018094691)) { 269 + if (tile->primary_gt && XE_GT_WA(tile->primary_gt, 14018094691)) { 270 270 fw_ref = xe_force_wake_get(gt_to_fw(tile->primary_gt), XE_FORCEWAKE_ALL); 271 271 272 272 /* ··· 281 281 282 282 ret = gsc_upload(gsc); 283 283 284 - if (XE_GT_WA(tile->primary_gt, 14018094691)) 284 + if (tile->primary_gt && XE_GT_WA(tile->primary_gt, 14018094691)) 285 285 xe_force_wake_put(gt_to_fw(tile->primary_gt), fw_ref); 286 286 287 287 if (ret)
+27 -26
drivers/gpu/drm/xe/xe_gt.c
··· 65 65 #include "xe_wa.h" 66 66 #include "xe_wopcm.h" 67 67 68 - static void gt_fini(struct drm_device *drm, void *arg) 69 - { 70 - struct xe_gt *gt = arg; 71 - 72 - destroy_workqueue(gt->ordered_wq); 73 - } 74 - 75 68 struct xe_gt *xe_gt_alloc(struct xe_tile *tile) 76 69 { 70 + struct xe_device *xe = tile_to_xe(tile); 71 + struct drm_device *drm = &xe->drm; 72 + bool shared_wq = xe->info.needs_shared_vf_gt_wq && tile->primary_gt && 73 + IS_SRIOV_VF(xe); 74 + struct workqueue_struct *ordered_wq; 77 75 struct xe_gt *gt; 78 - int err; 79 76 80 - gt = drmm_kzalloc(&tile_to_xe(tile)->drm, sizeof(*gt), GFP_KERNEL); 77 + gt = drmm_kzalloc(drm, sizeof(*gt), GFP_KERNEL); 81 78 if (!gt) 82 79 return ERR_PTR(-ENOMEM); 83 80 84 81 gt->tile = tile; 85 - gt->ordered_wq = alloc_ordered_workqueue("gt-ordered-wq", 86 - WQ_MEM_RECLAIM); 82 + if (shared_wq && tile->primary_gt->ordered_wq) 83 + ordered_wq = tile->primary_gt->ordered_wq; 84 + else 85 + ordered_wq = drmm_alloc_ordered_workqueue(drm, "gt-ordered-wq", 86 + WQ_MEM_RECLAIM); 87 + if (IS_ERR(ordered_wq)) 88 + return ERR_CAST(ordered_wq); 87 89 88 - err = drmm_add_action_or_reset(&gt_to_xe(gt)->drm, gt_fini, gt); 89 - if (err) 90 - return ERR_PTR(err); 90 + gt->ordered_wq = ordered_wq; 91 91 92 92 return gt; 93 93 } ··· 398 398 return err; 399 399 } 400 400 401 + if (IS_SRIOV_VF(gt_to_xe(gt))) { 402 + err = xe_gt_sriov_vf_init_early(gt); 403 + if (err) 404 + return err; 405 + } 406 + 401 407 xe_reg_sr_init(&gt->reg_sr, "GT", gt_to_xe(gt)); 402 408 403 409 err = xe_wa_gt_init(gt); ··· 589 583 if (IS_SRIOV_PF(gt_to_xe(gt)) && xe_gt_is_main_type(gt)) 590 584 xe_lmtt_init_hw(&gt_to_tile(gt)->sriov.pf.lmtt); 591 585 592 - if (IS_SRIOV_PF(gt_to_xe(gt))) { 593 - xe_gt_sriov_pf_init(gt); 586 + if (IS_SRIOV_PF(gt_to_xe(gt))) 594 587 xe_gt_sriov_pf_init_hw(gt); 595 - } 596 588 597 589 xe_force_wake_put(gt_to_fw(gt), fw_ref); 598 590 ··· 660 656 err = xe_eu_stall_init(gt); 661 657 if (err) 662 658 return err; 659 + 660 + if (IS_SRIOV_VF(gt_to_xe(gt))) { 661 + err = xe_gt_sriov_vf_init(gt); 662 + if (err) 663 + return err; 664 + } 663 665 664 666 return 0; 665 667 } ··· 813 803 return 0; 814 804 } 815 805 816 - static int gt_wait_reset_unblock(struct xe_gt *gt) 817 - { 818 - return xe_guc_wait_reset_unblock(&gt->uc.guc); 819 - } 820 - 821 806 static int gt_reset(struct xe_gt *gt) 822 807 { 823 808 unsigned int fw_ref; ··· 826 821 return -ENODEV; 827 822 828 823 xe_gt_info(gt, "reset started\n"); 829 - 830 - err = gt_wait_reset_unblock(gt); 831 - if (!err) 832 - xe_gt_warn(gt, "reset block failed to get lifted"); 833 824 834 825 xe_pm_runtime_get(gt_to_xe(gt)); 835 826
+19
drivers/gpu/drm/xe/xe_gt.h
··· 12 12 13 13 #include "xe_device.h" 14 14 #include "xe_device_types.h" 15 + #include "xe_gt_sriov_vf.h" 15 16 #include "xe_hw_engine.h" 16 17 17 18 #define for_each_hw_engine(hwe__, gt__, id__) \ ··· 21 20 xe_hw_engine_is_valid((hwe__))) 22 21 23 22 #define CCS_MASK(gt) (((gt)->info.engine_mask & XE_HW_ENGINE_CCS_MASK) >> XE_HW_ENGINE_CCS0) 23 + 24 + #define GT_VER(gt) ({ \ 25 + typeof(gt) gt_ = (gt); \ 26 + struct xe_device *xe = gt_to_xe(gt_); \ 27 + xe_gt_is_media_type(gt_) ? MEDIA_VER(xe) : GRAPHICS_VER(xe); \ 28 + }) 24 29 25 30 extern struct fault_attr gt_reset_failure; 26 31 static inline bool xe_fault_inject_gt_reset(void) ··· 129 122 130 123 return xe->info.has_usm && hwe->class == XE_ENGINE_CLASS_COPY && 131 124 hwe->instance == gt->usm.reserved_bcs_instance; 125 + } 126 + 127 + /** 128 + * xe_gt_recovery_pending() - GT recovery pending 129 + * @gt: the &xe_gt 130 + * 131 + * Return: True if GT recovery in pending, False otherwise 132 + */ 133 + static inline bool xe_gt_recovery_pending(struct xe_gt *gt) 134 + { 135 + return IS_SRIOV_VF(gt_to_xe(gt)) && 136 + xe_gt_sriov_vf_recovery_pending(gt); 132 137 } 133 138 134 139 #endif
-19
drivers/gpu/drm/xe/xe_gt_clock.c
··· 55 55 } 56 56 } 57 57 58 - static void check_ctc_mode(struct xe_gt *gt) 59 - { 60 - /* 61 - * CTC_MODE[0] = 1 is definitely not supported for Xe2 and later 62 - * platforms. In theory it could be a valid setting for pre-Xe2 63 - * platforms, but there's no documentation on how to properly handle 64 - * this case. Reading TIMESTAMP_OVERRIDE, as the driver attempted in 65 - * the past has been confirmed as incorrect by the hardware architects. 66 - * 67 - * For now just warn if we ever encounter hardware in the wild that 68 - * has this setting and move on as if it hadn't been set. 69 - */ 70 - if (xe_mmio_read32(&gt->mmio, CTC_MODE) & CTC_SOURCE_DIVIDE_LOGIC) 71 - xe_gt_warn(gt, "CTC_MODE[0] is set; this is unexpected and undocumented\n"); 72 - } 73 - 74 58 int xe_gt_clock_init(struct xe_gt *gt) 75 59 { 76 60 u32 freq; 77 61 u32 c0; 78 - 79 - if (!IS_SRIOV_VF(gt_to_xe(gt))) 80 - check_ctc_mode(gt); 81 62 82 63 c0 = xe_mmio_read32(&gt->mmio, RPM_CONFIG0); 83 64 read_crystal_clock(gt, c0, &freq, &gt->info.timestamp_base);
+45 -114
drivers/gpu/drm/xe/xe_gt_debugfs.c
··· 12 12 13 13 #include "xe_device.h" 14 14 #include "xe_force_wake.h" 15 - #include "xe_ggtt.h" 16 15 #include "xe_gt.h" 17 16 #include "xe_gt_mcr.h" 18 17 #include "xe_gt_idle.h" ··· 34 35 #include "xe_tuning.h" 35 36 #include "xe_uc_debugfs.h" 36 37 #include "xe_wa.h" 38 + 39 + static struct xe_gt *node_to_gt(struct drm_info_node *node) 40 + { 41 + return node->dent->d_parent->d_inode->i_private; 42 + } 37 43 38 44 /** 39 45 * xe_gt_debugfs_simple_show - A show callback for struct drm_info_list ··· 82 78 { 83 79 struct drm_printer p = drm_seq_file_printer(m); 84 80 struct drm_info_node *node = m->private; 85 - struct dentry *parent = node->dent->d_parent; 86 - struct xe_gt *gt = parent->d_inode->i_private; 81 + struct xe_gt *gt = node_to_gt(node); 87 82 int (*print)(struct xe_gt *, struct drm_printer *) = node->info_ent->data; 88 83 89 84 if (WARN_ON(!print)) ··· 91 88 return print(gt, &p); 92 89 } 93 90 91 + /** 92 + * xe_gt_debugfs_show_with_rpm - A show callback for struct drm_info_list 93 + * @m: the &seq_file 94 + * @data: data used by the drm debugfs helpers 95 + * 96 + * Similar to xe_gt_debugfs_simple_show() but implicitly takes a RPM ref. 97 + * 98 + * Return: 0 on success or a negative error code on failure. 99 + */ 100 + int xe_gt_debugfs_show_with_rpm(struct seq_file *m, void *data) 101 + { 102 + struct drm_info_node *node = m->private; 103 + struct xe_gt *gt = node_to_gt(node); 104 + struct xe_device *xe = gt_to_xe(gt); 105 + int ret; 106 + 107 + xe_pm_runtime_get(xe); 108 + ret = xe_gt_debugfs_simple_show(m, data); 109 + xe_pm_runtime_put(xe); 110 + 111 + return ret; 112 + } 113 + 94 114 static int hw_engines(struct xe_gt *gt, struct drm_printer *p) 95 115 { 96 - struct xe_device *xe = gt_to_xe(gt); 97 116 struct xe_hw_engine *hwe; 98 117 enum xe_hw_engine_id id; 99 118 unsigned int fw_ref; 100 119 int ret = 0; 101 120 102 - xe_pm_runtime_get(xe); 103 121 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 104 122 if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { 105 123 ret = -ETIMEDOUT; ··· 132 108 133 109 fw_put: 134 110 xe_force_wake_put(gt_to_fw(gt), fw_ref); 135 - xe_pm_runtime_put(xe); 136 111 137 112 return ret; 138 - } 139 - 140 - static int powergate_info(struct xe_gt *gt, struct drm_printer *p) 141 - { 142 - int ret; 143 - 144 - xe_pm_runtime_get(gt_to_xe(gt)); 145 - ret = xe_gt_idle_pg_print(gt, p); 146 - xe_pm_runtime_put(gt_to_xe(gt)); 147 - 148 - return ret; 149 - } 150 - 151 - static int topology(struct xe_gt *gt, struct drm_printer *p) 152 - { 153 - xe_pm_runtime_get(gt_to_xe(gt)); 154 - xe_gt_topology_dump(gt, p); 155 - xe_pm_runtime_put(gt_to_xe(gt)); 156 - 157 - return 0; 158 113 } 159 114 160 115 static int steering(struct xe_gt *gt, struct drm_printer *p) 161 116 { 162 - xe_pm_runtime_get(gt_to_xe(gt)); 163 117 xe_gt_mcr_steering_dump(gt, p); 164 - xe_pm_runtime_put(gt_to_xe(gt)); 165 - 166 118 return 0; 167 - } 168 - 169 - static int ggtt(struct xe_gt *gt, struct drm_printer *p) 170 - { 171 - int ret; 172 - 173 - xe_pm_runtime_get(gt_to_xe(gt)); 174 - ret = xe_ggtt_dump(gt_to_tile(gt)->mem.ggtt, p); 175 - xe_pm_runtime_put(gt_to_xe(gt)); 176 - 177 - return ret; 178 119 } 179 120 180 121 static int register_save_restore(struct xe_gt *gt, struct drm_printer *p) 181 122 { 182 123 struct xe_hw_engine *hwe; 183 124 enum xe_hw_engine_id id; 184 - 185 - xe_pm_runtime_get(gt_to_xe(gt)); 186 125 187 126 xe_reg_sr_dump(&gt->reg_sr, p); 188 127 drm_printf(p, "\n"); ··· 164 177 for_each_hw_engine(hwe, gt, id) 165 178 xe_reg_whitelist_dump(&hwe->reg_whitelist, p); 166 179 167 - xe_pm_runtime_put(gt_to_xe(gt)); 168 - 169 - return 0; 170 - } 171 - 172 - static int workarounds(struct xe_gt *gt, struct drm_printer *p) 173 - { 174 - xe_pm_runtime_get(gt_to_xe(gt)); 175 - xe_wa_dump(gt, p); 176 - xe_pm_runtime_put(gt_to_xe(gt)); 177 - 178 - return 0; 179 - } 180 - 181 - static int tunings(struct xe_gt *gt, struct drm_printer *p) 182 - { 183 - xe_pm_runtime_get(gt_to_xe(gt)); 184 - xe_tuning_dump(gt, p); 185 - xe_pm_runtime_put(gt_to_xe(gt)); 186 - 187 - return 0; 188 - } 189 - 190 - static int pat(struct xe_gt *gt, struct drm_printer *p) 191 - { 192 - xe_pm_runtime_get(gt_to_xe(gt)); 193 - xe_pat_dump(gt, p); 194 - xe_pm_runtime_put(gt_to_xe(gt)); 195 - 196 - return 0; 197 - } 198 - 199 - static int mocs(struct xe_gt *gt, struct drm_printer *p) 200 - { 201 - xe_pm_runtime_get(gt_to_xe(gt)); 202 - xe_mocs_dump(gt, p); 203 - xe_pm_runtime_put(gt_to_xe(gt)); 204 - 205 180 return 0; 206 181 } 207 182 208 183 static int rcs_default_lrc(struct xe_gt *gt, struct drm_printer *p) 209 184 { 210 - xe_pm_runtime_get(gt_to_xe(gt)); 211 185 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_RENDER); 212 - xe_pm_runtime_put(gt_to_xe(gt)); 213 - 214 186 return 0; 215 187 } 216 188 217 189 static int ccs_default_lrc(struct xe_gt *gt, struct drm_printer *p) 218 190 { 219 - xe_pm_runtime_get(gt_to_xe(gt)); 220 191 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_COMPUTE); 221 - xe_pm_runtime_put(gt_to_xe(gt)); 222 - 223 192 return 0; 224 193 } 225 194 226 195 static int bcs_default_lrc(struct xe_gt *gt, struct drm_printer *p) 227 196 { 228 - xe_pm_runtime_get(gt_to_xe(gt)); 229 197 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_COPY); 230 - xe_pm_runtime_put(gt_to_xe(gt)); 231 - 232 198 return 0; 233 199 } 234 200 235 201 static int vcs_default_lrc(struct xe_gt *gt, struct drm_printer *p) 236 202 { 237 - xe_pm_runtime_get(gt_to_xe(gt)); 238 203 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_VIDEO_DECODE); 239 - xe_pm_runtime_put(gt_to_xe(gt)); 240 - 241 204 return 0; 242 205 } 243 206 244 207 static int vecs_default_lrc(struct xe_gt *gt, struct drm_printer *p) 245 208 { 246 - xe_pm_runtime_get(gt_to_xe(gt)); 247 209 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_VIDEO_ENHANCE); 248 - xe_pm_runtime_put(gt_to_xe(gt)); 249 - 250 210 return 0; 251 211 } 252 212 253 213 static int hwconfig(struct xe_gt *gt, struct drm_printer *p) 254 214 { 255 - xe_pm_runtime_get(gt_to_xe(gt)); 256 215 xe_guc_hwconfig_dump(&gt->uc.guc, p); 257 - xe_pm_runtime_put(gt_to_xe(gt)); 258 - 259 216 return 0; 260 217 } 261 218 ··· 209 278 * - without access to the PF specific data 210 279 */ 211 280 static const struct drm_info_list vf_safe_debugfs_list[] = { 212 - {"topology", .show = xe_gt_debugfs_simple_show, .data = topology}, 213 - {"ggtt", .show = xe_gt_debugfs_simple_show, .data = ggtt}, 214 - {"register-save-restore", .show = xe_gt_debugfs_simple_show, .data = register_save_restore}, 215 - {"workarounds", .show = xe_gt_debugfs_simple_show, .data = workarounds}, 216 - {"tunings", .show = xe_gt_debugfs_simple_show, .data = tunings}, 217 - {"default_lrc_rcs", .show = xe_gt_debugfs_simple_show, .data = rcs_default_lrc}, 218 - {"default_lrc_ccs", .show = xe_gt_debugfs_simple_show, .data = ccs_default_lrc}, 219 - {"default_lrc_bcs", .show = xe_gt_debugfs_simple_show, .data = bcs_default_lrc}, 220 - {"default_lrc_vcs", .show = xe_gt_debugfs_simple_show, .data = vcs_default_lrc}, 221 - {"default_lrc_vecs", .show = xe_gt_debugfs_simple_show, .data = vecs_default_lrc}, 222 - {"hwconfig", .show = xe_gt_debugfs_simple_show, .data = hwconfig}, 281 + { "topology", .show = xe_gt_debugfs_show_with_rpm, .data = xe_gt_topology_dump }, 282 + { "register-save-restore", 283 + .show = xe_gt_debugfs_show_with_rpm, .data = register_save_restore }, 284 + { "workarounds", .show = xe_gt_debugfs_show_with_rpm, .data = xe_wa_gt_dump }, 285 + { "tunings", .show = xe_gt_debugfs_show_with_rpm, .data = xe_tuning_dump }, 286 + { "default_lrc_rcs", .show = xe_gt_debugfs_show_with_rpm, .data = rcs_default_lrc }, 287 + { "default_lrc_ccs", .show = xe_gt_debugfs_show_with_rpm, .data = ccs_default_lrc }, 288 + { "default_lrc_bcs", .show = xe_gt_debugfs_show_with_rpm, .data = bcs_default_lrc }, 289 + { "default_lrc_vcs", .show = xe_gt_debugfs_show_with_rpm, .data = vcs_default_lrc }, 290 + { "default_lrc_vecs", .show = xe_gt_debugfs_show_with_rpm, .data = vecs_default_lrc }, 291 + { "hwconfig", .show = xe_gt_debugfs_show_with_rpm, .data = hwconfig }, 223 292 }; 224 293 225 294 /* everything else should be added here */ 226 295 static const struct drm_info_list pf_only_debugfs_list[] = { 227 - {"hw_engines", .show = xe_gt_debugfs_simple_show, .data = hw_engines}, 228 - {"mocs", .show = xe_gt_debugfs_simple_show, .data = mocs}, 229 - {"pat", .show = xe_gt_debugfs_simple_show, .data = pat}, 230 - {"powergate_info", .show = xe_gt_debugfs_simple_show, .data = powergate_info}, 231 - {"steering", .show = xe_gt_debugfs_simple_show, .data = steering}, 296 + { "hw_engines", .show = xe_gt_debugfs_show_with_rpm, .data = hw_engines }, 297 + { "mocs", .show = xe_gt_debugfs_show_with_rpm, .data = xe_mocs_dump }, 298 + { "pat", .show = xe_gt_debugfs_show_with_rpm, .data = xe_pat_dump }, 299 + { "powergate_info", .show = xe_gt_debugfs_show_with_rpm, .data = xe_gt_idle_pg_print }, 300 + { "steering", .show = xe_gt_debugfs_show_with_rpm, .data = steering }, 232 301 }; 233 302 234 303 static ssize_t write_to_gt_call(const char __user *userbuf, size_t count, loff_t *ppos,
+1
drivers/gpu/drm/xe/xe_gt_debugfs.h
··· 11 11 12 12 void xe_gt_debugfs_register(struct xe_gt *gt); 13 13 int xe_gt_debugfs_simple_show(struct seq_file *m, void *data); 14 + int xe_gt_debugfs_show_with_rpm(struct seq_file *m, void *data); 14 15 15 16 #endif
+1 -6
drivers/gpu/drm/xe/xe_gt_freq.c
··· 99 99 { 100 100 struct device *dev = kobj_to_dev(kobj); 101 101 struct xe_guc_pc *pc = dev_to_pc(dev); 102 - u32 freq; 103 102 104 - xe_pm_runtime_get(dev_to_xe(dev)); 105 - freq = xe_guc_pc_get_rp0_freq(pc); 106 - xe_pm_runtime_put(dev_to_xe(dev)); 107 - 108 - return sysfs_emit(buf, "%d\n", freq); 103 + return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rp0_freq(pc)); 109 104 } 110 105 static struct kobj_attribute attr_rp0_freq = __ATTR_RO(rp0_freq); 111 106
+63 -4
drivers/gpu/drm/xe/xe_gt_mcr.c
··· 169 169 {}, 170 170 }; 171 171 172 + static const struct xe_mmio_range xe3p_xpc_xecore_steering_table[] = { 173 + { 0x008140, 0x00817F }, /* SLICE, XeCore, SLICE */ 174 + { 0x009480, 0x00955F }, /* SLICE, XeCore */ 175 + { 0x00D800, 0x00D87F }, /* SLICE */ 176 + { 0x00DC00, 0x00E9FF }, /* SLICE, rsvd, XeCore, rsvd, XeCore, rsvd, XeCore */ 177 + { 0x013000, 0x0135FF }, /* XeCore, SLICE */ 178 + {}, 179 + }; 180 + 172 181 static const struct xe_mmio_range xelpmp_oaddrm_steering_table[] = { 173 182 { 0x393200, 0x39323F }, 174 183 { 0x393400, 0x3934FF }, ··· 245 236 }; 246 237 247 238 static const struct xe_mmio_range xe3lpm_instance0_steering_table[] = { 248 - { 0x384000, 0x3847DF }, /* GAM, rsvd, GAM */ 239 + { 0x384000, 0x3841FF }, /* GAM */ 240 + { 0x384400, 0x3847DF }, /* GAM */ 249 241 { 0x384900, 0x384AFF }, /* GAM */ 250 242 { 0x389560, 0x3895FF }, /* MEDIAINF */ 251 243 { 0x38B600, 0x38B8FF }, /* L3BANK */ 252 244 { 0x38C800, 0x38D07F }, /* GAM, MEDIAINF */ 253 - { 0x38D0D0, 0x38F0FF }, /* MEDIAINF, GAM */ 245 + { 0x38D0D0, 0x38F0FF }, /* MEDIAINF, rsvd, GAM */ 254 246 { 0x393C00, 0x393C7F }, /* MEDIAINF */ 247 + {}, 248 + }; 249 + 250 + /* 251 + * Different "GAM" ranges have different rules; GAMWKRS, STLB, and GAMREQSTRM 252 + * range subtypes need to be steered to (1,0), while all other GAM subtypes 253 + * are steered to (0,0) and are included in the "INSTANCE0" table farther 254 + * down. 255 + */ 256 + static const struct xe_mmio_range xe3p_xpc_gam_grp1_steering_table[] = { 257 + { 0x004000, 0x004AFF }, /* GAMREQSTRM, rsvd, STLB, GAMWKRS, GAMREQSTRM */ 258 + { 0x00F100, 0x00FFFF }, /* GAMWKRS */ 259 + {}, 260 + }; 261 + 262 + static const struct xe_mmio_range xe3p_xpc_psmi_grp19_steering_table[] = { 263 + { 0x00B500, 0x00B5FF }, 264 + {}, 265 + }; 266 + 267 + static const struct xe_mmio_range xe3p_xpc_instance0_steering_table[] = { 268 + { 0x00B600, 0x00B6FF }, /* PSMI0 */ 269 + { 0x00C800, 0x00CFFF }, /* GAMCTRL */ 270 + { 0x00F000, 0x00F0FF }, /* GAMCTRL */ 255 271 {}, 256 272 }; 257 273 ··· 452 418 gt->steering[SQIDI_PSMI].instance_target = select & 0x1; 453 419 } 454 420 421 + static void init_steering_psmi(struct xe_gt *gt) 422 + { 423 + gt->steering[PSMI19].group_target = 19; 424 + gt->steering[PSMI19].instance_target = 0; 425 + } 426 + 427 + static void init_steering_gam1(struct xe_gt *gt) 428 + { 429 + gt->steering[GAM1].group_target = 1; 430 + gt->steering[GAM1].instance_target = 0; 431 + } 432 + 455 433 static const struct { 456 434 const char *name; 457 435 void (*init)(struct xe_gt *gt); ··· 471 425 [L3BANK] = { "L3BANK", init_steering_l3bank }, 472 426 [MSLICE] = { "MSLICE", init_steering_mslice }, 473 427 [LNCF] = { "LNCF", NULL }, /* initialized by mslice init */ 474 - [DSS] = { "DSS", init_steering_dss }, 428 + [DSS] = { "DSS / XeCore", init_steering_dss }, 475 429 [OADDRM] = { "OADDRM / GPMXMT", init_steering_oaddrm }, 476 430 [SQIDI_PSMI] = { "SQIDI_PSMI", init_steering_sqidi_psmi }, 431 + [PSMI19] = { "PSMI[19]", init_steering_psmi }, 432 + [GAM1] = { "GAMWKRS / STLB / GAMREQSTRM", init_steering_gam1 }, 477 433 [INSTANCE0] = { "INSTANCE 0", NULL }, 478 434 [IMPLICIT_STEERING] = { "IMPLICIT", NULL }, 479 435 }; ··· 514 466 gt->steering[OADDRM].ranges = xelpmp_oaddrm_steering_table; 515 467 } 516 468 } else { 517 - if (GRAPHICS_VER(xe) >= 20) { 469 + if (GRAPHICS_VERx100(xe) == 3511) { 470 + /* 471 + * TODO: there are some ranges in bspec with missing 472 + * termination: [0x00B000, 0x00B0FF] and 473 + * [0x00D880, 0x00D8FF] (NODE); [0x00B100, 0x00B3FF] 474 + * (L3BANK). Update them here once bspec is updated. 475 + */ 476 + gt->steering[DSS].ranges = xe3p_xpc_xecore_steering_table; 477 + gt->steering[GAM1].ranges = xe3p_xpc_gam_grp1_steering_table; 478 + gt->steering[INSTANCE0].ranges = xe3p_xpc_instance0_steering_table; 479 + gt->steering[PSMI19].ranges = xe3p_xpc_psmi_grp19_steering_table; 480 + } else if (GRAPHICS_VER(xe) >= 20) { 518 481 gt->steering[DSS].ranges = xe2lpg_dss_steering_table; 519 482 gt->steering[SQIDI_PSMI].ranges = xe2lpg_sqidi_psmi_steering_table; 520 483 gt->steering[INSTANCE0].ranges = xe2lpg_instance0_steering_table;
+4 -2
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
··· 1484 1484 XE_BO_FLAG_VRAM_IF_DGFX(tile) | 1485 1485 XE_BO_FLAG_NEEDS_2M | 1486 1486 XE_BO_FLAG_PINNED | 1487 - XE_BO_FLAG_PINNED_LATE_RESTORE); 1487 + XE_BO_FLAG_PINNED_LATE_RESTORE | 1488 + XE_BO_FLAG_FORCE_USER_VRAM); 1488 1489 if (IS_ERR(bo)) 1489 1490 return PTR_ERR(bo); 1490 1491 ··· 1548 1547 { 1549 1548 int err; 1550 1549 1551 - xe_gt_assert(gt, xe_device_has_lmtt(gt_to_xe(gt))); 1550 + if (!xe_device_has_lmtt(gt_to_xe(gt))) 1551 + return -EPERM; 1552 1552 1553 1553 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 1554 1554 if (vfid)
+89 -9
drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c
··· 18 18 #include "xe_gt_sriov_printk.h" 19 19 #include "xe_guc_ct.h" 20 20 #include "xe_sriov.h" 21 + #include "xe_sriov_pf_control.h" 21 22 #include "xe_sriov_pf_service.h" 22 23 #include "xe_tile.h" 23 24 ··· 171 170 CASE2STR(FLR_SEND_START); 172 171 CASE2STR(FLR_WAIT_GUC); 173 172 CASE2STR(FLR_GUC_DONE); 173 + CASE2STR(FLR_SYNC); 174 174 CASE2STR(FLR_RESET_CONFIG); 175 175 CASE2STR(FLR_RESET_DATA); 176 176 CASE2STR(FLR_RESET_MMIO); ··· 273 271 return result; 274 272 } 275 273 274 + static void pf_track_vf_state(struct xe_gt *gt, unsigned int vfid, 275 + enum xe_gt_sriov_control_bits bit, 276 + const char *what) 277 + { 278 + xe_gt_sriov_dbg_verbose(gt, "VF%u state %s(%d) %s\n", 279 + vfid, control_bit_to_string(bit), bit, what); 280 + } 281 + 276 282 static bool pf_enter_vf_state(struct xe_gt *gt, unsigned int vfid, 277 283 enum xe_gt_sriov_control_bits bit) 278 284 { 279 285 if (!test_and_set_bit(bit, pf_peek_vf_state(gt, vfid))) { 280 - xe_gt_sriov_dbg_verbose(gt, "VF%u state %s(%d) enter\n", 281 - vfid, control_bit_to_string(bit), bit); 286 + pf_track_vf_state(gt, vfid, bit, "enter"); 282 287 return true; 283 288 } 284 289 return false; ··· 295 286 enum xe_gt_sriov_control_bits bit) 296 287 { 297 288 if (test_and_clear_bit(bit, pf_peek_vf_state(gt, vfid))) { 298 - xe_gt_sriov_dbg_verbose(gt, "VF%u state %s(%d) exit\n", 299 - vfid, control_bit_to_string(bit), bit); 289 + pf_track_vf_state(gt, vfid, bit, "exit"); 300 290 return true; 301 291 } 302 292 return false; ··· 624 616 } 625 617 626 618 if (pf_expect_vf_state(gt, vfid, XE_GT_SRIOV_STATE_PAUSED)) { 627 - xe_gt_sriov_info(gt, "VF%u paused!\n", vfid); 619 + xe_gt_sriov_dbg(gt, "VF%u paused!\n", vfid); 628 620 return 0; 629 621 } 630 622 ··· 763 755 return err; 764 756 765 757 if (pf_expect_vf_state(gt, vfid, XE_GT_SRIOV_STATE_RESUMED)) { 766 - xe_gt_sriov_info(gt, "VF%u resumed!\n", vfid); 758 + xe_gt_sriov_dbg(gt, "VF%u resumed!\n", vfid); 767 759 return 0; 768 760 } 769 761 ··· 904 896 return err; 905 897 906 898 if (pf_expect_vf_state(gt, vfid, XE_GT_SRIOV_STATE_STOPPED)) { 907 - xe_gt_sriov_info(gt, "VF%u stopped!\n", vfid); 899 + xe_gt_sriov_dbg(gt, "VF%u stopped!\n", vfid); 908 900 return 0; 909 901 } 910 902 ··· 941 933 * : | : | | 942 934 * : v : | | 943 935 * : FLR_GUC_DONE : | | 936 + * : | : | | 937 + * : | o--<--sync : | | 938 + * : |/ / : | | 939 + * : FLR_SYNC--o : | | 944 940 * : | : | | 945 941 * : FLR_RESET_CONFIG---failed--->-----------o--------+-----------o 946 942 * : | : | | ··· 1153 1141 return true; 1154 1142 } 1155 1143 1144 + static bool pf_exit_vf_flr_sync(struct xe_gt *gt, unsigned int vfid) 1145 + { 1146 + if (!pf_exit_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SYNC)) 1147 + return false; 1148 + 1149 + pf_enter_vf_flr_reset_config(gt, vfid); 1150 + return true; 1151 + } 1152 + 1153 + static void pf_enter_vf_flr_sync(struct xe_gt *gt, unsigned int vfid) 1154 + { 1155 + int ret; 1156 + 1157 + if (!pf_enter_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SYNC)) 1158 + pf_enter_vf_state_machine_bug(gt, vfid); 1159 + 1160 + ret = xe_sriov_pf_control_sync_flr(gt_to_xe(gt), vfid); 1161 + if (ret < 0) { 1162 + xe_gt_sriov_dbg_verbose(gt, "FLR checkpoint %pe\n", ERR_PTR(ret)); 1163 + pf_expect_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SYNC); 1164 + } else { 1165 + xe_gt_sriov_dbg_verbose(gt, "FLR checkpoint pass\n"); 1166 + pf_expect_vf_not_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SYNC); 1167 + } 1168 + } 1169 + 1156 1170 static bool pf_exit_vf_flr_guc_done(struct xe_gt *gt, unsigned int vfid) 1157 1171 { 1158 1172 if (!pf_exit_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_GUC_DONE)) 1159 1173 return false; 1160 1174 1161 - pf_enter_vf_flr_reset_config(gt, vfid); 1175 + pf_enter_vf_flr_sync(gt, vfid); 1162 1176 return true; 1163 1177 } 1164 1178 ··· 1205 1167 */ 1206 1168 int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid) 1207 1169 { 1170 + pf_enter_vf_flr_wip(gt, vfid); 1171 + 1172 + return 0; 1173 + } 1174 + 1175 + /** 1176 + * xe_gt_sriov_pf_control_sync_flr() - Synchronize on the VF FLR checkpoint. 1177 + * @gt: the &xe_gt 1178 + * @vfid: the VF identifier 1179 + * @sync: if true it will allow to exit the checkpoint 1180 + * 1181 + * Return: non-zero if FLR checkpoint has been reached, zero if the is no FLR 1182 + * in progress, or a negative error code on the FLR busy or failed. 1183 + */ 1184 + int xe_gt_sriov_pf_control_sync_flr(struct xe_gt *gt, unsigned int vfid, bool sync) 1185 + { 1186 + if (sync && pf_exit_vf_flr_sync(gt, vfid)) 1187 + return 1; 1188 + if (pf_check_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_SYNC)) 1189 + return 1; 1190 + if (pf_check_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_WIP)) 1191 + return -EBUSY; 1192 + if (pf_check_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_FAILED)) 1193 + return -EIO; 1194 + return 0; 1195 + } 1196 + 1197 + /** 1198 + * xe_gt_sriov_pf_control_wait_flr() - Wait for a VF FLR to complete. 1199 + * @gt: the &xe_gt 1200 + * @vfid: the VF identifier 1201 + * 1202 + * This function is for PF only. 1203 + * 1204 + * Return: 0 on success or a negative error code on failure. 1205 + */ 1206 + int xe_gt_sriov_pf_control_wait_flr(struct xe_gt *gt, unsigned int vfid) 1207 + { 1208 1208 unsigned long timeout = pf_get_default_timeout(XE_GT_SRIOV_STATE_FLR_WIP); 1209 1209 int err; 1210 1210 1211 - pf_enter_vf_flr_wip(gt, vfid); 1211 + if (pf_check_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_FAILED)) 1212 + return -EIO; 1213 + 1214 + if (!pf_check_vf_state(gt, vfid, XE_GT_SRIOV_STATE_FLR_WIP)) 1215 + return 0; 1212 1216 1213 1217 err = pf_wait_vf_wip_done(gt, vfid, timeout); 1214 1218 if (err) {
+2
drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h
··· 18 18 int xe_gt_sriov_pf_control_resume_vf(struct xe_gt *gt, unsigned int vfid); 19 19 int xe_gt_sriov_pf_control_stop_vf(struct xe_gt *gt, unsigned int vfid); 20 20 int xe_gt_sriov_pf_control_trigger_flr(struct xe_gt *gt, unsigned int vfid); 21 + int xe_gt_sriov_pf_control_sync_flr(struct xe_gt *gt, unsigned int vfid, bool sync); 22 + int xe_gt_sriov_pf_control_wait_flr(struct xe_gt *gt, unsigned int vfid); 21 23 22 24 #ifdef CONFIG_PCI_IOV 23 25 int xe_gt_sriov_pf_control_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32 len);
+2
drivers/gpu/drm/xe/xe_gt_sriov_pf_control_types.h
··· 18 18 * @XE_GT_SRIOV_STATE_FLR_SEND_START: indicates that the PF wants to send a FLR START command. 19 19 * @XE_GT_SRIOV_STATE_FLR_WAIT_GUC: indicates that the PF awaits for a response from the GuC. 20 20 * @XE_GT_SRIOV_STATE_FLR_GUC_DONE: indicates that the PF has received a response from the GuC. 21 + * @XE_GT_SRIOV_STATE_FLR_SYNC: indicates that the PF awaits to synchronize with other GuCs. 21 22 * @XE_GT_SRIOV_STATE_FLR_RESET_CONFIG: indicates that the PF needs to clear VF's resources. 22 23 * @XE_GT_SRIOV_STATE_FLR_RESET_DATA: indicates that the PF needs to clear VF's data. 23 24 * @XE_GT_SRIOV_STATE_FLR_RESET_MMIO: indicates that the PF needs to reset VF's registers. ··· 48 47 XE_GT_SRIOV_STATE_FLR_SEND_START, 49 48 XE_GT_SRIOV_STATE_FLR_WAIT_GUC, 50 49 XE_GT_SRIOV_STATE_FLR_GUC_DONE, 50 + XE_GT_SRIOV_STATE_FLR_SYNC, 51 51 XE_GT_SRIOV_STATE_FLR_RESET_CONFIG, 52 52 XE_GT_SRIOV_STATE_FLR_RESET_DATA, 53 53 XE_GT_SRIOV_STATE_FLR_RESET_MMIO,
+258 -182
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c
··· 23 23 #include "xe_gt_sriov_pf_service.h" 24 24 #include "xe_pm.h" 25 25 #include "xe_sriov_pf.h" 26 + #include "xe_sriov_pf_provision.h" 26 27 27 28 /* 28 - * /sys/kernel/debug/dri/0/ 29 - * ├── gt0 # d_inode->i_private = gt 30 - * │   ├── pf # d_inode->i_private = gt 31 - * │   ├── vf1 # d_inode->i_private = VFID(1) 32 - * :   : 33 - * │   ├── vfN # d_inode->i_private = VFID(N) 29 + * /sys/kernel/debug/dri/BDF/ 30 + * ├── sriov # d_inode->i_private = (xe_device*) 31 + * │ ├── pf # d_inode->i_private = (xe_device*) 32 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 33 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 34 + * │ │ │ ├── gt1 # d_inode->i_private = (xe_gt*) 35 + * │ │ ├── tile1 36 + * │ │ │ : 37 + * │ ├── vf1 # d_inode->i_private = VFID(1) 38 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 39 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 40 + * │ │ │ ├── gt1 # d_inode->i_private = (xe_gt*) 41 + * │ │ ├── tile1 42 + * │ │ │ : 43 + * : : 44 + * │ ├── vfN # d_inode->i_private = VFID(N) 34 45 */ 35 46 36 47 static void *extract_priv(struct dentry *d) ··· 51 40 52 41 static struct xe_gt *extract_gt(struct dentry *d) 53 42 { 54 - return extract_priv(d->d_parent); 43 + return extract_priv(d); 44 + } 45 + 46 + static struct xe_device *extract_xe(struct dentry *d) 47 + { 48 + return extract_priv(d->d_parent->d_parent->d_parent); 55 49 } 56 50 57 51 static unsigned int extract_vfid(struct dentry *d) 58 52 { 59 - return extract_priv(d) == extract_gt(d) ? PFID : (uintptr_t)extract_priv(d); 53 + void *priv = extract_priv(d->d_parent->d_parent); 54 + 55 + return priv == extract_xe(d) ? PFID : (uintptr_t)priv; 60 56 } 61 57 62 58 /* 63 - * /sys/kernel/debug/dri/0/ 64 - * ├── gt0 65 - * │   ├── pf 66 - * │   │   ├── contexts_provisioned 67 - * │   │   ├── doorbells_provisioned 68 - * │   │   ├── runtime_registers 69 - * │   │   ├── negotiated_versions 70 - * │   │   ├── adverse_events 71 - * ├── gt1 72 - * │   ├── pf 73 - * │   │   ├── ... 59 + * /sys/kernel/debug/dri/BDF/ 60 + * ├── sriov 61 + * : ├── pf 62 + * : ├── tile0 63 + * : ├── gt0 64 + * : ├── contexts_provisioned 65 + * ├── doorbells_provisioned 66 + * ├── runtime_registers 67 + * ├── adverse_events 74 68 */ 75 69 76 70 static const struct drm_info_list pf_info[] = { ··· 102 86 }; 103 87 104 88 /* 105 - * /sys/kernel/debug/dri/0/ 106 - * ├── gt0 107 - * │   ├── pf 108 - * │   │   ├── ggtt_available 109 - * │   │   ├── ggtt_provisioned 110 - */ 111 - 112 - static const struct drm_info_list pf_ggtt_info[] = { 113 - { 114 - "ggtt_available", 115 - .show = xe_gt_debugfs_simple_show, 116 - .data = xe_gt_sriov_pf_config_print_available_ggtt, 117 - }, 118 - { 119 - "ggtt_provisioned", 120 - .show = xe_gt_debugfs_simple_show, 121 - .data = xe_gt_sriov_pf_config_print_ggtt, 122 - }, 123 - }; 124 - 125 - /* 126 - * /sys/kernel/debug/dri/0/ 127 - * ├── gt0 128 - * │   ├── pf 129 - * │   │   ├── lmem_provisioned 130 - */ 131 - 132 - static const struct drm_info_list pf_lmem_info[] = { 133 - { 134 - "lmem_provisioned", 135 - .show = xe_gt_debugfs_simple_show, 136 - .data = xe_gt_sriov_pf_config_print_lmem, 137 - }, 138 - }; 139 - 140 - /* 141 - * /sys/kernel/debug/dri/0/ 142 - * ├── gt0 143 - * │   ├── pf 144 - * │   │   ├── reset_engine 145 - * │   │   ├── sample_period 146 - * │   │   ├── sched_if_idle 89 + * /sys/kernel/debug/dri/BDF/ 90 + * ├── sriov 91 + * : ├── pf 92 + * : ├── tile0 93 + * : ├── gt0 94 + * : ├── reset_engine 95 + * ├── sample_period 96 + * ├── sched_if_idle 147 97 */ 148 98 149 99 #define DEFINE_SRIOV_GT_POLICY_DEBUGFS_ATTRIBUTE(POLICY, TYPE, FORMAT) \ ··· 125 143 \ 126 144 xe_pm_runtime_get(xe); \ 127 145 err = xe_gt_sriov_pf_policy_set_##POLICY(gt, val); \ 146 + if (!err) \ 147 + xe_sriov_pf_provision_set_custom_mode(xe); \ 128 148 xe_pm_runtime_put(xe); \ 129 149 \ 130 150 return err; \ ··· 157 173 } 158 174 159 175 /* 160 - * /sys/kernel/debug/dri/0/ 161 - * ├── gt0 162 - * │   ├── pf 163 - * │   │   ├── ggtt_spare 164 - * │   │   ├── lmem_spare 165 - * │   │   ├── doorbells_spare 166 - * │   │   ├── contexts_spare 167 - * │   │   ├── exec_quantum_ms 168 - * │   │   ├── preempt_timeout_us 169 - * │   │   ├── sched_priority 170 - * │   ├── vf1 171 - * │   │   ├── ggtt_quota 172 - * │   │   ├── lmem_quota 173 - * │   │   ├── doorbells_quota 174 - * │   │   ├── contexts_quota 175 - * │   │   ├── exec_quantum_ms 176 - * │   │   ├── preempt_timeout_us 177 - * │   │   ├── sched_priority 176 + * /sys/kernel/debug/dri/BDF/ 177 + * ├── sriov 178 + * : ├── pf 179 + * │ ├── tile0 180 + * │ : ├── gt0 181 + * │ : ├── doorbells_spare 182 + * │ ├── contexts_spare 183 + * │ ├── exec_quantum_ms 184 + * │ ├── preempt_timeout_us 185 + * │ ├── sched_priority 186 + * ├── vf1 187 + * : ├── tile0 188 + * : ├── gt0 189 + * : ├── doorbells_quota 190 + * ├── contexts_quota 191 + * ├── exec_quantum_ms 192 + * ├── preempt_timeout_us 193 + * ├── sched_priority 178 194 */ 179 195 180 196 #define DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(CONFIG, TYPE, FORMAT) \ ··· 192 208 xe_pm_runtime_get(xe); \ 193 209 err = xe_sriov_pf_wait_ready(xe) ?: \ 194 210 xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \ 211 + if (!err) \ 212 + xe_sriov_pf_provision_set_custom_mode(xe); \ 195 213 xe_pm_runtime_put(xe); \ 196 214 \ 197 215 return err; \ ··· 210 224 \ 211 225 DEFINE_DEBUGFS_ATTRIBUTE(CONFIG##_fops, CONFIG##_get, CONFIG##_set, FORMAT) 212 226 213 - DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, u64, "%llu\n"); 214 - DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(lmem, u64, "%llu\n"); 215 227 DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(ctxs, u32, "%llu\n"); 216 228 DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(dbs, u32, "%llu\n"); 217 229 DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(exec_quantum, u32, "%llu\n"); ··· 217 233 DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(sched_priority, u32, "%llu\n"); 218 234 219 235 /* 220 - * /sys/kernel/debug/dri/0/ 221 - * ├── gt0 222 - * │   ├── pf 223 - * │   │   ├── threshold_cat_error_count 224 - * │   │   ├── threshold_doorbell_time_us 225 - * │   │   ├── threshold_engine_reset_count 226 - * │   │   ├── threshold_guc_time_us 227 - * │   │   ├── threshold_irq_time_us 228 - * │   │   ├── threshold_page_fault_count 229 - * │   ├── vf1 230 - * │   │   ├── threshold_cat_error_count 231 - * │   │   ├── threshold_doorbell_time_us 232 - * │   │   ├── threshold_engine_reset_count 233 - * │   │   ├── threshold_guc_time_us 234 - * │   │   ├── threshold_irq_time_us 235 - * │   │   ├── threshold_page_fault_count 236 + * /sys/kernel/debug/dri/BDF/ 237 + * ├── sriov 238 + * : ├── pf 239 + * │ ├── tile0 240 + * │ : ├── gt0 241 + * │ : ├── threshold_cat_error_count 242 + * │ ├── threshold_doorbell_time_us 243 + * │ ├── threshold_engine_reset_count 244 + * │ ├── threshold_guc_time_us 245 + * │ ├── threshold_irq_time_us 246 + * │ ├── threshold_page_fault_count 247 + * ├── vf1 248 + * : ├── tile0 249 + * : ├── gt0 250 + * : ├── threshold_cat_error_count 251 + * ├── threshold_doorbell_time_us 252 + * ├── threshold_engine_reset_count 253 + * ├── threshold_guc_time_us 254 + * ├── threshold_irq_time_us 255 + * ├── threshold_page_fault_count 236 256 */ 237 257 238 258 static int set_threshold(void *data, u64 val, enum xe_guc_klv_threshold_index index) ··· 251 263 252 264 xe_pm_runtime_get(xe); 253 265 err = xe_gt_sriov_pf_config_set_threshold(gt, vfid, index, val); 266 + if (!err) 267 + xe_sriov_pf_provision_set_custom_mode(xe); 254 268 xe_pm_runtime_put(xe); 255 269 256 270 return err; ··· 292 302 xe_gt_assert(gt, gt == extract_gt(parent)); 293 303 xe_gt_assert(gt, vfid == extract_vfid(parent)); 294 304 295 - if (xe_gt_is_main_type(gt)) { 296 - debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare", 297 - 0644, parent, parent, &ggtt_fops); 298 - if (xe_device_has_lmtt(gt_to_xe(gt))) 299 - debugfs_create_file_unsafe(vfid ? "lmem_quota" : "lmem_spare", 300 - 0644, parent, parent, &lmem_fops); 301 - } 302 305 debugfs_create_file_unsafe(vfid ? "doorbells_quota" : "doorbells_spare", 303 306 0644, parent, parent, &dbs_fops); 304 307 debugfs_create_file_unsafe(vfid ? "contexts_quota" : "contexts_spare", ··· 312 329 } 313 330 314 331 /* 315 - * /sys/kernel/debug/dri/0/ 316 - * ├── gt0 317 - * │   ├── vf1 318 - * │   │   ├── control { stop, pause, resume } 332 + * /sys/kernel/debug/dri/BDF/ 333 + * ├── sriov 334 + * : ├── vf1 335 + * : ├── tile0 336 + * : ├── gt0 337 + * : ├── control { stop, pause, resume } 319 338 */ 320 339 321 340 static const struct { ··· 394 409 }; 395 410 396 411 /* 397 - * /sys/kernel/debug/dri/0/ 398 - * ├── gt0 399 - * │   ├── vf1 400 - * │   │   ├── guc_state 412 + * /sys/kernel/debug/dri/BDF/ 413 + * ├── sriov 414 + * : ├── vf1 415 + * : ├── tile0 416 + * : ├── gt0 417 + * : ├── guc_state 401 418 */ 419 + 402 420 static ssize_t guc_state_read(struct file *file, char __user *buf, 403 421 size_t count, loff_t *pos) 404 422 { ··· 435 447 }; 436 448 437 449 /* 438 - * /sys/kernel/debug/dri/0/ 439 - * ├── gt0 440 - * │   ├── vf1 441 - * │   │   ├── config_blob 450 + * /sys/kernel/debug/dri/BDF/ 451 + * ├── sriov 452 + * : ├── vf1 453 + * : ├── tile0 454 + * : ├── gt0 455 + * : ├── config_blob 442 456 */ 443 - static ssize_t config_blob_read(struct file *file, char __user *buf, 444 - size_t count, loff_t *pos) 457 + 458 + struct config_blob_data { 459 + size_t size; 460 + u8 blob[]; 461 + }; 462 + 463 + static int config_blob_open(struct inode *inode, struct file *file) 445 464 { 446 465 struct dentry *dent = file_dentry(file); 447 466 struct dentry *parent = dent->d_parent; 448 467 struct xe_gt *gt = extract_gt(parent); 449 468 unsigned int vfid = extract_vfid(parent); 469 + struct config_blob_data *cbd; 450 470 ssize_t ret; 451 - void *tmp; 452 471 453 472 ret = xe_gt_sriov_pf_config_save(gt, vfid, NULL, 0); 454 473 if (!ret) ··· 463 468 if (ret < 0) 464 469 return ret; 465 470 466 - tmp = kzalloc(ret, GFP_KERNEL); 467 - if (!tmp) 471 + cbd = kzalloc(struct_size(cbd, blob, ret), GFP_KERNEL); 472 + if (!cbd) 468 473 return -ENOMEM; 469 474 470 - ret = xe_gt_sriov_pf_config_save(gt, vfid, tmp, ret); 471 - if (ret > 0) 472 - ret = simple_read_from_buffer(buf, count, pos, tmp, ret); 475 + ret = xe_gt_sriov_pf_config_save(gt, vfid, cbd->blob, ret); 476 + if (ret < 0) { 477 + kfree(cbd); 478 + return ret; 479 + } 473 480 474 - kfree(tmp); 475 - return ret; 481 + cbd->size = ret; 482 + file->private_data = cbd; 483 + return nonseekable_open(inode, file); 484 + } 485 + 486 + static ssize_t config_blob_read(struct file *file, char __user *buf, 487 + size_t count, loff_t *pos) 488 + { 489 + struct config_blob_data *cbd = file->private_data; 490 + 491 + return simple_read_from_buffer(buf, count, pos, cbd->blob, cbd->size); 476 492 } 477 493 478 494 static ssize_t config_blob_write(struct file *file, const char __user *buf, ··· 520 514 return ret; 521 515 } 522 516 517 + static int config_blob_release(struct inode *inode, struct file *file) 518 + { 519 + kfree(file->private_data); 520 + return 0; 521 + } 522 + 523 523 static const struct file_operations config_blob_ops = { 524 524 .owner = THIS_MODULE, 525 + .open = config_blob_open, 525 526 .read = config_blob_read, 526 527 .write = config_blob_write, 527 - .llseek = default_llseek, 528 + .release = config_blob_release, 528 529 }; 529 530 530 - /** 531 - * xe_gt_sriov_pf_debugfs_register - Register SR-IOV PF specific entries in GT debugfs. 532 - * @gt: the &xe_gt to register 533 - * @root: the &dentry that represents the GT directory 534 - * 535 - * Register SR-IOV PF entries that are GT related and must be shown under GT debugfs. 536 - */ 537 - void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) 531 + static void pf_add_compat_attrs(struct xe_gt *gt, struct dentry *dent, unsigned int vfid) 532 + { 533 + struct xe_device *xe = gt_to_xe(gt); 534 + 535 + if (!xe_gt_is_main_type(gt)) 536 + return; 537 + 538 + if (vfid) { 539 + debugfs_create_symlink("ggtt_quota", dent, "../ggtt_quota"); 540 + if (xe_device_has_lmtt(xe)) 541 + debugfs_create_symlink("lmem_quota", dent, "../vram_quota"); 542 + } else { 543 + debugfs_create_symlink("ggtt_spare", dent, "../ggtt_spare"); 544 + debugfs_create_symlink("ggtt_available", dent, "../ggtt_available"); 545 + debugfs_create_symlink("ggtt_provisioned", dent, "../ggtt_provisioned"); 546 + if (xe_device_has_lmtt(xe)) { 547 + debugfs_create_symlink("lmem_spare", dent, "../vram_spare"); 548 + debugfs_create_symlink("lmem_provisioned", dent, "../vram_provisioned"); 549 + } 550 + } 551 + } 552 + 553 + static void pf_populate_gt(struct xe_gt *gt, struct dentry *dent, unsigned int vfid) 538 554 { 539 555 struct xe_device *xe = gt_to_xe(gt); 540 556 struct drm_minor *minor = xe->drm.primary; 541 - int n, totalvfs = xe_sriov_pf_get_totalvfs(xe); 542 - struct dentry *pfdentry; 543 - struct dentry *vfdentry; 544 - char buf[14]; /* should be enough up to "vf%u\0" for 2^32 - 1 */ 545 557 546 - xe_gt_assert(gt, IS_SRIOV_PF(xe)); 547 - xe_gt_assert(gt, root->d_inode->i_private == gt); 558 + if (vfid) { 559 + pf_add_config_attrs(gt, dent, vfid); 548 560 549 - /* 550 - * /sys/kernel/debug/dri/0/ 551 - * ├── gt0 552 - * │   ├── pf 553 - */ 554 - pfdentry = debugfs_create_dir("pf", root); 555 - if (IS_ERR(pfdentry)) 556 - return; 557 - pfdentry->d_inode->i_private = gt; 558 - 559 - drm_debugfs_create_files(pf_info, ARRAY_SIZE(pf_info), pfdentry, minor); 560 - if (xe_gt_is_main_type(gt)) { 561 - drm_debugfs_create_files(pf_ggtt_info, 562 - ARRAY_SIZE(pf_ggtt_info), 563 - pfdentry, minor); 564 - if (xe_device_has_lmtt(gt_to_xe(gt))) 565 - drm_debugfs_create_files(pf_lmem_info, 566 - ARRAY_SIZE(pf_lmem_info), 567 - pfdentry, minor); 568 - } 569 - 570 - pf_add_policy_attrs(gt, pfdentry); 571 - pf_add_config_attrs(gt, pfdentry, PFID); 572 - 573 - for (n = 1; n <= totalvfs; n++) { 574 - /* 575 - * /sys/kernel/debug/dri/0/ 576 - * ├── gt0 577 - * │   ├── vf1 578 - * │   ├── vf2 579 - */ 580 - snprintf(buf, sizeof(buf), "vf%u", n); 581 - vfdentry = debugfs_create_dir(buf, root); 582 - if (IS_ERR(vfdentry)) 583 - break; 584 - vfdentry->d_inode->i_private = (void *)(uintptr_t)n; 585 - 586 - pf_add_config_attrs(gt, vfdentry, VFID(n)); 587 - debugfs_create_file("control", 0600, vfdentry, NULL, &control_ops); 561 + debugfs_create_file("control", 0600, dent, NULL, &control_ops); 588 562 589 563 /* for testing/debugging purposes only! */ 590 564 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) { 591 565 debugfs_create_file("guc_state", 592 566 IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ? 0600 : 0400, 593 - vfdentry, NULL, &guc_state_ops); 567 + dent, NULL, &guc_state_ops); 594 568 debugfs_create_file("config_blob", 595 569 IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ? 0600 : 0400, 596 - vfdentry, NULL, &config_blob_ops); 570 + dent, NULL, &config_blob_ops); 597 571 } 572 + 573 + } else { 574 + pf_add_config_attrs(gt, dent, PFID); 575 + pf_add_policy_attrs(gt, dent); 576 + 577 + drm_debugfs_create_files(pf_info, ARRAY_SIZE(pf_info), dent, minor); 598 578 } 579 + 580 + /* for backward compatibility only */ 581 + pf_add_compat_attrs(gt, dent, vfid); 582 + } 583 + 584 + /** 585 + * xe_gt_sriov_pf_debugfs_populate() - Create SR-IOV GT-level debugfs directories and files. 586 + * @gt: the &xe_gt to register 587 + * @parent: the parent &dentry that represents a &xe_tile 588 + * @vfid: the VF identifier 589 + * 590 + * Add to the @parent directory new debugfs directory that will represent a @gt and 591 + * populate it with GT files that are related to the SR-IOV @vfid function. 592 + * 593 + * This function can only be called on PF. 594 + */ 595 + void xe_gt_sriov_pf_debugfs_populate(struct xe_gt *gt, struct dentry *parent, unsigned int vfid) 596 + { 597 + struct dentry *dent; 598 + char name[8]; /* should be enough up to "gt%u\0" for 2^8 - 1 */ 599 + 600 + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 601 + xe_gt_assert(gt, extract_priv(parent) == gt->tile); 602 + xe_gt_assert(gt, extract_priv(parent->d_parent) == gt_to_xe(gt) || 603 + (uintptr_t)extract_priv(parent->d_parent) == vfid); 604 + 605 + /* 606 + * /sys/kernel/debug/dri/BDF/ 607 + * ├── sriov 608 + * │ ├── pf 609 + * │ │ ├── tile0 # parent 610 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 611 + * │ │ │ ├── gt1 612 + * │ │ : : 613 + * │ ├── vf1 614 + * │ │ ├── tile0 # parent 615 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 616 + * │ │ │ ├── gt1 617 + * │ : : : 618 + */ 619 + snprintf(name, sizeof(name), "gt%u", gt->info.id); 620 + dent = debugfs_create_dir(name, parent); 621 + if (IS_ERR(dent)) 622 + return; 623 + dent->d_inode->i_private = gt; 624 + 625 + xe_gt_assert(gt, extract_gt(dent) == gt); 626 + xe_gt_assert(gt, extract_vfid(dent) == vfid); 627 + 628 + pf_populate_gt(gt, dent, vfid); 629 + } 630 + 631 + static void pf_add_links(struct xe_gt *gt, struct dentry *dent) 632 + { 633 + unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); 634 + unsigned int vfid; 635 + char name[16]; /* should be more than enough for "vf%u\0" and VFID(UINT_MAX) */ 636 + char symlink[64]; /* should be more enough for "../../sriov/vf%u/tile%u/gt%u\0" */ 637 + 638 + for (vfid = 0; vfid <= totalvfs; vfid++) { 639 + if (vfid) 640 + snprintf(name, sizeof(name), "vf%u", vfid); 641 + else 642 + snprintf(name, sizeof(name), "pf"); 643 + snprintf(symlink, sizeof(symlink), "../../sriov/%s/tile%u/gt%u", 644 + name, gt->tile->id, gt->info.id); 645 + debugfs_create_symlink(name, dent, symlink); 646 + } 647 + } 648 + 649 + /** 650 + * xe_gt_sriov_pf_debugfs_register - Register SR-IOV PF specific entries in GT debugfs. 651 + * @gt: the &xe_gt to register 652 + * @dent: the &dentry that represents the GT directory 653 + * 654 + * Instead of actual files, create symlinks for PF and each VF to their GT specific 655 + * attributes that should be already exposed in the dedicated debugfs SR-IOV tree. 656 + */ 657 + void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *dent) 658 + { 659 + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 660 + xe_gt_assert(gt, dent->d_inode->i_private == gt); 661 + 662 + pf_add_links(gt, dent); 599 663 }
+1
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.h
··· 11 11 12 12 #ifdef CONFIG_PCI_IOV 13 13 void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root); 14 + void xe_gt_sriov_pf_debugfs_populate(struct xe_gt *gt, struct dentry *parent, unsigned int vfid); 14 15 #else 15 16 static inline void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) { } 16 17 #endif
+5 -2
drivers/gpu/drm/xe/xe_gt_sriov_printk.h
··· 7 7 #define _XE_GT_SRIOV_PRINTK_H_ 8 8 9 9 #include "xe_gt_printk.h" 10 - #include "xe_sriov_printk.h" 10 + #include "xe_tile_sriov_printk.h" 11 + 12 + #define __XE_GT_SRIOV_PRINTK_FMT(_gt, _fmt, ...) \ 13 + __XE_TILE_SRIOV_PRINTK_FMT((_gt)->tile, __XE_GT_PRINTK_FMT((_gt), _fmt, ##__VA_ARGS__)) 11 14 12 15 #define __xe_gt_sriov_printk(gt, _level, fmt, ...) \ 13 - xe_gt_printk((gt), _level, "%s" fmt, xe_sriov_printk_prefix(gt_to_xe(gt)), ##__VA_ARGS__) 16 + xe_sriov_##_level(gt_to_xe(gt), __XE_GT_SRIOV_PRINTK_FMT((gt), fmt, ##__VA_ARGS__)) 14 17 15 18 #define xe_gt_sriov_err(_gt, _fmt, ...) \ 16 19 __xe_gt_sriov_printk(_gt, err, _fmt, ##__VA_ARGS__)
+366 -104
drivers/gpu/drm/xe/xe_gt_sriov_vf.c
··· 23 23 #include "xe_gt_sriov_vf.h" 24 24 #include "xe_gt_sriov_vf_types.h" 25 25 #include "xe_guc.h" 26 + #include "xe_guc_ct.h" 26 27 #include "xe_guc_hxg_helpers.h" 27 28 #include "xe_guc_relay.h" 29 + #include "xe_guc_submit.h" 30 + #include "xe_irq.h" 28 31 #include "xe_lrc.h" 32 + #include "xe_memirq.h" 29 33 #include "xe_mmio.h" 34 + #include "xe_pm.h" 30 35 #include "xe_sriov.h" 31 36 #include "xe_sriov_vf.h" 37 + #include "xe_sriov_vf_ccs.h" 38 + #include "xe_tile_sriov_vf.h" 39 + #include "xe_tlb_inval.h" 32 40 #include "xe_uc_fw.h" 33 41 #include "xe_wopcm.h" 34 42 ··· 315 307 } 316 308 317 309 /** 318 - * xe_gt_sriov_vf_notify_resfix_done - Notify GuC about resource fixups apply completed. 310 + * vf_notify_resfix_done - Notify GuC about resource fixups apply completed. 319 311 * @gt: the &xe_gt struct instance linked to target GuC 320 312 * 321 313 * Returns: 0 if the operation completed successfully, or a negative error 322 314 * code otherwise. 323 315 */ 324 - int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt) 316 + static int vf_notify_resfix_done(struct xe_gt *gt) 325 317 { 326 318 struct xe_guc *guc = &gt->uc.guc; 327 319 int err; ··· 441 433 442 434 static int vf_get_ggtt_info(struct xe_gt *gt) 443 435 { 444 - struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config; 436 + struct xe_tile *tile = gt_to_tile(gt); 437 + struct xe_ggtt *ggtt = tile->mem.ggtt; 445 438 struct xe_guc *guc = &gt->uc.guc; 446 - u64 start, size; 439 + u64 start, size, ggtt_size; 440 + s64 shift; 447 441 int err; 448 442 449 443 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 444 + 445 + guard(mutex)(&ggtt->lock); 450 446 451 447 err = guc_action_query_single_klv64(guc, GUC_KLV_VF_CFG_GGTT_START_KEY, &start); 452 448 if (unlikely(err)) ··· 460 448 if (unlikely(err)) 461 449 return err; 462 450 463 - if (config->ggtt_size && config->ggtt_size != size) { 451 + if (!size) 452 + return -ENODATA; 453 + 454 + ggtt_size = xe_tile_sriov_vf_ggtt(tile); 455 + if (ggtt_size && ggtt_size != size) { 464 456 xe_gt_sriov_err(gt, "Unexpected GGTT reassignment: %lluK != %lluK\n", 465 - size / SZ_1K, config->ggtt_size / SZ_1K); 457 + size / SZ_1K, ggtt_size / SZ_1K); 466 458 return -EREMCHG; 467 459 } 468 460 469 461 xe_gt_sriov_dbg_verbose(gt, "GGTT %#llx-%#llx = %lluK\n", 470 462 start, start + size - 1, size / SZ_1K); 471 463 472 - config->ggtt_shift = start - (s64)config->ggtt_base; 473 - config->ggtt_base = start; 474 - config->ggtt_size = size; 464 + shift = start - (s64)xe_tile_sriov_vf_ggtt_base(tile); 465 + xe_tile_sriov_vf_ggtt_base_store(tile, start); 466 + xe_tile_sriov_vf_ggtt_store(tile, size); 475 467 476 - return config->ggtt_size ? 0 : -ENODATA; 468 + if (shift && shift != start) { 469 + xe_gt_sriov_info(gt, "Shifting GGTT base by %lld to 0x%016llx\n", 470 + shift, start); 471 + xe_tile_sriov_vf_fixup_ggtt_nodes_locked(gt_to_tile(gt), shift); 472 + } 473 + 474 + if (xe_sriov_vf_migration_supported(gt_to_xe(gt))) { 475 + WRITE_ONCE(gt->sriov.vf.migration.ggtt_need_fixes, false); 476 + smp_wmb(); /* Ensure above write visible before wake */ 477 + wake_up_all(&gt->sriov.vf.migration.wq); 478 + } 479 + 480 + return 0; 477 481 } 478 482 479 483 static int vf_get_lmem_info(struct xe_gt *gt) 480 484 { 481 - struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config; 485 + struct xe_tile *tile = gt_to_tile(gt); 482 486 struct xe_guc *guc = &gt->uc.guc; 483 487 char size_str[10]; 484 - u64 size; 488 + u64 size, lmem_size; 485 489 int err; 486 490 487 491 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); ··· 506 478 if (unlikely(err)) 507 479 return err; 508 480 509 - if (config->lmem_size && config->lmem_size != size) { 481 + lmem_size = xe_tile_sriov_vf_lmem(tile); 482 + if (lmem_size && lmem_size != size) { 510 483 xe_gt_sriov_err(gt, "Unexpected LMEM reassignment: %lluM != %lluM\n", 511 - size / SZ_1M, config->lmem_size / SZ_1M); 484 + size / SZ_1M, lmem_size / SZ_1M); 512 485 return -EREMCHG; 513 486 } 514 487 515 488 string_get_size(size, 1, STRING_UNITS_2, size_str, sizeof(size_str)); 516 489 xe_gt_sriov_dbg_verbose(gt, "LMEM %lluM %s\n", size / SZ_1M, size_str); 517 490 518 - config->lmem_size = size; 491 + xe_tile_sriov_vf_lmem_store(tile, size); 519 492 520 - return config->lmem_size ? 0 : -ENODATA; 493 + return size ? 0 : -ENODATA; 521 494 } 522 495 523 496 static int vf_get_submission_cfg(struct xe_gt *gt) ··· 569 540 * xe_gt_sriov_vf_query_config - Query SR-IOV config data over MMIO. 570 541 * @gt: the &xe_gt 571 542 * 572 - * This function is for VF use only. 543 + * This function is for VF use only. This function may shift the GGTT and is 544 + * performed under GGTT lock, making this step visible to all GTs that share a 545 + * GGTT. 573 546 * 574 547 * Return: 0 on success or a negative error code on failure. 575 548 */ ··· 615 584 xe_gt_assert(gt, gt->sriov.vf.self_config.num_ctxs); 616 585 617 586 return gt->sriov.vf.self_config.num_ctxs; 618 - } 619 - 620 - /** 621 - * xe_gt_sriov_vf_lmem - VF LMEM configuration. 622 - * @gt: the &xe_gt 623 - * 624 - * This function is for VF use only. 625 - * 626 - * Return: size of the LMEM assigned to VF. 627 - */ 628 - u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) 629 - { 630 - xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 631 - xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 632 - xe_gt_assert(gt, gt->sriov.vf.self_config.lmem_size); 633 - 634 - return gt->sriov.vf.self_config.lmem_size; 635 - } 636 - 637 - /** 638 - * xe_gt_sriov_vf_ggtt - VF GGTT configuration. 639 - * @gt: the &xe_gt 640 - * 641 - * This function is for VF use only. 642 - * 643 - * Return: size of the GGTT assigned to VF. 644 - */ 645 - u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt) 646 - { 647 - xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 648 - xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 649 - xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size); 650 - 651 - return gt->sriov.vf.self_config.ggtt_size; 652 - } 653 - 654 - /** 655 - * xe_gt_sriov_vf_ggtt_base - VF GGTT base offset. 656 - * @gt: the &xe_gt 657 - * 658 - * This function is for VF use only. 659 - * 660 - * Return: base offset of the GGTT assigned to VF. 661 - */ 662 - u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt) 663 - { 664 - xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 665 - xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 666 - xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size); 667 - 668 - return gt->sriov.vf.self_config.ggtt_base; 669 - } 670 - 671 - /** 672 - * xe_gt_sriov_vf_ggtt_shift - Return shift in GGTT range due to VF migration 673 - * @gt: the &xe_gt struct instance 674 - * 675 - * This function is for VF use only. 676 - * 677 - * Return: The shift value; could be negative 678 - */ 679 - s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt) 680 - { 681 - struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config; 682 - 683 - xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 684 - xe_gt_assert(gt, xe_gt_is_main_type(gt)); 685 - 686 - return config->ggtt_shift; 687 587 } 688 588 689 589 static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor) ··· 717 755 * xe_gt_sriov_vf_default_lrcs_hwsp_rebase - Update GGTT references in HWSP of default LRCs. 718 756 * @gt: the &xe_gt struct instance 719 757 */ 720 - void xe_gt_sriov_vf_default_lrcs_hwsp_rebase(struct xe_gt *gt) 758 + static void xe_gt_sriov_vf_default_lrcs_hwsp_rebase(struct xe_gt *gt) 721 759 { 722 760 struct xe_hw_engine *hwe; 723 761 enum xe_hw_engine_id id; 724 762 725 763 for_each_hw_engine(hwe, gt, id) 726 764 xe_default_lrc_update_memirq_regs_with_address(hwe); 765 + } 766 + 767 + static void vf_start_migration_recovery(struct xe_gt *gt) 768 + { 769 + bool started; 770 + 771 + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 772 + 773 + spin_lock(&gt->sriov.vf.migration.lock); 774 + 775 + if (!gt->sriov.vf.migration.recovery_queued || 776 + !gt->sriov.vf.migration.recovery_teardown) { 777 + gt->sriov.vf.migration.recovery_queued = true; 778 + WRITE_ONCE(gt->sriov.vf.migration.recovery_inprogress, true); 779 + WRITE_ONCE(gt->sriov.vf.migration.ggtt_need_fixes, true); 780 + smp_wmb(); /* Ensure above writes visable before wake */ 781 + 782 + xe_guc_ct_wake_waiters(&gt->uc.guc.ct); 783 + 784 + started = queue_work(gt->ordered_wq, &gt->sriov.vf.migration.worker); 785 + xe_gt_sriov_info(gt, "VF migration recovery %s\n", started ? 786 + "scheduled" : "already in progress"); 787 + } 788 + 789 + spin_unlock(&gt->sriov.vf.migration.lock); 727 790 } 728 791 729 792 /** ··· 763 776 struct xe_device *xe = gt_to_xe(gt); 764 777 765 778 xe_gt_assert(gt, IS_SRIOV_VF(xe)); 779 + xe_gt_assert(gt, xe_gt_sriov_vf_recovery_pending(gt)); 766 780 767 - set_bit(gt->info.id, &xe->sriov.vf.migration.gt_flags); 768 - /* 769 - * We need to be certain that if all flags were set, at least one 770 - * thread will notice that and schedule the recovery. 771 - */ 772 - smp_mb__after_atomic(); 781 + if (!xe_sriov_vf_migration_supported(xe)) { 782 + xe_gt_sriov_err(gt, "migration not supported\n"); 783 + return; 784 + } 773 785 774 786 xe_gt_sriov_info(gt, "ready for recovery after migration\n"); 775 - xe_sriov_vf_start_migration_recovery(xe); 787 + vf_start_migration_recovery(gt); 776 788 } 777 789 778 790 static bool vf_is_negotiated(struct xe_gt *gt, u16 major, u16 minor) ··· 1026 1040 { 1027 1041 struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config; 1028 1042 struct xe_device *xe = gt_to_xe(gt); 1043 + u64 lmem_size; 1029 1044 char buf[10]; 1030 1045 1031 1046 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1032 1047 1033 - drm_printf(p, "GGTT range:\t%#llx-%#llx\n", 1034 - config->ggtt_base, 1035 - config->ggtt_base + config->ggtt_size - 1); 1048 + if (xe_gt_is_main_type(gt)) { 1049 + u64 ggtt_size = xe_tile_sriov_vf_ggtt(gt_to_tile(gt)); 1050 + u64 ggtt_base = xe_tile_sriov_vf_ggtt_base(gt_to_tile(gt)); 1036 1051 1037 - string_get_size(config->ggtt_size, 1, STRING_UNITS_2, buf, sizeof(buf)); 1038 - drm_printf(p, "GGTT size:\t%llu (%s)\n", config->ggtt_size, buf); 1052 + drm_printf(p, "GGTT range:\t%#llx-%#llx\n", 1053 + ggtt_base, ggtt_base + ggtt_size - 1); 1054 + string_get_size(ggtt_size, 1, STRING_UNITS_2, buf, sizeof(buf)); 1055 + drm_printf(p, "GGTT size:\t%llu (%s)\n", ggtt_size, buf); 1039 1056 1040 - drm_printf(p, "GGTT shift on last restore:\t%lld\n", config->ggtt_shift); 1041 - 1042 - if (IS_DGFX(xe) && xe_gt_is_main_type(gt)) { 1043 - string_get_size(config->lmem_size, 1, STRING_UNITS_2, buf, sizeof(buf)); 1044 - drm_printf(p, "LMEM size:\t%llu (%s)\n", config->lmem_size, buf); 1057 + if (IS_DGFX(xe)) { 1058 + lmem_size = xe_tile_sriov_vf_lmem(gt_to_tile(gt)); 1059 + string_get_size(lmem_size, 1, STRING_UNITS_2, buf, sizeof(buf)); 1060 + drm_printf(p, "LMEM size:\t%llu (%s)\n", lmem_size, buf); 1061 + } 1045 1062 } 1046 1063 1047 1064 drm_printf(p, "GuC contexts:\t%u\n", config->num_ctxs); ··· 1106 1117 GUC_RELAY_VERSION_LATEST_MAJOR, GUC_RELAY_VERSION_LATEST_MINOR); 1107 1118 drm_printf(p, "\thandshake:\t%u.%u\n", 1108 1119 pf_version->major, pf_version->minor); 1120 + } 1121 + 1122 + static bool vf_post_migration_shutdown(struct xe_gt *gt) 1123 + { 1124 + struct xe_device *xe = gt_to_xe(gt); 1125 + 1126 + /* 1127 + * On platforms where CCS must be restored by the primary GT, the media 1128 + * GT's VF post-migration recovery must run afterward. Detect this case 1129 + * and re-queue the media GT's restore work item if necessary. 1130 + */ 1131 + if (xe->info.needs_shared_vf_gt_wq && xe_gt_is_media_type(gt)) { 1132 + struct xe_gt *primary_gt = gt_to_tile(gt)->primary_gt; 1133 + 1134 + if (xe_gt_sriov_vf_recovery_pending(primary_gt)) 1135 + return true; 1136 + } 1137 + 1138 + spin_lock_irq(&gt->sriov.vf.migration.lock); 1139 + gt->sriov.vf.migration.recovery_queued = false; 1140 + spin_unlock_irq(&gt->sriov.vf.migration.lock); 1141 + 1142 + xe_guc_ct_flush_and_stop(&gt->uc.guc.ct); 1143 + xe_guc_submit_pause(&gt->uc.guc); 1144 + xe_tlb_inval_reset(&gt->tlb_inval); 1145 + 1146 + return false; 1147 + } 1148 + 1149 + static size_t post_migration_scratch_size(struct xe_device *xe) 1150 + { 1151 + return max(xe_lrc_reg_size(xe), LRC_WA_BB_SIZE); 1152 + } 1153 + 1154 + static int vf_post_migration_fixups(struct xe_gt *gt) 1155 + { 1156 + void *buf = gt->sriov.vf.migration.scratch; 1157 + int err; 1158 + 1159 + /* xe_gt_sriov_vf_query_config will fixup the GGTT addresses */ 1160 + err = xe_gt_sriov_vf_query_config(gt); 1161 + if (err) 1162 + return err; 1163 + 1164 + if (xe_gt_is_main_type(gt)) 1165 + xe_sriov_vf_ccs_rebase(gt_to_xe(gt)); 1166 + 1167 + xe_gt_sriov_vf_default_lrcs_hwsp_rebase(gt); 1168 + err = xe_guc_contexts_hwsp_rebase(&gt->uc.guc, buf); 1169 + if (err) 1170 + return err; 1171 + 1172 + return 0; 1173 + } 1174 + 1175 + static void vf_post_migration_rearm(struct xe_gt *gt) 1176 + { 1177 + xe_guc_ct_restart(&gt->uc.guc.ct); 1178 + xe_guc_submit_unpause_prepare(&gt->uc.guc); 1179 + } 1180 + 1181 + static void vf_post_migration_kickstart(struct xe_gt *gt) 1182 + { 1183 + xe_guc_submit_unpause(&gt->uc.guc); 1184 + } 1185 + 1186 + static void vf_post_migration_abort(struct xe_gt *gt) 1187 + { 1188 + spin_lock_irq(&gt->sriov.vf.migration.lock); 1189 + WRITE_ONCE(gt->sriov.vf.migration.recovery_inprogress, false); 1190 + WRITE_ONCE(gt->sriov.vf.migration.ggtt_need_fixes, false); 1191 + spin_unlock_irq(&gt->sriov.vf.migration.lock); 1192 + 1193 + wake_up_all(&gt->sriov.vf.migration.wq); 1194 + 1195 + xe_guc_submit_pause_abort(&gt->uc.guc); 1196 + } 1197 + 1198 + static int vf_post_migration_notify_resfix_done(struct xe_gt *gt) 1199 + { 1200 + bool skip_resfix = false; 1201 + 1202 + spin_lock_irq(&gt->sriov.vf.migration.lock); 1203 + if (gt->sriov.vf.migration.recovery_queued) { 1204 + skip_resfix = true; 1205 + xe_gt_sriov_dbg(gt, "another recovery imminent, resfix skipped\n"); 1206 + } else { 1207 + WRITE_ONCE(gt->sriov.vf.migration.recovery_inprogress, false); 1208 + } 1209 + spin_unlock_irq(&gt->sriov.vf.migration.lock); 1210 + 1211 + if (skip_resfix) 1212 + return -EAGAIN; 1213 + 1214 + /* 1215 + * Make sure interrupts on the new HW are properly set. The GuC IRQ 1216 + * must be working at this point, since the recovery did started, 1217 + * but the rest was not enabled using the procedure from spec. 1218 + */ 1219 + xe_irq_resume(gt_to_xe(gt)); 1220 + 1221 + return vf_notify_resfix_done(gt); 1222 + } 1223 + 1224 + static void vf_post_migration_recovery(struct xe_gt *gt) 1225 + { 1226 + struct xe_device *xe = gt_to_xe(gt); 1227 + int err; 1228 + bool retry; 1229 + 1230 + xe_gt_sriov_dbg(gt, "migration recovery in progress\n"); 1231 + 1232 + xe_pm_runtime_get(xe); 1233 + retry = vf_post_migration_shutdown(gt); 1234 + if (retry) 1235 + goto queue; 1236 + 1237 + if (!xe_sriov_vf_migration_supported(xe)) { 1238 + xe_gt_sriov_err(gt, "migration is not supported\n"); 1239 + err = -ENOTRECOVERABLE; 1240 + goto fail; 1241 + } 1242 + 1243 + err = vf_post_migration_fixups(gt); 1244 + if (err) 1245 + goto fail; 1246 + 1247 + vf_post_migration_rearm(gt); 1248 + 1249 + err = vf_post_migration_notify_resfix_done(gt); 1250 + if (err && err != -EAGAIN) 1251 + goto fail; 1252 + 1253 + vf_post_migration_kickstart(gt); 1254 + 1255 + xe_pm_runtime_put(xe); 1256 + xe_gt_sriov_notice(gt, "migration recovery ended\n"); 1257 + return; 1258 + fail: 1259 + vf_post_migration_abort(gt); 1260 + xe_pm_runtime_put(xe); 1261 + xe_gt_sriov_err(gt, "migration recovery failed (%pe)\n", ERR_PTR(err)); 1262 + xe_device_declare_wedged(xe); 1263 + return; 1264 + 1265 + queue: 1266 + xe_gt_sriov_info(gt, "Re-queuing migration recovery\n"); 1267 + queue_work(gt->ordered_wq, &gt->sriov.vf.migration.worker); 1268 + xe_pm_runtime_put(xe); 1269 + } 1270 + 1271 + static void migration_worker_func(struct work_struct *w) 1272 + { 1273 + struct xe_gt *gt = container_of(w, struct xe_gt, 1274 + sriov.vf.migration.worker); 1275 + 1276 + vf_post_migration_recovery(gt); 1277 + } 1278 + 1279 + static void vf_migration_fini(void *arg) 1280 + { 1281 + struct xe_gt *gt = arg; 1282 + 1283 + spin_lock_irq(&gt->sriov.vf.migration.lock); 1284 + gt->sriov.vf.migration.recovery_teardown = true; 1285 + spin_unlock_irq(&gt->sriov.vf.migration.lock); 1286 + 1287 + cancel_work_sync(&gt->sriov.vf.migration.worker); 1288 + } 1289 + 1290 + /** 1291 + * xe_gt_sriov_vf_init_early() - GT VF init early 1292 + * @gt: the &xe_gt 1293 + * 1294 + * Return 0 on success, errno on failure 1295 + */ 1296 + int xe_gt_sriov_vf_init_early(struct xe_gt *gt) 1297 + { 1298 + void *buf; 1299 + 1300 + if (!xe_sriov_vf_migration_supported(gt_to_xe(gt))) 1301 + return 0; 1302 + 1303 + buf = drmm_kmalloc(&gt_to_xe(gt)->drm, 1304 + post_migration_scratch_size(gt_to_xe(gt)), 1305 + GFP_KERNEL); 1306 + if (!buf) 1307 + return -ENOMEM; 1308 + 1309 + gt->sriov.vf.migration.scratch = buf; 1310 + spin_lock_init(&gt->sriov.vf.migration.lock); 1311 + INIT_WORK(&gt->sriov.vf.migration.worker, migration_worker_func); 1312 + init_waitqueue_head(&gt->sriov.vf.migration.wq); 1313 + 1314 + return 0; 1315 + } 1316 + 1317 + /** 1318 + * xe_gt_sriov_vf_init() - GT VF init 1319 + * @gt: the &xe_gt 1320 + * 1321 + * Return 0 on success, errno on failure 1322 + */ 1323 + int xe_gt_sriov_vf_init(struct xe_gt *gt) 1324 + { 1325 + if (!xe_sriov_vf_migration_supported(gt_to_xe(gt))) 1326 + return 0; 1327 + 1328 + /* 1329 + * We want to tear down the VF post-migration early during driver 1330 + * unload; therefore, we add this finalization action later during 1331 + * driver load. 1332 + */ 1333 + return devm_add_action_or_reset(gt_to_xe(gt)->drm.dev, 1334 + vf_migration_fini, gt); 1335 + } 1336 + 1337 + /** 1338 + * xe_gt_sriov_vf_recovery_pending() - VF post migration recovery pending 1339 + * @gt: the &xe_gt 1340 + * 1341 + * The return value of this function must be immediately visible upon vCPU 1342 + * unhalt and must persist until RESFIX_DONE is issued. This guarantee is 1343 + * currently implemented only for platforms that support memirq. If non-memirq 1344 + * platforms begin to support VF migration, this function will need to be 1345 + * updated accordingly. 1346 + * 1347 + * Return: True if VF post migration recovery is pending, False otherwise 1348 + */ 1349 + bool xe_gt_sriov_vf_recovery_pending(struct xe_gt *gt) 1350 + { 1351 + struct xe_memirq *memirq = &gt_to_tile(gt)->memirq; 1352 + 1353 + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1354 + 1355 + /* early detection until recovery starts */ 1356 + if (xe_device_uses_memirq(gt_to_xe(gt)) && 1357 + xe_memirq_guc_sw_int_0_irq_pending(memirq, &gt->uc.guc)) 1358 + return true; 1359 + 1360 + return READ_ONCE(gt->sriov.vf.migration.recovery_inprogress); 1361 + } 1362 + 1363 + static bool vf_valid_ggtt(struct xe_gt *gt) 1364 + { 1365 + struct xe_memirq *memirq = &gt_to_tile(gt)->memirq; 1366 + bool irq_pending = xe_device_uses_memirq(gt_to_xe(gt)) && 1367 + xe_memirq_guc_sw_int_0_irq_pending(memirq, &gt->uc.guc); 1368 + 1369 + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1370 + 1371 + if (irq_pending || READ_ONCE(gt->sriov.vf.migration.ggtt_need_fixes)) 1372 + return false; 1373 + 1374 + return true; 1375 + } 1376 + 1377 + /** 1378 + * xe_gt_sriov_vf_wait_valid_ggtt() - VF wait for valid GGTT addresses 1379 + * @gt: the &xe_gt 1380 + */ 1381 + void xe_gt_sriov_vf_wait_valid_ggtt(struct xe_gt *gt) 1382 + { 1383 + int ret; 1384 + 1385 + if (!IS_SRIOV_VF(gt_to_xe(gt)) || 1386 + !xe_sriov_vf_migration_supported(gt_to_xe(gt))) 1387 + return; 1388 + 1389 + ret = wait_event_interruptible_timeout(gt->sriov.vf.migration.wq, 1390 + vf_valid_ggtt(gt), 1391 + HZ * 5); 1392 + xe_gt_WARN_ON(gt, !ret); 1109 1393 }
+6 -5
drivers/gpu/drm/xe/xe_gt_sriov_vf.h
··· 21 21 int xe_gt_sriov_vf_query_config(struct xe_gt *gt); 22 22 int xe_gt_sriov_vf_connect(struct xe_gt *gt); 23 23 int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); 24 - void xe_gt_sriov_vf_default_lrcs_hwsp_rebase(struct xe_gt *gt); 25 - int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); 26 24 void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); 25 + 26 + int xe_gt_sriov_vf_init_early(struct xe_gt *gt); 27 + int xe_gt_sriov_vf_init(struct xe_gt *gt); 28 + bool xe_gt_sriov_vf_recovery_pending(struct xe_gt *gt); 27 29 28 30 u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt); 29 31 u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt); 30 32 u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt); 31 - u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt); 32 - u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt); 33 - s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt); 34 33 35 34 u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg); 36 35 void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val); ··· 37 38 void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p); 38 39 void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p); 39 40 void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p); 41 + 42 + void xe_gt_sriov_vf_wait_valid_ggtt(struct xe_gt *gt); 40 43 41 44 #endif
+26 -8
drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
··· 7 7 #define _XE_GT_SRIOV_VF_TYPES_H_ 8 8 9 9 #include <linux/types.h> 10 + #include <linux/wait.h> 11 + #include <linux/workqueue.h> 10 12 #include "xe_uc_fw_types.h" 11 13 12 14 /** 13 15 * struct xe_gt_sriov_vf_selfconfig - VF configuration data. 14 16 */ 15 17 struct xe_gt_sriov_vf_selfconfig { 16 - /** @ggtt_base: assigned base offset of the GGTT region. */ 17 - u64 ggtt_base; 18 - /** @ggtt_size: assigned size of the GGTT region. */ 19 - u64 ggtt_size; 20 - /** @ggtt_shift: difference in ggtt_base on last migration */ 21 - s64 ggtt_shift; 22 - /** @lmem_size: assigned size of the LMEM. */ 23 - u64 lmem_size; 24 18 /** @num_ctxs: assigned number of GuC submission context IDs. */ 25 19 u16 num_ctxs; 26 20 /** @num_dbs: assigned number of GuC doorbells IDs. */ ··· 41 47 }; 42 48 43 49 /** 50 + * xe_gt_sriov_vf_migration - VF migration data. 51 + */ 52 + struct xe_gt_sriov_vf_migration { 53 + /** @migration: VF migration recovery worker */ 54 + struct work_struct worker; 55 + /** @lock: Protects recovery_queued, teardown */ 56 + spinlock_t lock; 57 + /** @wq: wait queue for migration fixes */ 58 + wait_queue_head_t wq; 59 + /** @scratch: Scratch memory for VF recovery */ 60 + void *scratch; 61 + /** @recovery_teardown: VF post migration recovery is being torn down */ 62 + bool recovery_teardown; 63 + /** @recovery_queued: VF post migration recovery in queued */ 64 + bool recovery_queued; 65 + /** @recovery_inprogress: VF post migration recovery in progress */ 66 + bool recovery_inprogress; 67 + /** @ggtt_need_fixes: VF GGTT needs fixes */ 68 + bool ggtt_need_fixes; 69 + }; 70 + 71 + /** 44 72 * struct xe_gt_sriov_vf - GT level VF virtualization data. 45 73 */ 46 74 struct xe_gt_sriov_vf { ··· 74 58 struct xe_gt_sriov_vf_selfconfig self_config; 75 59 /** @runtime: runtime data retrieved from the PF. */ 76 60 struct xe_gt_sriov_vf_runtime runtime; 61 + /** @migration: migration data for the VF. */ 62 + struct xe_gt_sriov_vf_migration migration; 77 63 }; 78 64 79 65 #endif
+14 -3
drivers/gpu/drm/xe/xe_gt_topology.c
··· 148 148 if (!xe_gt_topology_report_l3(gt)) 149 149 return; 150 150 151 - if (GRAPHICS_VER(xe) >= 30) { 151 + if (GRAPHICS_VER(xe) >= 35) { 152 + u32 fuse_val = xe_mmio_read32(mmio, MIRROR_L3BANK_ENABLE); 153 + 154 + bitmap_from_arr32(l3_bank_mask, &fuse_val, 32); 155 + } else if (GRAPHICS_VER(xe) >= 30) { 152 156 xe_l3_bank_mask_t per_node = {}; 153 157 u32 meml3_en = REG_FIELD_GET(XE2_NODE_ENABLE_MASK, fuse3); 154 158 u32 mirror_l3bank_enable = xe_mmio_read32(mmio, MIRROR_L3BANK_ENABLE); ··· 273 269 return NULL; 274 270 } 275 271 276 - void 277 - xe_gt_topology_dump(struct xe_gt *gt, struct drm_printer *p) 272 + /** 273 + * xe_gt_topology_dump() - Dump GT topology into a drm printer. 274 + * @gt: the &xe_gt 275 + * @p: the &drm_printer 276 + * 277 + * Return: always 0. 278 + */ 279 + int xe_gt_topology_dump(struct xe_gt *gt, struct drm_printer *p) 278 280 { 279 281 drm_printf(p, "dss mask (geometry): %*pb\n", XE_MAX_DSS_FUSE_BITS, 280 282 gt->fuse_topo.g_dss_mask); ··· 295 285 if (xe_gt_topology_report_l3(gt)) 296 286 drm_printf(p, "L3 bank mask: %*pb\n", XE_MAX_L3_BANK_MASK_BITS, 297 287 gt->fuse_topo.l3_bank_mask); 288 + return 0; 298 289 } 299 290 300 291 /*
+1 -1
drivers/gpu/drm/xe/xe_gt_topology.h
··· 23 23 24 24 void xe_gt_topology_init(struct xe_gt *gt); 25 25 26 - void xe_gt_topology_dump(struct xe_gt *gt, struct drm_printer *p); 26 + int xe_gt_topology_dump(struct xe_gt *gt, struct drm_printer *p); 27 27 28 28 /** 29 29 * xe_gt_topology_mask_last_dss() - Returns the index of the last DSS in a mask.
+20 -5
drivers/gpu/drm/xe/xe_gt_types.h
··· 73 73 SQIDI_PSMI, 74 74 75 75 /* 76 + * The bspec lists multiple ranges as "PSMI," but the different 77 + * ranges with that label have different grpid steering values so we 78 + * treat them independently in code. Note that the ranges with grpid=0 79 + * are included in the INSTANCE0 group above. 80 + */ 81 + PSMI19, 82 + 83 + /* 84 + * Although most GAM ranges must be steered to (0,0) and thus use the 85 + * INSTANCE0 type farther down, some platforms have special rules 86 + * for specific subtypes that require steering to (1,0) instead. 87 + */ 88 + GAM1, 89 + 90 + /* 76 91 * On some platforms there are multiple types of MCR registers that 77 92 * will always return a non-terminated value at instance (0, 0). We'll 78 93 * lump those all into a single category to keep things simple. ··· 217 202 /** 218 203 * @usm.bb_pool: Pool from which batchbuffers, for USM operations 219 204 * (e.g. migrations, fixing page tables), are allocated. 220 - * Dedicated pool needed so USM operations to not get blocked 205 + * Dedicated pool needed so USM operations do not get blocked 221 206 * behind any user operations which may have resulted in a 222 207 * fault. 223 208 */ 224 209 struct xe_sa_manager *bb_pool; 225 210 /** 226 211 * @usm.reserved_bcs_instance: reserved BCS instance used for USM 227 - * operations (e.g. mmigrations, fixing page tables) 212 + * operations (e.g. migrations, fixing page tables) 228 213 */ 229 214 u16 reserved_bcs_instance; 230 215 /** @usm.pf_wq: page fault work queue, unbound, high priority */ ··· 235 220 * @usm.pf_queue: Page fault queue used to sync faults so faults can 236 221 * be processed not under the GuC CT lock. The queue is sized so 237 222 * it can sync all possible faults (1 per physical engine). 238 - * Multiple queues exists for page faults from different VMs are 239 - * be processed in parallel. 223 + * Multiple queues exist for page faults from different VMs to be 224 + * processed in parallel. 240 225 */ 241 226 struct pf_queue { 242 227 /** @usm.pf_queue.gt: back pointer to GT */ ··· 402 387 /** 403 388 * @wa_active.oob_initialized: mark oob as initialized to help 404 389 * detecting misuse of XE_GT_WA() - it can only be called on 405 - * initialization after OOB WAs have being processed 390 + * initialization after OOB WAs have been processed 406 391 */ 407 392 bool oob_initialized; 408 393 } wa_active;
+120 -153
drivers/gpu/drm/xe/xe_guc.c
··· 5 5 6 6 #include "xe_guc.h" 7 7 8 + #include <linux/iopoll.h> 8 9 #include <drm/drm_managed.h> 9 10 10 11 #include <generated/xe_wa_oob.h> ··· 972 971 } 973 972 974 973 /* 975 - * Check a previously read GuC status register (GUC_STATUS) looking for 976 - * known terminal states (either completion or failure) of either the 977 - * microkernel status field or the boot ROM status field. Returns +1 for 978 - * successful completion, -1 for failure and 0 for any intermediate state. 974 + * Wait for the GuC to start up. 975 + * 976 + * Measurements indicate this should take no more than 20ms (assuming the GT 977 + * clock is at maximum frequency). However, thermal throttling and other issues 978 + * can prevent the clock hitting max and thus making the load take significantly 979 + * longer. Allow up to 3s as a safety margin in normal builds. For 980 + * CONFIG_DRM_XE_DEBUG allow up to 10s to account for slower execution, issues 981 + * in PCODE, driver, fan, etc. 982 + * 983 + * Keep checking the GUC_STATUS every 10ms with a debug message every 100 984 + * attempts as a "I'm slow, but alive" message. Regardless, if it takes more 985 + * than 200ms, emit a warning. 979 986 */ 980 - static int guc_load_done(u32 status) 981 - { 982 - u32 uk_val = REG_FIELD_GET(GS_UKERNEL_MASK, status); 983 - u32 br_val = REG_FIELD_GET(GS_BOOTROM_MASK, status); 984 987 985 - switch (uk_val) { 988 + #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) 989 + #define GUC_LOAD_TIMEOUT_SEC 20 990 + #else 991 + #define GUC_LOAD_TIMEOUT_SEC 3 992 + #endif 993 + #define GUC_LOAD_TIME_WARN_MSEC 200 994 + 995 + static void print_load_status_err(struct xe_gt *gt, u32 status) 996 + { 997 + struct xe_mmio *mmio = &gt->mmio; 998 + u32 ukernel = REG_FIELD_GET(GS_UKERNEL_MASK, status); 999 + u32 bootrom = REG_FIELD_GET(GS_BOOTROM_MASK, status); 1000 + 1001 + xe_gt_err(gt, "load failed: status: Reset = %d, BootROM = 0x%02X, UKernel = 0x%02X, MIA = 0x%02X, Auth = 0x%02X\n", 1002 + REG_FIELD_GET(GS_MIA_IN_RESET, status), 1003 + bootrom, ukernel, 1004 + REG_FIELD_GET(GS_MIA_MASK, status), 1005 + REG_FIELD_GET(GS_AUTH_STATUS_MASK, status)); 1006 + 1007 + switch (bootrom) { 1008 + case XE_BOOTROM_STATUS_NO_KEY_FOUND: 1009 + xe_gt_err(gt, "invalid key requested, header = 0x%08X\n", 1010 + xe_mmio_read32(mmio, GUC_HEADER_INFO)); 1011 + break; 1012 + case XE_BOOTROM_STATUS_RSA_FAILED: 1013 + xe_gt_err(gt, "firmware signature verification failed\n"); 1014 + break; 1015 + case XE_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE: 1016 + xe_gt_err(gt, "firmware production part check failure\n"); 1017 + break; 1018 + } 1019 + 1020 + switch (ukernel) { 1021 + case XE_GUC_LOAD_STATUS_HWCONFIG_START: 1022 + xe_gt_err(gt, "still extracting hwconfig table.\n"); 1023 + break; 1024 + case XE_GUC_LOAD_STATUS_EXCEPTION: 1025 + xe_gt_err(gt, "firmware exception. EIP: %#x\n", 1026 + xe_mmio_read32(mmio, SOFT_SCRATCH(13))); 1027 + break; 1028 + case XE_GUC_LOAD_STATUS_INIT_DATA_INVALID: 1029 + xe_gt_err(gt, "illegal init/ADS data\n"); 1030 + break; 1031 + case XE_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID: 1032 + xe_gt_err(gt, "illegal register in save/restore workaround list\n"); 1033 + break; 1034 + case XE_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR: 1035 + xe_gt_err(gt, "illegal workaround KLV data\n"); 1036 + break; 1037 + case XE_GUC_LOAD_STATUS_INVALID_FTR_FLAG: 1038 + xe_gt_err(gt, "illegal feature flag specified\n"); 1039 + break; 1040 + } 1041 + } 1042 + 1043 + /* 1044 + * Check GUC_STATUS looking for known terminal states (either completion or 1045 + * failure) of either the microkernel status field or the boot ROM status field. 1046 + * 1047 + * Returns 1 for successful completion, -1 for failure and 0 for any 1048 + * intermediate state. 1049 + */ 1050 + static int guc_load_done(struct xe_gt *gt, u32 *status, u32 *tries) 1051 + { 1052 + u32 ukernel, bootrom; 1053 + 1054 + *status = xe_mmio_read32(&gt->mmio, GUC_STATUS); 1055 + ukernel = REG_FIELD_GET(GS_UKERNEL_MASK, *status); 1056 + bootrom = REG_FIELD_GET(GS_BOOTROM_MASK, *status); 1057 + 1058 + switch (ukernel) { 986 1059 case XE_GUC_LOAD_STATUS_READY: 987 1060 return 1; 988 - 989 1061 case XE_GUC_LOAD_STATUS_ERROR_DEVID_BUILD_MISMATCH: 990 1062 case XE_GUC_LOAD_STATUS_GUC_PREPROD_BUILD_MISMATCH: 991 1063 case XE_GUC_LOAD_STATUS_ERROR_DEVID_INVALID_GUCTYPE: ··· 1074 1000 return -1; 1075 1001 } 1076 1002 1077 - switch (br_val) { 1003 + switch (bootrom) { 1078 1004 case XE_BOOTROM_STATUS_NO_KEY_FOUND: 1079 1005 case XE_BOOTROM_STATUS_RSA_FAILED: 1080 1006 case XE_BOOTROM_STATUS_PAVPC_FAILED: ··· 1088 1014 return -1; 1089 1015 } 1090 1016 1017 + if (++*tries >= 100) { 1018 + struct xe_guc_pc *guc_pc = &gt->uc.guc.pc; 1019 + 1020 + *tries = 0; 1021 + xe_gt_dbg(gt, "GuC load still in progress, freq = %dMHz (req %dMHz), status = 0x%08X [0x%02X/%02X]\n", 1022 + xe_guc_pc_get_act_freq(guc_pc), 1023 + xe_guc_pc_get_cur_freq_fw(guc_pc), 1024 + *status, ukernel, bootrom); 1025 + } 1026 + 1091 1027 return 0; 1092 1028 } 1093 - 1094 - static s32 guc_pc_get_cur_freq(struct xe_guc_pc *guc_pc) 1095 - { 1096 - u32 freq; 1097 - int ret = xe_guc_pc_get_cur_freq(guc_pc, &freq); 1098 - 1099 - return ret ? ret : freq; 1100 - } 1101 - 1102 - /* 1103 - * Wait for the GuC to start up. 1104 - * 1105 - * Measurements indicate this should take no more than 20ms (assuming the GT 1106 - * clock is at maximum frequency). However, thermal throttling and other issues 1107 - * can prevent the clock hitting max and thus making the load take significantly 1108 - * longer. Allow up to 200ms as a safety margin for real world worst case situations. 1109 - * 1110 - * However, bugs anywhere from KMD to GuC to PCODE to fan failure in a CI farm can 1111 - * lead to even longer times. E.g. if the GT is clamped to minimum frequency then 1112 - * the load times can be in the seconds range. So the timeout is increased for debug 1113 - * builds to ensure that problems can be correctly analysed. For release builds, the 1114 - * timeout is kept short so that users don't wait forever to find out that there is a 1115 - * problem. In either case, if the load took longer than is reasonable even with some 1116 - * 'sensible' throttling, then flag a warning because something is not right. 1117 - * 1118 - * Note that there is a limit on how long an individual usleep_range() can wait for, 1119 - * hence longer waits require wrapping a shorter wait in a loop. 1120 - * 1121 - * Note that the only reason an end user should hit the shorter timeout is in case of 1122 - * extreme thermal throttling. And a system that is that hot during boot is probably 1123 - * dead anyway! 1124 - */ 1125 - #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) 1126 - #define GUC_LOAD_RETRY_LIMIT 20 1127 - #else 1128 - #define GUC_LOAD_RETRY_LIMIT 3 1129 - #endif 1130 - #define GUC_LOAD_TIME_WARN_MS 200 1131 1029 1132 1030 static int guc_wait_ucode(struct xe_guc *guc) 1133 1031 { 1134 1032 struct xe_gt *gt = guc_to_gt(guc); 1135 - struct xe_mmio *mmio = &gt->mmio; 1136 1033 struct xe_guc_pc *guc_pc = &gt->uc.guc.pc; 1137 - ktime_t before, after, delta; 1138 - int load_done; 1139 - u32 status = 0; 1140 - int count = 0; 1034 + u32 before_freq, act_freq, cur_freq; 1035 + u32 status = 0, tries = 0; 1036 + ktime_t before; 1141 1037 u64 delta_ms; 1142 - u32 before_freq; 1038 + int ret; 1143 1039 1144 1040 before_freq = xe_guc_pc_get_act_freq(guc_pc); 1145 1041 before = ktime_get(); 1146 - /* 1147 - * Note, can't use any kind of timing information from the call to xe_mmio_wait. 1148 - * It could return a thousand intermediate stages at random times. Instead, must 1149 - * manually track the total time taken and locally implement the timeout. 1150 - */ 1151 - do { 1152 - u32 last_status = status & (GS_UKERNEL_MASK | GS_BOOTROM_MASK); 1153 - int ret; 1154 1042 1155 - /* 1156 - * Wait for any change (intermediate or terminal) in the status register. 1157 - * Note, the return value is a don't care. The only failure code is timeout 1158 - * but the timeouts need to be accumulated over all the intermediate partial 1159 - * timeouts rather than allowing a huge timeout each time. So basically, need 1160 - * to treat a timeout no different to a value change. 1161 - */ 1162 - ret = xe_mmio_wait32_not(mmio, GUC_STATUS, GS_UKERNEL_MASK | GS_BOOTROM_MASK, 1163 - last_status, 1000 * 1000, &status, false); 1164 - if (ret < 0) 1165 - count++; 1166 - after = ktime_get(); 1167 - delta = ktime_sub(after, before); 1168 - delta_ms = ktime_to_ms(delta); 1043 + ret = poll_timeout_us(ret = guc_load_done(gt, &status, &tries), ret, 1044 + 10 * USEC_PER_MSEC, 1045 + GUC_LOAD_TIMEOUT_SEC * USEC_PER_SEC, false); 1169 1046 1170 - load_done = guc_load_done(status); 1171 - if (load_done != 0) 1172 - break; 1047 + delta_ms = ktime_to_ms(ktime_sub(ktime_get(), before)); 1048 + act_freq = xe_guc_pc_get_act_freq(guc_pc); 1049 + cur_freq = xe_guc_pc_get_cur_freq_fw(guc_pc); 1173 1050 1174 - if (delta_ms >= (GUC_LOAD_RETRY_LIMIT * 1000)) 1175 - break; 1176 - 1177 - xe_gt_dbg(gt, "load still in progress, timeouts = %d, freq = %dMHz (req %dMHz), status = 0x%08X [0x%02X/%02X]\n", 1178 - count, xe_guc_pc_get_act_freq(guc_pc), 1179 - guc_pc_get_cur_freq(guc_pc), status, 1180 - REG_FIELD_GET(GS_BOOTROM_MASK, status), 1181 - REG_FIELD_GET(GS_UKERNEL_MASK, status)); 1182 - } while (1); 1183 - 1184 - if (load_done != 1) { 1185 - u32 ukernel = REG_FIELD_GET(GS_UKERNEL_MASK, status); 1186 - u32 bootrom = REG_FIELD_GET(GS_BOOTROM_MASK, status); 1187 - 1188 - xe_gt_err(gt, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz (req %dMHz), done = %d\n", 1051 + if (ret) { 1052 + xe_gt_err(gt, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz (req %dMHz)\n", 1189 1053 status, delta_ms, xe_guc_pc_get_act_freq(guc_pc), 1190 - guc_pc_get_cur_freq(guc_pc), load_done); 1191 - xe_gt_err(gt, "load failed: status: Reset = %d, BootROM = 0x%02X, UKernel = 0x%02X, MIA = 0x%02X, Auth = 0x%02X\n", 1192 - REG_FIELD_GET(GS_MIA_IN_RESET, status), 1193 - bootrom, ukernel, 1194 - REG_FIELD_GET(GS_MIA_MASK, status), 1195 - REG_FIELD_GET(GS_AUTH_STATUS_MASK, status)); 1196 - 1197 - switch (bootrom) { 1198 - case XE_BOOTROM_STATUS_NO_KEY_FOUND: 1199 - xe_gt_err(gt, "invalid key requested, header = 0x%08X\n", 1200 - xe_mmio_read32(mmio, GUC_HEADER_INFO)); 1201 - break; 1202 - 1203 - case XE_BOOTROM_STATUS_RSA_FAILED: 1204 - xe_gt_err(gt, "firmware signature verification failed\n"); 1205 - break; 1206 - 1207 - case XE_BOOTROM_STATUS_PROD_KEY_CHECK_FAILURE: 1208 - xe_gt_err(gt, "firmware production part check failure\n"); 1209 - break; 1210 - } 1211 - 1212 - switch (ukernel) { 1213 - case XE_GUC_LOAD_STATUS_HWCONFIG_START: 1214 - xe_gt_err(gt, "still extracting hwconfig table.\n"); 1215 - break; 1216 - 1217 - case XE_GUC_LOAD_STATUS_EXCEPTION: 1218 - xe_gt_err(gt, "firmware exception. EIP: %#x\n", 1219 - xe_mmio_read32(mmio, SOFT_SCRATCH(13))); 1220 - break; 1221 - 1222 - case XE_GUC_LOAD_STATUS_INIT_DATA_INVALID: 1223 - xe_gt_err(gt, "illegal init/ADS data\n"); 1224 - break; 1225 - 1226 - case XE_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID: 1227 - xe_gt_err(gt, "illegal register in save/restore workaround list\n"); 1228 - break; 1229 - 1230 - case XE_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR: 1231 - xe_gt_err(gt, "illegal workaround KLV data\n"); 1232 - break; 1233 - 1234 - case XE_GUC_LOAD_STATUS_INVALID_FTR_FLAG: 1235 - xe_gt_err(gt, "illegal feature flag specified\n"); 1236 - break; 1237 - } 1054 + xe_guc_pc_get_cur_freq_fw(guc_pc)); 1055 + print_load_status_err(gt, status); 1238 1056 1239 1057 return -EPROTO; 1240 - } else if (delta_ms > GUC_LOAD_TIME_WARN_MS) { 1241 - xe_gt_warn(gt, "excessive init time: %lldms! [status = 0x%08X, timeouts = %d]\n", 1242 - delta_ms, status, count); 1243 - xe_gt_warn(gt, "excessive init time: [freq = %dMHz (req = %dMHz), before = %dMHz, perf_limit_reasons = 0x%08X]\n", 1244 - xe_guc_pc_get_act_freq(guc_pc), guc_pc_get_cur_freq(guc_pc), 1245 - before_freq, xe_gt_throttle_get_limit_reasons(gt)); 1058 + } 1059 + 1060 + if (delta_ms > GUC_LOAD_TIME_WARN_MSEC) { 1061 + xe_gt_warn(gt, "GuC load: excessive init time: %lldms! [status = 0x%08X]\n", 1062 + delta_ms, status); 1063 + xe_gt_warn(gt, "GuC load: excessive init time: [freq = %dMHz (req = %dMHz), before = %dMHz, perf_limit_reasons = 0x%08X]\n", 1064 + act_freq, cur_freq, before_freq, 1065 + xe_gt_throttle_get_limit_reasons(gt)); 1246 1066 } else { 1247 - xe_gt_dbg(gt, "init took %lldms, freq = %dMHz (req = %dMHz), before = %dMHz, status = 0x%08X, timeouts = %d\n", 1248 - delta_ms, xe_guc_pc_get_act_freq(guc_pc), guc_pc_get_cur_freq(guc_pc), 1249 - before_freq, status, count); 1067 + xe_gt_dbg(gt, "GuC load: init took %lldms, freq = %dMHz (req = %dMHz), before = %dMHz, status = 0x%08X\n", 1068 + delta_ms, act_freq, cur_freq, before_freq, status); 1250 1069 } 1251 1070 1252 1071 return 0; ··· 1439 1472 BUILD_BUG_ON((GUC_HXG_TYPE_RESPONSE_SUCCESS ^ GUC_HXG_TYPE_RESPONSE_FAILURE) != 1); 1440 1473 1441 1474 ret = xe_mmio_wait32(mmio, reply_reg, resp_mask, resp_mask, 1442 - 1000000, &header, false); 1475 + 2000000, &header, false); 1443 1476 1444 1477 if (unlikely(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) != 1445 1478 GUC_HXG_ORIGIN_GUC))
+1 -1
drivers/gpu/drm/xe/xe_guc_ads.c
··· 18 18 #include "xe_bo.h" 19 19 #include "xe_gt.h" 20 20 #include "xe_gt_ccs_mode.h" 21 + #include "xe_gt_mcr.h" 21 22 #include "xe_gt_printk.h" 22 23 #include "xe_guc.h" 23 24 #include "xe_guc_buf.h" ··· 31 30 #include "xe_platform_types.h" 32 31 #include "xe_uc_fw.h" 33 32 #include "xe_wa.h" 34 - #include "xe_gt_mcr.h" 35 33 36 34 /* Slack of a few additional entries per engine */ 37 35 #define ADS_REGSET_EXTRA_MAX 8
+28 -1
drivers/gpu/drm/xe/xe_guc_capture.c
··· 122 122 { RING_IPEHR(0), REG_32BIT, 0, 0, 0, "IPEHR"}, \ 123 123 { RING_INSTDONE(0), REG_32BIT, 0, 0, 0, "RING_INSTDONE"}, \ 124 124 { INDIRECT_RING_STATE(0), REG_32BIT, 0, 0, 0, "INDIRECT_RING_STATE"}, \ 125 + { RING_CURRENT_LRCA(0), REG_32BIT, 0, 0, 0, "CURRENT_LRCA"}, \ 125 126 { RING_ACTHD(0), REG_64BIT_LOW_DW, 0, 0, 0, NULL}, \ 126 127 { RING_ACTHD_UDW(0), REG_64BIT_HI_DW, 0, 0, 0, "ACTHD"}, \ 127 128 { RING_BBADDR(0), REG_64BIT_LOW_DW, 0, 0, 0, NULL}, \ ··· 149 148 { SFC_DONE(1), 0, 0, 0, 0, "SFC_DONE[1]"}, \ 150 149 { SFC_DONE(2), 0, 0, 0, 0, "SFC_DONE[2]"}, \ 151 150 { SFC_DONE(3), 0, 0, 0, 0, "SFC_DONE[3]"} 151 + 152 + #define XE3P_BASE_ENGINE_INSTANCE \ 153 + { RING_CSMQDEBUG(0), REG_32BIT, 0, 0, 0, "CSMQDEBUG"} 152 154 153 155 /* XE_LP Global */ 154 156 static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { ··· 197 193 /* XE_LP - GSC Per-Engine-Instance */ 198 194 static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { 199 195 COMMON_BASE_ENGINE_INSTANCE, 196 + }; 197 + 198 + /* Render / Compute Per-Engine-Instance */ 199 + static const struct __guc_mmio_reg_descr xe3p_rc_inst_regs[] = { 200 + COMMON_BASE_ENGINE_INSTANCE, 201 + XE3P_BASE_ENGINE_INSTANCE, 200 202 }; 201 203 202 204 /* ··· 255 245 {} 256 246 }; 257 247 248 + /* List of lists for Xe3p and beyond */ 249 + static const struct __guc_mmio_reg_descr_group xe3p_lists[] = { 250 + MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 251 + MAKE_REGLIST(xe_hpg_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 252 + MAKE_REGLIST(xe3p_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 253 + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 254 + MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 255 + MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 256 + MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 257 + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 258 + MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 259 + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 260 + MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 261 + {} 262 + }; 258 263 static const char * const capture_list_type_names[] = { 259 264 "Global", 260 265 "Class", ··· 317 292 static const struct __guc_mmio_reg_descr_group * 318 293 guc_capture_get_device_reglist(struct xe_device *xe) 319 294 { 320 - if (GRAPHICS_VERx100(xe) >= 1255) 295 + if (GRAPHICS_VER(xe) >= 35) 296 + return xe3p_lists; 297 + else if (GRAPHICS_VERx100(xe) >= 1255) 321 298 return xe_hpg_lists; 322 299 else 323 300 return xe_lp_lists;
+135 -236
drivers/gpu/drm/xe/xe_guc_ct.c
··· 25 25 #include "xe_gt_printk.h" 26 26 #include "xe_gt_sriov_pf_control.h" 27 27 #include "xe_gt_sriov_pf_monitor.h" 28 - #include "xe_gt_sriov_printk.h" 29 28 #include "xe_guc.h" 30 29 #include "xe_guc_log.h" 31 30 #include "xe_guc_relay.h" ··· 32 33 #include "xe_guc_tlb_inval.h" 33 34 #include "xe_map.h" 34 35 #include "xe_pm.h" 36 + #include "xe_sriov_vf.h" 35 37 #include "xe_trace_guc.h" 36 38 37 39 static void receive_g2h(struct xe_guc_ct *ct); ··· 92 92 bool fail; 93 93 bool done; 94 94 }; 95 - 96 - #define make_u64(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo))) 97 95 98 96 static void g2h_fence_init(struct g2h_fence *g2h_fence, u32 *response_buffer) 99 97 { ··· 167 169 */ 168 170 169 171 #define CTB_DESC_SIZE ALIGN(sizeof(struct guc_ct_buffer_desc), SZ_2K) 172 + #define CTB_H2G_BUFFER_OFFSET (CTB_DESC_SIZE * 2) 170 173 #define CTB_H2G_BUFFER_SIZE (SZ_4K) 171 174 #define CTB_G2H_BUFFER_SIZE (SZ_128K) 172 175 #define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 2) ··· 191 192 192 193 static size_t guc_ct_size(void) 193 194 { 194 - return 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + 195 + return CTB_H2G_BUFFER_OFFSET + CTB_H2G_BUFFER_SIZE + 195 196 CTB_G2H_BUFFER_SIZE; 196 197 } 197 198 ··· 332 333 h2g->desc = *map; 333 334 xe_map_memset(xe, &h2g->desc, 0, 0, sizeof(struct guc_ct_buffer_desc)); 334 335 335 - h2g->cmds = IOSYS_MAP_INIT_OFFSET(map, CTB_DESC_SIZE * 2); 336 + h2g->cmds = IOSYS_MAP_INIT_OFFSET(map, CTB_H2G_BUFFER_OFFSET); 336 337 } 337 338 338 339 static void guc_ct_ctb_g2h_init(struct xe_device *xe, struct guc_ctb *g2h, ··· 350 351 g2h->desc = IOSYS_MAP_INIT_OFFSET(map, CTB_DESC_SIZE); 351 352 xe_map_memset(xe, &g2h->desc, 0, 0, sizeof(struct guc_ct_buffer_desc)); 352 353 353 - g2h->cmds = IOSYS_MAP_INIT_OFFSET(map, CTB_DESC_SIZE * 2 + 354 + g2h->cmds = IOSYS_MAP_INIT_OFFSET(map, CTB_H2G_BUFFER_OFFSET + 354 355 CTB_H2G_BUFFER_SIZE); 355 356 } 356 357 ··· 361 362 int err; 362 363 363 364 desc_addr = xe_bo_ggtt_addr(ct->bo); 364 - ctb_addr = xe_bo_ggtt_addr(ct->bo) + CTB_DESC_SIZE * 2; 365 + ctb_addr = xe_bo_ggtt_addr(ct->bo) + CTB_H2G_BUFFER_OFFSET; 365 366 size = ct->ctbs.h2g.info.size * sizeof(u32); 366 367 367 368 err = xe_guc_self_cfg64(guc, ··· 388 389 int err; 389 390 390 391 desc_addr = xe_bo_ggtt_addr(ct->bo) + CTB_DESC_SIZE; 391 - ctb_addr = xe_bo_ggtt_addr(ct->bo) + CTB_DESC_SIZE * 2 + 392 + ctb_addr = xe_bo_ggtt_addr(ct->bo) + CTB_H2G_BUFFER_OFFSET + 392 393 CTB_H2G_BUFFER_SIZE; 393 394 size = ct->ctbs.g2h.info.size * sizeof(u32); 394 395 ··· 502 503 xe_gt_dbg(ct_to_gt(ct), "GuC CT safe-mode disabled\n"); 503 504 } 504 505 505 - int xe_guc_ct_enable(struct xe_guc_ct *ct) 506 + static int __xe_guc_ct_start(struct xe_guc_ct *ct, bool needs_register) 506 507 { 507 508 struct xe_device *xe = ct_to_xe(ct); 508 509 struct xe_gt *gt = ct_to_gt(ct); ··· 510 511 511 512 xe_gt_assert(gt, !xe_guc_ct_enabled(ct)); 512 513 513 - xe_map_memset(xe, &ct->bo->vmap, 0, 0, xe_bo_size(ct->bo)); 514 - guc_ct_ctb_h2g_init(xe, &ct->ctbs.h2g, &ct->bo->vmap); 515 - guc_ct_ctb_g2h_init(xe, &ct->ctbs.g2h, &ct->bo->vmap); 514 + if (needs_register) { 515 + xe_map_memset(xe, &ct->bo->vmap, 0, 0, xe_bo_size(ct->bo)); 516 + guc_ct_ctb_h2g_init(xe, &ct->ctbs.h2g, &ct->bo->vmap); 517 + guc_ct_ctb_g2h_init(xe, &ct->ctbs.g2h, &ct->bo->vmap); 516 518 517 - err = guc_ct_ctb_h2g_register(ct); 518 - if (err) 519 - goto err_out; 519 + err = guc_ct_ctb_h2g_register(ct); 520 + if (err) 521 + goto err_out; 520 522 521 - err = guc_ct_ctb_g2h_register(ct); 522 - if (err) 523 - goto err_out; 523 + err = guc_ct_ctb_g2h_register(ct); 524 + if (err) 525 + goto err_out; 524 526 525 - err = guc_ct_control_toggle(ct, true); 526 - if (err) 527 - goto err_out; 527 + err = guc_ct_control_toggle(ct, true); 528 + if (err) 529 + goto err_out; 530 + } else { 531 + ct->ctbs.h2g.info.broken = false; 532 + ct->ctbs.g2h.info.broken = false; 533 + /* Skip everything in H2G buffer */ 534 + xe_map_memset(xe, &ct->bo->vmap, CTB_H2G_BUFFER_OFFSET, 0, 535 + CTB_H2G_BUFFER_SIZE); 536 + } 528 537 529 538 guc_ct_change_state(ct, XE_GUC_CT_STATE_ENABLED); 530 539 ··· 564 557 return err; 565 558 } 566 559 560 + /** 561 + * xe_guc_ct_restart() - Restart GuC CT 562 + * @ct: the &xe_guc_ct 563 + * 564 + * Restart GuC CT to an empty state without issuing a CT register MMIO command. 565 + * 566 + * Return: 0 on success, or a negative errno on failure. 567 + */ 568 + int xe_guc_ct_restart(struct xe_guc_ct *ct) 569 + { 570 + return __xe_guc_ct_start(ct, false); 571 + } 572 + 573 + /** 574 + * xe_guc_ct_enable() - Enable GuC CT 575 + * @ct: the &xe_guc_ct 576 + * 577 + * Enable GuC CT to an empty state and issue a CT register MMIO command. 578 + * 579 + * Return: 0 on success, or a negative errno on failure. 580 + */ 581 + int xe_guc_ct_enable(struct xe_guc_ct *ct) 582 + { 583 + return __xe_guc_ct_start(ct, true); 584 + } 585 + 567 586 static void stop_g2h_handler(struct xe_guc_ct *ct) 568 587 { 569 588 cancel_work_sync(&ct->g2h_worker); ··· 607 574 guc_ct_change_state(ct, XE_GUC_CT_STATE_DISABLED); 608 575 ct_exit_safe_mode(ct); 609 576 stop_g2h_handler(ct); 577 + } 578 + 579 + /** 580 + * xe_guc_ct_flush_and_stop - Flush and stop all processing of G2H / H2G 581 + * @ct: the &xe_guc_ct 582 + */ 583 + void xe_guc_ct_flush_and_stop(struct xe_guc_ct *ct) 584 + { 585 + receive_g2h(ct); 586 + xe_guc_ct_stop(ct); 610 587 } 611 588 612 589 /** ··· 782 739 return seqno; 783 740 } 784 741 742 + #define MAKE_ACTION(type, __action) \ 743 + ({ \ 744 + FIELD_PREP(GUC_HXG_MSG_0_TYPE, type) | \ 745 + FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | \ 746 + GUC_HXG_EVENT_MSG_0_DATA0, __action); \ 747 + }) 748 + 749 + static bool vf_action_can_safely_fail(struct xe_device *xe, u32 action) 750 + { 751 + /* 752 + * When resuming a VF, we can't reliably track whether context 753 + * registration has completed in the GuC state machine. It is harmless 754 + * to resend the request, as it will fail silently if GUC_HXG_TYPE_EVENT 755 + * is used. Additionally, if there is an H2G protocol issue on a VF, 756 + * subsequent H2G messages sent as GUC_HXG_TYPE_FAST_REQUEST will likely 757 + * fail. 758 + */ 759 + return IS_SRIOV_VF(xe) && xe_sriov_vf_migration_supported(xe) && 760 + (action == XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC || 761 + action == XE_GUC_ACTION_REGISTER_CONTEXT); 762 + } 763 + 785 764 #define H2G_CT_HEADERS (GUC_CTB_HDR_LEN + 1) /* one DW CTB header and one DW HxG header */ 786 765 787 766 static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len, ··· 875 810 FIELD_PREP(GUC_CTB_MSG_0_NUM_DWORDS, len) | 876 811 FIELD_PREP(GUC_CTB_MSG_0_FENCE, ct_fence_value); 877 812 if (want_response) { 878 - cmd[1] = 879 - FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 880 - FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | 881 - GUC_HXG_EVENT_MSG_0_DATA0, action[0]); 813 + cmd[1] = MAKE_ACTION(GUC_HXG_TYPE_REQUEST, action[0]); 814 + } else if (vf_action_can_safely_fail(xe, action[0])) { 815 + cmd[1] = MAKE_ACTION(GUC_HXG_TYPE_EVENT, action[0]); 882 816 } else { 883 817 fast_req_track(ct, ct_fence_value, 884 818 FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, action[0])); 885 819 886 - cmd[1] = 887 - FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_FAST_REQUEST) | 888 - FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | 889 - GUC_HXG_EVENT_MSG_0_DATA0, action[0]); 820 + cmd[1] = MAKE_ACTION(GUC_HXG_TYPE_FAST_REQUEST, action[0]); 890 821 } 891 822 892 823 /* H2G header in cmd[1] replaces action[0] so: */ ··· 915 854 u32 len, u32 g2h_len, u32 num_g2h, 916 855 struct g2h_fence *g2h_fence) 917 856 { 918 - struct xe_gt *gt __maybe_unused = ct_to_gt(ct); 857 + struct xe_gt *gt = ct_to_gt(ct); 919 858 u16 seqno; 920 859 int ret; 921 860 ··· 936 875 goto out; 937 876 } 938 877 939 - if (ct->state == XE_GUC_CT_STATE_STOPPED) { 878 + if (ct->state == XE_GUC_CT_STATE_STOPPED || xe_gt_recovery_pending(gt)) { 940 879 ret = -ECANCELED; 941 880 goto out; 942 881 } ··· 991 930 992 931 static int dequeue_one_g2h(struct xe_guc_ct *ct); 993 932 994 - static int guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action, u32 len, 995 - u32 g2h_len, u32 num_g2h, 996 - struct g2h_fence *g2h_fence) 933 + /* 934 + * wait before retry of sending h2g message 935 + * Return: true if ready for retry, false if the wait timeouted 936 + */ 937 + static bool guc_ct_send_wait_for_retry(struct xe_guc_ct *ct, u32 len, 938 + u32 g2h_len, struct g2h_fence *g2h_fence, 939 + unsigned int *sleep_period_ms) 997 940 { 998 941 struct xe_device *xe = ct_to_xe(ct); 999 - struct xe_gt *gt = ct_to_gt(ct); 1000 - unsigned int sleep_period_ms = 1; 1001 - int ret; 1002 - 1003 - xe_gt_assert(gt, !g2h_len || !g2h_fence); 1004 - lockdep_assert_held(&ct->lock); 1005 - xe_device_assert_mem_access(ct_to_xe(ct)); 1006 - 1007 - try_again: 1008 - ret = __guc_ct_send_locked(ct, action, len, g2h_len, num_g2h, 1009 - g2h_fence); 1010 942 1011 943 /* 1012 944 * We wait to try to restore credits for about 1 second before bailing. ··· 1008 954 * the case of G2H we process any G2H in the channel, hopefully freeing 1009 955 * credits as we consume the G2H messages. 1010 956 */ 1011 - if (unlikely(ret == -EBUSY && 1012 - !h2g_has_room(ct, len + GUC_CTB_HDR_LEN))) { 957 + if (!h2g_has_room(ct, len + GUC_CTB_HDR_LEN)) { 1013 958 struct guc_ctb *h2g = &ct->ctbs.h2g; 1014 959 1015 - if (sleep_period_ms == 1024) 1016 - goto broken; 960 + if (*sleep_period_ms == 1024) 961 + return false; 1017 962 1018 963 trace_xe_guc_ct_h2g_flow_control(xe, h2g->info.head, h2g->info.tail, 1019 964 h2g->info.size, 1020 965 h2g->info.space, 1021 966 len + GUC_CTB_HDR_LEN); 1022 - msleep(sleep_period_ms); 1023 - sleep_period_ms <<= 1; 1024 - 1025 - goto try_again; 1026 - } else if (unlikely(ret == -EBUSY)) { 967 + msleep(*sleep_period_ms); 968 + *sleep_period_ms <<= 1; 969 + } else { 1027 970 struct xe_device *xe = ct_to_xe(ct); 1028 971 struct guc_ctb *g2h = &ct->ctbs.g2h; 972 + int ret; 1029 973 1030 974 trace_xe_guc_ct_g2h_flow_control(xe, g2h->info.head, 1031 975 desc_read(xe, g2h, tail), ··· 1037 985 (desc_read(ct_to_xe(ct), (&ct->ctbs.g2h), tail) != ct->ctbs.g2h.info.head) 1038 986 if (!wait_event_timeout(ct->wq, !ct->g2h_outstanding || 1039 987 g2h_avail(ct), HZ)) 1040 - goto broken; 988 + return false; 1041 989 #undef g2h_avail 1042 990 1043 991 ret = dequeue_one_g2h(ct); ··· 1045 993 if (ret != -ECANCELED) 1046 994 xe_gt_err(ct_to_gt(ct), "CTB receive failed (%pe)", 1047 995 ERR_PTR(ret)); 1048 - goto broken; 996 + return false; 1049 997 } 998 + } 999 + return true; 1000 + } 1050 1001 1002 + static int guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action, u32 len, 1003 + u32 g2h_len, u32 num_g2h, 1004 + struct g2h_fence *g2h_fence) 1005 + { 1006 + struct xe_gt *gt = ct_to_gt(ct); 1007 + unsigned int sleep_period_ms = 1; 1008 + int ret; 1009 + 1010 + xe_gt_assert(gt, !g2h_len || !g2h_fence); 1011 + lockdep_assert_held(&ct->lock); 1012 + xe_device_assert_mem_access(ct_to_xe(ct)); 1013 + 1014 + try_again: 1015 + ret = __guc_ct_send_locked(ct, action, len, g2h_len, num_g2h, 1016 + g2h_fence); 1017 + 1018 + if (unlikely(ret == -EBUSY)) { 1019 + if (!guc_ct_send_wait_for_retry(ct, len, g2h_len, g2h_fence, 1020 + &sleep_period_ms)) 1021 + goto broken; 1051 1022 goto try_again; 1052 1023 } 1053 1024 ··· 1411 1336 type, fence); 1412 1337 1413 1338 fast_req_report(ct, fence); 1339 + 1340 + /* FIXME: W/A race in the GuC, will get in firmware soon */ 1341 + if (xe_gt_recovery_pending(gt)) 1342 + return 0; 1414 1343 1415 1344 CT_DEAD(ct, NULL, PARSE_G2H_RESPONSE); 1416 1345 ··· 1870 1791 struct xe_guc_ct *ct = container_of(w, struct xe_guc_ct, g2h_worker); 1871 1792 1872 1793 receive_g2h(ct); 1873 - } 1874 - 1875 - static void xe_fixup_u64_in_cmds(struct xe_device *xe, struct iosys_map *cmds, 1876 - u32 size, u32 idx, s64 shift) 1877 - { 1878 - u32 hi, lo; 1879 - u64 offset; 1880 - 1881 - lo = xe_map_rd_ring_u32(xe, cmds, idx, size); 1882 - hi = xe_map_rd_ring_u32(xe, cmds, idx + 1, size); 1883 - offset = make_u64(hi, lo); 1884 - offset += shift; 1885 - lo = lower_32_bits(offset); 1886 - hi = upper_32_bits(offset); 1887 - xe_map_wr_ring_u32(xe, cmds, idx, size, lo); 1888 - xe_map_wr_ring_u32(xe, cmds, idx + 1, size, hi); 1889 - } 1890 - 1891 - /* 1892 - * Shift any GGTT addresses within a single message left within CTB from 1893 - * before post-migration recovery. 1894 - * @ct: pointer to CT struct of the target GuC 1895 - * @cmds: iomap buffer containing CT messages 1896 - * @head: start of the target message within the buffer 1897 - * @len: length of the target message 1898 - * @size: size of the commands buffer 1899 - * @shift: the address shift to be added to each GGTT reference 1900 - * Return: true if the message was fixed or needed no fixups, false on failure 1901 - */ 1902 - static bool ct_fixup_ggtt_in_message(struct xe_guc_ct *ct, 1903 - struct iosys_map *cmds, u32 head, 1904 - u32 len, u32 size, s64 shift) 1905 - { 1906 - struct xe_gt *gt = ct_to_gt(ct); 1907 - struct xe_device *xe = ct_to_xe(ct); 1908 - u32 msg[GUC_HXG_MSG_MIN_LEN]; 1909 - u32 action, i, n; 1910 - 1911 - xe_gt_assert(gt, len >= GUC_HXG_MSG_MIN_LEN); 1912 - 1913 - msg[0] = xe_map_rd_ring_u32(xe, cmds, head, size); 1914 - action = FIELD_GET(GUC_HXG_REQUEST_MSG_0_ACTION, msg[0]); 1915 - 1916 - xe_gt_sriov_dbg_verbose(gt, "fixing H2G %#x\n", action); 1917 - 1918 - switch (action) { 1919 - case XE_GUC_ACTION_REGISTER_CONTEXT: 1920 - if (len != XE_GUC_REGISTER_CONTEXT_MSG_LEN) 1921 - goto err_len; 1922 - xe_fixup_u64_in_cmds(xe, cmds, size, head + 1923 - XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER, 1924 - shift); 1925 - xe_fixup_u64_in_cmds(xe, cmds, size, head + 1926 - XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER, 1927 - shift); 1928 - xe_fixup_u64_in_cmds(xe, cmds, size, head + 1929 - XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR, shift); 1930 - break; 1931 - case XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC: 1932 - if (len < XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN) 1933 - goto err_len; 1934 - n = xe_map_rd_ring_u32(xe, cmds, head + 1935 - XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS, size); 1936 - if (len != XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN + 2 * n) 1937 - goto err_len; 1938 - xe_fixup_u64_in_cmds(xe, cmds, size, head + 1939 - XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER, 1940 - shift); 1941 - xe_fixup_u64_in_cmds(xe, cmds, size, head + 1942 - XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER, 1943 - shift); 1944 - for (i = 0; i < n; i++) 1945 - xe_fixup_u64_in_cmds(xe, cmds, size, head + 1946 - XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR 1947 - + 2 * i, shift); 1948 - break; 1949 - default: 1950 - break; 1951 - } 1952 - return true; 1953 - 1954 - err_len: 1955 - xe_gt_err(gt, "Skipped G2G %#x message fixups, unexpected length (%u)\n", action, len); 1956 - return false; 1957 - } 1958 - 1959 - /* 1960 - * Apply fixups to the next outgoing CT message within given CTB 1961 - * @ct: the &xe_guc_ct struct instance representing the target GuC 1962 - * @h2g: the &guc_ctb struct instance of the target buffer 1963 - * @shift: shift to be added to all GGTT addresses within the CTB 1964 - * @mhead: pointer to an integer storing message start position; the 1965 - * position is changed to next message before this function return 1966 - * @avail: size of the area available for parsing, that is length 1967 - * of all remaining messages stored within the CTB 1968 - * Return: size of the area available for parsing after one message 1969 - * has been parsed, that is length remaining from the updated mhead 1970 - */ 1971 - static int ct_fixup_ggtt_in_buffer(struct xe_guc_ct *ct, struct guc_ctb *h2g, 1972 - s64 shift, u32 *mhead, s32 avail) 1973 - { 1974 - struct xe_gt *gt = ct_to_gt(ct); 1975 - struct xe_device *xe = ct_to_xe(ct); 1976 - u32 msg[GUC_HXG_MSG_MIN_LEN]; 1977 - u32 size = h2g->info.size; 1978 - u32 head = *mhead; 1979 - u32 len; 1980 - 1981 - xe_gt_assert(gt, avail >= (s32)GUC_CTB_MSG_MIN_LEN); 1982 - 1983 - /* Read header */ 1984 - msg[0] = xe_map_rd_ring_u32(xe, &h2g->cmds, head, size); 1985 - len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, msg[0]) + GUC_CTB_MSG_MIN_LEN; 1986 - 1987 - if (unlikely(len > (u32)avail)) { 1988 - xe_gt_err(gt, "H2G channel broken on read, avail=%d, len=%d, fixups skipped\n", 1989 - avail, len); 1990 - return 0; 1991 - } 1992 - 1993 - head = (head + GUC_CTB_MSG_MIN_LEN) % size; 1994 - if (!ct_fixup_ggtt_in_message(ct, &h2g->cmds, head, msg_len_to_hxg_len(len), size, shift)) 1995 - return 0; 1996 - *mhead = (head + msg_len_to_hxg_len(len)) % size; 1997 - 1998 - return avail - len; 1999 - } 2000 - 2001 - /** 2002 - * xe_guc_ct_fixup_messages_with_ggtt - Fixup any pending H2G CTB messages 2003 - * @ct: pointer to CT struct of the target GuC 2004 - * @ggtt_shift: shift to be added to all GGTT addresses within the CTB 2005 - * 2006 - * Messages in GuC to Host CTB are owned by GuC and any fixups in them 2007 - * are made by GuC. But content of the Host to GuC CTB is owned by the 2008 - * KMD, so fixups to GGTT references in any pending messages need to be 2009 - * applied here. 2010 - * This function updates GGTT offsets in payloads of pending H2G CTB 2011 - * messages (messages which were not consumed by GuC before the VF got 2012 - * paused). 2013 - */ 2014 - void xe_guc_ct_fixup_messages_with_ggtt(struct xe_guc_ct *ct, s64 ggtt_shift) 2015 - { 2016 - struct guc_ctb *h2g = &ct->ctbs.h2g; 2017 - struct xe_guc *guc = ct_to_guc(ct); 2018 - struct xe_gt *gt = guc_to_gt(guc); 2019 - u32 head, tail, size; 2020 - s32 avail; 2021 - 2022 - if (unlikely(h2g->info.broken)) 2023 - return; 2024 - 2025 - h2g->info.head = desc_read(ct_to_xe(ct), h2g, head); 2026 - head = h2g->info.head; 2027 - tail = READ_ONCE(h2g->info.tail); 2028 - size = h2g->info.size; 2029 - 2030 - if (unlikely(head > size)) 2031 - goto corrupted; 2032 - 2033 - if (unlikely(tail >= size)) 2034 - goto corrupted; 2035 - 2036 - avail = tail - head; 2037 - 2038 - /* beware of buffer wrap case */ 2039 - if (unlikely(avail < 0)) 2040 - avail += size; 2041 - xe_gt_dbg(gt, "available %d (%u:%u:%u)\n", avail, head, tail, size); 2042 - xe_gt_assert(gt, avail >= 0); 2043 - 2044 - while (avail > 0) 2045 - avail = ct_fixup_ggtt_in_buffer(ct, h2g, ggtt_shift, &head, avail); 2046 - 2047 - return; 2048 - 2049 - corrupted: 2050 - xe_gt_err(gt, "Corrupted H2G descriptor head=%u tail=%u size=%u, fixups not applied\n", 2051 - head, tail, size); 2052 - h2g->info.broken = true; 2053 1794 } 2054 1795 2055 1796 static struct xe_guc_ct_snapshot *guc_ct_snapshot_alloc(struct xe_guc_ct *ct, bool atomic,
+11 -2
drivers/gpu/drm/xe/xe_guc_ct.h
··· 15 15 int xe_guc_ct_init(struct xe_guc_ct *ct); 16 16 int xe_guc_ct_init_post_hwconfig(struct xe_guc_ct *ct); 17 17 int xe_guc_ct_enable(struct xe_guc_ct *ct); 18 + int xe_guc_ct_restart(struct xe_guc_ct *ct); 18 19 void xe_guc_ct_disable(struct xe_guc_ct *ct); 19 20 void xe_guc_ct_stop(struct xe_guc_ct *ct); 21 + void xe_guc_ct_flush_and_stop(struct xe_guc_ct *ct); 20 22 void xe_guc_ct_fast_path(struct xe_guc_ct *ct); 21 23 22 24 struct xe_guc_ct_snapshot *xe_guc_ct_snapshot_capture(struct xe_guc_ct *ct); 23 25 void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, struct drm_printer *p); 24 26 void xe_guc_ct_snapshot_free(struct xe_guc_ct_snapshot *snapshot); 25 27 void xe_guc_ct_print(struct xe_guc_ct *ct, struct drm_printer *p, bool want_ctb); 26 - 27 - void xe_guc_ct_fixup_messages_with_ggtt(struct xe_guc_ct *ct, s64 ggtt_shift); 28 28 29 29 static inline bool xe_guc_ct_initialized(struct xe_guc_ct *ct) 30 30 { ··· 73 73 } 74 74 75 75 long xe_guc_ct_queue_proc_time_jiffies(struct xe_guc_ct *ct); 76 + 77 + /** 78 + * xe_guc_ct_wake_waiters() - GuC CT wake up waiters 79 + * @ct: GuC CT object 80 + */ 81 + static inline void xe_guc_ct_wake_waiters(struct xe_guc_ct *ct) 82 + { 83 + wake_up_all(&ct->wq); 84 + } 76 85 77 86 #endif
+15
drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
··· 51 51 wait_queue_head_t suspend_wait; 52 52 /** @suspend_pending: a suspend of the exec_queue is pending */ 53 53 bool suspend_pending; 54 + /** 55 + * @needs_cleanup: Needs a cleanup message during VF post migration 56 + * recovery. 57 + */ 58 + bool needs_cleanup; 59 + /** 60 + * @needs_suspend: Needs a suspend message during VF post migration 61 + * recovery. 62 + */ 63 + bool needs_suspend; 64 + /** 65 + * @needs_resume: Needs a resume message during VF post migration 66 + * recovery. 67 + */ 68 + bool needs_resume; 54 69 }; 55 70 56 71 #endif
+15 -32
drivers/gpu/drm/xe/xe_guc_pc.c
··· 7 7 8 8 #include <linux/cleanup.h> 9 9 #include <linux/delay.h> 10 + #include <linux/iopoll.h> 10 11 #include <linux/jiffies.h> 11 12 #include <linux/ktime.h> 12 13 #include <linux/wait_bit.h> 13 14 14 15 #include <drm/drm_managed.h> 15 16 #include <drm/drm_print.h> 17 + #include <generated/xe_device_wa_oob.h> 16 18 #include <generated/xe_wa_oob.h> 17 19 18 20 #include "abi/guc_actions_slpc_abi.h" ··· 132 130 FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC, count)) 133 131 134 132 static int wait_for_pc_state(struct xe_guc_pc *pc, 135 - enum slpc_global_state state, 133 + enum slpc_global_state target_state, 136 134 int timeout_ms) 137 135 { 138 - int timeout_us = 1000 * timeout_ms; 139 - int slept, wait = 10; 136 + enum slpc_global_state state; 140 137 141 138 xe_device_assert_mem_access(pc_to_xe(pc)); 142 139 143 - for (slept = 0; slept < timeout_us;) { 144 - if (slpc_shared_data_read(pc, header.global_state) == state) 145 - return 0; 146 - 147 - usleep_range(wait, wait << 1); 148 - slept += wait; 149 - wait <<= 1; 150 - if (slept + wait > timeout_us) 151 - wait = timeout_us - slept; 152 - } 153 - 154 - return -ETIMEDOUT; 140 + return poll_timeout_us(state = slpc_shared_data_read(pc, header.global_state), 141 + state == target_state, 142 + 20, timeout_ms * USEC_PER_MSEC, false); 155 143 } 156 144 157 145 static int wait_for_flush_complete(struct xe_guc_pc *pc) ··· 156 164 return 0; 157 165 } 158 166 159 - static int wait_for_act_freq_limit(struct xe_guc_pc *pc, u32 freq) 167 + static int wait_for_act_freq_max_limit(struct xe_guc_pc *pc, u32 max_limit) 160 168 { 161 - int timeout_us = SLPC_ACT_FREQ_TIMEOUT_MS * USEC_PER_MSEC; 162 - int slept, wait = 10; 169 + u32 freq; 163 170 164 - for (slept = 0; slept < timeout_us;) { 165 - if (xe_guc_pc_get_act_freq(pc) <= freq) 166 - return 0; 167 - 168 - usleep_range(wait, wait << 1); 169 - slept += wait; 170 - wait <<= 1; 171 - if (slept + wait > timeout_us) 172 - wait = timeout_us - slept; 173 - } 174 - 175 - return -ETIMEDOUT; 171 + return poll_timeout_us(freq = xe_guc_pc_get_act_freq(pc), 172 + freq <= max_limit, 173 + 20, SLPC_ACT_FREQ_TIMEOUT_MS * USEC_PER_MSEC, false); 176 174 } 175 + 177 176 static int pc_action_reset(struct xe_guc_pc *pc) 178 177 { 179 178 struct xe_guc_ct *ct = pc_to_ct(pc); ··· 887 904 if (pc_get_min_freq(pc) > pc->rp0_freq) 888 905 ret = pc_set_min_freq(pc, pc->rp0_freq); 889 906 890 - if (XE_GT_WA(tile->primary_gt, 14022085890)) 907 + if (XE_DEVICE_WA(tile_to_xe(tile), 14022085890)) 891 908 ret = pc_set_min_freq(pc, max(BMG_MIN_FREQ, pc_get_min_freq(pc))); 892 909 893 910 out: ··· 966 983 * Wait for actual freq to go below the flush cap: even if the previous 967 984 * max was below cap, the current one might still be above it 968 985 */ 969 - ret = wait_for_act_freq_limit(pc, BMG_MERT_FLUSH_FREQ_CAP); 986 + ret = wait_for_act_freq_max_limit(pc, BMG_MERT_FLUSH_FREQ_CAP); 970 987 if (ret) 971 988 xe_gt_err_once(gt, "Actual freq did not reduce to %u, %pe\n", 972 989 BMG_MERT_FLUSH_FREQ_CAP, ERR_PTR(ret));
+15 -2
drivers/gpu/drm/xe/xe_guc_relay.c
··· 56 56 return gt_to_xe(relay_to_gt(relay)); 57 57 } 58 58 59 + #define XE_RELAY_DIAG_RATELIMIT_INTERVAL (10 * HZ) 60 + #define XE_RELAY_DIAG_RATELIMIT_BURST 10 61 + 62 + #define relay_ratelimit_printk(relay, _level, fmt...) ({ \ 63 + typeof(relay) _r = (relay); \ 64 + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) || \ 65 + ___ratelimit(&_r->diag_ratelimit, "xe_guc_relay")) \ 66 + xe_gt_sriov_##_level(relay_to_gt(_r), "relay: " fmt); \ 67 + }) 68 + 59 69 #define relay_assert(relay, condition) xe_gt_assert(relay_to_gt(relay), condition) 60 - #define relay_notice(relay, msg...) xe_gt_sriov_notice(relay_to_gt(relay), "relay: " msg) 61 - #define relay_debug(relay, msg...) xe_gt_sriov_dbg_verbose(relay_to_gt(relay), "relay: " msg) 70 + #define relay_notice(relay, msg...) relay_ratelimit_printk((relay), notice, msg) 71 + #define relay_debug(relay, msg...) relay_ratelimit_printk((relay), dbg_verbose, msg) 62 72 63 73 static int relay_get_totalvfs(struct xe_guc_relay *relay) 64 74 { ··· 355 345 INIT_WORK(&relay->worker, relays_worker_fn); 356 346 INIT_LIST_HEAD(&relay->pending_relays); 357 347 INIT_LIST_HEAD(&relay->incoming_actions); 348 + ratelimit_state_init(&relay->diag_ratelimit, 349 + XE_RELAY_DIAG_RATELIMIT_INTERVAL, 350 + XE_RELAY_DIAG_RATELIMIT_BURST); 358 351 359 352 err = mempool_init_kmalloc_pool(&relay->pool, XE_RELAY_MEMPOOL_MIN_NUM + 360 353 relay_get_totalvfs(relay),
+4
drivers/gpu/drm/xe/xe_guc_relay_types.h
··· 7 7 #define _XE_GUC_RELAY_TYPES_H_ 8 8 9 9 #include <linux/mempool.h> 10 + #include <linux/ratelimit_types.h> 10 11 #include <linux/spinlock.h> 11 12 #include <linux/workqueue.h> 12 13 ··· 32 31 33 32 /** @last_rid: last Relay-ID used while sending a message. */ 34 33 u32 last_rid; 34 + 35 + /** @diag_ratelimit: ratelimit state used to throttle diagnostics messages. */ 36 + struct ratelimit_state diag_ratelimit; 35 37 }; 36 38 37 39 #endif
+443 -161
drivers/gpu/drm/xe/xe_guc_submit.c
··· 70 70 #define EXEC_QUEUE_STATE_BANNED (1 << 9) 71 71 #define EXEC_QUEUE_STATE_CHECK_TIMEOUT (1 << 10) 72 72 #define EXEC_QUEUE_STATE_EXTRA_REF (1 << 11) 73 + #define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 12) 74 + #define EXEC_QUEUE_STATE_PENDING_TDR_EXIT (1 << 13) 73 75 74 76 static bool exec_queue_registered(struct xe_exec_queue *q) 75 77 { ··· 141 139 static void set_exec_queue_destroyed(struct xe_exec_queue *q) 142 140 { 143 141 atomic_or(EXEC_QUEUE_STATE_DESTROYED, &q->guc->state); 142 + } 143 + 144 + static void clear_exec_queue_destroyed(struct xe_exec_queue *q) 145 + { 146 + atomic_and(~EXEC_QUEUE_STATE_DESTROYED, &q->guc->state); 144 147 } 145 148 146 149 static bool exec_queue_banned(struct xe_exec_queue *q) ··· 226 219 static void set_exec_queue_extra_ref(struct xe_exec_queue *q) 227 220 { 228 221 atomic_or(EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); 222 + } 223 + 224 + static void clear_exec_queue_extra_ref(struct xe_exec_queue *q) 225 + { 226 + atomic_and(~EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); 227 + } 228 + 229 + static bool exec_queue_pending_resume(struct xe_exec_queue *q) 230 + { 231 + return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_RESUME; 232 + } 233 + 234 + static void set_exec_queue_pending_resume(struct xe_exec_queue *q) 235 + { 236 + atomic_or(EXEC_QUEUE_STATE_PENDING_RESUME, &q->guc->state); 237 + } 238 + 239 + static void clear_exec_queue_pending_resume(struct xe_exec_queue *q) 240 + { 241 + atomic_and(~EXEC_QUEUE_STATE_PENDING_RESUME, &q->guc->state); 242 + } 243 + 244 + static bool exec_queue_pending_tdr_exit(struct xe_exec_queue *q) 245 + { 246 + return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_TDR_EXIT; 247 + } 248 + 249 + static void set_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) 250 + { 251 + atomic_or(EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); 252 + } 253 + 254 + static void clear_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) 255 + { 256 + atomic_and(~EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); 229 257 } 230 258 231 259 static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q) ··· 712 670 return (WQ_SIZE - q->guc->wqi_tail); 713 671 } 714 672 673 + static bool vf_recovery(struct xe_guc *guc) 674 + { 675 + return xe_gt_recovery_pending(guc_to_gt(guc)); 676 + } 677 + 715 678 static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size) 716 679 { 717 680 struct xe_guc *guc = exec_queue_to_guc(q); ··· 726 679 727 680 #define AVAILABLE_SPACE \ 728 681 CIRC_SPACE(q->guc->wqi_tail, q->guc->wqi_head, WQ_SIZE) 729 - if (wqi_size > AVAILABLE_SPACE) { 682 + if (wqi_size > AVAILABLE_SPACE && !vf_recovery(guc)) { 730 683 try_again: 731 684 q->guc->wqi_head = parallel_read(xe, map, wq_desc.head); 732 685 if (wqi_size > AVAILABLE_SPACE) { ··· 783 736 if (wq_wait_for_space(q, wqi_size)) 784 737 return; 785 738 786 - xe_gt_assert(guc_to_gt(guc), i == XE_GUC_CONTEXT_WQ_HEADER_DATA_0_TYPE_LEN); 787 739 wqi[i++] = FIELD_PREP(WQ_TYPE_MASK, WQ_TYPE_MULTI_LRC) | 788 740 FIELD_PREP(WQ_LEN_MASK, len_dw); 789 - xe_gt_assert(guc_to_gt(guc), i == XE_GUC_CONTEXT_WQ_EL_INFO_DATA_1_CTX_DESC_LOW); 790 741 wqi[i++] = xe_lrc_descriptor(q->lrc[0]); 791 - xe_gt_assert(guc_to_gt(guc), i == 792 - XE_GUC_CONTEXT_WQ_EL_INFO_DATA_2_GUCCTX_RINGTAIL_FREEZEPOCS); 793 742 wqi[i++] = FIELD_PREP(WQ_GUC_ID_MASK, q->guc->id) | 794 743 FIELD_PREP(WQ_RING_TAIL_MASK, q->lrc[0]->ring.tail / sizeof(u64)); 795 - xe_gt_assert(guc_to_gt(guc), i == XE_GUC_CONTEXT_WQ_EL_INFO_DATA_3_WI_FENCE_ID); 796 744 wqi[i++] = 0; 797 - xe_gt_assert(guc_to_gt(guc), i == XE_GUC_CONTEXT_WQ_EL_CHILD_LIST_DATA_4_RINGTAIL); 798 745 for (j = 1; j < q->width; ++j) { 799 746 struct xe_lrc *lrc = q->lrc[j]; 800 747 ··· 809 768 parallel_write(xe, map, wq_desc.tail, q->guc->wqi_tail); 810 769 } 811 770 812 - static int wq_items_rebase(struct xe_exec_queue *q) 813 - { 814 - struct xe_guc *guc = exec_queue_to_guc(q); 815 - struct xe_device *xe = guc_to_xe(guc); 816 - struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]); 817 - int i = q->guc->wqi_head; 818 - 819 - /* the ring starts after a header struct */ 820 - iosys_map_incr(&map, offsetof(struct guc_submit_parallel_scratch, wq[0])); 821 - 822 - while ((i % WQ_SIZE) != (q->guc->wqi_tail % WQ_SIZE)) { 823 - u32 len_dw, type, val; 824 - 825 - if (drm_WARN_ON_ONCE(&xe->drm, i < 0 || i > 2 * WQ_SIZE)) 826 - break; 827 - 828 - val = xe_map_rd_ring_u32(xe, &map, i / sizeof(u32) + 829 - XE_GUC_CONTEXT_WQ_HEADER_DATA_0_TYPE_LEN, 830 - WQ_SIZE / sizeof(u32)); 831 - len_dw = FIELD_GET(WQ_LEN_MASK, val); 832 - type = FIELD_GET(WQ_TYPE_MASK, val); 833 - 834 - if (drm_WARN_ON_ONCE(&xe->drm, len_dw >= WQ_SIZE / sizeof(u32))) 835 - break; 836 - 837 - if (type == WQ_TYPE_MULTI_LRC) { 838 - val = xe_lrc_descriptor(q->lrc[0]); 839 - xe_map_wr_ring_u32(xe, &map, i / sizeof(u32) + 840 - XE_GUC_CONTEXT_WQ_EL_INFO_DATA_1_CTX_DESC_LOW, 841 - WQ_SIZE / sizeof(u32), val); 842 - } else if (drm_WARN_ON_ONCE(&xe->drm, type != WQ_TYPE_NOOP)) { 843 - break; 844 - } 845 - 846 - i += (len_dw + 1) * sizeof(u32); 847 - } 848 - 849 - if ((i % WQ_SIZE) != (q->guc->wqi_tail % WQ_SIZE)) { 850 - xe_gt_err(q->gt, "Exec queue fixups incomplete - wqi parse failed\n"); 851 - return -EBADMSG; 852 - } 853 - return 0; 854 - } 855 - 856 771 #define RESUME_PENDING ~0x0ull 857 - static void submit_exec_queue(struct xe_exec_queue *q) 772 + static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job) 858 773 { 859 774 struct xe_guc *guc = exec_queue_to_guc(q); 860 775 struct xe_lrc *lrc = q->lrc[0]; ··· 822 825 823 826 xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q)); 824 827 825 - if (xe_exec_queue_is_parallel(q)) 826 - wq_item_append(q); 827 - else 828 - xe_lrc_set_ring_tail(lrc, lrc->ring.tail); 828 + if (!job->skip_emit || job->last_replay) { 829 + if (xe_exec_queue_is_parallel(q)) 830 + wq_item_append(q); 831 + else 832 + xe_lrc_set_ring_tail(lrc, lrc->ring.tail); 833 + job->last_replay = false; 834 + } 829 835 830 836 if (exec_queue_suspended(q) && !xe_exec_queue_is_parallel(q)) 831 837 return; ··· 870 870 struct xe_sched_job *job = to_xe_sched_job(drm_job); 871 871 struct xe_exec_queue *q = job->q; 872 872 struct xe_guc *guc = exec_queue_to_guc(q); 873 - struct dma_fence *fence = NULL; 874 - bool lr = xe_exec_queue_is_lr(q); 873 + bool lr = xe_exec_queue_is_lr(q), killed_or_banned_or_wedged = 874 + exec_queue_killed_or_banned_or_wedged(q); 875 875 876 876 xe_gt_assert(guc_to_gt(guc), !(exec_queue_destroyed(q) || exec_queue_pending_disable(q)) || 877 877 exec_queue_banned(q) || exec_queue_suspended(q)); 878 878 879 879 trace_xe_sched_job_run(job); 880 880 881 - if (!exec_queue_killed_or_banned_or_wedged(q) && !xe_sched_job_is_error(job)) { 881 + if (!killed_or_banned_or_wedged && !xe_sched_job_is_error(job)) { 882 882 if (!exec_queue_registered(q)) 883 883 register_exec_queue(q, GUC_CONTEXT_NORMAL); 884 - if (!lr) /* LR jobs are emitted in the exec IOCTL */ 884 + if (!job->skip_emit) 885 885 q->ring_ops->emit_job(job); 886 - submit_exec_queue(q); 886 + submit_exec_queue(q, job); 887 + job->skip_emit = false; 887 888 } 888 - 889 - if (lr) { 890 - xe_sched_job_set_error(job, -EOPNOTSUPP); 891 - dma_fence_put(job->fence); /* Drop ref from xe_sched_job_arm */ 892 - } else { 893 - fence = job->fence; 894 - } 895 - 896 - return fence; 897 - } 898 - 899 - /** 900 - * xe_guc_jobs_ring_rebase - Re-emit ring commands of requests pending 901 - * on all queues under a guc. 902 - * @guc: the &xe_guc struct instance 903 - */ 904 - void xe_guc_jobs_ring_rebase(struct xe_guc *guc) 905 - { 906 - struct xe_exec_queue *q; 907 - unsigned long index; 908 889 909 890 /* 910 - * This routine is used within VF migration recovery. This means 911 - * using the lock here introduces a restriction: we cannot wait 912 - * for any GFX HW response while the lock is taken. 891 + * We don't care about job-fence ordering in LR VMs because these fences 892 + * are never exported; they are used solely to keep jobs on the pending 893 + * list. Once a queue enters an error state, there's no need to track 894 + * them. 913 895 */ 914 - mutex_lock(&guc->submission_state.lock); 915 - xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { 916 - if (exec_queue_killed_or_banned_or_wedged(q)) 917 - continue; 918 - xe_exec_queue_jobs_ring_restore(q); 919 - } 920 - mutex_unlock(&guc->submission_state.lock); 896 + if (killed_or_banned_or_wedged && lr) 897 + xe_sched_job_set_error(job, -ECANCELED); 898 + 899 + return job->fence; 921 900 } 922 901 923 902 static void guc_exec_queue_free_job(struct drm_sched_job *drm_job) ··· 930 951 ret = wait_event_timeout(guc->ct.wq, 931 952 (!exec_queue_pending_enable(q) && 932 953 !exec_queue_pending_disable(q)) || 933 - xe_guc_read_stopped(guc), 954 + xe_guc_read_stopped(guc) || 955 + vf_recovery(guc), 934 956 HZ * 5); 935 - if (!ret) { 957 + if (!ret && !vf_recovery(guc)) { 936 958 struct xe_gpu_scheduler *sched = &q->guc->sched; 937 959 938 960 xe_gt_warn(q->gt, "Pending enable/disable failed to respond\n"); 939 961 xe_sched_submission_start(sched); 940 962 xe_gt_reset_async(q->gt); 941 - xe_sched_tdr_queue_imm(sched); 963 + if (!xe_exec_queue_is_lr(q)) 964 + xe_sched_tdr_queue_imm(sched); 942 965 return; 943 966 } 944 967 ··· 1032 1051 struct xe_exec_queue *q = ge->q; 1033 1052 struct xe_guc *guc = exec_queue_to_guc(q); 1034 1053 struct xe_gpu_scheduler *sched = &ge->sched; 1054 + struct xe_sched_job *job; 1035 1055 bool wedged = false; 1036 1056 1037 1057 xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_lr(q)); 1058 + 1059 + if (vf_recovery(guc)) 1060 + return; 1061 + 1038 1062 trace_xe_exec_queue_lr_cleanup(q); 1039 1063 1040 1064 if (!exec_queue_killed(q)) ··· 1072 1086 */ 1073 1087 ret = wait_event_timeout(guc->ct.wq, 1074 1088 !exec_queue_pending_disable(q) || 1075 - xe_guc_read_stopped(guc), HZ * 5); 1089 + xe_guc_read_stopped(guc) || 1090 + vf_recovery(guc), HZ * 5); 1091 + if (vf_recovery(guc)) 1092 + return; 1093 + 1076 1094 if (!ret) { 1077 1095 xe_gt_warn(q->gt, "Schedule disable failed to respond, guc_id=%d\n", 1078 1096 q->guc->id); ··· 1091 1101 if (!exec_queue_killed(q) && !xe_lrc_ring_is_idle(q->lrc[0])) 1092 1102 xe_devcoredump(q, NULL, "LR job cleanup, guc_id=%d", q->guc->id); 1093 1103 1104 + xe_hw_fence_irq_stop(q->fence_irq); 1105 + 1094 1106 xe_sched_submission_start(sched); 1107 + 1108 + spin_lock(&sched->base.job_list_lock); 1109 + list_for_each_entry(job, &sched->base.pending_list, drm.list) 1110 + xe_sched_job_set_error(job, -ECANCELED); 1111 + spin_unlock(&sched->base.job_list_lock); 1112 + 1113 + xe_hw_fence_irq_start(q->fence_irq); 1095 1114 } 1096 1115 1097 1116 #define ADJUST_FIVE_PERCENT(__t) mul_u64_u32_div(__t, 105, 100) ··· 1166 1167 1167 1168 ret = wait_event_timeout(guc->ct.wq, 1168 1169 !exec_queue_pending_enable(q) || 1169 - xe_guc_read_stopped(guc), HZ * 5); 1170 - if (!ret || xe_guc_read_stopped(guc)) { 1170 + xe_guc_read_stopped(guc) || 1171 + vf_recovery(guc), HZ * 5); 1172 + if ((!ret && !vf_recovery(guc)) || xe_guc_read_stopped(guc)) { 1171 1173 xe_gt_warn(guc_to_gt(guc), "Schedule enable failed to respond"); 1172 1174 set_exec_queue_banned(q); 1173 1175 xe_gt_reset_async(q->gt); 1174 - xe_sched_tdr_queue_imm(&q->guc->sched); 1176 + if (!xe_exec_queue_is_lr(q)) 1177 + xe_sched_tdr_queue_imm(&q->guc->sched); 1175 1178 } 1176 1179 } 1177 1180 ··· 1231 1230 int i = 0; 1232 1231 bool wedged = false, skip_timeout_check; 1233 1232 1233 + xe_gt_assert(guc_to_gt(guc), !xe_exec_queue_is_lr(q)); 1234 + 1234 1235 /* 1235 1236 * TDR has fired before free job worker. Common if exec queue 1236 1237 * immediately closed after last fence signaled. Add back to pending 1237 1238 * list so job can be freed and kick scheduler ensuring free job is not 1238 1239 * lost. 1239 1240 */ 1240 - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags)) 1241 + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags) || 1242 + vf_recovery(guc)) 1241 1243 return DRM_GPU_SCHED_STAT_NO_HANG; 1242 1244 1243 1245 /* Kill the run_job entry point */ ··· 1292 1288 ret = wait_event_timeout(guc->ct.wq, 1293 1289 (!exec_queue_pending_enable(q) && 1294 1290 !exec_queue_pending_disable(q)) || 1295 - xe_guc_read_stopped(guc), HZ * 5); 1291 + xe_guc_read_stopped(guc) || 1292 + vf_recovery(guc), HZ * 5); 1293 + if (vf_recovery(guc)) 1294 + goto handle_vf_resume; 1296 1295 if (!ret || xe_guc_read_stopped(guc)) 1297 1296 goto trigger_reset; 1298 1297 ··· 1320 1313 smp_rmb(); 1321 1314 ret = wait_event_timeout(guc->ct.wq, 1322 1315 !exec_queue_pending_disable(q) || 1323 - xe_guc_read_stopped(guc), HZ * 5); 1316 + xe_guc_read_stopped(guc) || 1317 + vf_recovery(guc), HZ * 5); 1318 + if (vf_recovery(guc)) 1319 + goto handle_vf_resume; 1324 1320 if (!ret || xe_guc_read_stopped(guc)) { 1325 1321 trigger_reset: 1326 1322 if (!ret) ··· 1419 1409 return DRM_GPU_SCHED_STAT_RESET; 1420 1410 1421 1411 sched_enable: 1412 + set_exec_queue_pending_tdr_exit(q); 1422 1413 enable_scheduling(q); 1423 1414 rearm: 1424 1415 /* ··· 1428 1417 * some thought, do this in a follow up. 1429 1418 */ 1430 1419 xe_sched_submission_start(sched); 1420 + handle_vf_resume: 1431 1421 return DRM_GPU_SCHED_STAT_NO_HANG; 1432 1422 } 1433 1423 ··· 1535 1523 1536 1524 static void __suspend_fence_signal(struct xe_exec_queue *q) 1537 1525 { 1526 + struct xe_guc *guc = exec_queue_to_guc(q); 1527 + struct xe_device *xe = guc_to_xe(guc); 1528 + 1538 1529 if (!q->guc->suspend_pending) 1539 1530 return; 1540 1531 1541 1532 WRITE_ONCE(q->guc->suspend_pending, false); 1542 - wake_up(&q->guc->suspend_wait); 1533 + 1534 + /* 1535 + * We use a GuC shared wait queue for VFs because the VF resfix start 1536 + * interrupt must be able to wake all instances of suspend_wait. This 1537 + * prevents the VF migration worker from being starved during 1538 + * scheduling. 1539 + */ 1540 + if (IS_SRIOV_VF(xe)) 1541 + wake_up_all(&guc->ct.wq); 1542 + else 1543 + wake_up(&q->guc->suspend_wait); 1543 1544 } 1544 1545 1545 1546 static void suspend_fence_signal(struct xe_exec_queue *q) ··· 1573 1548 1574 1549 if (guc_exec_queue_allowed_to_change_state(q) && !exec_queue_suspended(q) && 1575 1550 exec_queue_enabled(q)) { 1576 - wait_event(guc->ct.wq, (q->guc->resume_time != RESUME_PENDING || 1577 - xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q)); 1551 + wait_event(guc->ct.wq, vf_recovery(guc) || 1552 + ((q->guc->resume_time != RESUME_PENDING || 1553 + xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q))); 1578 1554 1579 1555 if (!xe_guc_read_stopped(guc)) { 1580 1556 s64 since_resume_ms = ··· 1604 1578 clear_exec_queue_suspended(q); 1605 1579 if (!exec_queue_enabled(q)) { 1606 1580 q->guc->resume_time = RESUME_PENDING; 1581 + set_exec_queue_pending_resume(q); 1607 1582 enable_scheduling(q); 1608 1583 } 1609 1584 } else { ··· 1618 1591 #define RESUME 4 1619 1592 #define OPCODE_MASK 0xf 1620 1593 #define MSG_LOCKED BIT(8) 1594 + #define MSG_HEAD BIT(9) 1621 1595 1622 1596 static void guc_exec_queue_process_msg(struct xe_sched_msg *msg) 1623 1597 { ··· 1681 1653 timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT : 1682 1654 msecs_to_jiffies(q->sched_props.job_timeout_ms); 1683 1655 err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops, 1684 - NULL, q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, 64, 1656 + NULL, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64, 1685 1657 timeout, guc_to_gt(guc)->ordered_wq, NULL, 1686 1658 q->name, gt_to_xe(q->gt)->drm.dev); 1687 1659 if (err) ··· 1703 1675 1704 1676 q->entity = &ge->entity; 1705 1677 1706 - if (xe_guc_read_stopped(guc)) 1678 + if (xe_guc_read_stopped(guc) || vf_recovery(guc)) 1707 1679 xe_sched_stop(sched); 1708 1680 1709 1681 mutex_unlock(&guc->submission_state.lock); ··· 1743 1715 msg->private_data = q; 1744 1716 1745 1717 trace_xe_sched_msg_add(msg); 1746 - if (opcode & MSG_LOCKED) 1718 + if (opcode & MSG_HEAD) 1719 + xe_sched_add_msg_head(&q->guc->sched, msg); 1720 + else if (opcode & MSG_LOCKED) 1747 1721 xe_sched_add_msg_locked(&q->guc->sched, msg); 1748 1722 else 1749 1723 xe_sched_add_msg(&q->guc->sched, msg); 1724 + } 1725 + 1726 + static void guc_exec_queue_try_add_msg_head(struct xe_exec_queue *q, 1727 + struct xe_sched_msg *msg, 1728 + u32 opcode) 1729 + { 1730 + if (!list_empty(&msg->link)) 1731 + return; 1732 + 1733 + guc_exec_queue_add_msg(q, msg, opcode | MSG_LOCKED | MSG_HEAD); 1750 1734 } 1751 1735 1752 1736 static bool guc_exec_queue_try_add_msg(struct xe_exec_queue *q, ··· 1861 1821 static int guc_exec_queue_suspend_wait(struct xe_exec_queue *q) 1862 1822 { 1863 1823 struct xe_guc *guc = exec_queue_to_guc(q); 1824 + struct xe_device *xe = guc_to_xe(guc); 1864 1825 int ret; 1865 1826 1866 1827 /* ··· 1869 1828 * suspend_pending upon kill but to be paranoid but races in which 1870 1829 * suspend_pending is set after kill also check kill here. 1871 1830 */ 1872 - ret = wait_event_interruptible_timeout(q->guc->suspend_wait, 1873 - !READ_ONCE(q->guc->suspend_pending) || 1874 - exec_queue_killed(q) || 1875 - xe_guc_read_stopped(guc), 1876 - HZ * 5); 1831 + #define WAIT_COND \ 1832 + (!READ_ONCE(q->guc->suspend_pending) || exec_queue_killed(q) || \ 1833 + xe_guc_read_stopped(guc)) 1834 + 1835 + retry: 1836 + if (IS_SRIOV_VF(xe)) 1837 + ret = wait_event_interruptible_timeout(guc->ct.wq, WAIT_COND || 1838 + vf_recovery(guc), 1839 + HZ * 5); 1840 + else 1841 + ret = wait_event_interruptible_timeout(q->guc->suspend_wait, 1842 + WAIT_COND, HZ * 5); 1843 + 1844 + if (vf_recovery(guc) && !xe_device_wedged((guc_to_xe(guc)))) 1845 + return -EAGAIN; 1877 1846 1878 1847 if (!ret) { 1879 1848 xe_gt_warn(guc_to_gt(guc), ··· 1891 1840 q->guc->id); 1892 1841 /* XXX: Trigger GT reset? */ 1893 1842 return -ETIME; 1843 + } else if (IS_SRIOV_VF(xe) && !WAIT_COND) { 1844 + /* Corner case on RESFIX DONE where vf_recovery() changes */ 1845 + goto retry; 1894 1846 } 1847 + 1848 + #undef WAIT_COND 1895 1849 1896 1850 return ret < 0 ? ret : 0; 1897 1851 } ··· 1992 1936 } 1993 1937 } 1994 1938 1995 - /** 1996 - * xe_guc_submit_reset_block - Disallow reset calls on given GuC. 1997 - * @guc: the &xe_guc struct instance 1998 - */ 1999 - int xe_guc_submit_reset_block(struct xe_guc *guc) 2000 - { 2001 - return atomic_fetch_or(1, &guc->submission_state.reset_blocked); 2002 - } 2003 - 2004 - /** 2005 - * xe_guc_submit_reset_unblock - Allow back reset calls on given GuC. 2006 - * @guc: the &xe_guc struct instance 2007 - */ 2008 - void xe_guc_submit_reset_unblock(struct xe_guc *guc) 2009 - { 2010 - atomic_set_release(&guc->submission_state.reset_blocked, 0); 2011 - wake_up_all(&guc->ct.wq); 2012 - } 2013 - 2014 - static int guc_submit_reset_is_blocked(struct xe_guc *guc) 2015 - { 2016 - return atomic_read_acquire(&guc->submission_state.reset_blocked); 2017 - } 2018 - 2019 - /* Maximum time of blocking reset */ 2020 - #define RESET_BLOCK_PERIOD_MAX (HZ * 5) 2021 - 2022 - /** 2023 - * xe_guc_wait_reset_unblock - Wait until reset blocking flag is lifted, or timeout. 2024 - * @guc: the &xe_guc struct instance 2025 - */ 2026 - int xe_guc_wait_reset_unblock(struct xe_guc *guc) 2027 - { 2028 - return wait_event_timeout(guc->ct.wq, 2029 - !guc_submit_reset_is_blocked(guc), RESET_BLOCK_PERIOD_MAX); 2030 - } 2031 - 2032 1939 int xe_guc_submit_reset_prepare(struct xe_guc *guc) 2033 1940 { 2034 1941 int ret; 1942 + 1943 + if (xe_gt_WARN_ON(guc_to_gt(guc), vf_recovery(guc))) 1944 + return 0; 2035 1945 2036 1946 if (!guc->submission_state.initialized) 2037 1947 return 0; ··· 2048 2026 2049 2027 } 2050 2028 2029 + static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, 2030 + struct xe_exec_queue *q) 2031 + { 2032 + bool pending_enable, pending_disable, pending_resume; 2033 + 2034 + pending_enable = exec_queue_pending_enable(q); 2035 + pending_resume = exec_queue_pending_resume(q); 2036 + 2037 + if (pending_enable && pending_resume) { 2038 + q->guc->needs_resume = true; 2039 + xe_gt_dbg(guc_to_gt(guc), "Replay RESUME - guc_id=%d", 2040 + q->guc->id); 2041 + } 2042 + 2043 + if (pending_enable && !pending_resume && 2044 + !exec_queue_pending_tdr_exit(q)) { 2045 + clear_exec_queue_registered(q); 2046 + if (xe_exec_queue_is_lr(q)) 2047 + xe_exec_queue_put(q); 2048 + xe_gt_dbg(guc_to_gt(guc), "Replay REGISTER - guc_id=%d", 2049 + q->guc->id); 2050 + } 2051 + 2052 + if (pending_enable) { 2053 + clear_exec_queue_enabled(q); 2054 + clear_exec_queue_pending_resume(q); 2055 + clear_exec_queue_pending_tdr_exit(q); 2056 + clear_exec_queue_pending_enable(q); 2057 + xe_gt_dbg(guc_to_gt(guc), "Replay ENABLE - guc_id=%d", 2058 + q->guc->id); 2059 + } 2060 + 2061 + if (exec_queue_destroyed(q) && exec_queue_registered(q)) { 2062 + clear_exec_queue_destroyed(q); 2063 + if (exec_queue_extra_ref(q)) 2064 + xe_exec_queue_put(q); 2065 + else 2066 + q->guc->needs_cleanup = true; 2067 + clear_exec_queue_extra_ref(q); 2068 + xe_gt_dbg(guc_to_gt(guc), "Replay CLEANUP - guc_id=%d", 2069 + q->guc->id); 2070 + } 2071 + 2072 + pending_disable = exec_queue_pending_disable(q); 2073 + 2074 + if (pending_disable && exec_queue_suspended(q)) { 2075 + clear_exec_queue_suspended(q); 2076 + q->guc->needs_suspend = true; 2077 + xe_gt_dbg(guc_to_gt(guc), "Replay SUSPEND - guc_id=%d", 2078 + q->guc->id); 2079 + } 2080 + 2081 + if (pending_disable) { 2082 + if (!pending_enable) 2083 + set_exec_queue_enabled(q); 2084 + clear_exec_queue_pending_disable(q); 2085 + clear_exec_queue_check_timeout(q); 2086 + xe_gt_dbg(guc_to_gt(guc), "Replay DISABLE - guc_id=%d", 2087 + q->guc->id); 2088 + } 2089 + 2090 + q->guc->resume_time = 0; 2091 + } 2092 + 2093 + /* 2094 + * This function is quite complex but only real way to ensure no state is lost 2095 + * during VF resume flows. The function scans the queue state, make adjustments 2096 + * as needed, and queues jobs / messages which replayed upon unpause. 2097 + */ 2098 + static void guc_exec_queue_pause(struct xe_guc *guc, struct xe_exec_queue *q) 2099 + { 2100 + struct xe_gpu_scheduler *sched = &q->guc->sched; 2101 + struct xe_sched_job *job; 2102 + int i; 2103 + 2104 + lockdep_assert_held(&guc->submission_state.lock); 2105 + 2106 + /* Stop scheduling + flush any DRM scheduler operations */ 2107 + xe_sched_submission_stop(sched); 2108 + if (xe_exec_queue_is_lr(q)) 2109 + cancel_work_sync(&q->guc->lr_tdr); 2110 + else 2111 + cancel_delayed_work_sync(&sched->base.work_tdr); 2112 + 2113 + guc_exec_queue_revert_pending_state_change(guc, q); 2114 + 2115 + if (xe_exec_queue_is_parallel(q)) { 2116 + struct xe_device *xe = guc_to_xe(guc); 2117 + struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]); 2118 + 2119 + /* 2120 + * NOP existing WQ commands that may contain stale GGTT 2121 + * addresses. These will be replayed upon unpause. The hardware 2122 + * seems to get confused if the WQ head/tail pointers are 2123 + * adjusted. 2124 + */ 2125 + for (i = 0; i < WQ_SIZE / sizeof(u32); ++i) 2126 + parallel_write(xe, map, wq[i], 2127 + FIELD_PREP(WQ_TYPE_MASK, WQ_TYPE_NOOP) | 2128 + FIELD_PREP(WQ_LEN_MASK, 0)); 2129 + } 2130 + 2131 + job = xe_sched_first_pending_job(sched); 2132 + if (job) { 2133 + /* 2134 + * Adjust software tail so jobs submitted overwrite previous 2135 + * position in ring buffer with new GGTT addresses. 2136 + */ 2137 + for (i = 0; i < q->width; ++i) 2138 + q->lrc[i]->ring.tail = job->ptrs[i].head; 2139 + } 2140 + } 2141 + 2051 2142 /** 2052 2143 * xe_guc_submit_pause - Stop further runs of submission tasks on given GuC. 2053 2144 * @guc: the &xe_guc struct instance whose scheduler is to be disabled ··· 2170 2035 struct xe_exec_queue *q; 2171 2036 unsigned long index; 2172 2037 2173 - xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) 2174 - xe_sched_submission_stop_async(&q->guc->sched); 2038 + xe_gt_assert(guc_to_gt(guc), vf_recovery(guc)); 2039 + 2040 + mutex_lock(&guc->submission_state.lock); 2041 + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { 2042 + /* Prevent redundant attempts to stop parallel queues */ 2043 + if (q->guc->id != index) 2044 + continue; 2045 + 2046 + guc_exec_queue_pause(guc, q); 2047 + } 2048 + mutex_unlock(&guc->submission_state.lock); 2175 2049 } 2176 2050 2177 2051 static void guc_exec_queue_start(struct xe_exec_queue *q) ··· 2188 2044 struct xe_gpu_scheduler *sched = &q->guc->sched; 2189 2045 2190 2046 if (!exec_queue_killed_or_banned_or_wedged(q)) { 2047 + struct xe_sched_job *job = xe_sched_first_pending_job(sched); 2191 2048 int i; 2192 2049 2193 2050 trace_xe_exec_queue_resubmit(q); 2194 - for (i = 0; i < q->width; ++i) 2195 - xe_lrc_set_ring_head(q->lrc[i], q->lrc[i]->ring.tail); 2051 + if (job) { 2052 + for (i = 0; i < q->width; ++i) { 2053 + /* 2054 + * The GuC context is unregistered at this point 2055 + * time, adjusting software ring tail ensures 2056 + * jobs are rewritten in original placement, 2057 + * adjusting LRC tail ensures the newly loaded 2058 + * GuC / contexts only view the LRC tail 2059 + * increasing as jobs are written out. 2060 + */ 2061 + q->lrc[i]->ring.tail = job->ptrs[i].head; 2062 + xe_lrc_set_ring_tail(q->lrc[i], 2063 + xe_lrc_ring_head(q->lrc[i])); 2064 + } 2065 + } 2196 2066 xe_sched_resubmit_jobs(sched); 2197 2067 } 2198 2068 ··· 2237 2079 return 0; 2238 2080 } 2239 2081 2240 - static void guc_exec_queue_unpause(struct xe_exec_queue *q) 2082 + static void guc_exec_queue_unpause_prepare(struct xe_guc *guc, 2083 + struct xe_exec_queue *q) 2241 2084 { 2242 2085 struct xe_gpu_scheduler *sched = &q->guc->sched; 2086 + struct drm_sched_job *s_job; 2087 + struct xe_sched_job *job = NULL; 2243 2088 2089 + list_for_each_entry(s_job, &sched->base.pending_list, list) { 2090 + job = to_xe_sched_job(s_job); 2091 + 2092 + xe_gt_dbg(guc_to_gt(guc), "Replay JOB - guc_id=%d, seqno=%d", 2093 + q->guc->id, xe_sched_job_seqno(job)); 2094 + 2095 + q->ring_ops->emit_job(job); 2096 + job->skip_emit = true; 2097 + } 2098 + 2099 + if (job) 2100 + job->last_replay = true; 2101 + } 2102 + 2103 + /** 2104 + * xe_guc_submit_unpause_prepare - Prepare unpause submission tasks on given GuC. 2105 + * @guc: the &xe_guc struct instance whose scheduler is to be prepared for unpause 2106 + */ 2107 + void xe_guc_submit_unpause_prepare(struct xe_guc *guc) 2108 + { 2109 + struct xe_exec_queue *q; 2110 + unsigned long index; 2111 + 2112 + xe_gt_assert(guc_to_gt(guc), vf_recovery(guc)); 2113 + 2114 + mutex_lock(&guc->submission_state.lock); 2115 + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { 2116 + /* Prevent redundant attempts to stop parallel queues */ 2117 + if (q->guc->id != index) 2118 + continue; 2119 + 2120 + guc_exec_queue_unpause_prepare(guc, q); 2121 + } 2122 + mutex_unlock(&guc->submission_state.lock); 2123 + } 2124 + 2125 + static void guc_exec_queue_replay_pending_state_change(struct xe_exec_queue *q) 2126 + { 2127 + struct xe_gpu_scheduler *sched = &q->guc->sched; 2128 + struct xe_sched_msg *msg; 2129 + 2130 + if (q->guc->needs_cleanup) { 2131 + msg = q->guc->static_msgs + STATIC_MSG_CLEANUP; 2132 + 2133 + guc_exec_queue_add_msg(q, msg, CLEANUP); 2134 + q->guc->needs_cleanup = false; 2135 + } 2136 + 2137 + if (q->guc->needs_suspend) { 2138 + msg = q->guc->static_msgs + STATIC_MSG_SUSPEND; 2139 + 2140 + xe_sched_msg_lock(sched); 2141 + guc_exec_queue_try_add_msg_head(q, msg, SUSPEND); 2142 + xe_sched_msg_unlock(sched); 2143 + 2144 + q->guc->needs_suspend = false; 2145 + } 2146 + 2147 + /* 2148 + * The resume must be in the message queue before the suspend as it is 2149 + * not possible for a resume to be issued if a suspend pending is, but 2150 + * the inverse is possible. 2151 + */ 2152 + if (q->guc->needs_resume) { 2153 + msg = q->guc->static_msgs + STATIC_MSG_RESUME; 2154 + 2155 + xe_sched_msg_lock(sched); 2156 + guc_exec_queue_try_add_msg_head(q, msg, RESUME); 2157 + xe_sched_msg_unlock(sched); 2158 + 2159 + q->guc->needs_resume = false; 2160 + } 2161 + } 2162 + 2163 + static void guc_exec_queue_unpause(struct xe_guc *guc, struct xe_exec_queue *q) 2164 + { 2165 + struct xe_gpu_scheduler *sched = &q->guc->sched; 2166 + bool needs_tdr = exec_queue_killed_or_banned_or_wedged(q); 2167 + 2168 + lockdep_assert_held(&guc->submission_state.lock); 2169 + 2170 + xe_sched_resubmit_jobs(sched); 2171 + guc_exec_queue_replay_pending_state_change(q); 2244 2172 xe_sched_submission_start(sched); 2173 + if (needs_tdr) 2174 + xe_guc_exec_queue_trigger_cleanup(q); 2175 + xe_sched_submission_resume_tdr(sched); 2245 2176 } 2246 2177 2247 2178 /** ··· 2342 2095 struct xe_exec_queue *q; 2343 2096 unsigned long index; 2344 2097 2345 - xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) 2346 - guc_exec_queue_unpause(q); 2098 + mutex_lock(&guc->submission_state.lock); 2099 + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { 2100 + /* 2101 + * Prevent redundant attempts to stop parallel queues, or queues 2102 + * created after resfix done. 2103 + */ 2104 + if (q->guc->id != index || 2105 + !READ_ONCE(q->guc->sched.base.pause_submit)) 2106 + continue; 2347 2107 2348 - wake_up_all(&guc->ct.wq); 2108 + guc_exec_queue_unpause(guc, q); 2109 + } 2110 + mutex_unlock(&guc->submission_state.lock); 2111 + } 2112 + 2113 + /** 2114 + * xe_guc_submit_pause_abort - Abort all paused submission task on given GuC. 2115 + * @guc: the &xe_guc struct instance whose scheduler is to be aborted 2116 + */ 2117 + void xe_guc_submit_pause_abort(struct xe_guc *guc) 2118 + { 2119 + struct xe_exec_queue *q; 2120 + unsigned long index; 2121 + 2122 + mutex_lock(&guc->submission_state.lock); 2123 + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { 2124 + struct xe_gpu_scheduler *sched = &q->guc->sched; 2125 + 2126 + /* Prevent redundant attempts to stop parallel queues */ 2127 + if (q->guc->id != index) 2128 + continue; 2129 + 2130 + xe_sched_submission_start(sched); 2131 + if (exec_queue_killed_or_banned_or_wedged(q)) 2132 + xe_guc_exec_queue_trigger_cleanup(q); 2133 + } 2134 + mutex_unlock(&guc->submission_state.lock); 2349 2135 } 2350 2136 2351 2137 static struct xe_exec_queue * ··· 2430 2150 xe_gt_assert(guc_to_gt(guc), exec_queue_pending_enable(q)); 2431 2151 2432 2152 q->guc->resume_time = ktime_get(); 2153 + clear_exec_queue_pending_resume(q); 2154 + clear_exec_queue_pending_tdr_exit(q); 2433 2155 clear_exec_queue_pending_enable(q); 2434 2156 smp_wmb(); 2435 2157 wake_up_all(&guc->ct.wq); ··· 2959 2677 2960 2678 mutex_lock(&guc->submission_state.lock); 2961 2679 xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { 2680 + /* Prevent redundant attempts to stop parallel queues */ 2681 + if (q->guc->id != index) 2682 + continue; 2683 + 2962 2684 err = xe_exec_queue_contexts_hwsp_rebase(q, scratch); 2963 - if (err) 2964 - break; 2965 - if (xe_exec_queue_is_parallel(q)) 2966 - err = wq_items_rebase(q); 2967 2685 if (err) 2968 2686 break; 2969 2687 }
+2 -5
drivers/gpu/drm/xe/xe_guc_submit.h
··· 22 22 int xe_guc_submit_start(struct xe_guc *guc); 23 23 void xe_guc_submit_pause(struct xe_guc *guc); 24 24 void xe_guc_submit_unpause(struct xe_guc *guc); 25 - int xe_guc_submit_reset_block(struct xe_guc *guc); 26 - void xe_guc_submit_reset_unblock(struct xe_guc *guc); 27 - int xe_guc_wait_reset_unblock(struct xe_guc *guc); 25 + void xe_guc_submit_unpause_prepare(struct xe_guc *guc); 26 + void xe_guc_submit_pause_abort(struct xe_guc *guc); 28 27 void xe_guc_submit_wedge(struct xe_guc *guc); 29 28 30 29 int xe_guc_read_stopped(struct xe_guc *guc); ··· 34 35 u32 len); 35 36 int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len); 36 37 int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len); 37 - 38 - void xe_guc_jobs_ring_rebase(struct xe_guc *guc); 39 38 40 39 struct xe_guc_submit_exec_queue_snapshot * 41 40 xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q);
+7 -3
drivers/gpu/drm/xe/xe_huc.c
··· 66 66 int xe_huc_init(struct xe_huc *huc) 67 67 { 68 68 struct xe_gt *gt = huc_to_gt(huc); 69 - struct xe_tile *tile = gt_to_tile(gt); 70 69 struct xe_device *xe = gt_to_xe(gt); 71 70 int ret; 72 71 73 72 huc->fw.type = XE_UC_FW_TYPE_HUC; 74 73 75 - /* On platforms with a media GT the HuC is only available there */ 76 - if (tile->media_gt && (gt != tile->media_gt)) { 74 + /* 75 + * The HuC is only available on the media GT on most platforms. The 76 + * exception to that rule are the old Xe1 platforms where there was 77 + * no separate GT for media IP, so the HuC was part of the primary 78 + * GT. Such platforms have graphics versions 12.55 and earlier. 79 + */ 80 + if (!xe_gt_is_media_type(gt) && GRAPHICS_VERx100(xe) > 1255) { 77 81 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED); 78 82 return 0; 79 83 }
+48 -14
drivers/gpu/drm/xe/xe_hw_engine.c
··· 346 346 xe_hw_engine_mmio_read32(hwe, RING_MI_MODE(0)); 347 347 } 348 348 349 - static bool xe_hw_engine_match_fixed_cslice_mode(const struct xe_gt *gt, 349 + static bool xe_hw_engine_match_fixed_cslice_mode(const struct xe_device *xe, 350 + const struct xe_gt *gt, 350 351 const struct xe_hw_engine *hwe) 351 352 { 353 + /* 354 + * Xe3p no longer supports load balance mode, so "fixed cslice" mode 355 + * is automatic and no RCU_MODE programming is required. 356 + */ 357 + if (GRAPHICS_VER(gt_to_xe(gt)) >= 35) 358 + return false; 359 + 352 360 return xe_gt_ccs_mode_enabled(gt) && 353 - xe_rtp_match_first_render_or_compute(gt, hwe); 361 + xe_rtp_match_first_render_or_compute(xe, gt, hwe); 354 362 } 355 363 356 - static bool xe_rtp_cfeg_wmtp_disabled(const struct xe_gt *gt, 364 + static bool xe_rtp_cfeg_wmtp_disabled(const struct xe_device *xe, 365 + const struct xe_gt *gt, 357 366 const struct xe_hw_engine *hwe) 358 367 { 359 - if (GRAPHICS_VER(gt_to_xe(gt)) < 20) 368 + if (GRAPHICS_VER(xe) < 20) 360 369 return false; 361 370 362 371 if (hwe->class != XE_ENGINE_CLASS_COMPUTE && ··· 718 709 } 719 710 } 720 711 712 + static u32 infer_svccopy_from_meml3(struct xe_gt *gt) 713 + { 714 + u32 meml3 = REG_FIELD_GET(MEML3_EN_MASK, 715 + xe_mmio_read32(&gt->mmio, MIRROR_FUSE3)); 716 + u32 svccopy_mask = 0; 717 + 718 + /* 719 + * Each of the four meml3 bits determines the fusing of two service 720 + * copy engines. 721 + */ 722 + for (int i = 0; i < 4; i++) 723 + svccopy_mask |= (meml3 & BIT(i)) ? 0b11 << 2 * i : 0; 724 + 725 + return svccopy_mask; 726 + } 727 + 728 + static u32 read_svccopy_fuses(struct xe_gt *gt) 729 + { 730 + return REG_FIELD_GET(FUSE_SERVICE_COPY_ENABLE_MASK, 731 + xe_mmio_read32(&gt->mmio, SERVICE_COPY_ENABLE)); 732 + } 733 + 721 734 static void read_copy_fuses(struct xe_gt *gt) 722 735 { 723 736 struct xe_device *xe = gt_to_xe(gt); 724 737 u32 bcs_mask; 725 738 726 - if (GRAPHICS_VERx100(xe) < 1260 || GRAPHICS_VERx100(xe) >= 1270) 727 - return; 728 - 729 739 xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT); 730 740 731 - bcs_mask = xe_mmio_read32(&gt->mmio, MIRROR_FUSE3); 732 - bcs_mask = REG_FIELD_GET(MEML3_EN_MASK, bcs_mask); 741 + if (GRAPHICS_VER(xe) >= 35) 742 + bcs_mask = read_svccopy_fuses(gt); 743 + else if (GRAPHICS_VERx100(xe) == 1260) 744 + bcs_mask = infer_svccopy_from_meml3(gt); 745 + else 746 + return; 733 747 734 - /* BCS0 is always present; only BCS1-BCS8 may be fused off */ 735 - for (int i = XE_HW_ENGINE_BCS1, j = 0; i <= XE_HW_ENGINE_BCS8; ++i, ++j) { 748 + /* Only BCS1-BCS8 may be fused off */ 749 + bcs_mask <<= XE_HW_ENGINE_BCS1; 750 + for (int i = XE_HW_ENGINE_BCS1; i <= XE_HW_ENGINE_BCS8; ++i) { 736 751 if (!(gt->info.engine_mask & BIT(i))) 737 752 continue; 738 753 739 - if (!(BIT(j / 2) & bcs_mask)) { 754 + if (!(bcs_mask & BIT(i))) { 740 755 gt->info.engine_mask &= ~BIT(i); 741 - xe_gt_info(gt, "bcs%u fused off\n", j); 756 + xe_gt_info(gt, "bcs%u fused off\n", 757 + i - XE_HW_ENGINE_BCS0); 742 758 } 743 759 } 744 760 } ··· 904 870 if (hwe->irq_handler) 905 871 hwe->irq_handler(hwe, intr_vec); 906 872 907 - if (intr_vec & GT_RENDER_USER_INTERRUPT) 873 + if (intr_vec & GT_MI_USER_INTERRUPT) 908 874 xe_hw_fence_irq_run(hwe->fence_irq); 909 875 } 910 876
-8
drivers/gpu/drm/xe/xe_hwmon.c
··· 658 658 struct xe_reg rapl_limit; 659 659 struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); 660 660 661 - xe_pm_runtime_get(hwmon->xe); 662 - 663 661 if (hwmon->xe->info.has_mbx_power_limits) { 664 662 xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, &uval); 665 663 } else if (power_attr != PL2_HWMON_ATTR) { ··· 666 668 uval = xe_mmio_read32(mmio, rapl_limit); 667 669 } 668 670 ret = (uval & PWR_LIM_EN) ? attr->mode : 0; 669 - 670 - xe_pm_runtime_put(hwmon->xe); 671 671 672 672 return ret; 673 673 } ··· 1092 1096 struct xe_hwmon *hwmon = (struct xe_hwmon *)drvdata; 1093 1097 int ret; 1094 1098 1095 - xe_pm_runtime_get(hwmon->xe); 1096 - 1097 1099 switch (type) { 1098 1100 case hwmon_temp: 1099 1101 ret = xe_hwmon_temp_is_visible(hwmon, attr, channel); ··· 1115 1121 ret = 0; 1116 1122 break; 1117 1123 } 1118 - 1119 - xe_pm_runtime_put(hwmon->xe); 1120 1124 1121 1125 return ret; 1122 1126 }
+27 -1
drivers/gpu/drm/xe/xe_i2c.c
··· 160 160 return xe->i2c && xe->i2c->ep.cookie == XE_I2C_EP_COOKIE_DEVICE; 161 161 } 162 162 163 + static bool xe_i2c_irq_present(struct xe_device *xe) 164 + { 165 + return xe->i2c && xe->i2c->adapter_irq; 166 + } 167 + 163 168 /** 164 169 * xe_i2c_irq_handler: Handler for I2C interrupts 165 170 * @xe: xe device instance ··· 175 170 */ 176 171 void xe_i2c_irq_handler(struct xe_device *xe, u32 master_ctl) 177 172 { 178 - if (!xe->i2c || !xe->i2c->adapter_irq) 173 + if (!xe_i2c_irq_present(xe)) 179 174 return; 180 175 181 176 if (master_ctl & I2C_IRQ) 182 177 generic_handle_irq_safe(xe->i2c->adapter_irq); 178 + } 179 + 180 + void xe_i2c_irq_reset(struct xe_device *xe) 181 + { 182 + struct xe_mmio *mmio = xe_root_tile_mmio(xe); 183 + 184 + if (!xe_i2c_irq_present(xe)) 185 + return; 186 + 187 + xe_mmio_rmw32(mmio, I2C_BRIDGE_PCICFGCTL, ACPI_INTR_EN, 0); 188 + } 189 + 190 + void xe_i2c_irq_postinstall(struct xe_device *xe) 191 + { 192 + struct xe_mmio *mmio = xe_root_tile_mmio(xe); 193 + 194 + if (!xe_i2c_irq_present(xe)) 195 + return; 196 + 197 + xe_mmio_rmw32(mmio, I2C_BRIDGE_PCICFGCTL, 0, ACPI_INTR_EN); 183 198 } 184 199 185 200 static int xe_i2c_irq_map(struct irq_domain *h, unsigned int virq, ··· 359 334 if (ret) 360 335 goto err_remove_irq; 361 336 337 + xe_i2c_irq_postinstall(xe); 362 338 return devm_add_action_or_reset(drm_dev, xe_i2c_remove, i2c); 363 339 364 340 err_remove_irq:
+4
drivers/gpu/drm/xe/xe_i2c.h
··· 51 51 int xe_i2c_probe(struct xe_device *xe); 52 52 bool xe_i2c_present(struct xe_device *xe); 53 53 void xe_i2c_irq_handler(struct xe_device *xe, u32 master_ctl); 54 + void xe_i2c_irq_postinstall(struct xe_device *xe); 55 + void xe_i2c_irq_reset(struct xe_device *xe); 54 56 void xe_i2c_pm_suspend(struct xe_device *xe); 55 57 void xe_i2c_pm_resume(struct xe_device *xe, bool d3cold); 56 58 #else 57 59 static inline int xe_i2c_probe(struct xe_device *xe) { return 0; } 58 60 static inline bool xe_i2c_present(struct xe_device *xe) { return false; } 59 61 static inline void xe_i2c_irq_handler(struct xe_device *xe, u32 master_ctl) { } 62 + static inline void xe_i2c_irq_postinstall(struct xe_device *xe) { } 63 + static inline void xe_i2c_irq_reset(struct xe_device *xe) { } 60 64 static inline void xe_i2c_pm_suspend(struct xe_device *xe) { } 61 65 static inline void xe_i2c_pm_resume(struct xe_device *xe, bool d3cold) { } 62 66 #endif
+93 -43
drivers/gpu/drm/xe/xe_irq.c
··· 139 139 { 140 140 struct xe_device *xe = gt_to_xe(gt); 141 141 struct xe_mmio *mmio = &gt->mmio; 142 - u32 ccs_mask, bcs_mask; 143 - u32 irqs, dmask, smask; 144 - u32 gsc_mask = 0; 145 - u32 heci_mask = 0; 142 + u32 common_mask, val, gsc_mask = 0, heci_mask = 0, 143 + rcs_mask = 0, bcs_mask = 0, vcs_mask = 0, vecs_mask = 0, 144 + ccs_mask = 0; 146 145 147 146 if (xe_device_uses_memirq(xe)) 148 147 return; 149 148 150 149 if (xe_device_uc_enabled(xe)) { 151 - irqs = GT_RENDER_USER_INTERRUPT | 152 - GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; 150 + common_mask = GT_MI_USER_INTERRUPT | 151 + GT_FLUSH_COMPLETE_INTERRUPT; 152 + 153 + /* Enable Compute Walker Interrupt for non-MSIX platforms */ 154 + if (GRAPHICS_VERx100(xe) >= 3511 && !xe_device_has_msix(xe)) { 155 + rcs_mask |= GT_COMPUTE_WALKER_INTERRUPT; 156 + ccs_mask |= GT_COMPUTE_WALKER_INTERRUPT; 157 + } 153 158 } else { 154 - irqs = GT_RENDER_USER_INTERRUPT | 155 - GT_CS_MASTER_ERROR_INTERRUPT | 156 - GT_CONTEXT_SWITCH_INTERRUPT | 157 - GT_WAIT_SEMAPHORE_INTERRUPT; 159 + common_mask = GT_MI_USER_INTERRUPT | 160 + GT_CS_MASTER_ERROR_INTERRUPT | 161 + GT_CONTEXT_SWITCH_INTERRUPT | 162 + GT_WAIT_SEMAPHORE_INTERRUPT; 158 163 } 159 164 160 - ccs_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_COMPUTE); 161 - bcs_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_COPY); 162 - 163 - dmask = irqs << 16 | irqs; 164 - smask = irqs << 16; 165 + rcs_mask |= common_mask; 166 + bcs_mask |= common_mask; 167 + vcs_mask |= common_mask; 168 + vecs_mask |= common_mask; 169 + ccs_mask |= common_mask; 165 170 166 171 if (xe_gt_is_main_type(gt)) { 172 + /* 173 + * For enabling the interrupts, the information about fused off 174 + * engines doesn't matter much, but this also allows to check if 175 + * the engine is available architecturally in the platform 176 + */ 177 + u32 ccs_fuse_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_COMPUTE); 178 + u32 bcs_fuse_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_COPY); 179 + 167 180 /* Enable interrupts for each engine class */ 168 - xe_mmio_write32(mmio, RENDER_COPY_INTR_ENABLE, dmask); 169 - if (ccs_mask) 170 - xe_mmio_write32(mmio, CCS_RSVD_INTR_ENABLE, smask); 181 + xe_mmio_write32(mmio, RENDER_COPY_INTR_ENABLE, 182 + REG_FIELD_PREP(ENGINE1_MASK, rcs_mask) | 183 + REG_FIELD_PREP(ENGINE0_MASK, bcs_mask)); 184 + if (ccs_fuse_mask) 185 + xe_mmio_write32(mmio, CCS_RSVD_INTR_ENABLE, 186 + REG_FIELD_PREP(ENGINE1_MASK, ccs_mask)); 171 187 172 188 /* Unmask interrupts for each engine instance */ 173 - xe_mmio_write32(mmio, RCS0_RSVD_INTR_MASK, ~smask); 174 - xe_mmio_write32(mmio, BCS_RSVD_INTR_MASK, ~smask); 175 - if (bcs_mask & (BIT(1)|BIT(2))) 176 - xe_mmio_write32(mmio, XEHPC_BCS1_BCS2_INTR_MASK, ~dmask); 177 - if (bcs_mask & (BIT(3)|BIT(4))) 178 - xe_mmio_write32(mmio, XEHPC_BCS3_BCS4_INTR_MASK, ~dmask); 179 - if (bcs_mask & (BIT(5)|BIT(6))) 180 - xe_mmio_write32(mmio, XEHPC_BCS5_BCS6_INTR_MASK, ~dmask); 181 - if (bcs_mask & (BIT(7)|BIT(8))) 182 - xe_mmio_write32(mmio, XEHPC_BCS7_BCS8_INTR_MASK, ~dmask); 183 - if (ccs_mask & (BIT(0)|BIT(1))) 184 - xe_mmio_write32(mmio, CCS0_CCS1_INTR_MASK, ~dmask); 185 - if (ccs_mask & (BIT(2)|BIT(3))) 186 - xe_mmio_write32(mmio, CCS2_CCS3_INTR_MASK, ~dmask); 189 + val = ~REG_FIELD_PREP(ENGINE1_MASK, rcs_mask); 190 + xe_mmio_write32(mmio, RCS0_RSVD_INTR_MASK, val); 191 + val = ~REG_FIELD_PREP(ENGINE1_MASK, bcs_mask); 192 + xe_mmio_write32(mmio, BCS_RSVD_INTR_MASK, val); 193 + 194 + val = ~(REG_FIELD_PREP(ENGINE1_MASK, bcs_mask) | 195 + REG_FIELD_PREP(ENGINE0_MASK, bcs_mask)); 196 + if (bcs_fuse_mask & (BIT(1)|BIT(2))) 197 + xe_mmio_write32(mmio, XEHPC_BCS1_BCS2_INTR_MASK, val); 198 + if (bcs_fuse_mask & (BIT(3)|BIT(4))) 199 + xe_mmio_write32(mmio, XEHPC_BCS3_BCS4_INTR_MASK, val); 200 + if (bcs_fuse_mask & (BIT(5)|BIT(6))) 201 + xe_mmio_write32(mmio, XEHPC_BCS5_BCS6_INTR_MASK, val); 202 + if (bcs_fuse_mask & (BIT(7)|BIT(8))) 203 + xe_mmio_write32(mmio, XEHPC_BCS7_BCS8_INTR_MASK, val); 204 + 205 + val = ~(REG_FIELD_PREP(ENGINE1_MASK, ccs_mask) | 206 + REG_FIELD_PREP(ENGINE0_MASK, ccs_mask)); 207 + if (ccs_fuse_mask & (BIT(0)|BIT(1))) 208 + xe_mmio_write32(mmio, CCS0_CCS1_INTR_MASK, val); 209 + if (ccs_fuse_mask & (BIT(2)|BIT(3))) 210 + xe_mmio_write32(mmio, CCS2_CCS3_INTR_MASK, val); 187 211 } 188 212 189 213 if (xe_gt_is_media_type(gt) || MEDIA_VER(xe) < 13) { 214 + u32 vcs_fuse_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_VIDEO_DECODE); 215 + u32 vecs_fuse_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_VIDEO_ENHANCE); 216 + u32 other_fuse_mask = xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_OTHER); 217 + 190 218 /* Enable interrupts for each engine class */ 191 - xe_mmio_write32(mmio, VCS_VECS_INTR_ENABLE, dmask); 219 + xe_mmio_write32(mmio, VCS_VECS_INTR_ENABLE, 220 + REG_FIELD_PREP(ENGINE1_MASK, vcs_mask) | 221 + REG_FIELD_PREP(ENGINE0_MASK, vecs_mask)); 192 222 193 223 /* Unmask interrupts for each engine instance */ 194 - xe_mmio_write32(mmio, VCS0_VCS1_INTR_MASK, ~dmask); 195 - xe_mmio_write32(mmio, VCS2_VCS3_INTR_MASK, ~dmask); 196 - xe_mmio_write32(mmio, VECS0_VECS1_INTR_MASK, ~dmask); 224 + val = ~(REG_FIELD_PREP(ENGINE1_MASK, vcs_mask) | 225 + REG_FIELD_PREP(ENGINE0_MASK, vcs_mask)); 226 + if (vcs_fuse_mask & (BIT(0) | BIT(1))) 227 + xe_mmio_write32(mmio, VCS0_VCS1_INTR_MASK, val); 228 + if (vcs_fuse_mask & (BIT(2) | BIT(3))) 229 + xe_mmio_write32(mmio, VCS2_VCS3_INTR_MASK, val); 230 + if (vcs_fuse_mask & (BIT(4) | BIT(5))) 231 + xe_mmio_write32(mmio, VCS4_VCS5_INTR_MASK, val); 232 + if (vcs_fuse_mask & (BIT(6) | BIT(7))) 233 + xe_mmio_write32(mmio, VCS6_VCS7_INTR_MASK, val); 234 + 235 + val = ~(REG_FIELD_PREP(ENGINE1_MASK, vecs_mask) | 236 + REG_FIELD_PREP(ENGINE0_MASK, vecs_mask)); 237 + if (vecs_fuse_mask & (BIT(0) | BIT(1))) 238 + xe_mmio_write32(mmio, VECS0_VECS1_INTR_MASK, val); 239 + if (vecs_fuse_mask & (BIT(2) | BIT(3))) 240 + xe_mmio_write32(mmio, VECS2_VECS3_INTR_MASK, val); 197 241 198 242 /* 199 243 * the heci2 interrupt is enabled via the same register as the 200 244 * GSCCS interrupts, but it has its own mask register. 201 245 */ 202 - if (xe_hw_engine_mask_per_class(gt, XE_ENGINE_CLASS_OTHER)) { 203 - gsc_mask = irqs | GSC_ER_COMPLETE; 246 + if (other_fuse_mask) { 247 + gsc_mask = common_mask | GSC_ER_COMPLETE; 204 248 heci_mask = GSC_IRQ_INTF(1); 205 249 } else if (xe->info.has_heci_gscfi) { 206 250 gsc_mask = GSC_IRQ_INTF(1); ··· 538 494 static void gt_irq_reset(struct xe_tile *tile) 539 495 { 540 496 struct xe_mmio *mmio = &tile->mmio; 497 + u32 ccs_mask = ~0; 498 + u32 bcs_mask = ~0; 541 499 542 - u32 ccs_mask = xe_hw_engine_mask_per_class(tile->primary_gt, 543 - XE_ENGINE_CLASS_COMPUTE); 544 - u32 bcs_mask = xe_hw_engine_mask_per_class(tile->primary_gt, 545 - XE_ENGINE_CLASS_COPY); 500 + if (tile->primary_gt) { 501 + ccs_mask = xe_hw_engine_mask_per_class(tile->primary_gt, 502 + XE_ENGINE_CLASS_COMPUTE); 503 + bcs_mask = xe_hw_engine_mask_per_class(tile->primary_gt, 504 + XE_ENGINE_CLASS_COPY); 505 + } 546 506 547 507 /* Disable RCS, BCS, VCS and VECS class engines. */ 548 508 xe_mmio_write32(mmio, RENDER_COPY_INTR_ENABLE, 0); ··· 664 616 tile = xe_device_get_root_tile(xe); 665 617 mask_and_disable(tile, GU_MISC_IRQ_OFFSET); 666 618 xe_display_irq_reset(xe); 619 + xe_i2c_irq_reset(xe); 667 620 668 621 /* 669 622 * The tile's top-level status register should be the last one ··· 705 656 xe_memirq_postinstall(&tile->memirq); 706 657 } 707 658 708 - xe_display_irq_postinstall(xe, xe_root_mmio_gt(xe)); 659 + xe_display_irq_postinstall(xe); 660 + xe_i2c_irq_postinstall(xe); 709 661 710 662 /* 711 663 * ASLE backlight operations are reported via GUnit GSE interrupts
+5 -6
drivers/gpu/drm/xe/xe_lmtt.c
··· 17 17 #include "xe_mmio.h" 18 18 #include "xe_res_cursor.h" 19 19 #include "xe_sriov.h" 20 - #include "xe_sriov_printk.h" 20 + #include "xe_tile_sriov_printk.h" 21 21 22 22 /** 23 23 * DOC: Local Memory Translation Table ··· 32 32 */ 33 33 34 34 #define lmtt_assert(lmtt, condition) xe_tile_assert(lmtt_to_tile(lmtt), condition) 35 - #define lmtt_debug(lmtt, msg...) xe_sriov_dbg_verbose(lmtt_to_xe(lmtt), "LMTT: " msg) 35 + #define lmtt_debug(lmtt, msg...) xe_tile_sriov_dbg_verbose(lmtt_to_tile(lmtt), "LMTT: " msg) 36 36 37 37 static bool xe_has_multi_level_lmtt(struct xe_device *xe) 38 38 { ··· 267 267 */ 268 268 void xe_lmtt_invalidate_hw(struct xe_lmtt *lmtt) 269 269 { 270 - struct xe_device *xe = lmtt_to_xe(lmtt); 271 270 int err; 272 271 273 - lmtt_assert(lmtt, IS_SRIOV_PF(xe)); 272 + lmtt_assert(lmtt, IS_SRIOV_PF(lmtt_to_xe(lmtt))); 274 273 275 274 err = lmtt_invalidate_hw(lmtt); 276 275 if (err) 277 - xe_sriov_warn(xe, "LMTT%u invalidation failed (%pe)", 278 - lmtt_to_tile(lmtt)->id, ERR_PTR(err)); 276 + xe_tile_sriov_err(lmtt_to_tile(lmtt), "LMTT invalidation failed (%pe)", 277 + ERR_PTR(err)); 279 278 } 280 279 281 280 static void lmtt_write_pte(struct xe_lmtt *lmtt, struct xe_lmtt_pt *pt,
+13 -7
drivers/gpu/drm/xe/xe_lrc.c
··· 1214 1214 ssize_t remain; 1215 1215 1216 1216 if (state->lrc->bo->vmap.is_iomem) { 1217 - if (!state->buffer) 1218 - return -ENOMEM; 1217 + xe_gt_assert(state->hwe->gt, state->buffer); 1219 1218 state->ptr = state->buffer; 1220 1219 } else { 1221 1220 state->ptr = state->lrc->bo->vmap.vaddr + state->offset; ··· 1247 1248 1248 1249 static void finish_bo(struct bo_setup_state *state) 1249 1250 { 1250 - if (!state->buffer) 1251 + if (!state->lrc->bo->vmap.is_iomem) 1251 1252 return; 1252 1253 1253 1254 xe_map_memcpy_to(gt_to_xe(state->lrc->gt), &state->lrc->bo->vmap, ··· 1302 1303 u32 *buf = NULL; 1303 1304 int ret; 1304 1305 1305 - if (lrc->bo->vmap.is_iomem) 1306 + if (lrc->bo->vmap.is_iomem) { 1306 1307 buf = kmalloc(LRC_WA_BB_SIZE, GFP_KERNEL); 1308 + if (!buf) 1309 + return -ENOMEM; 1310 + } 1307 1311 1308 1312 ret = xe_lrc_setup_wa_bb_with_scratch(lrc, hwe, buf); 1309 1313 ··· 1349 1347 if (xe_gt_WARN_ON(lrc->gt, !state.funcs)) 1350 1348 return 0; 1351 1349 1352 - if (lrc->bo->vmap.is_iomem) 1350 + if (lrc->bo->vmap.is_iomem) { 1353 1351 state.buffer = kmalloc(state.max_size, GFP_KERNEL); 1352 + if (!state.buffer) 1353 + return -ENOMEM; 1354 + } 1354 1355 1355 1356 ret = setup_bo(&state); 1356 1357 if (ret) { ··· 1417 1412 1418 1413 bo_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile) | XE_BO_FLAG_GGTT | 1419 1414 XE_BO_FLAG_GGTT_INVALIDATE; 1420 - if (vm && vm->xef) /* userspace */ 1421 - bo_flags |= XE_BO_FLAG_PINNED_LATE_RESTORE; 1415 + 1416 + if ((vm && vm->xef) || init_flags & XE_LRC_CREATE_USER_CTX) /* userspace */ 1417 + bo_flags |= XE_BO_FLAG_PINNED_LATE_RESTORE | XE_BO_FLAG_FORCE_USER_VRAM; 1422 1418 1423 1419 lrc->bo = xe_bo_create_pin_map_novm(xe, tile, 1424 1420 bo_size,
+14 -2
drivers/gpu/drm/xe/xe_lrc.h
··· 44 44 45 45 #define LRC_WA_BB_SIZE SZ_4K 46 46 47 - #define XE_LRC_CREATE_RUNALONE 0x1 48 - #define XE_LRC_CREATE_PXP 0x2 47 + #define XE_LRC_CREATE_RUNALONE BIT(0) 48 + #define XE_LRC_CREATE_PXP BIT(1) 49 + #define XE_LRC_CREATE_USER_CTX BIT(2) 50 + 49 51 struct xe_lrc *xe_lrc_create(struct xe_hw_engine *hwe, struct xe_vm *vm, 50 52 u32 ring_size, u16 msix_vec, u32 flags); 51 53 void xe_lrc_destroy(struct kref *ref); ··· 74 72 static inline void xe_lrc_put(struct xe_lrc *lrc) 75 73 { 76 74 kref_put(&lrc->refcount, xe_lrc_destroy); 75 + } 76 + 77 + /** 78 + * xe_lrc_ring_size() - Xe LRC ring size 79 + * 80 + * Return: Size of LRC ring buffer 81 + */ 82 + static inline size_t xe_lrc_ring_size(void) 83 + { 84 + return SZ_16K; 77 85 } 78 86 79 87 size_t xe_gt_lrc_size(struct xe_gt *gt, enum xe_engine_class class);
-18
drivers/gpu/drm/xe/xe_map.h
··· 78 78 iosys_map_wr(map__, offset__, type__, val__); \ 79 79 }) 80 80 81 - #define xe_map_rd_array(xe__, map__, index__, type__) \ 82 - xe_map_rd(xe__, map__, (index__) * sizeof(type__), type__) 83 - 84 - #define xe_map_wr_array(xe__, map__, index__, type__, val__) \ 85 - xe_map_wr(xe__, map__, (index__) * sizeof(type__), type__, val__) 86 - 87 - #define xe_map_rd_array_u32(xe__, map__, index__) \ 88 - xe_map_rd_array(xe__, map__, index__, u32) 89 - 90 - #define xe_map_wr_array_u32(xe__, map__, index__, val__) \ 91 - xe_map_wr_array(xe__, map__, index__, u32, val__) 92 - 93 - #define xe_map_rd_ring_u32(xe__, map__, index__, size__) \ 94 - xe_map_rd_array_u32(xe__, map__, (index__) % (size__)) 95 - 96 - #define xe_map_wr_ring_u32(xe__, map__, index__, size__, val__) \ 97 - xe_map_wr_array_u32(xe__, map__, (index__) % (size__), val__) 98 - 99 81 #define xe_map_rd_field(xe__, map__, struct_offset__, struct_type__, field__) ({ \ 100 82 struct xe_device *__xe = xe__; \ 101 83 xe_device_assert_mem_access(__xe); \
+48 -9
drivers/gpu/drm/xe/xe_memirq.c
··· 14 14 #include "xe_device.h" 15 15 #include "xe_device_types.h" 16 16 #include "xe_gt.h" 17 - #include "xe_gt_printk.h" 18 17 #include "xe_guc.h" 19 18 #include "xe_hw_engine.h" 20 19 #include "xe_map.h" 21 20 #include "xe_memirq.h" 21 + #include "xe_tile_printk.h" 22 22 23 23 #define memirq_assert(m, condition) xe_tile_assert(memirq_to_tile(m), condition) 24 24 #define memirq_printk(m, _level, _fmt, ...) \ 25 - drm_##_level(&memirq_to_xe(m)->drm, "MEMIRQ%u: " _fmt, \ 26 - memirq_to_tile(m)->id, ##__VA_ARGS__) 25 + xe_tile_##_level(memirq_to_tile(m), "MEMIRQ: " _fmt, ##__VA_ARGS__) 27 26 28 27 #ifdef CONFIG_DRM_XE_DEBUG_MEMIRQ 29 28 #define memirq_debug(m, _fmt, ...) memirq_printk(m, dbg, _fmt, ##__VA_ARGS__) ··· 397 398 memirq_set_enable(memirq, true); 398 399 } 399 400 400 - static bool memirq_received(struct xe_memirq *memirq, struct iosys_map *vector, 401 - u16 offset, const char *name) 401 + static bool __memirq_received(struct xe_memirq *memirq, 402 + struct iosys_map *vector, u16 offset, 403 + const char *name, bool clear) 402 404 { 403 405 u8 value; 404 406 ··· 409 409 memirq_err_ratelimited(memirq, 410 410 "Unexpected memirq value %#x from %s at %u\n", 411 411 value, name, offset); 412 - iosys_map_wr(vector, offset, u8, 0x00); 412 + if (clear) 413 + iosys_map_wr(vector, offset, u8, 0x00); 413 414 } 414 415 415 416 return value; 417 + } 418 + 419 + static bool memirq_received_noclear(struct xe_memirq *memirq, 420 + struct iosys_map *vector, 421 + u16 offset, const char *name) 422 + { 423 + return __memirq_received(memirq, vector, offset, name, false); 424 + } 425 + 426 + static bool memirq_received(struct xe_memirq *memirq, struct iosys_map *vector, 427 + u16 offset, const char *name) 428 + { 429 + return __memirq_received(memirq, vector, offset, name, true); 416 430 } 417 431 418 432 static void memirq_dispatch_engine(struct xe_memirq *memirq, struct iosys_map *status, ··· 434 420 { 435 421 memirq_debug(memirq, "STATUS %s %*ph\n", hwe->name, 16, status->vaddr); 436 422 437 - if (memirq_received(memirq, status, ilog2(GT_RENDER_USER_INTERRUPT), hwe->name)) 438 - xe_hw_engine_handle_irq(hwe, GT_RENDER_USER_INTERRUPT); 423 + if (memirq_received(memirq, status, ilog2(GT_MI_USER_INTERRUPT), hwe->name)) 424 + xe_hw_engine_handle_irq(hwe, GT_MI_USER_INTERRUPT); 439 425 } 440 426 441 427 static void memirq_dispatch_guc(struct xe_memirq *memirq, struct iosys_map *status, ··· 448 434 if (memirq_received(memirq, status, ilog2(GUC_INTR_GUC2HOST), name)) 449 435 xe_guc_irq_handler(guc, GUC_INTR_GUC2HOST); 450 436 451 - if (memirq_received(memirq, status, ilog2(GUC_INTR_SW_INT_0), name)) 437 + /* 438 + * This is a software interrupt that must be cleared after it's consumed 439 + * to avoid race conditions where xe_gt_sriov_vf_recovery_pending() 440 + * returns false. 441 + */ 442 + if (memirq_received_noclear(memirq, status, ilog2(GUC_INTR_SW_INT_0), 443 + name)) { 452 444 xe_guc_irq_handler(guc, GUC_INTR_SW_INT_0); 445 + iosys_map_wr(status, ilog2(GUC_INTR_SW_INT_0), u8, 0x00); 446 + } 453 447 } 454 448 455 449 /** ··· 480 458 XE_MEMIRQ_STATUS_OFFSET(instance) + offset * SZ_16); 481 459 memirq_dispatch_engine(memirq, &status_offset, hwe); 482 460 } 461 + } 462 + 463 + /** 464 + * xe_memirq_guc_sw_int_0_irq_pending() - SW_INT_0 IRQ is pending 465 + * @memirq: the &xe_memirq 466 + * @guc: the &xe_guc to check for IRQ 467 + * 468 + * Return: True if SW_INT_0 IRQ is pending on @guc, False otherwise 469 + */ 470 + bool xe_memirq_guc_sw_int_0_irq_pending(struct xe_memirq *memirq, struct xe_guc *guc) 471 + { 472 + struct xe_gt *gt = guc_to_gt(guc); 473 + u32 offset = xe_gt_is_media_type(gt) ? ilog2(INTR_MGUC) : ilog2(INTR_GUC); 474 + struct iosys_map map = IOSYS_MAP_INIT_OFFSET(&memirq->status, offset * SZ_16); 475 + 476 + return memirq_received_noclear(memirq, &map, ilog2(GUC_INTR_SW_INT_0), 477 + guc_name(guc)); 483 478 } 484 479 485 480 /**
+2
drivers/gpu/drm/xe/xe_memirq.h
··· 25 25 26 26 int xe_memirq_init_guc(struct xe_memirq *memirq, struct xe_guc *guc); 27 27 28 + bool xe_memirq_guc_sw_int_0_irq_pending(struct xe_memirq *memirq, struct xe_guc *guc); 29 + 28 30 #endif
+85 -22
drivers/gpu/drm/xe/xe_migrate.c
··· 57 57 u64 usm_batch_base_ofs; 58 58 /** @cleared_mem_ofs: VM offset of @cleared_bo. */ 59 59 u64 cleared_mem_ofs; 60 + /** @large_page_copy_ofs: VM offset of 2M pages used for large copies */ 61 + u64 large_page_copy_ofs; 62 + /** 63 + * @large_page_copy_pdes: BO offset to writeout 2M pages (PDEs) used for 64 + * large copies 65 + */ 66 + u64 large_page_copy_pdes; 60 67 /** 61 68 * @fence: dma-fence representing the last migration job batch. 62 69 * Protected by @job_mutex. ··· 294 287 xe_map_wr(xe, &bo->vmap, map_ofs + XE_PAGE_SIZE + 295 288 (i + 1) * 8, u64, entry); 296 289 } 290 + 291 + /* Reserve 2M PDEs */ 292 + level = 1; 293 + m->large_page_copy_ofs = NUM_PT_SLOTS << xe_pt_shift(level); 294 + m->large_page_copy_pdes = map_ofs + XE_PAGE_SIZE * level + 295 + NUM_PT_SLOTS * 8; 297 296 298 297 /* Set up a 1GiB NULL mapping at 255GiB offset. */ 299 298 level = 2; ··· 993 980 return migrate->q->lrc[0]; 994 981 } 995 982 996 - static int emit_flush_invalidate(struct xe_exec_queue *q, u32 *dw, int i, 997 - u32 flags) 983 + static u64 migrate_vm_ppgtt_addr_tlb_inval(void) 998 984 { 999 - struct xe_lrc *lrc = xe_exec_queue_lrc(q); 985 + /* 986 + * The migrate VM is self-referential so it can modify its own PTEs (see 987 + * pte_update_size() or emit_pte() functions). We reserve NUM_KERNEL_PDE 988 + * entries for kernel operations (copies, clears, CCS migrate), and 989 + * suballocate the rest to user operations (binds/unbinds). With 990 + * NUM_KERNEL_PDE = 15, NUM_KERNEL_PDE - 1 is already used for PTE updates, 991 + * so assign NUM_KERNEL_PDE - 2 for TLB invalidation. 992 + */ 993 + return (NUM_KERNEL_PDE - 2) * XE_PAGE_SIZE; 994 + } 995 + 996 + static int emit_flush_invalidate(u32 *dw, int i, u32 flags) 997 + { 998 + u64 addr = migrate_vm_ppgtt_addr_tlb_inval(); 999 + 1000 1000 dw[i++] = MI_FLUSH_DW | MI_INVALIDATE_TLB | MI_FLUSH_DW_OP_STOREDW | 1001 1001 MI_FLUSH_IMM_DW | flags; 1002 - dw[i++] = lower_32_bits(xe_lrc_start_seqno_ggtt_addr(lrc)) | 1003 - MI_FLUSH_DW_USE_GTT; 1004 - dw[i++] = upper_32_bits(xe_lrc_start_seqno_ggtt_addr(lrc)); 1002 + dw[i++] = lower_32_bits(addr); 1003 + dw[i++] = upper_32_bits(addr); 1005 1004 dw[i++] = MI_NOOP; 1006 1005 dw[i++] = MI_NOOP; 1007 1006 ··· 1126 1101 1127 1102 emit_pte(m, bb, ccs_pt, false, false, &ccs_it, ccs_size, src); 1128 1103 1129 - bb->len = emit_flush_invalidate(q, bb->cs, bb->len, flush_flags); 1104 + bb->len = emit_flush_invalidate(bb->cs, bb->len, flush_flags); 1130 1105 flush_flags = xe_migrate_ccs_copy(m, bb, src_L0_ofs, src_is_pltt, 1131 1106 src_L0_ofs, dst_is_pltt, 1132 1107 src_L0, ccs_ofs, true); 1133 - bb->len = emit_flush_invalidate(q, bb->cs, bb->len, flush_flags); 1108 + bb->len = emit_flush_invalidate(bb->cs, bb->len, flush_flags); 1134 1109 1135 1110 size -= src_L0; 1136 1111 } ··· 1791 1766 static void build_pt_update_batch_sram(struct xe_migrate *m, 1792 1767 struct xe_bb *bb, u32 pt_offset, 1793 1768 struct drm_pagemap_addr *sram_addr, 1794 - u32 size) 1769 + u32 size, int level) 1795 1770 { 1796 1771 u16 pat_index = tile_to_xe(m->tile)->pat.idx[XE_CACHE_WB]; 1772 + u64 gpu_page_size = 0x1ull << xe_pt_shift(level); 1797 1773 u32 ptes; 1798 1774 int i = 0; 1799 1775 1800 - ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE); 1776 + ptes = DIV_ROUND_UP(size, gpu_page_size); 1801 1777 while (ptes) { 1802 1778 u32 chunk = min(MAX_PTE_PER_SDI, ptes); 1803 1779 1780 + chunk = ALIGN_DOWN(chunk, PAGE_SIZE / XE_PAGE_SIZE); 1804 1781 bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk); 1805 1782 bb->cs[bb->len++] = pt_offset; 1806 1783 bb->cs[bb->len++] = 0; ··· 1811 1784 ptes -= chunk; 1812 1785 1813 1786 while (chunk--) { 1814 - u64 addr = sram_addr[i].addr & PAGE_MASK; 1787 + u64 addr = sram_addr[i].addr & ~(gpu_page_size - 1); 1788 + u64 pte, orig_addr = addr; 1815 1789 1816 1790 xe_tile_assert(m->tile, sram_addr[i].proto == 1817 1791 DRM_INTERCONNECT_SYSTEM); 1818 1792 xe_tile_assert(m->tile, addr); 1819 - addr = m->q->vm->pt_ops->pte_encode_addr(m->tile->xe, 1820 - addr, pat_index, 1821 - 0, false, 0); 1822 - bb->cs[bb->len++] = lower_32_bits(addr); 1823 - bb->cs[bb->len++] = upper_32_bits(addr); 1824 1793 1825 - i++; 1794 + again: 1795 + pte = m->q->vm->pt_ops->pte_encode_addr(m->tile->xe, 1796 + addr, pat_index, 1797 + level, false, 0); 1798 + bb->cs[bb->len++] = lower_32_bits(pte); 1799 + bb->cs[bb->len++] = upper_32_bits(pte); 1800 + 1801 + if (gpu_page_size < PAGE_SIZE) { 1802 + addr += XE_PAGE_SIZE; 1803 + if (orig_addr + PAGE_SIZE != addr) { 1804 + chunk--; 1805 + goto again; 1806 + } 1807 + i++; 1808 + } else { 1809 + i += gpu_page_size / PAGE_SIZE; 1810 + } 1826 1811 } 1827 1812 } 1813 + } 1814 + 1815 + static bool xe_migrate_vram_use_pde(struct drm_pagemap_addr *sram_addr, 1816 + unsigned long size) 1817 + { 1818 + u32 large_size = (0x1 << xe_pt_shift(1)); 1819 + unsigned long i, incr = large_size / PAGE_SIZE; 1820 + 1821 + for (i = 0; i < DIV_ROUND_UP(size, PAGE_SIZE); i += incr) 1822 + if (PAGE_SIZE << sram_addr[i].order != large_size) 1823 + return false; 1824 + 1825 + return true; 1828 1826 } 1829 1827 1830 1828 enum xe_migrate_copy_dir { ··· 1881 1829 PAGE_SIZE : 4; 1882 1830 int err; 1883 1831 unsigned long i, j; 1832 + bool use_pde = xe_migrate_vram_use_pde(sram_addr, len + sram_offset); 1884 1833 1885 1834 if (drm_WARN_ON(&xe->drm, (len & XE_CACHELINE_MASK) || 1886 1835 (sram_offset | vram_addr) & XE_CACHELINE_MASK)) ··· 1906 1853 * struct drm_pagemap_addr. Ensure this is the case even with higher 1907 1854 * orders. 1908 1855 */ 1909 - for (i = 0; i < npages;) { 1856 + for (i = 0; !use_pde && i < npages;) { 1910 1857 unsigned int order = sram_addr[i].order; 1911 1858 1912 1859 for (j = 1; j < NR_PAGES(order) && i + j < npages; j++) ··· 1916 1863 i += NR_PAGES(order); 1917 1864 } 1918 1865 1919 - build_pt_update_batch_sram(m, bb, pt_slot * XE_PAGE_SIZE, 1920 - sram_addr, len + sram_offset); 1866 + if (use_pde) 1867 + build_pt_update_batch_sram(m, bb, m->large_page_copy_pdes, 1868 + sram_addr, len + sram_offset, 1); 1869 + else 1870 + build_pt_update_batch_sram(m, bb, pt_slot * XE_PAGE_SIZE, 1871 + sram_addr, len + sram_offset, 0); 1921 1872 1922 1873 if (dir == XE_MIGRATE_COPY_TO_VRAM) { 1923 - src_L0_ofs = xe_migrate_vm_addr(pt_slot, 0) + sram_offset; 1874 + if (use_pde) 1875 + src_L0_ofs = m->large_page_copy_ofs + sram_offset; 1876 + else 1877 + src_L0_ofs = xe_migrate_vm_addr(pt_slot, 0) + sram_offset; 1924 1878 dst_L0_ofs = xe_migrate_vram_ofs(xe, vram_addr, false); 1925 1879 1926 1880 } else { 1927 1881 src_L0_ofs = xe_migrate_vram_ofs(xe, vram_addr, false); 1928 - dst_L0_ofs = xe_migrate_vm_addr(pt_slot, 0) + sram_offset; 1882 + if (use_pde) 1883 + dst_L0_ofs = m->large_page_copy_ofs + sram_offset; 1884 + else 1885 + dst_L0_ofs = xe_migrate_vm_addr(pt_slot, 0) + sram_offset; 1929 1886 } 1930 1887 1931 1888 bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
+14 -2
drivers/gpu/drm/xe/xe_mocs.c
··· 576 576 memset(info, 0, sizeof(struct xe_mocs_info)); 577 577 578 578 switch (xe->info.platform) { 579 + case XE_NOVALAKE_S: 579 580 case XE_PANTHERLAKE: 580 581 case XE_LUNARLAKE: 581 582 case XE_BATTLEMAGE: ··· 773 772 init_l3cc_table(gt, &table); 774 773 } 775 774 776 - void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) 775 + /** 776 + * xe_mocs_dump() - Dump MOCS table. 777 + * @gt: the &xe_gt with MOCS table 778 + * @p: the &drm_printer to dump info to 779 + * 780 + * Return: 0 on success or a negative error code on failure. 781 + */ 782 + int xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) 777 783 { 778 784 struct xe_device *xe = gt_to_xe(gt); 779 785 enum xe_force_wake_domains domain; 780 786 struct xe_mocs_info table; 781 787 unsigned int fw_ref, flags; 788 + int err = 0; 782 789 783 790 flags = get_mocs_settings(xe, &table); 784 791 ··· 794 785 xe_pm_runtime_get_noresume(xe); 795 786 fw_ref = xe_force_wake_get(gt_to_fw(gt), domain); 796 787 797 - if (!xe_force_wake_ref_has_domain(fw_ref, domain)) 788 + if (!xe_force_wake_ref_has_domain(fw_ref, domain)) { 789 + err = -ETIMEDOUT; 798 790 goto err_fw; 791 + } 799 792 800 793 table.ops->dump(&table, flags, gt, p); 801 794 802 795 err_fw: 803 796 xe_force_wake_put(gt_to_fw(gt), fw_ref); 804 797 xe_pm_runtime_put(xe); 798 + return err; 805 799 } 806 800 807 801 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
+1 -7
drivers/gpu/drm/xe/xe_mocs.h
··· 11 11 12 12 void xe_mocs_init_early(struct xe_gt *gt); 13 13 void xe_mocs_init(struct xe_gt *gt); 14 - 15 - /** 16 - * xe_mocs_dump - Dump mocs table 17 - * @gt: GT structure 18 - * @p: Printer to dump info to 19 - */ 20 - void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p); 14 + int xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p); 21 15 22 16 #endif
+2 -1
drivers/gpu/drm/xe/xe_oa.c
··· 837 837 xe_oa_configure_oa_context(stream, false); 838 838 839 839 /* Make sure we disable noa to save power. */ 840 - xe_mmio_rmw32(mmio, RPM_CONFIG1, GT_NOA_ENABLE, 0); 840 + if (GT_VER(stream->gt) < 35) 841 + xe_mmio_rmw32(mmio, RPM_CONFIG1, GT_NOA_ENABLE, 0); 841 842 842 843 sqcnt1 = SQCNT1_PMON_ENABLE | 843 844 (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0);
+121 -15
drivers/gpu/drm/xe/xe_pat.c
··· 57 57 int n_entries); 58 58 void (*program_media)(struct xe_gt *gt, const struct xe_pat_table_entry table[], 59 59 int n_entries); 60 - void (*dump)(struct xe_gt *gt, struct drm_printer *p); 60 + int (*dump)(struct xe_gt *gt, struct drm_printer *p); 61 61 }; 62 62 63 63 static const struct xe_pat_table_entry xelp_pat_table[] = { ··· 154 154 static const struct xe_pat_table_entry xe2_pat_ats = XE2_PAT( 0, 0, 0, 0, 3, 3 ); 155 155 static const struct xe_pat_table_entry xe2_pat_pta = XE2_PAT( 0, 0, 0, 0, 3, 0 ); 156 156 157 + /* 158 + * Xe3p_XPC PAT table uses the same layout as Xe2/Xe3, except that there's no 159 + * option for compression. Also note that the "L3" and "L4" register fields 160 + * actually control L2 and L3 cache respectively on this platform. 161 + */ 162 + #define XE3P_XPC_PAT(no_promote, l3clos, l3_policy, l4_policy, __coh_mode) \ 163 + XE2_PAT(no_promote, 0, l3clos, l3_policy, l4_policy, __coh_mode) 164 + 165 + static const struct xe_pat_table_entry xe3p_xpc_pat_ats = XE3P_XPC_PAT( 0, 0, 0, 0, 3 ); 166 + static const struct xe_pat_table_entry xe3p_xpc_pat_pta = XE3P_XPC_PAT( 0, 0, 0, 0, 0 ); 167 + 168 + static const struct xe_pat_table_entry xe3p_xpc_pat_table[] = { 169 + [ 0] = XE3P_XPC_PAT( 0, 0, 0, 0, 0 ), 170 + [ 1] = XE3P_XPC_PAT( 0, 0, 0, 0, 2 ), 171 + [ 2] = XE3P_XPC_PAT( 0, 0, 0, 0, 3 ), 172 + [ 3] = XE3P_XPC_PAT( 0, 0, 3, 3, 0 ), 173 + [ 4] = XE3P_XPC_PAT( 0, 0, 3, 3, 2 ), 174 + [ 5] = XE3P_XPC_PAT( 0, 0, 3, 0, 0 ), 175 + [ 6] = XE3P_XPC_PAT( 0, 0, 3, 0, 2 ), 176 + [ 7] = XE3P_XPC_PAT( 0, 0, 3, 0, 3 ), 177 + [ 8] = XE3P_XPC_PAT( 0, 0, 0, 3, 0 ), 178 + [ 9] = XE3P_XPC_PAT( 0, 0, 0, 3, 2 ), 179 + [10] = XE3P_XPC_PAT( 0, 0, 0, 3, 3 ), 180 + /* 11..22 are reserved; leave set to all 0's */ 181 + [23] = XE3P_XPC_PAT( 0, 1, 0, 0, 0 ), 182 + [24] = XE3P_XPC_PAT( 0, 1, 0, 0, 2 ), 183 + [25] = XE3P_XPC_PAT( 0, 1, 0, 0, 3 ), 184 + [26] = XE3P_XPC_PAT( 0, 2, 0, 0, 0 ), 185 + [27] = XE3P_XPC_PAT( 0, 2, 0, 0, 2 ), 186 + [28] = XE3P_XPC_PAT( 0, 2, 0, 0, 3 ), 187 + [29] = XE3P_XPC_PAT( 0, 3, 0, 0, 0 ), 188 + [30] = XE3P_XPC_PAT( 0, 3, 0, 0, 2 ), 189 + [31] = XE3P_XPC_PAT( 0, 3, 0, 0, 3 ), 190 + }; 191 + 157 192 u16 xe_pat_index_get_coh_mode(struct xe_device *xe, u16 pat_index) 158 193 { 159 194 WARN_ON(pat_index >= xe->pat.n_entries); ··· 229 194 xe_gt_mcr_multicast_write(gt, XE_REG_MCR(_PAT_PTA), xe->pat.pat_pta->value); 230 195 } 231 196 232 - static void xelp_dump(struct xe_gt *gt, struct drm_printer *p) 197 + static int xelp_dump(struct xe_gt *gt, struct drm_printer *p) 233 198 { 234 199 struct xe_device *xe = gt_to_xe(gt); 235 200 unsigned int fw_ref; ··· 237 202 238 203 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 239 204 if (!fw_ref) 240 - return; 205 + return -ETIMEDOUT; 241 206 242 207 drm_printf(p, "PAT table:\n"); 243 208 ··· 250 215 } 251 216 252 217 xe_force_wake_put(gt_to_fw(gt), fw_ref); 218 + return 0; 253 219 } 254 220 255 221 static const struct xe_pat_ops xelp_pat_ops = { ··· 258 222 .dump = xelp_dump, 259 223 }; 260 224 261 - static void xehp_dump(struct xe_gt *gt, struct drm_printer *p) 225 + static int xehp_dump(struct xe_gt *gt, struct drm_printer *p) 262 226 { 263 227 struct xe_device *xe = gt_to_xe(gt); 264 228 unsigned int fw_ref; ··· 266 230 267 231 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 268 232 if (!fw_ref) 269 - return; 233 + return -ETIMEDOUT; 270 234 271 235 drm_printf(p, "PAT table:\n"); 272 236 ··· 281 245 } 282 246 283 247 xe_force_wake_put(gt_to_fw(gt), fw_ref); 248 + return 0; 284 249 } 285 250 286 251 static const struct xe_pat_ops xehp_pat_ops = { ··· 289 252 .dump = xehp_dump, 290 253 }; 291 254 292 - static void xehpc_dump(struct xe_gt *gt, struct drm_printer *p) 255 + static int xehpc_dump(struct xe_gt *gt, struct drm_printer *p) 293 256 { 294 257 struct xe_device *xe = gt_to_xe(gt); 295 258 unsigned int fw_ref; ··· 297 260 298 261 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 299 262 if (!fw_ref) 300 - return; 263 + return -ETIMEDOUT; 301 264 302 265 drm_printf(p, "PAT table:\n"); 303 266 ··· 310 273 } 311 274 312 275 xe_force_wake_put(gt_to_fw(gt), fw_ref); 276 + return 0; 313 277 } 314 278 315 279 static const struct xe_pat_ops xehpc_pat_ops = { ··· 318 280 .dump = xehpc_dump, 319 281 }; 320 282 321 - static void xelpg_dump(struct xe_gt *gt, struct drm_printer *p) 283 + static int xelpg_dump(struct xe_gt *gt, struct drm_printer *p) 322 284 { 323 285 struct xe_device *xe = gt_to_xe(gt); 324 286 unsigned int fw_ref; ··· 326 288 327 289 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 328 290 if (!fw_ref) 329 - return; 291 + return -ETIMEDOUT; 330 292 331 293 drm_printf(p, "PAT table:\n"); 332 294 ··· 344 306 } 345 307 346 308 xe_force_wake_put(gt_to_fw(gt), fw_ref); 309 + return 0; 347 310 } 348 311 349 312 /* ··· 357 318 .dump = xelpg_dump, 358 319 }; 359 320 360 - static void xe2_dump(struct xe_gt *gt, struct drm_printer *p) 321 + static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) 361 322 { 362 323 struct xe_device *xe = gt_to_xe(gt); 363 324 unsigned int fw_ref; ··· 366 327 367 328 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 368 329 if (!fw_ref) 369 - return; 330 + return -ETIMEDOUT; 370 331 371 332 drm_printf(p, "PAT table:\n"); 372 333 ··· 406 367 pat); 407 368 408 369 xe_force_wake_put(gt_to_fw(gt), fw_ref); 370 + return 0; 409 371 } 410 372 411 373 static const struct xe_pat_ops xe2_pat_ops = { ··· 415 375 .dump = xe2_dump, 416 376 }; 417 377 378 + static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p) 379 + { 380 + struct xe_device *xe = gt_to_xe(gt); 381 + unsigned int fw_ref; 382 + u32 pat; 383 + int i; 384 + 385 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 386 + if (!fw_ref) 387 + return -ETIMEDOUT; 388 + 389 + drm_printf(p, "PAT table:\n"); 390 + 391 + for (i = 0; i < xe->pat.n_entries; i++) { 392 + pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i))); 393 + 394 + drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u ] (%#8x)\n", i, 395 + !!(pat & XE2_NO_PROMOTE), 396 + REG_FIELD_GET(XE2_L3_CLOS, pat), 397 + REG_FIELD_GET(XE2_L3_POLICY, pat), 398 + REG_FIELD_GET(XE2_L4_POLICY, pat), 399 + REG_FIELD_GET(XE2_COH_MODE, pat), 400 + pat); 401 + } 402 + 403 + /* 404 + * Also print PTA_MODE, which describes how the hardware accesses 405 + * PPGTT entries. 406 + */ 407 + pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_PTA)); 408 + 409 + drm_printf(p, "Page Table Access:\n"); 410 + drm_printf(p, "PTA_MODE= [ %u, %u, %u, %u, %u ] (%#8x)\n", 411 + !!(pat & XE2_NO_PROMOTE), 412 + REG_FIELD_GET(XE2_L3_CLOS, pat), 413 + REG_FIELD_GET(XE2_L3_POLICY, pat), 414 + REG_FIELD_GET(XE2_L4_POLICY, pat), 415 + REG_FIELD_GET(XE2_COH_MODE, pat), 416 + pat); 417 + 418 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 419 + return 0; 420 + } 421 + 422 + static const struct xe_pat_ops xe3p_xpc_pat_ops = { 423 + .program_graphics = program_pat_mcr, 424 + .program_media = program_pat, 425 + .dump = xe3p_xpc_dump, 426 + }; 427 + 418 428 void xe_pat_init_early(struct xe_device *xe) 419 429 { 420 - if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) { 430 + if (GRAPHICS_VERx100(xe) == 3511) { 431 + xe->pat.ops = &xe3p_xpc_pat_ops; 432 + xe->pat.table = xe3p_xpc_pat_table; 433 + xe->pat.pat_ats = &xe3p_xpc_pat_ats; 434 + xe->pat.pat_pta = &xe3p_xpc_pat_pta; 435 + xe->pat.n_entries = ARRAY_SIZE(xe3p_xpc_pat_table); 436 + xe->pat.idx[XE_CACHE_NONE] = 3; 437 + xe->pat.idx[XE_CACHE_WT] = 3; /* N/A (no display); use UC */ 438 + xe->pat.idx[XE_CACHE_WB] = 2; 439 + } else if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) { 421 440 xe->pat.ops = &xe2_pat_ops; 422 441 xe->pat.table = xe2_pat_table; 423 442 xe->pat.pat_ats = &xe2_pat_ats; ··· 561 462 xe->pat.ops->program_graphics(gt, xe->pat.table, xe->pat.n_entries); 562 463 } 563 464 564 - void xe_pat_dump(struct xe_gt *gt, struct drm_printer *p) 465 + /** 466 + * xe_pat_dump() - Dump GT PAT table into a drm printer. 467 + * @gt: the &xe_gt 468 + * @p: the &drm_printer 469 + * 470 + * Return: 0 on success or a negative error code on failure. 471 + */ 472 + int xe_pat_dump(struct xe_gt *gt, struct drm_printer *p) 565 473 { 566 474 struct xe_device *xe = gt_to_xe(gt); 567 475 568 476 if (!xe->pat.ops) 569 - return; 477 + return -EOPNOTSUPP; 570 478 571 - xe->pat.ops->dump(gt, p); 479 + return xe->pat.ops->dump(gt, p); 572 480 }
+1 -6
drivers/gpu/drm/xe/xe_pat.h
··· 43 43 */ 44 44 void xe_pat_init(struct xe_gt *gt); 45 45 46 - /** 47 - * xe_pat_dump - Dump PAT table 48 - * @gt: GT structure 49 - * @p: Printer to dump info to 50 - */ 51 - void xe_pat_dump(struct xe_gt *gt, struct drm_printer *p); 46 + int xe_pat_dump(struct xe_gt *gt, struct drm_printer *p); 52 47 53 48 /** 54 49 * xe_pat_index_get_coh_mode - Extract the coherency mode for the given
+186 -78
drivers/gpu/drm/xe/xe_pci.c
··· 30 30 #include "xe_pci_sriov.h" 31 31 #include "xe_pci_types.h" 32 32 #include "xe_pm.h" 33 + #include "xe_printk.h" 33 34 #include "xe_sriov.h" 34 35 #include "xe_step.h" 35 36 #include "xe_survivability_mode.h" ··· 52 51 53 52 static const struct xe_graphics_desc graphics_xelp = { 54 53 .hw_engine_mask = BIT(XE_HW_ENGINE_RCS0) | BIT(XE_HW_ENGINE_BCS0), 55 - 56 - .va_bits = 48, 57 - .vm_max_level = 3, 58 54 }; 59 55 60 56 #define XE_HP_FEATURES \ 61 - .has_range_tlb_inval = true, \ 62 - .va_bits = 48, \ 63 - .vm_max_level = 3 57 + .has_range_tlb_inval = true 64 58 65 59 static const struct xe_graphics_desc graphics_xehpg = { 66 60 .hw_engine_mask = ··· 64 68 BIT(XE_HW_ENGINE_CCS2) | BIT(XE_HW_ENGINE_CCS3), 65 69 66 70 XE_HP_FEATURES, 67 - .vram_flags = XE_VRAM_FLAGS_NEED64K, 68 - 69 - .has_flat_ccs = 1, 70 71 }; 71 72 72 73 static const struct xe_graphics_desc graphics_xehpc = { ··· 77 84 BIT(XE_HW_ENGINE_CCS2) | BIT(XE_HW_ENGINE_CCS3), 78 85 79 86 XE_HP_FEATURES, 80 - .va_bits = 57, 81 - .vm_max_level = 4, 82 - .vram_flags = XE_VRAM_FLAGS_NEED64K, 83 87 84 88 .has_asid = 1, 85 89 .has_atomic_enable_pte_bit = 1, ··· 94 104 #define XE2_GFX_FEATURES \ 95 105 .has_asid = 1, \ 96 106 .has_atomic_enable_pte_bit = 1, \ 97 - .has_flat_ccs = 1, \ 98 107 .has_range_tlb_inval = 1, \ 99 108 .has_usm = 1, \ 100 109 .has_64bit_timestamp = 1, \ 101 - .va_bits = 48, \ 102 - .vm_max_level = 4, \ 103 110 .hw_engine_mask = \ 104 111 BIT(XE_HW_ENGINE_RCS0) | \ 105 112 BIT(XE_HW_ENGINE_BCS8) | BIT(XE_HW_ENGINE_BCS0) | \ ··· 104 117 105 118 static const struct xe_graphics_desc graphics_xe2 = { 106 119 XE2_GFX_FEATURES, 120 + }; 121 + 122 + static const struct xe_graphics_desc graphics_xe3p_xpc = { 123 + XE2_GFX_FEATURES, 124 + .hw_engine_mask = 125 + GENMASK(XE_HW_ENGINE_BCS8, XE_HW_ENGINE_BCS1) | 126 + GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0), 107 127 }; 108 128 109 129 static const struct xe_media_desc media_xem = { ··· 143 149 { 3000, "Xe3_LPG", &graphics_xe2 }, 144 150 { 3001, "Xe3_LPG", &graphics_xe2 }, 145 151 { 3003, "Xe3_LPG", &graphics_xe2 }, 152 + { 3004, "Xe3_LPG", &graphics_xe2 }, 153 + { 3005, "Xe3_LPG", &graphics_xe2 }, 154 + { 3511, "Xe3p_XPC", &graphics_xe3p_xpc }, 146 155 }; 147 156 148 157 /* Pre-GMDID Media IPs */ ··· 159 162 { 2000, "Xe2_LPM", &media_xelpmp }, 160 163 { 3000, "Xe3_LPM", &media_xelpmp }, 161 164 { 3002, "Xe3_LPM", &media_xelpmp }, 165 + { 3500, "Xe3p_LPM", &media_xelpmp }, 166 + { 3503, "Xe3p_HPM", &media_xelpmp }, 162 167 }; 163 168 164 169 static const struct xe_device_desc tgl_desc = { ··· 173 174 .has_sriov = true, 174 175 .max_gt_per_tile = 1, 175 176 .require_force_probe = true, 177 + .va_bits = 48, 178 + .vm_max_level = 3, 176 179 }; 177 180 178 181 static const struct xe_device_desc rkl_desc = { ··· 186 185 .has_llc = true, 187 186 .max_gt_per_tile = 1, 188 187 .require_force_probe = true, 188 + .va_bits = 48, 189 + .vm_max_level = 3, 189 190 }; 190 191 191 192 static const u16 adls_rpls_ids[] = { INTEL_RPLS_IDS(NOP), 0 }; ··· 206 203 { XE_SUBPLATFORM_ALDERLAKE_S_RPLS, "RPLS", adls_rpls_ids }, 207 204 {}, 208 205 }, 206 + .va_bits = 48, 207 + .vm_max_level = 3, 209 208 }; 210 209 211 210 static const u16 adlp_rplu_ids[] = { INTEL_RPLU_IDS(NOP), 0 }; ··· 226 221 { XE_SUBPLATFORM_ALDERLAKE_P_RPLU, "RPLU", adlp_rplu_ids }, 227 222 {}, 228 223 }, 224 + .va_bits = 48, 225 + .vm_max_level = 3, 229 226 }; 230 227 231 228 static const struct xe_device_desc adl_n_desc = { ··· 240 233 .has_sriov = true, 241 234 .max_gt_per_tile = 1, 242 235 .require_force_probe = true, 236 + .va_bits = 48, 237 + .vm_max_level = 3, 243 238 }; 244 239 245 240 #define DGFX_FEATURES \ ··· 258 249 .has_heci_gscfi = 1, 259 250 .max_gt_per_tile = 1, 260 251 .require_force_probe = true, 252 + .va_bits = 48, 253 + .vm_max_level = 3, 261 254 }; 262 255 263 256 static const u16 dg2_g10_ids[] = { INTEL_DG2_G10_IDS(NOP), INTEL_ATS_M150_IDS(NOP), 0 }; ··· 269 258 #define DG2_FEATURES \ 270 259 DGFX_FEATURES, \ 271 260 PLATFORM(DG2), \ 261 + .has_flat_ccs = 1, \ 272 262 .has_gsc_nvm = 1, \ 273 263 .has_heci_gscfi = 1, \ 274 264 .subplatforms = (const struct xe_subplatform_desc[]) { \ ··· 277 265 { XE_SUBPLATFORM_DG2_G11, "G11", dg2_g11_ids }, \ 278 266 { XE_SUBPLATFORM_DG2_G12, "G12", dg2_g12_ids }, \ 279 267 { } \ 280 - } 268 + }, \ 269 + .va_bits = 48, \ 270 + .vm_max_level = 3, \ 271 + .vram_flags = XE_VRAM_FLAGS_NEED64K 281 272 282 273 static const struct xe_device_desc ats_m_desc = { 283 274 .pre_gmdid_graphics_ip = &graphics_ip_xehpg, ··· 318 303 .max_gt_per_tile = 1, 319 304 .max_remote_tiles = 1, 320 305 .require_force_probe = true, 306 + .va_bits = 57, 307 + .vm_max_level = 4, 308 + .vram_flags = XE_VRAM_FLAGS_NEED64K, 321 309 .has_mbx_power_limits = false, 322 310 }; 323 311 ··· 332 314 .has_display = true, 333 315 .has_pxp = true, 334 316 .max_gt_per_tile = 2, 317 + .va_bits = 48, 318 + .vm_max_level = 4, 335 319 }; 336 320 337 321 static const struct xe_device_desc lnl_desc = { 338 322 PLATFORM(LUNARLAKE), 339 323 .dma_mask_size = 46, 340 324 .has_display = true, 325 + .has_flat_ccs = 1, 341 326 .has_pxp = true, 342 327 .max_gt_per_tile = 2, 343 328 .needs_scratch = true, 329 + .va_bits = 48, 330 + .vm_max_level = 4, 344 331 }; 332 + 333 + static const u16 bmg_g21_ids[] = { INTEL_BMG_G21_IDS(NOP), 0 }; 345 334 346 335 static const struct xe_device_desc bmg_desc = { 347 336 DGFX_FEATURES, ··· 356 331 .dma_mask_size = 46, 357 332 .has_display = true, 358 333 .has_fan_control = true, 334 + .has_flat_ccs = 1, 359 335 .has_mbx_power_limits = true, 360 336 .has_gsc_nvm = 1, 361 337 .has_heci_cscfi = 1, ··· 364 338 .has_sriov = true, 365 339 .max_gt_per_tile = 2, 366 340 .needs_scratch = true, 341 + .subplatforms = (const struct xe_subplatform_desc[]) { 342 + { XE_SUBPLATFORM_BATTLEMAGE_G21, "G21", bmg_g21_ids }, 343 + { } 344 + }, 345 + .va_bits = 48, 346 + .vm_max_level = 4, 367 347 }; 368 348 369 349 static const struct xe_device_desc ptl_desc = { 370 350 PLATFORM(PANTHERLAKE), 371 351 .dma_mask_size = 46, 372 352 .has_display = true, 353 + .has_flat_ccs = 1, 373 354 .has_sriov = true, 374 355 .max_gt_per_tile = 2, 375 356 .needs_scratch = true, 357 + .needs_shared_vf_gt_wq = true, 358 + .va_bits = 48, 359 + .vm_max_level = 4, 360 + }; 361 + 362 + static const struct xe_device_desc nvls_desc = { 363 + PLATFORM(NOVALAKE_S), 364 + .dma_mask_size = 46, 365 + .has_display = true, 366 + .has_flat_ccs = 1, 367 + .max_gt_per_tile = 2, 368 + .require_force_probe = true, 369 + .va_bits = 48, 370 + .vm_max_level = 4, 376 371 }; 377 372 378 373 #undef PLATFORM ··· 422 375 INTEL_LNL_IDS(INTEL_VGA_DEVICE, &lnl_desc), 423 376 INTEL_BMG_IDS(INTEL_VGA_DEVICE, &bmg_desc), 424 377 INTEL_PTL_IDS(INTEL_VGA_DEVICE, &ptl_desc), 378 + INTEL_NVLS_IDS(INTEL_VGA_DEVICE, &nvls_desc), 425 379 { } 426 380 }; 427 381 MODULE_DEVICE_TABLE(pci, pciidlist); ··· 495 447 GMDID_MEDIA 496 448 }; 497 449 498 - static void read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, u32 *ver, u32 *revid) 450 + static int read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, u32 *ver, u32 *revid) 499 451 { 500 452 struct xe_mmio *mmio = xe_root_tile_mmio(xe); 501 453 struct xe_reg gmdid_reg = GMD_ID; ··· 504 456 KUNIT_STATIC_STUB_REDIRECT(read_gmdid, xe, type, ver, revid); 505 457 506 458 if (IS_SRIOV_VF(xe)) { 507 - struct xe_gt *gt = xe_root_mmio_gt(xe); 508 - 509 459 /* 510 460 * To get the value of the GMDID register, VFs must obtain it 511 461 * from the GuC using MMIO communication. 512 462 * 513 - * Note that at this point the xe_gt is not fully uninitialized 514 - * and only basic access to MMIO registers is possible. To use 515 - * our existing GuC communication functions we must perform at 516 - * least basic xe_gt and xe_guc initialization. 517 - * 518 - * Since to obtain the value of GMDID_MEDIA we need to use the 519 - * media GuC, temporarily tweak the gt type. 463 + * Note that at this point the GTs are not initialized and only 464 + * tile-level access to MMIO registers is possible. To use our 465 + * existing GuC communication functions we must create a dummy 466 + * GT structure and perform at least basic xe_gt and xe_guc 467 + * initialization. 520 468 */ 521 - xe_gt_assert(gt, gt->info.type == XE_GT_TYPE_UNINITIALIZED); 469 + struct xe_gt *gt __free(kfree) = NULL; 470 + int err; 522 471 472 + gt = kzalloc(sizeof(*gt), GFP_KERNEL); 473 + if (!gt) 474 + return -ENOMEM; 475 + 476 + gt->tile = &xe->tiles[0]; 523 477 if (type == GMDID_MEDIA) { 524 478 gt->info.id = 1; 525 479 gt->info.type = XE_GT_TYPE_MEDIA; ··· 533 483 xe_gt_mmio_init(gt); 534 484 xe_guc_comm_init_early(&gt->uc.guc); 535 485 536 - /* Don't bother with GMDID if failed to negotiate the GuC ABI */ 537 - val = xe_gt_sriov_vf_bootstrap(gt) ? 0 : xe_gt_sriov_vf_gmdid(gt); 486 + err = xe_gt_sriov_vf_bootstrap(gt); 487 + if (err) 488 + return err; 538 489 539 - /* 540 - * Only undo xe_gt.info here, the remaining changes made above 541 - * will be overwritten as part of the regular initialization. 542 - */ 543 - gt->info.id = 0; 544 - gt->info.type = XE_GT_TYPE_UNINITIALIZED; 490 + val = xe_gt_sriov_vf_gmdid(gt); 545 491 } else { 546 492 /* 547 493 * GMD_ID is a GT register, but at this point in the driver ··· 555 509 556 510 *ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val) * 100 + REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); 557 511 *revid = REG_FIELD_GET(GMD_ID_REVID, val); 512 + 513 + return 0; 558 514 } 559 515 560 516 static const struct xe_ip *find_graphics_ip(unsigned int verx100) ··· 583 535 * Read IP version from hardware and select graphics/media IP descriptors 584 536 * based on the result. 585 537 */ 586 - static void handle_gmdid(struct xe_device *xe, 587 - const struct xe_ip **graphics_ip, 588 - const struct xe_ip **media_ip, 589 - u32 *graphics_revid, 590 - u32 *media_revid) 538 + static int handle_gmdid(struct xe_device *xe, 539 + const struct xe_ip **graphics_ip, 540 + const struct xe_ip **media_ip, 541 + u32 *graphics_revid, 542 + u32 *media_revid) 591 543 { 592 544 u32 ver; 545 + int ret; 593 546 594 547 *graphics_ip = NULL; 595 548 *media_ip = NULL; 596 549 597 - read_gmdid(xe, GMDID_GRAPHICS, &ver, graphics_revid); 550 + ret = read_gmdid(xe, GMDID_GRAPHICS, &ver, graphics_revid); 551 + if (ret) 552 + return ret; 598 553 599 554 *graphics_ip = find_graphics_ip(ver); 600 555 if (!*graphics_ip) { ··· 605 554 ver / 100, ver % 100); 606 555 } 607 556 608 - read_gmdid(xe, GMDID_MEDIA, &ver, media_revid); 557 + ret = read_gmdid(xe, GMDID_MEDIA, &ver, media_revid); 558 + if (ret) 559 + return ret; 560 + 609 561 /* Media may legitimately be fused off / not present */ 610 562 if (ver == 0) 611 - return; 563 + return 0; 612 564 613 565 *media_ip = find_media_ip(ver); 614 566 if (!*media_ip) { 615 567 drm_err(&xe->drm, "Hardware reports unknown media version %u.%02u\n", 616 568 ver / 100, ver % 100); 617 569 } 570 + 571 + return 0; 618 572 } 619 573 620 574 /* ··· 638 582 subplatform_desc->subplatform : XE_SUBPLATFORM_NONE; 639 583 640 584 xe->info.dma_mask_size = desc->dma_mask_size; 585 + xe->info.va_bits = desc->va_bits; 586 + xe->info.vm_max_level = desc->vm_max_level; 587 + xe->info.vram_flags = desc->vram_flags; 588 + 641 589 xe->info.is_dgfx = desc->is_dgfx; 642 590 xe->info.has_fan_control = desc->has_fan_control; 591 + /* runtime fusing may force flat_ccs to disabled later */ 592 + xe->info.has_flat_ccs = desc->has_flat_ccs; 643 593 xe->info.has_mbx_power_limits = desc->has_mbx_power_limits; 644 594 xe->info.has_gsc_nvm = desc->has_gsc_nvm; 645 595 xe->info.has_heci_gscfi = desc->has_heci_gscfi; ··· 653 591 xe->info.has_late_bind = desc->has_late_bind; 654 592 xe->info.has_llc = desc->has_llc; 655 593 xe->info.has_pxp = desc->has_pxp; 656 - xe->info.has_sriov = desc->has_sriov; 594 + xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) && 595 + desc->has_sriov; 657 596 xe->info.skip_guc_pc = desc->skip_guc_pc; 658 597 xe->info.skip_mtcfg = desc->skip_mtcfg; 659 598 xe->info.skip_pcode = desc->skip_pcode; 660 599 xe->info.needs_scratch = desc->needs_scratch; 600 + xe->info.needs_shared_vf_gt_wq = desc->needs_shared_vf_gt_wq; 661 601 662 602 xe->info.probe_display = IS_ENABLED(CONFIG_DRM_XE_DISPLAY) && 663 603 xe_modparam.probe_display && ··· 715 651 } 716 652 } 717 653 654 + static struct xe_gt *alloc_primary_gt(struct xe_tile *tile, 655 + const struct xe_graphics_desc *graphics_desc, 656 + const struct xe_media_desc *media_desc) 657 + { 658 + struct xe_device *xe = tile_to_xe(tile); 659 + struct xe_gt *gt; 660 + 661 + if (!xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev))) { 662 + xe_info(xe, "Primary GT disabled via configfs\n"); 663 + return NULL; 664 + } 665 + 666 + gt = xe_gt_alloc(tile); 667 + if (IS_ERR(gt)) 668 + return gt; 669 + 670 + gt->info.type = XE_GT_TYPE_MAIN; 671 + gt->info.id = tile->id * xe->info.max_gt_per_tile; 672 + gt->info.has_indirect_ring_state = graphics_desc->has_indirect_ring_state; 673 + gt->info.engine_mask = graphics_desc->hw_engine_mask; 674 + 675 + /* 676 + * Before media version 13, the media IP was part of the primary GT 677 + * so we need to add the media engines to the primary GT's engine list. 678 + */ 679 + if (MEDIA_VER(xe) < 13 && media_desc) 680 + gt->info.engine_mask |= media_desc->hw_engine_mask; 681 + 682 + return gt; 683 + } 684 + 685 + static struct xe_gt *alloc_media_gt(struct xe_tile *tile, 686 + const struct xe_media_desc *media_desc) 687 + { 688 + struct xe_device *xe = tile_to_xe(tile); 689 + struct xe_gt *gt; 690 + 691 + if (!xe_configfs_media_gt_allowed(to_pci_dev(xe->drm.dev))) { 692 + xe_info(xe, "Media GT disabled via configfs\n"); 693 + return NULL; 694 + } 695 + 696 + if (MEDIA_VER(xe) < 13 || !media_desc) 697 + return NULL; 698 + 699 + gt = xe_gt_alloc(tile); 700 + if (IS_ERR(gt)) 701 + return gt; 702 + 703 + gt->info.type = XE_GT_TYPE_MEDIA; 704 + gt->info.id = tile->id * xe->info.max_gt_per_tile + 1; 705 + gt->info.has_indirect_ring_state = media_desc->has_indirect_ring_state; 706 + gt->info.engine_mask = media_desc->hw_engine_mask; 707 + 708 + return gt; 709 + } 710 + 718 711 /* 719 712 * Initialize device info content that does require knowledge about 720 713 * graphics / media IP version. ··· 788 667 const struct xe_media_desc *media_desc; 789 668 struct xe_tile *tile; 790 669 struct xe_gt *gt; 670 + int ret; 791 671 u8 id; 792 672 793 673 /* ··· 804 682 xe->info.step = xe_step_pre_gmdid_get(xe); 805 683 } else { 806 684 xe_assert(xe, !desc->pre_gmdid_media_ip); 807 - handle_gmdid(xe, &graphics_ip, &media_ip, 808 - &graphics_gmdid_revid, &media_gmdid_revid); 685 + ret = handle_gmdid(xe, &graphics_ip, &media_ip, 686 + &graphics_gmdid_revid, &media_gmdid_revid); 687 + if (ret) 688 + return ret; 689 + 809 690 xe->info.step = xe_step_gmdid_get(xe, 810 691 graphics_gmdid_revid, 811 692 media_gmdid_revid); ··· 835 710 media_desc = NULL; 836 711 } 837 712 838 - xe->info.vram_flags = graphics_desc->vram_flags; 839 - xe->info.va_bits = graphics_desc->va_bits; 840 - xe->info.vm_max_level = graphics_desc->vm_max_level; 841 713 xe->info.has_asid = graphics_desc->has_asid; 842 714 xe->info.has_atomic_enable_pte_bit = graphics_desc->has_atomic_enable_pte_bit; 843 715 if (xe->info.platform != XE_PVC) 844 716 xe->info.has_device_atomics_on_smem = 1; 845 - 846 - /* Runtime detection may change this later */ 847 - xe->info.has_flat_ccs = graphics_desc->has_flat_ccs; 848 717 849 718 xe->info.has_range_tlb_inval = graphics_desc->has_range_tlb_inval; 850 719 xe->info.has_usm = graphics_desc->has_usm; ··· 854 735 return err; 855 736 } 856 737 857 - /* 858 - * All platforms have at least one primary GT. Any platform with media 859 - * version 13 or higher has an additional dedicated media GT. And 860 - * depending on the graphics IP there may be additional "remote tiles." 861 - * All of these together determine the overall GT count. 862 - */ 738 + /* Allocate any GT and VRAM structures necessary for the platform. */ 863 739 for_each_tile(tile, xe, id) { 864 740 int err; 865 - 866 - gt = tile->primary_gt; 867 - gt->info.type = XE_GT_TYPE_MAIN; 868 - gt->info.id = tile->id * xe->info.max_gt_per_tile; 869 - gt->info.has_indirect_ring_state = graphics_desc->has_indirect_ring_state; 870 - gt->info.engine_mask = graphics_desc->hw_engine_mask; 871 741 872 742 err = xe_tile_alloc_vram(tile); 873 743 if (err) 874 744 return err; 875 745 876 - if (MEDIA_VER(xe) < 13 && media_desc) 877 - gt->info.engine_mask |= media_desc->hw_engine_mask; 878 - 879 - if (MEDIA_VER(xe) < 13 || !media_desc) 880 - continue; 746 + tile->primary_gt = alloc_primary_gt(tile, graphics_desc, media_desc); 747 + if (IS_ERR(tile->primary_gt)) 748 + return PTR_ERR(tile->primary_gt); 881 749 882 750 /* 883 - * Allocate and setup media GT for platforms with standalone 884 - * media. 751 + * It's not currently possible to probe a device with the 752 + * primary GT disabled. With some work, this may be future in 753 + * the possible for igpu platforms (although probably not for 754 + * dgpu's since access to the primary GT's BCS engines is 755 + * required for VRAM management). 885 756 */ 886 - tile->media_gt = xe_gt_alloc(tile); 757 + if (!tile->primary_gt) { 758 + drm_err(&xe->drm, "Cannot probe device with without a primary GT\n"); 759 + return -ENODEV; 760 + } 761 + 762 + tile->media_gt = alloc_media_gt(tile, media_desc); 887 763 if (IS_ERR(tile->media_gt)) 888 764 return PTR_ERR(tile->media_gt); 889 - 890 - gt = tile->media_gt; 891 - gt->info.type = XE_GT_TYPE_MEDIA; 892 - gt->info.id = tile->id * xe->info.max_gt_per_tile + 1; 893 - gt->info.has_indirect_ring_state = media_desc->has_indirect_ring_state; 894 - gt->info.engine_mask = media_desc->hw_engine_mask; 895 765 } 896 766 897 767 /*
+7 -46
drivers/gpu/drm/xe/xe_pci_sriov.c
··· 17 17 #include "xe_pm.h" 18 18 #include "xe_sriov.h" 19 19 #include "xe_sriov_pf.h" 20 + #include "xe_sriov_pf_control.h" 20 21 #include "xe_sriov_pf_helpers.h" 22 + #include "xe_sriov_pf_provision.h" 21 23 #include "xe_sriov_printk.h" 22 24 23 - static int pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs) 25 + static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) 24 26 { 25 27 unsigned int n; 26 28 27 29 for (n = 1; n <= num_vfs; n++) 28 - if (!xe_gt_sriov_pf_config_is_empty(gt, n)) 29 - return false; 30 - 31 - return true; 32 - } 33 - 34 - static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 35 - { 36 - struct xe_gt *gt; 37 - unsigned int id; 38 - int result = 0, err; 39 - 40 - for_each_gt(gt, xe, id) { 41 - if (!pf_needs_provisioning(gt, num_vfs)) 42 - continue; 43 - err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); 44 - result = result ?: err; 45 - } 46 - 47 - return result; 48 - } 49 - 50 - static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 51 - { 52 - struct xe_gt *gt; 53 - unsigned int id; 54 - unsigned int n; 55 - 56 - for_each_gt(gt, xe, id) 57 - for (n = 1; n <= num_vfs; n++) 58 - xe_gt_sriov_pf_config_release(gt, n, true); 59 - } 60 - 61 - static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) 62 - { 63 - struct xe_gt *gt; 64 - unsigned int id; 65 - unsigned int n; 66 - 67 - for_each_gt(gt, xe, id) 68 - for (n = 1; n <= num_vfs; n++) 69 - xe_gt_sriov_pf_control_trigger_flr(gt, n); 30 + xe_sriov_pf_control_reset_vf(xe, n); 70 31 } 71 32 72 33 static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id) ··· 131 170 */ 132 171 xe_pm_runtime_get_noresume(xe); 133 172 134 - err = pf_provision_vfs(xe, num_vfs); 173 + err = xe_sriov_pf_provision_vfs(xe, num_vfs); 135 174 if (err < 0) 136 175 goto failed; 137 176 ··· 155 194 return num_vfs; 156 195 157 196 failed: 158 - pf_unprovision_vfs(xe, num_vfs); 197 + xe_sriov_pf_unprovision_vfs(xe, num_vfs); 159 198 xe_pm_runtime_put(xe); 160 199 out: 161 200 xe_sriov_notice(xe, "Failed to enable %u VF%s (%pe)\n", ··· 181 220 182 221 pf_reset_vfs(xe, num_vfs); 183 222 184 - pf_unprovision_vfs(xe, num_vfs); 223 + xe_sriov_pf_unprovision_vfs(xe, num_vfs); 185 224 186 225 /* not needed anymore - see pf_enable_vfs() */ 187 226 xe_pm_runtime_put(xe);
+5 -5
drivers/gpu/drm/xe/xe_pci_types.h
··· 30 30 u8 dma_mask_size; 31 31 u8 max_remote_tiles:2; 32 32 u8 max_gt_per_tile:2; 33 + u8 va_bits; 34 + u8 vm_max_level; 35 + u8 vram_flags; 33 36 34 37 u8 require_force_probe:1; 35 38 u8 is_dgfx:1; 36 39 37 40 u8 has_display:1; 38 41 u8 has_fan_control:1; 42 + u8 has_flat_ccs:1; 39 43 u8 has_gsc_nvm:1; 40 44 u8 has_heci_gscfi:1; 41 45 u8 has_heci_cscfi:1; ··· 52 48 u8 skip_guc_pc:1; 53 49 u8 skip_mtcfg:1; 54 50 u8 skip_pcode:1; 51 + u8 needs_shared_vf_gt_wq:1; 55 52 }; 56 53 57 54 struct xe_graphics_desc { 58 - u8 va_bits; 59 - u8 vm_max_level; 60 - u8 vram_flags; 61 - 62 55 u64 hw_engine_mask; /* hardware engines provided by graphics IP */ 63 56 64 57 u8 has_asid:1; 65 58 u8 has_atomic_enable_pte_bit:1; 66 - u8 has_flat_ccs:1; 67 59 u8 has_indirect_ring_state:1; 68 60 u8 has_range_tlb_inval:1; 69 61 u8 has_usm:1;
+2
drivers/gpu/drm/xe/xe_platform_types.h
··· 24 24 XE_LUNARLAKE, 25 25 XE_BATTLEMAGE, 26 26 XE_PANTHERLAKE, 27 + XE_NOVALAKE_S, 27 28 }; 28 29 29 30 enum xe_subplatform { ··· 35 34 XE_SUBPLATFORM_DG2_G10, 36 35 XE_SUBPLATFORM_DG2_G11, 37 36 XE_SUBPLATFORM_DG2_G12, 37 + XE_SUBPLATFORM_BATTLEMAGE_G21, 38 38 }; 39 39 40 40 #endif
+66
drivers/gpu/drm/xe/xe_pm.c
··· 83 83 static struct lockdep_map xe_pm_runtime_nod3cold_map = { 84 84 .name = "xe_rpm_nod3cold_map" 85 85 }; 86 + 87 + static struct lockdep_map xe_pm_block_lockdep_map = { 88 + .name = "xe_pm_block_map", 89 + }; 86 90 #endif 91 + 92 + static void xe_pm_block_begin_signalling(void) 93 + { 94 + lock_acquire_shared_recursive(&xe_pm_block_lockdep_map, 0, 1, NULL, _RET_IP_); 95 + } 96 + 97 + static void xe_pm_block_end_signalling(void) 98 + { 99 + lock_release(&xe_pm_block_lockdep_map, _RET_IP_); 100 + } 101 + 102 + /** 103 + * xe_pm_might_block_on_suspend() - Annotate that the code might block on suspend 104 + * 105 + * Annotation to use where the code might block or sieze to make 106 + * progress pending resume completion. 107 + */ 108 + void xe_pm_might_block_on_suspend(void) 109 + { 110 + lock_map_acquire(&xe_pm_block_lockdep_map); 111 + lock_map_release(&xe_pm_block_lockdep_map); 112 + } 113 + 114 + /** 115 + * xe_pm_might_block_on_suspend() - Block pending suspend. 116 + * @xe: The xe device about to be suspended. 117 + * 118 + * Block if the pm notifier has start evicting bos, to avoid 119 + * racing and validating those bos back. The function is 120 + * annotated to ensure no locks are held that are also grabbed 121 + * in the pm notifier or the device suspend / resume. 122 + * This is intended to be used by freezable tasks only. 123 + * (Not freezable workqueues), with the intention that the function 124 + * returns %-ERESTARTSYS when tasks are frozen during suspend, 125 + * and allows the task to freeze. The caller must be able to 126 + * handle the %-ERESTARTSYS. 127 + * 128 + * Return: %0 on success, %-ERESTARTSYS on signal pending or 129 + * if freezing requested. 130 + */ 131 + int xe_pm_block_on_suspend(struct xe_device *xe) 132 + { 133 + xe_pm_might_block_on_suspend(); 134 + 135 + return wait_for_completion_interruptible(&xe->pm_block); 136 + } 87 137 88 138 /** 89 139 * xe_rpm_reclaim_safe() - Whether runtime resume can be done from reclaim context ··· 174 124 int err; 175 125 176 126 drm_dbg(&xe->drm, "Suspending device\n"); 127 + xe_pm_block_begin_signalling(); 177 128 trace_xe_pm_suspend(xe, __builtin_return_address(0)); 178 129 179 130 err = xe_pxp_pm_suspend(xe->pxp); ··· 206 155 xe_i2c_pm_suspend(xe); 207 156 208 157 drm_dbg(&xe->drm, "Device suspended\n"); 158 + xe_pm_block_end_signalling(); 159 + 209 160 return 0; 210 161 211 162 err_display: ··· 215 162 xe_pxp_pm_resume(xe->pxp); 216 163 err: 217 164 drm_dbg(&xe->drm, "Device suspend failed %d\n", err); 165 + xe_pm_block_end_signalling(); 218 166 return err; 219 167 } 220 168 ··· 232 178 u8 id; 233 179 int err; 234 180 181 + xe_pm_block_begin_signalling(); 235 182 drm_dbg(&xe->drm, "Resuming device\n"); 236 183 trace_xe_pm_resume(xe, __builtin_return_address(0)); 237 184 ··· 277 222 xe_late_bind_fw_load(&xe->late_bind); 278 223 279 224 drm_dbg(&xe->drm, "Device resumed\n"); 225 + xe_pm_block_end_signalling(); 280 226 return 0; 281 227 err: 282 228 drm_dbg(&xe->drm, "Device resume failed %d\n", err); 229 + xe_pm_block_end_signalling(); 283 230 return err; 284 231 } 285 232 ··· 386 329 switch (action) { 387 330 case PM_HIBERNATION_PREPARE: 388 331 case PM_SUSPEND_PREPARE: 332 + { 333 + struct xe_validation_ctx ctx; 334 + 389 335 reinit_completion(&xe->pm_block); 336 + xe_pm_block_begin_signalling(); 390 337 xe_pm_runtime_get(xe); 338 + (void)xe_validation_ctx_init(&ctx, &xe->val, NULL, 339 + (struct xe_val_flags) {.exclusive = true}); 391 340 err = xe_bo_evict_all_user(xe); 341 + xe_validation_ctx_fini(&ctx); 392 342 if (err) 393 343 drm_dbg(&xe->drm, "Notifier evict user failed (%d)\n", err); 394 344 ··· 407 343 * avoid a runtime suspend interfering with evicted objects or backup 408 344 * allocations. 409 345 */ 346 + xe_pm_block_end_signalling(); 410 347 break; 348 + } 411 349 case PM_POST_HIBERNATION: 412 350 case PM_POST_SUSPEND: 413 351 complete_all(&xe->pm_block);
+2
drivers/gpu/drm/xe/xe_pm.h
··· 33 33 void xe_pm_d3cold_allowed_toggle(struct xe_device *xe); 34 34 bool xe_rpm_reclaim_safe(const struct xe_device *xe); 35 35 struct task_struct *xe_pm_read_callback_task(struct xe_device *xe); 36 + int xe_pm_block_on_suspend(struct xe_device *xe); 37 + void xe_pm_might_block_on_suspend(void); 36 38 int xe_pm_module_init(void); 37 39 38 40 #endif
+10 -1
drivers/gpu/drm/xe/xe_pmu.c
··· 497 497 static void set_supported_events(struct xe_pmu *pmu) 498 498 { 499 499 struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); 500 - struct xe_gt *gt = xe_device_get_gt(xe, 0); 500 + struct xe_gt *gt; 501 + int id; 502 + 503 + /* If there are no GTs, don't support any GT-related events */ 504 + if (xe->info.gt_count == 0) 505 + return; 501 506 502 507 if (!xe->info.skip_guc_pc) { 503 508 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_C6_RESIDENCY); 504 509 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_ACTUAL_FREQUENCY); 505 510 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_REQUESTED_FREQUENCY); 506 511 } 512 + 513 + /* Find the first available GT to query engine event capabilities */ 514 + for_each_gt(gt, xe, id) 515 + break; 507 516 508 517 if (xe_guc_engine_activity_supported(&gt->uc.guc)) { 509 518 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_ENGINE_ACTIVE_TICKS);
+11
drivers/gpu/drm/xe/xe_preempt_fence.c
··· 8 8 #include <linux/slab.h> 9 9 10 10 #include "xe_exec_queue.h" 11 + #include "xe_gt_printk.h" 12 + #include "xe_guc_exec_queue_types.h" 11 13 #include "xe_vm.h" 12 14 13 15 static void preempt_fence_work_func(struct work_struct *w) ··· 23 21 dma_fence_set_error(&pfence->base, pfence->error); 24 22 } else if (!q->ops->reset_status(q)) { 25 23 int err = q->ops->suspend_wait(q); 24 + 25 + if (err == -EAGAIN) { 26 + xe_gt_dbg(q->gt, "PREEMPT FENCE RETRY guc_id=%d", 27 + q->guc->id); 28 + queue_work(q->vm->xe->preempt_fence_wq, 29 + &pfence->preempt_work); 30 + dma_fence_end_signalling(cookie); 31 + return; 32 + } 26 33 27 34 if (err) 28 35 dma_fence_set_error(&pfence->base, err);
+2 -2
drivers/gpu/drm/xe/xe_psmi.c
··· 70 70 { 71 71 struct xe_tile *tile; 72 72 73 - if (!id || !bo_size) 74 - return NULL; 73 + xe_assert(xe, id); 74 + xe_assert(xe, bo_size); 75 75 76 76 tile = &xe->tiles[id - 1]; 77 77
+3 -3
drivers/gpu/drm/xe/xe_pt.c
··· 122 122 XE_BO_FLAG_IGNORE_MIN_PAGE_SIZE | 123 123 XE_BO_FLAG_NO_RESV_EVICT | XE_BO_FLAG_PAGETABLE; 124 124 if (vm->xef) /* userspace */ 125 - bo_flags |= XE_BO_FLAG_PINNED_LATE_RESTORE; 125 + bo_flags |= XE_BO_FLAG_PINNED_LATE_RESTORE | XE_BO_FLAG_FORCE_USER_VRAM; 126 126 127 127 pt->level = level; 128 128 ··· 2022 2022 case DRM_GPUVA_OP_MAP: 2023 2023 if ((!op->map.immediate && xe_vm_in_fault_mode(vm) && 2024 2024 !op->map.invalidate_on_bind) || 2025 - op->map.is_cpu_addr_mirror) 2025 + (op->map.vma_flags & XE_VMA_SYSTEM_ALLOCATOR)) 2026 2026 break; 2027 2027 2028 2028 err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma, ··· 2252 2252 switch (op->base.op) { 2253 2253 case DRM_GPUVA_OP_MAP: 2254 2254 if ((!op->map.immediate && xe_vm_in_fault_mode(vm)) || 2255 - op->map.is_cpu_addr_mirror) 2255 + (op->map.vma_flags & XE_VMA_SYSTEM_ALLOCATOR)) 2256 2256 break; 2257 2257 2258 2258 bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence,
+1 -1
drivers/gpu/drm/xe/xe_query.c
··· 436 436 struct drm_xe_device_query *query) 437 437 { 438 438 struct xe_gt *gt = xe_root_mmio_gt(xe); 439 - size_t size = xe_guc_hwconfig_size(&gt->uc.guc); 439 + size_t size = gt ? xe_guc_hwconfig_size(&gt->uc.guc) : 0; 440 440 void __user *query_ptr = u64_to_user_ptr(query->data); 441 441 void *hwconfig; 442 442
+2 -1
drivers/gpu/drm/xe/xe_reg_whitelist.c
··· 19 19 #undef XE_REG_MCR 20 20 #define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1) 21 21 22 - static bool match_not_render(const struct xe_gt *gt, 22 + static bool match_not_render(const struct xe_device *xe, 23 + const struct xe_gt *gt, 23 24 const struct xe_hw_engine *hwe) 24 25 { 25 26 return hwe->class != XE_ENGINE_CLASS_RENDER;
+19 -4
drivers/gpu/drm/xe/xe_ring_ops.c
··· 245 245 246 246 /* for engines that don't require any special HW handling (no EUs, no aux inval, etc) */ 247 247 static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc, 248 - u64 batch_addr, u32 seqno) 248 + u64 batch_addr, u32 *head, u32 seqno) 249 249 { 250 250 u32 dw[MAX_JOB_SIZE_DW], i = 0; 251 251 u32 ppgtt_flag = get_ppgtt_flag(job); 252 252 struct xe_gt *gt = job->q->gt; 253 + 254 + *head = lrc->ring.tail; 253 255 254 256 i = emit_copy_timestamp(lrc, dw, i); 255 257 ··· 298 296 } 299 297 300 298 static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc, 301 - u64 batch_addr, u32 seqno) 299 + u64 batch_addr, u32 *head, u32 seqno) 302 300 { 303 301 u32 dw[MAX_JOB_SIZE_DW], i = 0; 304 302 u32 ppgtt_flag = get_ppgtt_flag(job); 305 303 struct xe_gt *gt = job->q->gt; 306 304 struct xe_device *xe = gt_to_xe(gt); 307 305 bool decode = job->q->class == XE_ENGINE_CLASS_VIDEO_DECODE; 306 + 307 + *head = lrc->ring.tail; 308 308 309 309 i = emit_copy_timestamp(lrc, dw, i); 310 310 ··· 350 346 351 347 static void __emit_job_gen12_render_compute(struct xe_sched_job *job, 352 348 struct xe_lrc *lrc, 353 - u64 batch_addr, u32 seqno) 349 + u64 batch_addr, u32 *head, 350 + u32 seqno) 354 351 { 355 352 u32 dw[MAX_JOB_SIZE_DW], i = 0; 356 353 u32 ppgtt_flag = get_ppgtt_flag(job); ··· 359 354 struct xe_device *xe = gt_to_xe(gt); 360 355 bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK); 361 356 u32 mask_flags = 0; 357 + 358 + *head = lrc->ring.tail; 362 359 363 360 i = emit_copy_timestamp(lrc, dw, i); 364 361 ··· 403 396 } 404 397 405 398 static void emit_migration_job_gen12(struct xe_sched_job *job, 406 - struct xe_lrc *lrc, u32 seqno) 399 + struct xe_lrc *lrc, u32 *head, 400 + u32 seqno) 407 401 { 408 402 u32 saddr = xe_lrc_start_seqno_ggtt_addr(lrc); 409 403 u32 dw[MAX_JOB_SIZE_DW], i = 0; 404 + 405 + *head = lrc->ring.tail; 410 406 411 407 i = emit_copy_timestamp(lrc, dw, i); 412 408 ··· 444 434 445 435 __emit_job_gen12_simple(job, job->q->lrc[0], 446 436 job->ptrs[0].batch_addr, 437 + &job->ptrs[0].head, 447 438 xe_sched_job_lrc_seqno(job)); 448 439 } 449 440 ··· 454 443 455 444 if (xe_sched_job_is_migration(job->q)) { 456 445 emit_migration_job_gen12(job, job->q->lrc[0], 446 + &job->ptrs[0].head, 457 447 xe_sched_job_lrc_seqno(job)); 458 448 return; 459 449 } ··· 462 450 for (i = 0; i < job->q->width; ++i) 463 451 __emit_job_gen12_simple(job, job->q->lrc[i], 464 452 job->ptrs[i].batch_addr, 453 + &job->ptrs[i].head, 465 454 xe_sched_job_lrc_seqno(job)); 466 455 } 467 456 ··· 474 461 for (i = 0; i < job->q->width; ++i) 475 462 __emit_job_gen12_video(job, job->q->lrc[i], 476 463 job->ptrs[i].batch_addr, 464 + &job->ptrs[i].head, 477 465 xe_sched_job_lrc_seqno(job)); 478 466 } 479 467 ··· 485 471 for (i = 0; i < job->q->width; ++i) 486 472 __emit_job_gen12_render_compute(job, job->q->lrc[i], 487 473 job->ptrs[i].batch_addr, 474 + &job->ptrs[i].head, 488 475 xe_sched_job_lrc_seqno(job)); 489 476 } 490 477
+20 -11
drivers/gpu/drm/xe/xe_rtp.c
··· 133 133 match = hwe->class != r->engine_class; 134 134 break; 135 135 case XE_RTP_MATCH_FUNC: 136 - if (drm_WARN_ON(&xe->drm, !gt)) 137 - return false; 138 - 139 - match = r->match_func(gt, hwe); 136 + match = r->match_func(xe, gt, hwe); 140 137 break; 141 138 default: 142 139 drm_warn(&xe->drm, "Invalid RTP match %u\n", ··· 340 343 } 341 344 EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process); 342 345 343 - bool xe_rtp_match_even_instance(const struct xe_gt *gt, 346 + bool xe_rtp_match_even_instance(const struct xe_device *xe, 347 + const struct xe_gt *gt, 344 348 const struct xe_hw_engine *hwe) 345 349 { 346 350 return hwe->instance % 2 == 0; 347 351 } 348 352 349 - bool xe_rtp_match_first_render_or_compute(const struct xe_gt *gt, 353 + bool xe_rtp_match_first_render_or_compute(const struct xe_device *xe, 354 + const struct xe_gt *gt, 350 355 const struct xe_hw_engine *hwe) 351 356 { 352 357 u64 render_compute_mask = gt->info.engine_mask & ··· 358 359 hwe->engine_id == __ffs(render_compute_mask); 359 360 } 360 361 361 - bool xe_rtp_match_not_sriov_vf(const struct xe_gt *gt, 362 + bool xe_rtp_match_not_sriov_vf(const struct xe_device *xe, 363 + const struct xe_gt *gt, 362 364 const struct xe_hw_engine *hwe) 363 365 { 364 - return !IS_SRIOV_VF(gt_to_xe(gt)); 366 + return !IS_SRIOV_VF(xe); 365 367 } 366 368 367 - bool xe_rtp_match_psmi_enabled(const struct xe_gt *gt, 369 + bool xe_rtp_match_psmi_enabled(const struct xe_device *xe, 370 + const struct xe_gt *gt, 368 371 const struct xe_hw_engine *hwe) 369 372 { 370 - return xe_configfs_get_psmi_enabled(to_pci_dev(gt_to_xe(gt)->drm.dev)); 373 + return xe_configfs_get_psmi_enabled(to_pci_dev(xe->drm.dev)); 371 374 } 372 375 373 - bool xe_rtp_match_gt_has_discontiguous_dss_groups(const struct xe_gt *gt, 376 + bool xe_rtp_match_gt_has_discontiguous_dss_groups(const struct xe_device *xe, 377 + const struct xe_gt *gt, 374 378 const struct xe_hw_engine *hwe) 375 379 { 376 380 return xe_gt_has_discontiguous_dss_groups(gt); 381 + } 382 + 383 + bool xe_rtp_match_has_flat_ccs(const struct xe_device *xe, 384 + const struct xe_gt *gt, 385 + const struct xe_hw_engine *hwe) 386 + { 387 + return xe->info.has_flat_ccs; 377 388 }
+25 -5
drivers/gpu/drm/xe/xe_rtp.h
··· 440 440 441 441 /** 442 442 * xe_rtp_match_even_instance - Match if engine instance is even 443 + * @xe: Device structure 443 444 * @gt: GT structure 444 445 * @hwe: Engine instance 445 446 * 446 447 * Returns: true if engine instance is even, false otherwise 447 448 */ 448 - bool xe_rtp_match_even_instance(const struct xe_gt *gt, 449 + bool xe_rtp_match_even_instance(const struct xe_device *xe, 450 + const struct xe_gt *gt, 449 451 const struct xe_hw_engine *hwe); 450 452 451 453 /* 452 454 * xe_rtp_match_first_render_or_compute - Match if it's first render or compute 453 455 * engine in the GT 454 456 * 457 + * @xe: Device structure 455 458 * @gt: GT structure 456 459 * @hwe: Engine instance 457 460 * ··· 466 463 * Returns: true if engine id is the first to match the render reset domain, 467 464 * false otherwise. 468 465 */ 469 - bool xe_rtp_match_first_render_or_compute(const struct xe_gt *gt, 466 + bool xe_rtp_match_first_render_or_compute(const struct xe_device *xe, 467 + const struct xe_gt *gt, 470 468 const struct xe_hw_engine *hwe); 471 469 472 470 /* 473 471 * xe_rtp_match_not_sriov_vf - Match when not on SR-IOV VF device 474 472 * 473 + * @xe: Device structure 475 474 * @gt: GT structure 476 475 * @hwe: Engine instance 477 476 * 478 477 * Returns: true if device is not VF, false otherwise. 479 478 */ 480 - bool xe_rtp_match_not_sriov_vf(const struct xe_gt *gt, 479 + bool xe_rtp_match_not_sriov_vf(const struct xe_device *xe, 480 + const struct xe_gt *gt, 481 481 const struct xe_hw_engine *hwe); 482 482 483 - bool xe_rtp_match_psmi_enabled(const struct xe_gt *gt, 483 + bool xe_rtp_match_psmi_enabled(const struct xe_device *xe, 484 + const struct xe_gt *gt, 484 485 const struct xe_hw_engine *hwe); 485 486 486 - bool xe_rtp_match_gt_has_discontiguous_dss_groups(const struct xe_gt *gt, 487 + bool xe_rtp_match_gt_has_discontiguous_dss_groups(const struct xe_device *xe, 488 + const struct xe_gt *gt, 487 489 const struct xe_hw_engine *hwe); 490 + 491 + /** 492 + * xe_rtp_match_has_flat_ccs - Match when platform has FlatCCS compression 493 + * @xe: Device structure 494 + * @gt: GT structure 495 + * @hwe: Engine instance 496 + * 497 + * Returns: true if platform has FlatCCS compression, false otherwise 498 + */ 499 + bool xe_rtp_match_has_flat_ccs(const struct xe_device *xe, 500 + const struct xe_gt *gt, 501 + const struct xe_hw_engine *hwe); 488 502 489 503 #endif
+3 -1
drivers/gpu/drm/xe/xe_rtp_types.h
··· 10 10 11 11 #include "regs/xe_reg_defs.h" 12 12 13 + struct xe_device; 13 14 struct xe_hw_engine; 14 15 struct xe_gt; 15 16 ··· 87 86 u8 engine_class; 88 87 }; 89 88 /* MATCH_FUNC */ 90 - bool (*match_func)(const struct xe_gt *gt, 89 + bool (*match_func)(const struct xe_device *xe, 90 + const struct xe_gt *gt, 91 91 const struct xe_hw_engine *hwe); 92 92 }; 93 93 };
+9
drivers/gpu/drm/xe/xe_sched_job_types.h
··· 24 24 struct dma_fence_chain *chain_fence; 25 25 /** @batch_addr: Batch buffer address. */ 26 26 u64 batch_addr; 27 + /** 28 + * @head: The tail pointer of the LRC (so head pointer of job) when the 29 + * job was submitted 30 + */ 31 + u32 head; 27 32 }; 28 33 29 34 /** ··· 63 58 bool ring_ops_flush_tlb; 64 59 /** @ggtt: mapped in ggtt. */ 65 60 bool ggtt; 61 + /** @skip_emit: skip emitting the job */ 62 + bool skip_emit; 63 + /** @last_replay: last job being replayed */ 64 + bool last_replay; 66 65 /** @ptrs: per instance pointers. */ 67 66 struct xe_job_ptrs ptrs[]; 68 67 };
+2
drivers/gpu/drm/xe/xe_sriov.c
··· 167 167 */ 168 168 int xe_sriov_init_late(struct xe_device *xe) 169 169 { 170 + if (IS_SRIOV_PF(xe)) 171 + return xe_sriov_pf_init_late(xe); 170 172 if (IS_SRIOV_VF(xe)) 171 173 return xe_sriov_vf_init_late(xe); 172 174
+28 -42
drivers/gpu/drm/xe/xe_sriov_pf.c
··· 8 8 #include <drm/drm_managed.h> 9 9 10 10 #include "xe_assert.h" 11 + #include "xe_configfs.h" 11 12 #include "xe_device.h" 12 13 #include "xe_gt_sriov_pf.h" 13 14 #include "xe_module.h" ··· 20 19 21 20 static unsigned int wanted_max_vfs(struct xe_device *xe) 22 21 { 22 + if (IS_ENABLED(CONFIG_CONFIGFS_FS)) 23 + return xe_configfs_get_max_vfs(to_pci_dev(xe->drm.dev)); 23 24 return xe_modparam.max_vfs; 24 25 } 25 26 ··· 107 104 } 108 105 109 106 /** 107 + * xe_sriov_pf_init_late() - Late initialization of the SR-IOV PF. 108 + * @xe: the &xe_device to initialize 109 + * 110 + * This function can only be called on PF. 111 + * 112 + * Return: 0 on success or a negative error code on failure. 113 + */ 114 + int xe_sriov_pf_init_late(struct xe_device *xe) 115 + { 116 + struct xe_gt *gt; 117 + unsigned int id; 118 + int err; 119 + 120 + xe_assert(xe, IS_SRIOV_PF(xe)); 121 + 122 + for_each_gt(gt, xe, id) { 123 + err = xe_gt_sriov_pf_init(gt); 124 + if (err) 125 + return err; 126 + } 127 + 128 + return 0; 129 + } 130 + 131 + /** 110 132 * xe_sriov_pf_wait_ready() - Wait until PF is ready to operate. 111 133 * @xe: the &xe_device to test 112 134 * ··· 173 145 drm_printf(p, "total: %u\n", xe->sriov.pf.device_total_vfs); 174 146 drm_printf(p, "supported: %u\n", xe->sriov.pf.driver_max_vfs); 175 147 drm_printf(p, "enabled: %u\n", pci_num_vf(pdev)); 176 - } 177 - 178 - static int simple_show(struct seq_file *m, void *data) 179 - { 180 - struct drm_printer p = drm_seq_file_printer(m); 181 - struct drm_info_node *node = m->private; 182 - struct dentry *parent = node->dent->d_parent; 183 - struct xe_device *xe = parent->d_inode->i_private; 184 - void (*print)(struct xe_device *, struct drm_printer *) = node->info_ent->data; 185 - 186 - print(xe, &p); 187 - return 0; 188 - } 189 - 190 - static const struct drm_info_list debugfs_list[] = { 191 - { .name = "vfs", .show = simple_show, .data = xe_sriov_pf_print_vfs_summary }, 192 - { .name = "versions", .show = simple_show, .data = xe_sriov_pf_service_print_versions }, 193 - }; 194 - 195 - /** 196 - * xe_sriov_pf_debugfs_register - Register PF debugfs attributes. 197 - * @xe: the &xe_device 198 - * @root: the root &dentry 199 - * 200 - * Prepare debugfs attributes exposed by the PF. 201 - */ 202 - void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root) 203 - { 204 - struct drm_minor *minor = xe->drm.primary; 205 - struct dentry *parent; 206 - 207 - /* 208 - * /sys/kernel/debug/dri/0/ 209 - * ├── pf 210 - * │   ├── ... 211 - */ 212 - parent = debugfs_create_dir("pf", root); 213 - if (IS_ERR(parent)) 214 - return; 215 - parent->d_inode->i_private = xe; 216 - 217 - drm_debugfs_create_files(debugfs_list, ARRAY_SIZE(debugfs_list), parent, minor); 218 148 }
+4 -14
drivers/gpu/drm/xe/xe_sriov_pf.h
··· 15 15 #ifdef CONFIG_PCI_IOV 16 16 bool xe_sriov_pf_readiness(struct xe_device *xe); 17 17 int xe_sriov_pf_init_early(struct xe_device *xe); 18 + int xe_sriov_pf_init_late(struct xe_device *xe); 18 19 int xe_sriov_pf_wait_ready(struct xe_device *xe); 19 - void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root); 20 20 void xe_sriov_pf_print_vfs_summary(struct xe_device *xe, struct drm_printer *p); 21 21 #else 22 - static inline bool xe_sriov_pf_readiness(struct xe_device *xe) 23 - { 24 - return false; 25 - } 26 - 27 - static inline int xe_sriov_pf_init_early(struct xe_device *xe) 28 - { 29 - return 0; 30 - } 31 - 32 - static inline void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root) 33 - { 34 - } 22 + static inline bool xe_sriov_pf_readiness(struct xe_device *xe) { return false; } 23 + static inline int xe_sriov_pf_init_early(struct xe_device *xe) { return 0; } 24 + static inline int xe_sriov_pf_init_late(struct xe_device *xe) { return 0; } 35 25 #endif 36 26 37 27 #endif
+151
drivers/gpu/drm/xe/xe_sriov_pf_control.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include "xe_device.h" 7 + #include "xe_gt_sriov_pf_control.h" 8 + #include "xe_sriov_pf_control.h" 9 + #include "xe_sriov_printk.h" 10 + 11 + /** 12 + * xe_sriov_pf_control_pause_vf() - Pause a VF on all GTs. 13 + * @xe: the &xe_device 14 + * @vfid: the VF identifier (can't be 0 == PFID) 15 + * 16 + * This function is for PF only. 17 + * 18 + * Return: 0 on success or a negative error code on failure. 19 + */ 20 + int xe_sriov_pf_control_pause_vf(struct xe_device *xe, unsigned int vfid) 21 + { 22 + struct xe_gt *gt; 23 + unsigned int id; 24 + int result = 0; 25 + int err; 26 + 27 + for_each_gt(gt, xe, id) { 28 + err = xe_gt_sriov_pf_control_pause_vf(gt, vfid); 29 + result = result ? -EUCLEAN : err; 30 + } 31 + 32 + if (result) 33 + return result; 34 + 35 + xe_sriov_info(xe, "VF%u paused!\n", vfid); 36 + return 0; 37 + } 38 + 39 + /** 40 + * xe_sriov_pf_control_resume_vf() - Resume a VF on all GTs. 41 + * @xe: the &xe_device 42 + * @vfid: the VF identifier 43 + * 44 + * This function is for PF only. 45 + * 46 + * Return: 0 on success or a negative error code on failure. 47 + */ 48 + int xe_sriov_pf_control_resume_vf(struct xe_device *xe, unsigned int vfid) 49 + { 50 + struct xe_gt *gt; 51 + unsigned int id; 52 + int result = 0; 53 + int err; 54 + 55 + for_each_gt(gt, xe, id) { 56 + err = xe_gt_sriov_pf_control_resume_vf(gt, vfid); 57 + result = result ? -EUCLEAN : err; 58 + } 59 + 60 + if (result) 61 + return result; 62 + 63 + xe_sriov_info(xe, "VF%u resumed!\n", vfid); 64 + return 0; 65 + } 66 + 67 + /** 68 + * xe_sriov_pf_control_stop_vf - Stop a VF on all GTs. 69 + * @xe: the &xe_device 70 + * @vfid: the VF identifier 71 + * 72 + * This function is for PF only. 73 + * 74 + * Return: 0 on success or a negative error code on failure. 75 + */ 76 + int xe_sriov_pf_control_stop_vf(struct xe_device *xe, unsigned int vfid) 77 + { 78 + struct xe_gt *gt; 79 + unsigned int id; 80 + int result = 0; 81 + int err; 82 + 83 + for_each_gt(gt, xe, id) { 84 + err = xe_gt_sriov_pf_control_stop_vf(gt, vfid); 85 + result = result ? -EUCLEAN : err; 86 + } 87 + 88 + if (result) 89 + return result; 90 + 91 + xe_sriov_info(xe, "VF%u stopped!\n", vfid); 92 + return 0; 93 + } 94 + 95 + /** 96 + * xe_sriov_pf_control_reset_vf() - Perform a VF reset (FLR). 97 + * @xe: the &xe_device 98 + * @vfid: the VF identifier 99 + * 100 + * This function is for PF only. 101 + * 102 + * Return: 0 on success or a negative error code on failure. 103 + */ 104 + int xe_sriov_pf_control_reset_vf(struct xe_device *xe, unsigned int vfid) 105 + { 106 + struct xe_gt *gt; 107 + unsigned int id; 108 + int result = 0; 109 + int err; 110 + 111 + for_each_gt(gt, xe, id) { 112 + err = xe_gt_sriov_pf_control_trigger_flr(gt, vfid); 113 + result = result ? -EUCLEAN : err; 114 + } 115 + 116 + for_each_gt(gt, xe, id) { 117 + err = xe_gt_sriov_pf_control_wait_flr(gt, vfid); 118 + result = result ? -EUCLEAN : err; 119 + } 120 + 121 + return result; 122 + } 123 + 124 + /** 125 + * xe_sriov_pf_control_sync_flr() - Synchronize a VF FLR between all GTs. 126 + * @xe: the &xe_device 127 + * @vfid: the VF identifier 128 + * 129 + * This function is for PF only. 130 + * 131 + * Return: 0 on success or a negative error code on failure. 132 + */ 133 + int xe_sriov_pf_control_sync_flr(struct xe_device *xe, unsigned int vfid) 134 + { 135 + struct xe_gt *gt; 136 + unsigned int id; 137 + int ret; 138 + 139 + for_each_gt(gt, xe, id) { 140 + ret = xe_gt_sriov_pf_control_sync_flr(gt, vfid, false); 141 + if (ret < 0) 142 + return ret; 143 + } 144 + for_each_gt(gt, xe, id) { 145 + ret = xe_gt_sriov_pf_control_sync_flr(gt, vfid, true); 146 + if (ret < 0) 147 + return ret; 148 + } 149 + 150 + return 0; 151 + }
+17
drivers/gpu/drm/xe/xe_sriov_pf_control.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SRIOV_PF_CONTROL_H_ 7 + #define _XE_SRIOV_PF_CONTROL_H_ 8 + 9 + struct xe_device; 10 + 11 + int xe_sriov_pf_control_pause_vf(struct xe_device *xe, unsigned int vfid); 12 + int xe_sriov_pf_control_resume_vf(struct xe_device *xe, unsigned int vfid); 13 + int xe_sriov_pf_control_stop_vf(struct xe_device *xe, unsigned int vfid); 14 + int xe_sriov_pf_control_reset_vf(struct xe_device *xe, unsigned int vfid); 15 + int xe_sriov_pf_control_sync_flr(struct xe_device *xe, unsigned int vfid); 16 + 17 + #endif
+264
drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <linux/debugfs.h> 7 + #include <drm/drm_debugfs.h> 8 + 9 + #include "xe_device.h" 10 + #include "xe_device_types.h" 11 + #include "xe_pm.h" 12 + #include "xe_sriov_pf.h" 13 + #include "xe_sriov_pf_control.h" 14 + #include "xe_sriov_pf_debugfs.h" 15 + #include "xe_sriov_pf_helpers.h" 16 + #include "xe_sriov_pf_provision.h" 17 + #include "xe_sriov_pf_service.h" 18 + #include "xe_sriov_printk.h" 19 + #include "xe_tile_sriov_pf_debugfs.h" 20 + 21 + /* 22 + * /sys/kernel/debug/dri/BDF/ 23 + * ├── sriov # d_inode->i_private = (xe_device*) 24 + * │ ├── pf # d_inode->i_private = (xe_device*) 25 + * │ ├── vf1 # d_inode->i_private = VFID(1) 26 + * : : 27 + * │ ├── vfN # d_inode->i_private = VFID(N) 28 + */ 29 + 30 + static void *extract_priv(struct dentry *d) 31 + { 32 + return d->d_inode->i_private; 33 + } 34 + 35 + static struct xe_device *extract_xe(struct dentry *d) 36 + { 37 + return extract_priv(d->d_parent); 38 + } 39 + 40 + static unsigned int extract_vfid(struct dentry *d) 41 + { 42 + void *p = extract_priv(d); 43 + 44 + return p == extract_xe(d) ? PFID : (uintptr_t)p; 45 + } 46 + 47 + /* 48 + * /sys/kernel/debug/dri/BDF/ 49 + * ├── sriov 50 + * │ ├── restore_auto_provisioning 51 + * │ : 52 + * │ ├── pf/ 53 + * │ ├── vf1 54 + * │ │ ├── ... 55 + */ 56 + 57 + static ssize_t from_file_write_to_xe_call(struct file *file, const char __user *userbuf, 58 + size_t count, loff_t *ppos, 59 + int (*call)(struct xe_device *)) 60 + { 61 + struct dentry *dent = file_dentry(file); 62 + struct xe_device *xe = extract_xe(dent); 63 + bool yes; 64 + int ret; 65 + 66 + if (*ppos) 67 + return -EINVAL; 68 + ret = kstrtobool_from_user(userbuf, count, &yes); 69 + if (ret < 0) 70 + return ret; 71 + if (yes) { 72 + xe_pm_runtime_get(xe); 73 + ret = call(xe); 74 + xe_pm_runtime_put(xe); 75 + } 76 + if (ret < 0) 77 + return ret; 78 + return count; 79 + } 80 + 81 + #define DEFINE_SRIOV_ATTRIBUTE(OP) \ 82 + static int OP##_show(struct seq_file *s, void *unused) \ 83 + { \ 84 + return 0; \ 85 + } \ 86 + static ssize_t OP##_write(struct file *file, const char __user *userbuf, \ 87 + size_t count, loff_t *ppos) \ 88 + { \ 89 + return from_file_write_to_xe_call(file, userbuf, count, ppos, \ 90 + xe_sriov_pf_##OP); \ 91 + } \ 92 + DEFINE_SHOW_STORE_ATTRIBUTE(OP) 93 + 94 + static inline int xe_sriov_pf_restore_auto_provisioning(struct xe_device *xe) 95 + { 96 + return xe_sriov_pf_provision_set_mode(xe, XE_SRIOV_PROVISIONING_MODE_AUTO); 97 + } 98 + 99 + DEFINE_SRIOV_ATTRIBUTE(restore_auto_provisioning); 100 + 101 + static void pf_populate_root(struct xe_device *xe, struct dentry *dent) 102 + { 103 + debugfs_create_file("restore_auto_provisioning", 0200, dent, xe, 104 + &restore_auto_provisioning_fops); 105 + } 106 + 107 + static int simple_show(struct seq_file *m, void *data) 108 + { 109 + struct drm_printer p = drm_seq_file_printer(m); 110 + struct drm_info_node *node = m->private; 111 + struct dentry *parent = node->dent->d_parent; 112 + struct xe_device *xe = parent->d_inode->i_private; 113 + void (*print)(struct xe_device *, struct drm_printer *) = node->info_ent->data; 114 + 115 + print(xe, &p); 116 + return 0; 117 + } 118 + 119 + static const struct drm_info_list debugfs_list[] = { 120 + { .name = "vfs", .show = simple_show, .data = xe_sriov_pf_print_vfs_summary }, 121 + { .name = "versions", .show = simple_show, .data = xe_sriov_pf_service_print_versions }, 122 + }; 123 + 124 + static void pf_populate_pf(struct xe_device *xe, struct dentry *pfdent) 125 + { 126 + struct drm_minor *minor = xe->drm.primary; 127 + 128 + drm_debugfs_create_files(debugfs_list, ARRAY_SIZE(debugfs_list), pfdent, minor); 129 + } 130 + 131 + /* 132 + * /sys/kernel/debug/dri/BDF/ 133 + * ├── sriov 134 + * │ ├── vf1 135 + * │ │ ├── pause 136 + * │ │ ├── reset 137 + * │ │ ├── resume 138 + * │ │ ├── stop 139 + * │ │ : 140 + * │ ├── vf2 141 + * │ │ ├── ... 142 + */ 143 + 144 + static ssize_t from_file_write_to_vf_call(struct file *file, const char __user *userbuf, 145 + size_t count, loff_t *ppos, 146 + int (*call)(struct xe_device *, unsigned int)) 147 + { 148 + struct dentry *dent = file_dentry(file)->d_parent; 149 + struct xe_device *xe = extract_xe(dent); 150 + unsigned int vfid = extract_vfid(dent); 151 + bool yes; 152 + int ret; 153 + 154 + if (*ppos) 155 + return -EINVAL; 156 + ret = kstrtobool_from_user(userbuf, count, &yes); 157 + if (ret < 0) 158 + return ret; 159 + if (yes) { 160 + xe_pm_runtime_get(xe); 161 + ret = call(xe, vfid); 162 + xe_pm_runtime_put(xe); 163 + } 164 + if (ret < 0) 165 + return ret; 166 + return count; 167 + } 168 + 169 + #define DEFINE_VF_CONTROL_ATTRIBUTE(OP) \ 170 + static int OP##_show(struct seq_file *s, void *unused) \ 171 + { \ 172 + return 0; \ 173 + } \ 174 + static ssize_t OP##_write(struct file *file, const char __user *userbuf, \ 175 + size_t count, loff_t *ppos) \ 176 + { \ 177 + return from_file_write_to_vf_call(file, userbuf, count, ppos, \ 178 + xe_sriov_pf_control_##OP); \ 179 + } \ 180 + DEFINE_SHOW_STORE_ATTRIBUTE(OP) 181 + 182 + DEFINE_VF_CONTROL_ATTRIBUTE(pause_vf); 183 + DEFINE_VF_CONTROL_ATTRIBUTE(resume_vf); 184 + DEFINE_VF_CONTROL_ATTRIBUTE(stop_vf); 185 + DEFINE_VF_CONTROL_ATTRIBUTE(reset_vf); 186 + 187 + static void pf_populate_vf(struct xe_device *xe, struct dentry *vfdent) 188 + { 189 + debugfs_create_file("pause", 0200, vfdent, xe, &pause_vf_fops); 190 + debugfs_create_file("resume", 0200, vfdent, xe, &resume_vf_fops); 191 + debugfs_create_file("stop", 0200, vfdent, xe, &stop_vf_fops); 192 + debugfs_create_file("reset", 0200, vfdent, xe, &reset_vf_fops); 193 + } 194 + 195 + static void pf_populate_with_tiles(struct xe_device *xe, struct dentry *dent, unsigned int vfid) 196 + { 197 + struct xe_tile *tile; 198 + unsigned int id; 199 + 200 + for_each_tile(tile, xe, id) 201 + xe_tile_sriov_pf_debugfs_populate(tile, dent, vfid); 202 + } 203 + 204 + /** 205 + * xe_sriov_pf_debugfs_register - Register PF debugfs attributes. 206 + * @xe: the &xe_device 207 + * @root: the root &dentry 208 + * 209 + * Create separate directory that will contain all SR-IOV related files, 210 + * organized per each SR-IOV function (PF, VF1, VF2, ..., VFn). 211 + */ 212 + void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root) 213 + { 214 + int totalvfs = xe_sriov_pf_get_totalvfs(xe); 215 + struct dentry *pfdent; 216 + struct dentry *vfdent; 217 + struct dentry *dent; 218 + char vfname[16]; /* should be more than enough for "vf%u\0" and VFID(UINT_MAX) */ 219 + unsigned int n; 220 + 221 + /* 222 + * /sys/kernel/debug/dri/BDF/ 223 + * ├── sriov # d_inode->i_private = (xe_device*) 224 + * │ ├── ... 225 + */ 226 + dent = debugfs_create_dir("sriov", root); 227 + if (IS_ERR(dent)) 228 + return; 229 + dent->d_inode->i_private = xe; 230 + 231 + pf_populate_root(xe, dent); 232 + 233 + /* 234 + * /sys/kernel/debug/dri/BDF/ 235 + * ├── sriov # d_inode->i_private = (xe_device*) 236 + * │ ├── pf # d_inode->i_private = (xe_device*) 237 + * │ │ ├── ... 238 + */ 239 + pfdent = debugfs_create_dir("pf", dent); 240 + if (IS_ERR(pfdent)) 241 + return; 242 + pfdent->d_inode->i_private = xe; 243 + 244 + pf_populate_pf(xe, pfdent); 245 + pf_populate_with_tiles(xe, pfdent, PFID); 246 + 247 + /* 248 + * /sys/kernel/debug/dri/BDF/ 249 + * ├── sriov # d_inode->i_private = (xe_device*) 250 + * │ ├── vf1 # d_inode->i_private = VFID(1) 251 + * │ ├── vf2 # d_inode->i_private = VFID(2) 252 + * │ ├── ... 253 + */ 254 + for (n = 1; n <= totalvfs; n++) { 255 + snprintf(vfname, sizeof(vfname), "vf%u", VFID(n)); 256 + vfdent = debugfs_create_dir(vfname, dent); 257 + if (IS_ERR(vfdent)) 258 + return; 259 + vfdent->d_inode->i_private = (void *)(uintptr_t)VFID(n); 260 + 261 + pf_populate_vf(xe, vfdent); 262 + pf_populate_with_tiles(xe, vfdent, VFID(n)); 263 + } 264 + }
+18
drivers/gpu/drm/xe/xe_sriov_pf_debugfs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SRIOV_PF_DEBUGFS_H_ 7 + #define _XE_SRIOV_PF_DEBUGFS_H_ 8 + 9 + struct dentry; 10 + struct xe_device; 11 + 12 + #ifdef CONFIG_PCI_IOV 13 + void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root); 14 + #else 15 + static inline void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root) { } 16 + #endif 17 + 18 + #endif
+11
drivers/gpu/drm/xe/xe_sriov_pf_helpers.h
··· 37 37 return xe->sriov.pf.driver_max_vfs; 38 38 } 39 39 40 + /** 41 + * xe_sriov_pf_num_vfs() - Number of enabled VFs on the PF. 42 + * @xe: the PF &xe_device 43 + * 44 + * Return: Number of enabled VFs on the PF. 45 + */ 46 + static inline unsigned int xe_sriov_pf_num_vfs(const struct xe_device *xe) 47 + { 48 + return pci_num_vf(to_pci_dev(xe->drm.dev)); 49 + } 50 + 40 51 static inline struct mutex *xe_sriov_pf_master_mutex(struct xe_device *xe) 41 52 { 42 53 xe_assert(xe, IS_SRIOV_PF(xe));
+154
drivers/gpu/drm/xe/xe_sriov_pf_provision.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include "xe_assert.h" 7 + #include "xe_device.h" 8 + #include "xe_gt_sriov_pf_config.h" 9 + #include "xe_sriov.h" 10 + #include "xe_sriov_pf_helpers.h" 11 + #include "xe_sriov_pf_provision.h" 12 + #include "xe_sriov_pf_provision_types.h" 13 + #include "xe_sriov_printk.h" 14 + 15 + static const char *mode_to_string(enum xe_sriov_provisioning_mode mode) 16 + { 17 + switch (mode) { 18 + case XE_SRIOV_PROVISIONING_MODE_AUTO: 19 + return "auto"; 20 + case XE_SRIOV_PROVISIONING_MODE_CUSTOM: 21 + return "custom"; 22 + default: 23 + return "<invalid>"; 24 + } 25 + } 26 + 27 + static bool pf_auto_provisioning_mode(struct xe_device *xe) 28 + { 29 + xe_assert(xe, IS_SRIOV_PF(xe)); 30 + 31 + return xe->sriov.pf.provision.mode == XE_SRIOV_PROVISIONING_MODE_AUTO; 32 + } 33 + 34 + static bool pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs) 35 + { 36 + unsigned int n; 37 + 38 + for (n = 1; n <= num_vfs; n++) 39 + if (!xe_gt_sriov_pf_config_is_empty(gt, n)) 40 + return false; 41 + 42 + return true; 43 + } 44 + 45 + static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 46 + { 47 + struct xe_gt *gt; 48 + unsigned int id; 49 + int result = 0; 50 + int err; 51 + 52 + for_each_gt(gt, xe, id) { 53 + if (!pf_needs_provisioning(gt, num_vfs)) 54 + return -EUCLEAN; 55 + err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); 56 + result = result ?: err; 57 + } 58 + 59 + return result; 60 + } 61 + 62 + static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 63 + { 64 + struct xe_gt *gt; 65 + unsigned int id; 66 + unsigned int n; 67 + 68 + for_each_gt(gt, xe, id) 69 + for (n = 1; n <= num_vfs; n++) 70 + xe_gt_sriov_pf_config_release(gt, n, true); 71 + } 72 + 73 + static void pf_unprovision_all_vfs(struct xe_device *xe) 74 + { 75 + pf_unprovision_vfs(xe, xe_sriov_pf_get_totalvfs(xe)); 76 + } 77 + 78 + /** 79 + * xe_sriov_pf_provision_vfs() - Provision VFs in auto-mode. 80 + * @xe: the PF &xe_device 81 + * @num_vfs: the number of VFs to auto-provision 82 + * 83 + * This function can only be called on PF. 84 + * 85 + * Return: 0 on success or a negative error code on failure. 86 + */ 87 + int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 88 + { 89 + xe_assert(xe, IS_SRIOV_PF(xe)); 90 + 91 + if (!pf_auto_provisioning_mode(xe)) 92 + return 0; 93 + 94 + return pf_provision_vfs(xe, num_vfs); 95 + } 96 + 97 + /** 98 + * xe_sriov_pf_unprovision_vfs() - Unprovision VFs in auto-mode. 99 + * @xe: the PF &xe_device 100 + * @num_vfs: the number of VFs to unprovision 101 + * 102 + * This function can only be called on PF. 103 + * 104 + * Return: 0 on success or a negative error code on failure. 105 + */ 106 + int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 107 + { 108 + xe_assert(xe, IS_SRIOV_PF(xe)); 109 + 110 + if (!pf_auto_provisioning_mode(xe)) 111 + return 0; 112 + 113 + pf_unprovision_vfs(xe, num_vfs); 114 + return 0; 115 + } 116 + 117 + /** 118 + * xe_sriov_pf_provision_set_mode() - Change VFs provision mode. 119 + * @xe: the PF &xe_device 120 + * @mode: the new VFs provisioning mode 121 + * 122 + * When changing from AUTO to CUSTOM mode, any already allocated VFs resources 123 + * will remain allocated and will not be released upon VFs disabling. 124 + * 125 + * When changing back to AUTO mode, if VFs are not enabled, already allocated 126 + * VFs resources will be immediately released. If VFs are still enabled, such 127 + * mode change is rejected. 128 + * 129 + * This function can only be called on PF. 130 + * 131 + * Return: 0 on success or a negative error code on failure. 132 + */ 133 + int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode) 134 + { 135 + xe_assert(xe, IS_SRIOV_PF(xe)); 136 + 137 + if (mode == xe->sriov.pf.provision.mode) 138 + return 0; 139 + 140 + if (mode == XE_SRIOV_PROVISIONING_MODE_AUTO) { 141 + if (xe_sriov_pf_num_vfs(xe)) { 142 + xe_sriov_dbg(xe, "can't restore %s: VFs must be disabled!\n", 143 + mode_to_string(mode)); 144 + return -EBUSY; 145 + } 146 + pf_unprovision_all_vfs(xe); 147 + } 148 + 149 + xe_sriov_dbg(xe, "mode %s changed to %s by %ps\n", 150 + mode_to_string(xe->sriov.pf.provision.mode), 151 + mode_to_string(mode), __builtin_return_address(0)); 152 + xe->sriov.pf.provision.mode = mode; 153 + return 0; 154 + }
+31
drivers/gpu/drm/xe/xe_sriov_pf_provision.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SRIOV_PF_PROVISION_H_ 7 + #define _XE_SRIOV_PF_PROVISION_H_ 8 + 9 + #include "xe_sriov_pf_provision_types.h" 10 + 11 + struct xe_device; 12 + 13 + int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs); 14 + int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs); 15 + 16 + int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode); 17 + 18 + /** 19 + * xe_sriov_pf_provision_set_custom_mode() - Change VFs provision mode to custom. 20 + * @xe: the PF &xe_device 21 + * 22 + * This function can only be called on PF. 23 + * 24 + * Return: 0 on success or a negative error code on failure. 25 + */ 26 + static inline int xe_sriov_pf_provision_set_custom_mode(struct xe_device *xe) 27 + { 28 + return xe_sriov_pf_provision_set_mode(xe, XE_SRIOV_PROVISIONING_MODE_CUSTOM); 29 + } 30 + 31 + #endif
+36
drivers/gpu/drm/xe/xe_sriov_pf_provision_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_SRIOV_PF_PROVISION_TYPES_H_ 7 + #define _XE_SRIOV_PF_PROVISION_TYPES_H_ 8 + 9 + #include <linux/build_bug.h> 10 + 11 + /** 12 + * enum xe_sriov_provisioning_mode - SR-IOV provisioning mode. 13 + * 14 + * @XE_SRIOV_PROVISIONING_MODE_AUTO: VFs are provisioned during VFs enabling. 15 + * Any allocated resources to the VFs will be 16 + * automatically released when disabling VFs. 17 + * This is a default mode. 18 + * @XE_SRIOV_PROVISIONING_MODE_CUSTOM: Explicit VFs provisioning using uABI interfaces. 19 + * VFs resources remains allocated regardless if 20 + * VFs are enabled or not. 21 + */ 22 + enum xe_sriov_provisioning_mode { 23 + XE_SRIOV_PROVISIONING_MODE_AUTO, 24 + XE_SRIOV_PROVISIONING_MODE_CUSTOM, 25 + }; 26 + static_assert(XE_SRIOV_PROVISIONING_MODE_AUTO == 0); 27 + 28 + /** 29 + * struct xe_sriov_pf_provision - Data used by the PF provisioning. 30 + */ 31 + struct xe_sriov_pf_provision { 32 + /** @mode: selected provisioning mode. */ 33 + enum xe_sriov_provisioning_mode mode; 34 + }; 35 + 36 + #endif
+4
drivers/gpu/drm/xe/xe_sriov_pf_types.h
··· 9 9 #include <linux/mutex.h> 10 10 #include <linux/types.h> 11 11 12 + #include "xe_sriov_pf_provision_types.h" 12 13 #include "xe_sriov_pf_service_types.h" 13 14 14 15 /** ··· 35 34 36 35 /** @master_lock: protects all VFs configurations across GTs */ 37 36 struct mutex master_lock; 37 + 38 + /** @provision: device level provisioning data. */ 39 + struct xe_sriov_pf_provision provision; 38 40 39 41 /** @service: device level service data. */ 40 42 struct xe_sriov_pf_service service;
+6 -6
drivers/gpu/drm/xe/xe_sriov_printk.h
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 2 /* 3 - * Copyright © 2023 Intel Corporation 3 + * Copyright © 2023-2025 Intel Corporation 4 4 */ 5 5 6 6 #ifndef _XE_SRIOV_PRINTK_H_ 7 7 #define _XE_SRIOV_PRINTK_H_ 8 8 9 - #include <drm/drm_print.h> 10 - 11 - #include "xe_device_types.h" 12 - #include "xe_sriov_types.h" 9 + #include "xe_printk.h" 13 10 14 11 #define xe_sriov_printk_prefix(xe) \ 15 12 ((xe)->sriov.__mode == XE_SRIOV_MODE_PF ? "PF: " : \ 16 13 (xe)->sriov.__mode == XE_SRIOV_MODE_VF ? "VF: " : "") 17 14 15 + #define __XE_SRIOV_PRINTK_FMT(_xe, _fmt, _args...) \ 16 + "%s" _fmt, xe_sriov_printk_prefix(_xe), ##_args 17 + 18 18 #define xe_sriov_printk(xe, _level, fmt, ...) \ 19 - drm_##_level(&(xe)->drm, "%s" fmt, xe_sriov_printk_prefix(xe), ##__VA_ARGS__) 19 + xe_##_level((xe), __XE_SRIOV_PRINTK_FMT((xe), fmt, ##__VA_ARGS__)) 20 20 21 21 #define xe_sriov_err(xe, fmt, ...) \ 22 22 xe_sriov_printk((xe), err, fmt, ##__VA_ARGS__)
-243
drivers/gpu/drm/xe/xe_sriov_vf.c
··· 6 6 #include <drm/drm_debugfs.h> 7 7 #include <drm/drm_managed.h> 8 8 9 - #include "xe_assert.h" 10 - #include "xe_device.h" 11 9 #include "xe_gt.h" 12 - #include "xe_gt_sriov_printk.h" 13 10 #include "xe_gt_sriov_vf.h" 14 11 #include "xe_guc.h" 15 - #include "xe_guc_ct.h" 16 - #include "xe_guc_submit.h" 17 - #include "xe_irq.h" 18 - #include "xe_lrc.h" 19 - #include "xe_pm.h" 20 - #include "xe_sriov.h" 21 12 #include "xe_sriov_printk.h" 22 13 #include "xe_sriov_vf.h" 23 14 #include "xe_sriov_vf_ccs.h" 24 - #include "xe_tile_sriov_vf.h" 25 15 26 16 /** 27 17 * DOC: VF restore procedure in PF KMD and VF KMD ··· 149 159 xe->sriov.vf.migration.enabled = false; 150 160 } 151 161 152 - static void migration_worker_func(struct work_struct *w); 153 - 154 162 static void vf_migration_init_early(struct xe_device *xe) 155 163 { 156 164 /* ··· 173 185 guc_version.major, guc_version.minor); 174 186 } 175 187 176 - INIT_WORK(&xe->sriov.vf.migration.worker, migration_worker_func); 177 - 178 188 xe->sriov.vf.migration.enabled = true; 179 189 xe_sriov_dbg(xe, "migration support enabled\n"); 180 190 } ··· 184 198 void xe_sriov_vf_init_early(struct xe_device *xe) 185 199 { 186 200 vf_migration_init_early(xe); 187 - } 188 - 189 - /** 190 - * vf_post_migration_shutdown - Stop the driver activities after VF migration. 191 - * @xe: the &xe_device struct instance 192 - * 193 - * After this VM is migrated and assigned to a new VF, it is running on a new 194 - * hardware, and therefore many hardware-dependent states and related structures 195 - * require fixups. Without fixups, the hardware cannot do any work, and therefore 196 - * all GPU pipelines are stalled. 197 - * Stop some of kernel activities to make the fixup process faster. 198 - */ 199 - static void vf_post_migration_shutdown(struct xe_device *xe) 200 - { 201 - struct xe_gt *gt; 202 - unsigned int id; 203 - int ret = 0; 204 - 205 - for_each_gt(gt, xe, id) { 206 - xe_guc_submit_pause(&gt->uc.guc); 207 - ret |= xe_guc_submit_reset_block(&gt->uc.guc); 208 - } 209 - 210 - if (ret) 211 - drm_info(&xe->drm, "migration recovery encountered ongoing reset\n"); 212 - } 213 - 214 - /** 215 - * vf_post_migration_kickstart - Re-start the driver activities under new hardware. 216 - * @xe: the &xe_device struct instance 217 - * 218 - * After we have finished with all post-migration fixups, restart the driver 219 - * activities to continue feeding the GPU with workloads. 220 - */ 221 - static void vf_post_migration_kickstart(struct xe_device *xe) 222 - { 223 - struct xe_gt *gt; 224 - unsigned int id; 225 - 226 - /* 227 - * Make sure interrupts on the new HW are properly set. The GuC IRQ 228 - * must be working at this point, since the recovery did started, 229 - * but the rest was not enabled using the procedure from spec. 230 - */ 231 - xe_irq_resume(xe); 232 - 233 - for_each_gt(gt, xe, id) { 234 - xe_guc_submit_reset_unblock(&gt->uc.guc); 235 - xe_guc_submit_unpause(&gt->uc.guc); 236 - } 237 - } 238 - 239 - static bool gt_vf_post_migration_needed(struct xe_gt *gt) 240 - { 241 - return test_bit(gt->info.id, &gt_to_xe(gt)->sriov.vf.migration.gt_flags); 242 - } 243 - 244 - /* 245 - * Notify GuCs marked in flags about resource fixups apply finished. 246 - * @xe: the &xe_device struct instance 247 - * @gt_flags: flags marking to which GTs the notification shall be sent 248 - */ 249 - static int vf_post_migration_notify_resfix_done(struct xe_device *xe, unsigned long gt_flags) 250 - { 251 - struct xe_gt *gt; 252 - unsigned int id; 253 - int err = 0; 254 - 255 - for_each_gt(gt, xe, id) { 256 - if (!test_bit(id, &gt_flags)) 257 - continue; 258 - /* skip asking GuC for RESFIX exit if new recovery request arrived */ 259 - if (gt_vf_post_migration_needed(gt)) 260 - continue; 261 - err = xe_gt_sriov_vf_notify_resfix_done(gt); 262 - if (err) 263 - break; 264 - clear_bit(id, &gt_flags); 265 - } 266 - 267 - if (gt_flags && !err) 268 - drm_dbg(&xe->drm, "another recovery imminent, skipped some notifications\n"); 269 - return err; 270 - } 271 - 272 - static int vf_get_next_migrated_gt_id(struct xe_device *xe) 273 - { 274 - struct xe_gt *gt; 275 - unsigned int id; 276 - 277 - for_each_gt(gt, xe, id) { 278 - if (test_and_clear_bit(id, &xe->sriov.vf.migration.gt_flags)) 279 - return id; 280 - } 281 - return -1; 282 - } 283 - 284 - static size_t post_migration_scratch_size(struct xe_device *xe) 285 - { 286 - return max(xe_lrc_reg_size(xe), LRC_WA_BB_SIZE); 287 - } 288 - 289 - /** 290 - * Perform post-migration fixups on a single GT. 291 - * 292 - * After migration, GuC needs to be re-queried for VF configuration to check 293 - * if it matches previous provisioning. Most of VF provisioning shall be the 294 - * same, except GGTT range, since GGTT is not virtualized per-VF. If GGTT 295 - * range has changed, we have to perform fixups - shift all GGTT references 296 - * used anywhere within the driver. After the fixups in this function succeed, 297 - * it is allowed to ask the GuC bound to this GT to continue normal operation. 298 - * 299 - * Returns: 0 if the operation completed successfully, or a negative error 300 - * code otherwise. 301 - */ 302 - static int gt_vf_post_migration_fixups(struct xe_gt *gt) 303 - { 304 - s64 shift; 305 - void *buf; 306 - int err; 307 - 308 - buf = kmalloc(post_migration_scratch_size(gt_to_xe(gt)), GFP_KERNEL); 309 - if (!buf) 310 - return -ENOMEM; 311 - 312 - err = xe_gt_sriov_vf_query_config(gt); 313 - if (err) 314 - goto out; 315 - 316 - shift = xe_gt_sriov_vf_ggtt_shift(gt); 317 - if (shift) { 318 - xe_tile_sriov_vf_fixup_ggtt_nodes(gt_to_tile(gt), shift); 319 - xe_gt_sriov_vf_default_lrcs_hwsp_rebase(gt); 320 - err = xe_guc_contexts_hwsp_rebase(&gt->uc.guc, buf); 321 - if (err) 322 - goto out; 323 - xe_guc_jobs_ring_rebase(&gt->uc.guc); 324 - xe_guc_ct_fixup_messages_with_ggtt(&gt->uc.guc.ct, shift); 325 - } 326 - 327 - out: 328 - kfree(buf); 329 - return err; 330 - } 331 - 332 - static void vf_post_migration_recovery(struct xe_device *xe) 333 - { 334 - unsigned long fixed_gts = 0; 335 - int id, err; 336 - 337 - drm_dbg(&xe->drm, "migration recovery in progress\n"); 338 - xe_pm_runtime_get(xe); 339 - vf_post_migration_shutdown(xe); 340 - 341 - if (!xe_sriov_vf_migration_supported(xe)) { 342 - xe_sriov_err(xe, "migration is not supported\n"); 343 - err = -ENOTRECOVERABLE; 344 - goto fail; 345 - } 346 - 347 - while (id = vf_get_next_migrated_gt_id(xe), id >= 0) { 348 - struct xe_gt *gt = xe_device_get_gt(xe, id); 349 - 350 - err = gt_vf_post_migration_fixups(gt); 351 - if (err) 352 - goto fail; 353 - 354 - set_bit(id, &fixed_gts); 355 - } 356 - 357 - vf_post_migration_kickstart(xe); 358 - err = vf_post_migration_notify_resfix_done(xe, fixed_gts); 359 - if (err) 360 - goto fail; 361 - 362 - xe_pm_runtime_put(xe); 363 - drm_notice(&xe->drm, "migration recovery ended\n"); 364 - return; 365 - fail: 366 - xe_pm_runtime_put(xe); 367 - drm_err(&xe->drm, "migration recovery failed (%pe)\n", ERR_PTR(err)); 368 - xe_device_declare_wedged(xe); 369 - } 370 - 371 - static void migration_worker_func(struct work_struct *w) 372 - { 373 - struct xe_device *xe = container_of(w, struct xe_device, 374 - sriov.vf.migration.worker); 375 - 376 - vf_post_migration_recovery(xe); 377 - } 378 - 379 - /* 380 - * Check if post-restore recovery is coming on any of GTs. 381 - * @xe: the &xe_device struct instance 382 - * 383 - * Return: True if migration recovery worker will soon be running. Any worker currently 384 - * executing does not affect the result. 385 - */ 386 - static bool vf_ready_to_recovery_on_any_gts(struct xe_device *xe) 387 - { 388 - struct xe_gt *gt; 389 - unsigned int id; 390 - 391 - for_each_gt(gt, xe, id) { 392 - if (test_bit(id, &xe->sriov.vf.migration.gt_flags)) 393 - return true; 394 - } 395 - return false; 396 - } 397 - 398 - /** 399 - * xe_sriov_vf_start_migration_recovery - Start VF migration recovery. 400 - * @xe: the &xe_device to start recovery on 401 - * 402 - * This function shall be called only by VF. 403 - */ 404 - void xe_sriov_vf_start_migration_recovery(struct xe_device *xe) 405 - { 406 - bool started; 407 - 408 - xe_assert(xe, IS_SRIOV_VF(xe)); 409 - 410 - if (!vf_ready_to_recovery_on_any_gts(xe)) 411 - return; 412 - 413 - started = queue_work(xe->sriov.wq, &xe->sriov.vf.migration.worker); 414 - drm_info(&xe->drm, "VF migration recovery %s\n", started ? 415 - "scheduled" : "already in progress"); 416 201 } 417 202 418 203 /**
-1
drivers/gpu/drm/xe/xe_sriov_vf.h
··· 13 13 14 14 void xe_sriov_vf_init_early(struct xe_device *xe); 15 15 int xe_sriov_vf_init_late(struct xe_device *xe); 16 - void xe_sriov_vf_start_migration_recovery(struct xe_device *xe); 17 16 bool xe_sriov_vf_migration_supported(struct xe_device *xe); 18 17 void xe_sriov_vf_debugfs_register(struct xe_device *xe, struct dentry *root); 19 18
+28
drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
··· 175 175 struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q); 176 176 u32 dw[10], i = 0; 177 177 178 + /* 179 + * XXX: Save/restore fixes — for some reason, the GuC only accepts the 180 + * save/restore context if the LRC head pointer is zero. This is evident 181 + * from repeated VF migrations failing when the LRC head pointer is 182 + * non-zero. 183 + */ 184 + lrc->ring.tail = 0; 185 + xe_lrc_set_ring_head(lrc, 0); 186 + 178 187 dw[i++] = MI_ARB_ON_OFF | MI_ARB_ENABLE; 179 188 dw[i++] = MI_BATCH_BUFFER_START | XE_INSTR_NUM_DW(3); 180 189 dw[i++] = lower_32_bits(addr); ··· 193 184 194 185 xe_lrc_write_ring(lrc, dw, i * sizeof(u32)); 195 186 xe_lrc_set_ring_tail(lrc, lrc->ring.tail); 187 + } 188 + 189 + /** 190 + * xe_sriov_vf_ccs_rebase - Rebase GGTT addresses for CCS save / restore 191 + * @xe: the &xe_device. 192 + */ 193 + void xe_sriov_vf_ccs_rebase(struct xe_device *xe) 194 + { 195 + enum xe_sriov_vf_ccs_rw_ctxs ctx_id; 196 + 197 + if (!IS_VF_CCS_READY(xe)) 198 + return; 199 + 200 + for_each_ccs_rw_ctx(ctx_id) { 201 + struct xe_sriov_vf_ccs_ctx *ctx = 202 + &xe->sriov.vf.ccs.contexts[ctx_id]; 203 + 204 + ccs_rw_update_ring(ctx); 205 + } 196 206 } 197 207 198 208 static int register_save_restore_context(struct xe_sriov_vf_ccs_ctx *ctx)
+1
drivers/gpu/drm/xe/xe_sriov_vf_ccs.h
··· 18 18 int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo); 19 19 int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo); 20 20 int xe_sriov_vf_ccs_register_context(struct xe_device *xe); 21 + void xe_sriov_vf_ccs_rebase(struct xe_device *xe); 21 22 void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p); 22 23 23 24 static inline bool xe_sriov_vf_ccs_ready(struct xe_device *xe)
-4
drivers/gpu/drm/xe/xe_sriov_vf_types.h
··· 33 33 34 34 /** @migration: VF Migration state data */ 35 35 struct { 36 - /** @migration.worker: VF migration recovery worker */ 37 - struct work_struct worker; 38 - /** @migration.gt_flags: Per-GT request flags for VF migration recovery */ 39 - unsigned long gt_flags; 40 36 /** 41 37 * @migration.enabled: flag indicating if migration support 42 38 * was enabled or not due to missing prerequisites
+5
drivers/gpu/drm/xe/xe_svm.c
··· 302 302 if (!vma) 303 303 return -EINVAL; 304 304 305 + if (!(vma->gpuva.flags & XE_VMA_MADV_AUTORESET)) { 306 + drm_dbg(&vm->xe->drm, "Skipping madvise reset for vma.\n"); 307 + return 0; 308 + } 309 + 305 310 if (xe_vma_has_default_mem_attrs(vma)) 306 311 return 0; 307 312
+9 -5
drivers/gpu/drm/xe/xe_tile.c
··· 19 19 #include "xe_tile.h" 20 20 #include "xe_tile_sysfs.h" 21 21 #include "xe_ttm_vram_mgr.h" 22 - #include "xe_wa.h" 23 22 #include "xe_vram.h" 24 23 #include "xe_vram_types.h" 24 + #include "xe_wa.h" 25 25 26 26 /** 27 27 * DOC: Multi-tile Design ··· 124 124 return -ENOMEM; 125 125 tile->mem.vram = vram; 126 126 127 + /* 128 + * If the kernel_vram is not already allocated, 129 + * it means that tile has common VRAM region for 130 + * kernel and user space. 131 + */ 132 + if (!tile->mem.kernel_vram) 133 + tile->mem.kernel_vram = tile->mem.vram; 134 + 127 135 return 0; 128 136 } 129 137 ··· 156 148 err = xe_tile_alloc(tile); 157 149 if (err) 158 150 return err; 159 - 160 - tile->primary_gt = xe_gt_alloc(tile); 161 - if (IS_ERR(tile->primary_gt)) 162 - return PTR_ERR(tile->primary_gt); 163 151 164 152 xe_pcode_init(tile); 165 153
+13 -6
drivers/gpu/drm/xe/xe_tile_debugfs.c
··· 6 6 #include <linux/debugfs.h> 7 7 #include <drm/drm_debugfs.h> 8 8 9 + #include "xe_ggtt.h" 9 10 #include "xe_pm.h" 10 11 #include "xe_sa.h" 11 12 #include "xe_tile_debugfs.h" ··· 17 16 } 18 17 19 18 /** 20 - * tile_debugfs_simple_show - A show callback for struct drm_info_list 19 + * xe_tile_debugfs_simple_show() - A show callback for struct drm_info_list 21 20 * @m: the &seq_file 22 21 * @data: data used by the drm debugfs helpers 23 22 * ··· 58 57 * 59 58 * Return: 0 on success or a negative error code on failure. 60 59 */ 61 - static int tile_debugfs_simple_show(struct seq_file *m, void *data) 60 + int xe_tile_debugfs_simple_show(struct seq_file *m, void *data) 62 61 { 63 62 struct drm_printer p = drm_seq_file_printer(m); 64 63 struct drm_info_node *node = m->private; ··· 69 68 } 70 69 71 70 /** 72 - * tile_debugfs_show_with_rpm - A show callback for struct drm_info_list 71 + * xe_tile_debugfs_show_with_rpm() - A show callback for struct drm_info_list 73 72 * @m: the &seq_file 74 73 * @data: data used by the drm debugfs helpers 75 74 * ··· 77 76 * 78 77 * Return: 0 on success or a negative error code on failure. 79 78 */ 80 - static int tile_debugfs_show_with_rpm(struct seq_file *m, void *data) 79 + int xe_tile_debugfs_show_with_rpm(struct seq_file *m, void *data) 81 80 { 82 81 struct drm_info_node *node = m->private; 83 82 struct xe_tile *tile = node_to_tile(node); ··· 85 84 int ret; 86 85 87 86 xe_pm_runtime_get(xe); 88 - ret = tile_debugfs_simple_show(m, data); 87 + ret = xe_tile_debugfs_simple_show(m, data); 89 88 xe_pm_runtime_put(xe); 90 89 91 90 return ret; 91 + } 92 + 93 + static int ggtt(struct xe_tile *tile, struct drm_printer *p) 94 + { 95 + return xe_ggtt_dump(tile->mem.ggtt, p); 92 96 } 93 97 94 98 static int sa_info(struct xe_tile *tile, struct drm_printer *p) ··· 106 100 107 101 /* only for debugfs files which can be safely used on the VF */ 108 102 static const struct drm_info_list vf_safe_debugfs_list[] = { 109 - { "sa_info", .show = tile_debugfs_show_with_rpm, .data = sa_info }, 103 + { "ggtt", .show = xe_tile_debugfs_show_with_rpm, .data = ggtt }, 104 + { "sa_info", .show = xe_tile_debugfs_show_with_rpm, .data = sa_info }, 110 105 }; 111 106 112 107 /**
+3
drivers/gpu/drm/xe/xe_tile_debugfs.h
··· 6 6 #ifndef _XE_TILE_DEBUGFS_H_ 7 7 #define _XE_TILE_DEBUGFS_H_ 8 8 9 + struct seq_file; 9 10 struct xe_tile; 10 11 11 12 void xe_tile_debugfs_register(struct xe_tile *tile); 13 + int xe_tile_debugfs_simple_show(struct seq_file *m, void *data); 14 + int xe_tile_debugfs_show_with_rpm(struct seq_file *m, void *data); 12 15 13 16 #endif
+253
drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <linux/debugfs.h> 7 + #include <drm/drm_debugfs.h> 8 + 9 + #include "xe_device.h" 10 + #include "xe_device_types.h" 11 + #include "xe_gt_sriov_pf_config.h" 12 + #include "xe_gt_sriov_pf_debugfs.h" 13 + #include "xe_pm.h" 14 + #include "xe_tile_debugfs.h" 15 + #include "xe_tile_sriov_pf_debugfs.h" 16 + #include "xe_sriov.h" 17 + #include "xe_sriov_pf.h" 18 + #include "xe_sriov_pf_provision.h" 19 + 20 + /* 21 + * /sys/kernel/debug/dri/BDF/ 22 + * ├── sriov # d_inode->i_private = (xe_device*) 23 + * │ ├── pf # d_inode->i_private = (xe_device*) 24 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 25 + * │ │ ├── tile1 26 + * │ │ : : 27 + * │ ├── vf1 # d_inode->i_private = VFID(1) 28 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 29 + * │ │ ├── tile1 30 + * │ │ : : 31 + * │ ├── vfN # d_inode->i_private = VFID(N) 32 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 33 + * │ │ ├── tile1 34 + * : : : : 35 + */ 36 + 37 + static void *extract_priv(struct dentry *d) 38 + { 39 + return d->d_inode->i_private; 40 + } 41 + 42 + __maybe_unused 43 + static struct xe_tile *extract_tile(struct dentry *d) 44 + { 45 + return extract_priv(d); 46 + } 47 + 48 + static struct xe_device *extract_xe(struct dentry *d) 49 + { 50 + return extract_priv(d->d_parent->d_parent); 51 + } 52 + 53 + __maybe_unused 54 + static unsigned int extract_vfid(struct dentry *d) 55 + { 56 + void *pp = extract_priv(d->d_parent); 57 + 58 + return pp == extract_xe(d) ? PFID : (uintptr_t)pp; 59 + } 60 + 61 + /* 62 + * /sys/kernel/debug/dri/BDF/ 63 + * ├── sriov 64 + * : ├── pf 65 + * : ├── tile0 66 + * : ├── ggtt_available 67 + * ├── ggtt_provisioned 68 + */ 69 + 70 + static int pf_config_print_available_ggtt(struct xe_tile *tile, struct drm_printer *p) 71 + { 72 + return xe_gt_sriov_pf_config_print_available_ggtt(tile->primary_gt, p); 73 + } 74 + 75 + static int pf_config_print_ggtt(struct xe_tile *tile, struct drm_printer *p) 76 + { 77 + return xe_gt_sriov_pf_config_print_ggtt(tile->primary_gt, p); 78 + } 79 + 80 + static const struct drm_info_list pf_ggtt_info[] = { 81 + { 82 + "ggtt_available", 83 + .show = xe_tile_debugfs_simple_show, 84 + .data = pf_config_print_available_ggtt, 85 + }, 86 + { 87 + "ggtt_provisioned", 88 + .show = xe_tile_debugfs_simple_show, 89 + .data = pf_config_print_ggtt, 90 + }, 91 + }; 92 + 93 + /* 94 + * /sys/kernel/debug/dri/BDF/ 95 + * ├── sriov 96 + * : ├── pf 97 + * : ├── tile0 98 + * : ├── vram_provisioned 99 + */ 100 + 101 + static int pf_config_print_vram(struct xe_tile *tile, struct drm_printer *p) 102 + { 103 + return xe_gt_sriov_pf_config_print_lmem(tile->primary_gt, p); 104 + } 105 + 106 + static const struct drm_info_list pf_vram_info[] = { 107 + { 108 + "vram_provisioned", 109 + .show = xe_tile_debugfs_simple_show, 110 + .data = pf_config_print_vram, 111 + }, 112 + }; 113 + 114 + /* 115 + * /sys/kernel/debug/dri/BDF/ 116 + * ├── sriov 117 + * │ ├── pf 118 + * │ │ ├── tile0 119 + * │ │ │ ├── ggtt_spare 120 + * │ │ │ ├── vram_spare 121 + * │ │ ├── tile1 122 + * │ │ : : 123 + * │ ├── vf1 124 + * │ : ├── tile0 125 + * │ │ ├── ggtt_quota 126 + * │ │ ├── vram_quota 127 + * │ ├── tile1 128 + * │ : : 129 + */ 130 + 131 + #define DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(NAME, CONFIG, TYPE, FORMAT) \ 132 + \ 133 + static int NAME##_set(void *data, u64 val) \ 134 + { \ 135 + struct xe_tile *tile = extract_tile(data); \ 136 + unsigned int vfid = extract_vfid(data); \ 137 + struct xe_gt *gt = tile->primary_gt; \ 138 + struct xe_device *xe = tile->xe; \ 139 + int err; \ 140 + \ 141 + if (val > (TYPE)~0ull) \ 142 + return -EOVERFLOW; \ 143 + \ 144 + xe_pm_runtime_get(xe); \ 145 + err = xe_sriov_pf_wait_ready(xe) ?: \ 146 + xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \ 147 + if (!err) \ 148 + xe_sriov_pf_provision_set_custom_mode(xe); \ 149 + xe_pm_runtime_put(xe); \ 150 + \ 151 + return err; \ 152 + } \ 153 + \ 154 + static int NAME##_get(void *data, u64 *val) \ 155 + { \ 156 + struct xe_tile *tile = extract_tile(data); \ 157 + unsigned int vfid = extract_vfid(data); \ 158 + struct xe_gt *gt = tile->primary_gt; \ 159 + \ 160 + *val = xe_gt_sriov_pf_config_get_##CONFIG(gt, vfid); \ 161 + return 0; \ 162 + } \ 163 + \ 164 + DEFINE_DEBUGFS_ATTRIBUTE(NAME##_fops, NAME##_get, NAME##_set, FORMAT) 165 + 166 + DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, ggtt, u64, "%llu\n"); 167 + DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(vram, lmem, u64, "%llu\n"); 168 + 169 + static void pf_add_config_attrs(struct xe_tile *tile, struct dentry *dent, unsigned int vfid) 170 + { 171 + struct xe_device *xe = tile->xe; 172 + 173 + xe_tile_assert(tile, tile == extract_tile(dent)); 174 + xe_tile_assert(tile, vfid == extract_vfid(dent)); 175 + 176 + debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare", 177 + 0644, dent, dent, &ggtt_fops); 178 + if (IS_DGFX(xe)) 179 + debugfs_create_file_unsafe(vfid ? "vram_quota" : "vram_spare", 180 + xe_device_has_lmtt(xe) ? 0644 : 0444, 181 + dent, dent, &vram_fops); 182 + } 183 + 184 + static void pf_populate_tile(struct xe_tile *tile, struct dentry *dent, unsigned int vfid) 185 + { 186 + struct xe_device *xe = tile->xe; 187 + struct drm_minor *minor = xe->drm.primary; 188 + struct xe_gt *gt; 189 + unsigned int id; 190 + 191 + pf_add_config_attrs(tile, dent, vfid); 192 + 193 + if (!vfid) { 194 + drm_debugfs_create_files(pf_ggtt_info, 195 + ARRAY_SIZE(pf_ggtt_info), 196 + dent, minor); 197 + if (IS_DGFX(xe)) 198 + drm_debugfs_create_files(pf_vram_info, 199 + ARRAY_SIZE(pf_vram_info), 200 + dent, minor); 201 + } 202 + 203 + for_each_gt_on_tile(gt, tile, id) 204 + xe_gt_sriov_pf_debugfs_populate(gt, dent, vfid); 205 + } 206 + 207 + /** 208 + * xe_tile_sriov_pf_debugfs_populate() - Populate SR-IOV debugfs tree with tile files. 209 + * @tile: the &xe_tile to register 210 + * @parent: the parent &dentry that represents the SR-IOV @vfid function 211 + * @vfid: the VF identifier 212 + * 213 + * Add to the @parent directory new debugfs directory that will represent a @tile and 214 + * populate it with files that are related to the SR-IOV @vfid function. 215 + * 216 + * This function can only be called on PF. 217 + */ 218 + void xe_tile_sriov_pf_debugfs_populate(struct xe_tile *tile, struct dentry *parent, 219 + unsigned int vfid) 220 + { 221 + struct xe_device *xe = tile->xe; 222 + struct dentry *dent; 223 + char name[10]; /* should be enough up to "tile%u\0" for 2^16 - 1 */ 224 + 225 + xe_tile_assert(tile, IS_SRIOV_PF(xe)); 226 + xe_tile_assert(tile, extract_priv(parent->d_parent) == xe); 227 + xe_tile_assert(tile, extract_priv(parent) == tile->xe || 228 + (uintptr_t)extract_priv(parent) == vfid); 229 + 230 + /* 231 + * /sys/kernel/debug/dri/BDF/ 232 + * ├── sriov 233 + * │ ├── pf # parent, d_inode->i_private = (xe_device*) 234 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 235 + * │ │ ├── tile1 236 + * │ │ : : 237 + * │ ├── vf1 # parent, d_inode->i_private = VFID(1) 238 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 239 + * │ │ ├── tile1 240 + * : : : : 241 + */ 242 + snprintf(name, sizeof(name), "tile%u", tile->id); 243 + dent = debugfs_create_dir(name, parent); 244 + if (IS_ERR(dent)) 245 + return; 246 + dent->d_inode->i_private = tile; 247 + 248 + xe_tile_assert(tile, extract_tile(dent) == tile); 249 + xe_tile_assert(tile, extract_vfid(dent) == vfid); 250 + xe_tile_assert(tile, extract_xe(dent) == xe); 251 + 252 + pf_populate_tile(tile, dent, vfid); 253 + }
+15
drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_TILE_SRIOV_PF_DEBUGFS_H_ 7 + #define _XE_TILE_SRIOV_PF_DEBUGFS_H_ 8 + 9 + struct dentry; 10 + struct xe_tile; 11 + 12 + void xe_tile_sriov_pf_debugfs_populate(struct xe_tile *tile, struct dentry *parent, 13 + unsigned int vfid); 14 + 15 + #endif
+33
drivers/gpu/drm/xe/xe_tile_sriov_printk.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_TILE_SRIOV_PRINTK_H_ 7 + #define _XE_TILE_SRIOV_PRINTK_H_ 8 + 9 + #include "xe_tile_printk.h" 10 + #include "xe_sriov_printk.h" 11 + 12 + #define __XE_TILE_SRIOV_PRINTK_FMT(_tile, _fmt, ...) \ 13 + __XE_TILE_PRINTK_FMT((_tile), _fmt, ##__VA_ARGS__) 14 + 15 + #define xe_tile_sriov_printk(_tile, _level, _fmt, ...) \ 16 + xe_sriov_##_level((_tile)->xe, __XE_TILE_SRIOV_PRINTK_FMT((_tile), _fmt, ##__VA_ARGS__)) 17 + 18 + #define xe_tile_sriov_err(_tile, _fmt, ...) \ 19 + xe_tile_sriov_printk(_tile, err, _fmt, ##__VA_ARGS__) 20 + 21 + #define xe_tile_sriov_notice(_tile, _fmt, ...) \ 22 + xe_tile_sriov_printk(_tile, notice, _fmt, ##__VA_ARGS__) 23 + 24 + #define xe_tile_sriov_info(_tile, _fmt, ...) \ 25 + xe_tile_sriov_printk(_tile, info, _fmt, ##__VA_ARGS__) 26 + 27 + #define xe_tile_sriov_dbg(_tile, _fmt, ...) \ 28 + xe_tile_sriov_printk(_tile, dbg, _fmt, ##__VA_ARGS__) 29 + 30 + #define xe_tile_sriov_dbg_verbose(_tile, _fmt, ...) \ 31 + xe_tile_sriov_printk(_tile, dbg_verbose, _fmt, ##__VA_ARGS__) 32 + 33 + #endif
+104 -8
drivers/gpu/drm/xe/xe_tile_sriov_vf.c
··· 9 9 10 10 #include "xe_assert.h" 11 11 #include "xe_ggtt.h" 12 - #include "xe_gt_sriov_vf.h" 13 12 #include "xe_sriov.h" 14 13 #include "xe_sriov_printk.h" 15 14 #include "xe_tile_sriov_vf.h" ··· 39 40 * 40 41 * Return: 0 on success or a negative error code on failure. 41 42 */ 42 - int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) 43 + static int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile) 43 44 { 44 - u64 ggtt_base = xe_gt_sriov_vf_ggtt_base(tile->primary_gt); 45 - u64 ggtt_size = xe_gt_sriov_vf_ggtt(tile->primary_gt); 45 + u64 ggtt_base = tile->sriov.vf.self_config.ggtt_base; 46 + u64 ggtt_size = tile->sriov.vf.self_config.ggtt_size; 46 47 struct xe_device *xe = tile_to_xe(tile); 47 48 u64 wopcm = xe_wopcm_size(xe); 48 49 u64 start, end; ··· 231 232 */ 232 233 233 234 /** 234 - * xe_tile_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match assigned range. 235 + * xe_tile_sriov_vf_fixup_ggtt_nodes_locked - Shift GGTT allocations to match assigned range. 235 236 * @tile: the &xe_tile struct instance 236 237 * @shift: the shift value 237 238 * ··· 239 240 * within the global space. This range might have changed during migration, 240 241 * which requires all memory addresses pointing to GGTT to be shifted. 241 242 */ 242 - void xe_tile_sriov_vf_fixup_ggtt_nodes(struct xe_tile *tile, s64 shift) 243 + void xe_tile_sriov_vf_fixup_ggtt_nodes_locked(struct xe_tile *tile, s64 shift) 243 244 { 244 245 struct xe_ggtt *ggtt = tile->mem.ggtt; 245 246 246 - mutex_lock(&ggtt->lock); 247 + lockdep_assert_held(&ggtt->lock); 247 248 248 249 xe_tile_sriov_vf_deballoon_ggtt_locked(tile); 249 250 xe_ggtt_shift_nodes_locked(ggtt, shift); 250 251 xe_tile_sriov_vf_balloon_ggtt_locked(tile); 252 + } 251 253 252 - mutex_unlock(&ggtt->lock); 254 + /** 255 + * xe_tile_sriov_vf_lmem - VF LMEM configuration. 256 + * @tile: the &xe_tile 257 + * 258 + * This function is for VF use only. 259 + * 260 + * Return: size of the LMEM assigned to VF. 261 + */ 262 + u64 xe_tile_sriov_vf_lmem(struct xe_tile *tile) 263 + { 264 + struct xe_tile_sriov_vf_selfconfig *config = &tile->sriov.vf.self_config; 265 + 266 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 267 + 268 + return config->lmem_size; 269 + } 270 + 271 + /** 272 + * xe_tile_sriov_vf_lmem_store - Store VF LMEM configuration 273 + * @tile: the &xe_tile 274 + * @lmem_size: VF LMEM size to store 275 + * 276 + * This function is for VF use only. 277 + */ 278 + void xe_tile_sriov_vf_lmem_store(struct xe_tile *tile, u64 lmem_size) 279 + { 280 + struct xe_tile_sriov_vf_selfconfig *config = &tile->sriov.vf.self_config; 281 + 282 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 283 + 284 + config->lmem_size = lmem_size; 285 + } 286 + 287 + /** 288 + * xe_tile_sriov_vf_ggtt - VF GGTT configuration. 289 + * @tile: the &xe_tile 290 + * 291 + * This function is for VF use only. 292 + * 293 + * Return: size of the GGTT assigned to VF. 294 + */ 295 + u64 xe_tile_sriov_vf_ggtt(struct xe_tile *tile) 296 + { 297 + struct xe_tile_sriov_vf_selfconfig *config = &tile->sriov.vf.self_config; 298 + 299 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 300 + 301 + return config->ggtt_size; 302 + } 303 + 304 + /** 305 + * xe_tile_sriov_vf_ggtt_store - Store VF GGTT configuration 306 + * @tile: the &xe_tile 307 + * @ggtt_size: VF GGTT size to store 308 + * 309 + * This function is for VF use only. 310 + */ 311 + void xe_tile_sriov_vf_ggtt_store(struct xe_tile *tile, u64 ggtt_size) 312 + { 313 + struct xe_tile_sriov_vf_selfconfig *config = &tile->sriov.vf.self_config; 314 + 315 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 316 + 317 + config->ggtt_size = ggtt_size; 318 + } 319 + 320 + /** 321 + * xe_tile_sriov_vf_ggtt_base - VF GGTT base configuration. 322 + * @tile: the &xe_tile 323 + * 324 + * This function is for VF use only. 325 + * 326 + * Return: base of the GGTT assigned to VF. 327 + */ 328 + u64 xe_tile_sriov_vf_ggtt_base(struct xe_tile *tile) 329 + { 330 + struct xe_tile_sriov_vf_selfconfig *config = &tile->sriov.vf.self_config; 331 + 332 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 333 + 334 + return config->ggtt_base; 335 + } 336 + 337 + /** 338 + * xe_tile_sriov_vf_ggtt_base_store - Store VF GGTT base configuration 339 + * @tile: the &xe_tile 340 + * @ggtt_base: VF GGTT base to store 341 + * 342 + * This function is for VF use only. 343 + */ 344 + void xe_tile_sriov_vf_ggtt_base_store(struct xe_tile *tile, u64 ggtt_base) 345 + { 346 + struct xe_tile_sriov_vf_selfconfig *config = &tile->sriov.vf.self_config; 347 + 348 + xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); 349 + 350 + config->ggtt_base = ggtt_base; 253 351 }
+7 -2
drivers/gpu/drm/xe/xe_tile_sriov_vf.h
··· 11 11 struct xe_tile; 12 12 13 13 int xe_tile_sriov_vf_prepare_ggtt(struct xe_tile *tile); 14 - int xe_tile_sriov_vf_balloon_ggtt_locked(struct xe_tile *tile); 15 14 void xe_tile_sriov_vf_deballoon_ggtt_locked(struct xe_tile *tile); 16 - void xe_tile_sriov_vf_fixup_ggtt_nodes(struct xe_tile *tile, s64 shift); 15 + void xe_tile_sriov_vf_fixup_ggtt_nodes_locked(struct xe_tile *tile, s64 shift); 16 + u64 xe_tile_sriov_vf_ggtt(struct xe_tile *tile); 17 + void xe_tile_sriov_vf_ggtt_store(struct xe_tile *tile, u64 ggtt_size); 18 + u64 xe_tile_sriov_vf_ggtt_base(struct xe_tile *tile); 19 + void xe_tile_sriov_vf_ggtt_base_store(struct xe_tile *tile, u64 ggtt_size); 20 + u64 xe_tile_sriov_vf_lmem(struct xe_tile *tile); 21 + void xe_tile_sriov_vf_lmem_store(struct xe_tile *tile, u64 lmem_size); 17 22 18 23 #endif
+23
drivers/gpu/drm/xe/xe_tile_sriov_vf_types.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_TILE_SRIOV_VF_TYPES_H_ 7 + #define _XE_TILE_SRIOV_VF_TYPES_H_ 8 + 9 + #include <linux/types.h> 10 + 11 + /** 12 + * struct xe_tile_sriov_vf_selfconfig - VF configuration data. 13 + */ 14 + struct xe_tile_sriov_vf_selfconfig { 15 + /** @ggtt_base: assigned base offset of the GGTT region. */ 16 + u64 ggtt_base; 17 + /** @ggtt_size: assigned size of the GGTT region. */ 18 + u64 ggtt_size; 19 + /** @lmem_size: assigned size of the LMEM. */ 20 + u64 lmem_size; 21 + }; 22 + 23 + #endif
+5 -3
drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 /* 3 3 * Copyright © 2021-2023 Intel Corporation 4 - * Copyright (C) 2021-2002 Red Hat 4 + * Copyright (C) 2021-2022 Red Hat 5 5 */ 6 6 7 7 #include <drm/drm_managed.h> ··· 24 24 #include "xe_sriov.h" 25 25 #include "xe_ttm_stolen_mgr.h" 26 26 #include "xe_ttm_vram_mgr.h" 27 - #include "xe_wa.h" 28 27 #include "xe_vram.h" 28 + #include "xe_wa.h" 29 29 30 30 struct xe_ttm_stolen_mgr { 31 31 struct xe_ttm_vram_mgr base; ··· 81 81 return wopcm_size; 82 82 } 83 83 84 - static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) 84 + static u64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) 85 85 { 86 86 struct xe_vram_region *tile_vram = xe_device_get_root_tile(xe)->mem.vram; 87 87 resource_size_t tile_io_start = xe_vram_region_io_start(tile_vram); ··· 105 105 return 0; 106 106 107 107 stolen_size = tile_size - mgr->stolen_base; 108 + 109 + xe_assert(xe, stolen_size > wopcm_size); 108 110 stolen_size -= wopcm_size; 109 111 110 112 /* Verify usage fits in the actual resource available */
+3 -3
drivers/gpu/drm/xe/xe_ttm_sys_mgr.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 /* 3 3 * Copyright © 2021-2022 Intel Corporation 4 - * Copyright (C) 2021-2002 Red Hat 4 + * Copyright (C) 2021-2022 Red Hat 5 5 */ 6 6 7 7 #include "xe_ttm_sys_mgr.h" ··· 85 85 .debug = xe_ttm_sys_mgr_debug 86 86 }; 87 87 88 - static void ttm_sys_mgr_fini(struct drm_device *drm, void *arg) 88 + static void xe_ttm_sys_mgr_fini(struct drm_device *drm, void *arg) 89 89 { 90 90 struct xe_device *xe = (struct xe_device *)arg; 91 91 struct ttm_resource_manager *man = &xe->mem.sys_mgr; ··· 116 116 ttm_resource_manager_init(man, &xe->ttm, gtt_size >> PAGE_SHIFT); 117 117 ttm_set_driver_manager(&xe->ttm, XE_PL_TT, man); 118 118 ttm_resource_manager_set_used(man, true); 119 - return drmm_add_action_or_reset(&xe->drm, ttm_sys_mgr_fini, xe); 119 + return drmm_add_action_or_reset(&xe->drm, xe_ttm_sys_mgr_fini, xe); 120 120 }
+3 -3
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 /* 3 3 * Copyright © 2021-2022 Intel Corporation 4 - * Copyright (C) 2021-2002 Red Hat 4 + * Copyright (C) 2021-2022 Red Hat 5 5 */ 6 6 7 7 #include <drm/drm_managed.h> ··· 284 284 .debug = xe_ttm_vram_mgr_debug 285 285 }; 286 286 287 - static void ttm_vram_mgr_fini(struct drm_device *dev, void *arg) 287 + static void xe_ttm_vram_mgr_fini(struct drm_device *dev, void *arg) 288 288 { 289 289 struct xe_device *xe = to_xe_device(dev); 290 290 struct xe_ttm_vram_mgr *mgr = arg; ··· 335 335 ttm_set_driver_manager(&xe->ttm, mem_type, &mgr->manager); 336 336 ttm_resource_manager_set_used(&mgr->manager, true); 337 337 338 - return drmm_add_action_or_reset(&xe->drm, ttm_vram_mgr_fini, mgr); 338 + return drmm_add_action_or_reset(&xe->drm, xe_ttm_vram_mgr_fini, mgr); 339 339 } 340 340 341 341 /**
+20 -6
drivers/gpu/drm/xe/xe_tuning.c
··· 40 40 REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f))) 41 41 }, 42 42 { XE_RTP_NAME("Tuning: Compression Overfetch"), 43 - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED)), 43 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED), 44 + FUNC(xe_rtp_match_has_flat_ccs)), 44 45 XE_RTP_ACTIONS(CLR(CCCHKNREG1, ENCOMPPERFFIX), 45 46 SET(CCCHKNREG1, L3CMPCTRL)) 46 47 }, ··· 59 58 XE_RTP_ACTIONS(SET(XE2LPM_L3SQCREG3, COMPPWOVERFETCHEN)) 60 59 }, 61 60 { XE_RTP_NAME("Tuning: L2 Overfetch Compressible Only"), 62 - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED)), 61 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED), 62 + FUNC(xe_rtp_match_has_flat_ccs)), 63 63 XE_RTP_ACTIONS(SET(L3SQCREG2, 64 64 COMPMEMRD256BOVRFETCHEN)) 65 65 }, 66 66 { XE_RTP_NAME("Tuning: L2 Overfetch Compressible Only - media"), 67 - XE_RTP_RULES(MEDIA_VERSION_RANGE(2000, XE_RTP_END_VERSION_UNDEFINED)), 67 + XE_RTP_RULES(MEDIA_VERSION_RANGE(2000, XE_RTP_END_VERSION_UNDEFINED), 68 + FUNC(xe_rtp_match_has_flat_ccs)), 68 69 XE_RTP_ACTIONS(SET(XE2LPM_L3SQCREG2, 69 70 COMPMEMRD256BOVRFETCHEN)) 70 71 }, ··· 217 214 xe_rtp_process_to_sr(&ctx, lrc_tunings, ARRAY_SIZE(lrc_tunings), &hwe->reg_lrc); 218 215 } 219 216 220 - void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p) 217 + /** 218 + * xe_tuning_dump() - Dump GT tuning info into a drm printer. 219 + * @gt: the &xe_gt 220 + * @p: the &drm_printer 221 + * 222 + * Return: always 0. 223 + */ 224 + int xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p) 221 225 { 222 226 size_t idx; 223 227 ··· 232 222 for_each_set_bit(idx, gt->tuning_active.gt, ARRAY_SIZE(gt_tunings)) 233 223 drm_printf_indent(p, 1, "%s\n", gt_tunings[idx].name); 234 224 235 - drm_printf(p, "\nEngine Tunings\n"); 225 + drm_puts(p, "\n"); 226 + drm_printf(p, "Engine Tunings\n"); 236 227 for_each_set_bit(idx, gt->tuning_active.engine, ARRAY_SIZE(engine_tunings)) 237 228 drm_printf_indent(p, 1, "%s\n", engine_tunings[idx].name); 238 229 239 - drm_printf(p, "\nLRC Tunings\n"); 230 + drm_puts(p, "\n"); 231 + drm_printf(p, "LRC Tunings\n"); 240 232 for_each_set_bit(idx, gt->tuning_active.lrc, ARRAY_SIZE(lrc_tunings)) 241 233 drm_printf_indent(p, 1, "%s\n", lrc_tunings[idx].name); 234 + 235 + return 0; 242 236 }
+1 -1
drivers/gpu/drm/xe/xe_tuning.h
··· 14 14 void xe_tuning_process_gt(struct xe_gt *gt); 15 15 void xe_tuning_process_engine(struct xe_hw_engine *hwe); 16 16 void xe_tuning_process_lrc(struct xe_hw_engine *hwe); 17 - void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p); 17 + int xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p); 18 18 19 19 #endif
+3 -1
drivers/gpu/drm/xe/xe_userptr.c
··· 3 3 * Copyright © 2025 Intel Corporation 4 4 */ 5 5 6 + #include "xe_svm.h" 6 7 #include "xe_userptr.h" 7 8 8 9 #include <linux/mm.h> ··· 55 54 struct xe_device *xe = vm->xe; 56 55 struct drm_gpusvm_ctx ctx = { 57 56 .read_only = xe_vma_read_only(vma), 58 - .device_private_page_owner = NULL, 57 + .device_private_page_owner = xe_svm_devm_owner(xe), 58 + .allow_mixed = true, 59 59 }; 60 60 61 61 lockdep_assert_held(&vm->lock);
+66 -61
drivers/gpu/drm/xe/xe_vm.c
··· 35 35 #include "xe_pt.h" 36 36 #include "xe_pxp.h" 37 37 #include "xe_res_cursor.h" 38 + #include "xe_sriov_vf.h" 38 39 #include "xe_svm.h" 39 40 #include "xe_sync.h" 40 41 #include "xe_tile.h" ··· 112 111 static int wait_for_existing_preempt_fences(struct xe_vm *vm) 113 112 { 114 113 struct xe_exec_queue *q; 114 + bool vf_migration = IS_SRIOV_VF(vm->xe) && 115 + xe_sriov_vf_migration_supported(vm->xe); 116 + signed long wait_time = vf_migration ? HZ / 5 : MAX_SCHEDULE_TIMEOUT; 115 117 116 118 xe_vm_assert_held(vm); 117 119 118 120 list_for_each_entry(q, &vm->preempt.exec_queues, lr.link) { 119 121 if (q->lr.pfence) { 120 - long timeout = dma_fence_wait(q->lr.pfence, false); 122 + long timeout; 123 + 124 + timeout = dma_fence_wait_timeout(q->lr.pfence, false, 125 + wait_time); 126 + if (!timeout) { 127 + xe_assert(vm->xe, vf_migration); 128 + return -EAGAIN; 129 + } 121 130 122 131 /* Only -ETIME on fence indicates VM needs to be killed */ 123 132 if (timeout < 0 || q->lr.pfence->error == -ETIME) ··· 477 466 retry: 478 467 if (!try_wait_for_completion(&vm->xe->pm_block) && vm_suspend_rebind_worker(vm)) { 479 468 up_write(&vm->lock); 469 + /* We don't actually block but don't make progress. */ 470 + xe_pm_might_block_on_suspend(); 480 471 return; 481 472 } 482 473 ··· 552 539 out_unlock_outer: 553 540 if (err == -EAGAIN) { 554 541 trace_xe_vm_rebind_worker_retry(vm); 542 + 543 + /* 544 + * We can't block in workers on a VF which supports migration 545 + * given this can block the VF post-migration workers from 546 + * getting scheduled. 547 + */ 548 + if (IS_SRIOV_VF(vm->xe) && 549 + xe_sriov_vf_migration_supported(vm->xe)) { 550 + up_write(&vm->lock); 551 + xe_vm_queue_rebind_worker(vm); 552 + return; 553 + } 554 + 555 555 goto retry; 556 556 } 557 557 ··· 642 616 vops->pt_update_ops[i].num_ops += inc_val; 643 617 } 644 618 619 + #define XE_VMA_CREATE_MASK ( \ 620 + XE_VMA_READ_ONLY | \ 621 + XE_VMA_DUMPABLE | \ 622 + XE_VMA_SYSTEM_ALLOCATOR | \ 623 + DRM_GPUVA_SPARSE | \ 624 + XE_VMA_MADV_AUTORESET) 625 + 645 626 static void xe_vm_populate_rebind(struct xe_vma_op *op, struct xe_vma *vma, 646 627 u8 tile_mask) 647 628 { ··· 661 628 op->base.map.gem.offset = vma->gpuva.gem.offset; 662 629 op->map.vma = vma; 663 630 op->map.immediate = true; 664 - op->map.dumpable = vma->gpuva.flags & XE_VMA_DUMPABLE; 665 - op->map.is_null = xe_vma_is_null(vma); 631 + op->map.vma_flags = vma->gpuva.flags & XE_VMA_CREATE_MASK; 666 632 } 667 633 668 634 static int xe_vm_ops_add_rebind(struct xe_vma_ops *vops, struct xe_vma *vma, ··· 964 932 kfree(vma); 965 933 } 966 934 967 - #define VMA_CREATE_FLAG_READ_ONLY BIT(0) 968 - #define VMA_CREATE_FLAG_IS_NULL BIT(1) 969 - #define VMA_CREATE_FLAG_DUMPABLE BIT(2) 970 - #define VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR BIT(3) 971 - 972 935 static struct xe_vma *xe_vma_create(struct xe_vm *vm, 973 936 struct xe_bo *bo, 974 937 u64 bo_offset_or_userptr, ··· 974 947 struct xe_vma *vma; 975 948 struct xe_tile *tile; 976 949 u8 id; 977 - bool read_only = (flags & VMA_CREATE_FLAG_READ_ONLY); 978 - bool is_null = (flags & VMA_CREATE_FLAG_IS_NULL); 979 - bool dumpable = (flags & VMA_CREATE_FLAG_DUMPABLE); 980 - bool is_cpu_addr_mirror = 981 - (flags & VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR); 950 + bool is_null = (flags & DRM_GPUVA_SPARSE); 951 + bool is_cpu_addr_mirror = (flags & XE_VMA_SYSTEM_ALLOCATOR); 982 952 983 953 xe_assert(vm->xe, start < end); 984 954 xe_assert(vm->xe, end < vm->size); ··· 996 972 if (!vma) 997 973 return ERR_PTR(-ENOMEM); 998 974 999 - if (is_cpu_addr_mirror) 1000 - vma->gpuva.flags |= XE_VMA_SYSTEM_ALLOCATOR; 1001 - if (is_null) 1002 - vma->gpuva.flags |= DRM_GPUVA_SPARSE; 1003 975 if (bo) 1004 976 vma->gpuva.gem.obj = &bo->ttm.base; 1005 977 } ··· 1006 986 vma->gpuva.vm = &vm->gpuvm; 1007 987 vma->gpuva.va.addr = start; 1008 988 vma->gpuva.va.range = end - start + 1; 1009 - if (read_only) 1010 - vma->gpuva.flags |= XE_VMA_READ_ONLY; 1011 - if (dumpable) 1012 - vma->gpuva.flags |= XE_VMA_DUMPABLE; 989 + vma->gpuva.flags = flags; 1013 990 1014 991 for_each_tile(tile, vm->xe, id) 1015 992 vma->tile_mask |= 0x1 << id; ··· 1901 1884 struct xe_device *xe = to_xe_device(dev); 1902 1885 struct xe_file *xef = to_xe_file(file); 1903 1886 struct drm_xe_vm_create *args = data; 1887 + struct xe_gt *wa_gt = xe_root_mmio_gt(xe); 1904 1888 struct xe_vm *vm; 1905 1889 u32 id; 1906 1890 int err; ··· 1910 1892 if (XE_IOCTL_DBG(xe, args->extensions)) 1911 1893 return -EINVAL; 1912 1894 1913 - if (XE_GT_WA(xe_root_mmio_gt(xe), 14016763929)) 1895 + if (wa_gt && XE_GT_WA(wa_gt, 22014953428)) 1914 1896 args->flags |= DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE; 1915 1897 1916 1898 if (XE_IOCTL_DBG(xe, args->flags & DRM_XE_VM_CREATE_FLAG_FAULT_MODE && ··· 2290 2272 if (__op->op == DRM_GPUVA_OP_MAP) { 2291 2273 op->map.immediate = 2292 2274 flags & DRM_XE_VM_BIND_FLAG_IMMEDIATE; 2293 - op->map.read_only = 2294 - flags & DRM_XE_VM_BIND_FLAG_READONLY; 2295 - op->map.is_null = flags & DRM_XE_VM_BIND_FLAG_NULL; 2296 - op->map.is_cpu_addr_mirror = flags & 2297 - DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR; 2298 - op->map.dumpable = flags & DRM_XE_VM_BIND_FLAG_DUMPABLE; 2275 + if (flags & DRM_XE_VM_BIND_FLAG_READONLY) 2276 + op->map.vma_flags |= XE_VMA_READ_ONLY; 2277 + if (flags & DRM_XE_VM_BIND_FLAG_NULL) 2278 + op->map.vma_flags |= DRM_GPUVA_SPARSE; 2279 + if (flags & DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR) 2280 + op->map.vma_flags |= XE_VMA_SYSTEM_ALLOCATOR; 2281 + if (flags & DRM_XE_VM_BIND_FLAG_DUMPABLE) 2282 + op->map.vma_flags |= XE_VMA_DUMPABLE; 2283 + if (flags & DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) 2284 + op->map.vma_flags |= XE_VMA_MADV_AUTORESET; 2299 2285 op->map.pat_index = pat_index; 2300 2286 op->map.invalidate_on_bind = 2301 2287 __xe_vm_needs_clear_scratch_pages(vm, flags); ··· 2612 2590 .pat_index = op->map.pat_index, 2613 2591 }; 2614 2592 2615 - flags |= op->map.read_only ? 2616 - VMA_CREATE_FLAG_READ_ONLY : 0; 2617 - flags |= op->map.is_null ? 2618 - VMA_CREATE_FLAG_IS_NULL : 0; 2619 - flags |= op->map.dumpable ? 2620 - VMA_CREATE_FLAG_DUMPABLE : 0; 2621 - flags |= op->map.is_cpu_addr_mirror ? 2622 - VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0; 2593 + flags |= op->map.vma_flags & XE_VMA_CREATE_MASK; 2623 2594 2624 2595 vma = new_vma(vm, &op->base.map, &default_attr, 2625 2596 flags); ··· 2621 2606 2622 2607 op->map.vma = vma; 2623 2608 if (((op->map.immediate || !xe_vm_in_fault_mode(vm)) && 2624 - !op->map.is_cpu_addr_mirror) || 2609 + !(op->map.vma_flags & XE_VMA_SYSTEM_ALLOCATOR)) || 2625 2610 op->map.invalidate_on_bind) 2626 2611 xe_vma_ops_incr_pt_update_ops(vops, 2627 2612 op->tile_mask, 1); ··· 2652 2637 op->remap.start = xe_vma_start(old); 2653 2638 op->remap.range = xe_vma_size(old); 2654 2639 2655 - flags |= op->base.remap.unmap->va->flags & 2656 - XE_VMA_READ_ONLY ? 2657 - VMA_CREATE_FLAG_READ_ONLY : 0; 2658 - flags |= op->base.remap.unmap->va->flags & 2659 - DRM_GPUVA_SPARSE ? 2660 - VMA_CREATE_FLAG_IS_NULL : 0; 2661 - flags |= op->base.remap.unmap->va->flags & 2662 - XE_VMA_DUMPABLE ? 2663 - VMA_CREATE_FLAG_DUMPABLE : 0; 2664 - flags |= xe_vma_is_cpu_addr_mirror(old) ? 2665 - VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0; 2666 - 2640 + flags |= op->base.remap.unmap->va->flags & XE_VMA_CREATE_MASK; 2667 2641 if (op->base.remap.prev) { 2668 2642 vma = new_vma(vm, op->base.remap.prev, 2669 2643 &old->attr, flags); ··· 3283 3279 DRM_XE_VM_BIND_FLAG_NULL | \ 3284 3280 DRM_XE_VM_BIND_FLAG_DUMPABLE | \ 3285 3281 DRM_XE_VM_BIND_FLAG_CHECK_PXP | \ 3286 - DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR) 3282 + DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR | \ 3283 + DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) 3287 3284 3288 3285 #ifdef TEST_VM_OPS_ERROR 3289 3286 #define SUPPORTED_FLAGS (SUPPORTED_FLAGS_STUB | FORCE_OP_ERROR) ··· 3399 3394 XE_IOCTL_DBG(xe, (prefetch_region != DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC && 3400 3395 !(BIT(prefetch_region) & xe->info.mem_region_mask))) || 3401 3396 XE_IOCTL_DBG(xe, obj && 3402 - op == DRM_XE_VM_BIND_OP_UNMAP)) { 3397 + op == DRM_XE_VM_BIND_OP_UNMAP) || 3398 + XE_IOCTL_DBG(xe, (flags & DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) && 3399 + (!is_cpu_addr_mirror || op != DRM_XE_VM_BIND_OP_MAP))) { 3403 3400 err = -EINVAL; 3404 3401 goto free_bind_ops; 3405 3402 } ··· 4219 4212 struct xe_vma_ops vops; 4220 4213 struct drm_gpuva_ops *ops = NULL; 4221 4214 struct drm_gpuva_op *__op; 4222 - bool is_cpu_addr_mirror = false; 4215 + unsigned int vma_flags = 0; 4223 4216 bool remap_op = false; 4224 4217 struct xe_vma_mem_attr tmp_attr; 4225 4218 u16 default_pat; ··· 4249 4242 vma = gpuva_to_vma(op->base.unmap.va); 4250 4243 XE_WARN_ON(!xe_vma_has_default_mem_attrs(vma)); 4251 4244 default_pat = vma->attr.default_pat_index; 4245 + vma_flags = vma->gpuva.flags; 4252 4246 } 4253 4247 4254 4248 if (__op->op == DRM_GPUVA_OP_REMAP) { 4255 4249 vma = gpuva_to_vma(op->base.remap.unmap->va); 4256 4250 default_pat = vma->attr.default_pat_index; 4251 + vma_flags = vma->gpuva.flags; 4257 4252 } 4258 4253 4259 4254 if (__op->op == DRM_GPUVA_OP_MAP) { 4260 - op->map.is_cpu_addr_mirror = true; 4255 + op->map.vma_flags |= vma_flags & XE_VMA_CREATE_MASK; 4261 4256 op->map.pat_index = default_pat; 4262 4257 } 4263 4258 } else { ··· 4268 4259 xe_assert(vm->xe, !remap_op); 4269 4260 xe_assert(vm->xe, xe_vma_has_no_bo(vma)); 4270 4261 remap_op = true; 4271 - 4272 - if (xe_vma_is_cpu_addr_mirror(vma)) 4273 - is_cpu_addr_mirror = true; 4274 - else 4275 - is_cpu_addr_mirror = false; 4262 + vma_flags = vma->gpuva.flags; 4276 4263 } 4277 4264 4278 4265 if (__op->op == DRM_GPUVA_OP_MAP) { ··· 4277 4272 /* 4278 4273 * In case of madvise ops DRM_GPUVA_OP_MAP is 4279 4274 * always after DRM_GPUVA_OP_REMAP, so ensure 4280 - * we assign op->map.is_cpu_addr_mirror true 4281 - * if REMAP is for xe_vma_is_cpu_addr_mirror vma 4275 + * to propagate the flags from the vma we're 4276 + * unmapping. 4282 4277 */ 4283 - op->map.is_cpu_addr_mirror = is_cpu_addr_mirror; 4278 + op->map.vma_flags |= vma_flags & XE_VMA_CREATE_MASK; 4284 4279 } 4285 4280 } 4286 4281 print_op(vm->xe, __op);
+2 -8
drivers/gpu/drm/xe/xe_vm_types.h
··· 46 46 #define XE_VMA_PTE_COMPACT (DRM_GPUVA_USERBITS << 7) 47 47 #define XE_VMA_DUMPABLE (DRM_GPUVA_USERBITS << 8) 48 48 #define XE_VMA_SYSTEM_ALLOCATOR (DRM_GPUVA_USERBITS << 9) 49 + #define XE_VMA_MADV_AUTORESET (DRM_GPUVA_USERBITS << 10) 49 50 50 51 /** 51 52 * struct xe_vma_mem_attr - memory attributes associated with vma ··· 346 345 struct xe_vma_op_map { 347 346 /** @vma: VMA to map */ 348 347 struct xe_vma *vma; 348 + unsigned int vma_flags; 349 349 /** @immediate: Immediate bind */ 350 350 bool immediate; 351 351 /** @read_only: Read only */ 352 - bool read_only; 353 - /** @is_null: is NULL binding */ 354 - bool is_null; 355 - /** @is_cpu_addr_mirror: is CPU address mirror binding */ 356 - bool is_cpu_addr_mirror; 357 - /** @dumpable: whether BO is dumped on GPU hang */ 358 - bool dumpable; 359 - /** @invalidate: invalidate the VMA before bind */ 360 352 bool invalidate_on_bind; 361 353 /** @pat_index: The pat index to use for this operation. */ 362 354 u16 pat_index;
+8 -4
drivers/gpu/drm/xe/xe_vram.c
··· 13 13 #include "regs/xe_gt_regs.h" 14 14 #include "regs/xe_regs.h" 15 15 #include "xe_assert.h" 16 + #include "xe_bo.h" 16 17 #include "xe_device.h" 17 18 #include "xe_force_wake.h" 18 19 #include "xe_gt_mcr.h" 19 - #include "xe_gt_sriov_vf.h" 20 20 #include "xe_mmio.h" 21 21 #include "xe_module.h" 22 22 #include "xe_sriov.h" 23 + #include "xe_tile_sriov_vf.h" 23 24 #include "xe_ttm_vram_mgr.h" 24 25 #include "xe_vram.h" 25 26 #include "xe_vram_types.h" ··· 256 255 offset = 0; 257 256 for_each_tile(t, xe, id) 258 257 for_each_if(t->id < tile->id) 259 - offset += xe_gt_sriov_vf_lmem(t->primary_gt); 258 + offset += xe_tile_sriov_vf_lmem(t); 260 259 261 - *tile_size = xe_gt_sriov_vf_lmem(gt); 260 + *tile_size = xe_tile_sriov_vf_lmem(tile); 262 261 *vram_size = *tile_size; 263 262 *tile_offset = offset; 264 263 ··· 302 301 303 302 xe->mem.vram->mapping = NULL; 304 303 305 - for_each_tile(tile, xe, id) 304 + for_each_tile(tile, xe, id) { 306 305 tile->mem.vram->mapping = NULL; 306 + if (tile->mem.kernel_vram) 307 + tile->mem.kernel_vram->mapping = NULL; 308 + } 307 309 } 308 310 309 311 struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement)
+19 -8
drivers/gpu/drm/xe/xe_wa.c
··· 684 684 }, 685 685 { XE_RTP_NAME("13012615864"), 686 686 XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001), OR, 687 - GRAPHICS_VERSION(3003), 687 + GRAPHICS_VERSION_RANGE(3003, 3005), 688 688 FUNC(xe_rtp_match_first_render_or_compute)), 689 689 XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS)) 690 690 }, ··· 695 695 XE_RTP_ACTION_FLAG(ENGINE_BASE))) 696 696 }, 697 697 { XE_RTP_NAME("14021402888"), 698 - XE_RTP_RULES(GRAPHICS_VERSION(3003), FUNC(xe_rtp_match_first_render_or_compute)), 698 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3003, 3005), FUNC(xe_rtp_match_first_render_or_compute)), 699 699 XE_RTP_ACTIONS(SET(HALF_SLICE_CHICKEN7, CLEAR_OPTIMIZATION_DISABLE)) 700 700 }, 701 701 { XE_RTP_NAME("18041344222"), ··· 913 913 DIS_AUTOSTRIP)) 914 914 }, 915 915 { XE_RTP_NAME("22021007897"), 916 - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3003), ENGINE_CLASS(RENDER)), 916 + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)), 917 917 XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) 918 918 }, 919 919 }; ··· 1086 1086 drm_printf_indent(p, 1, "%s\n", device_oob_was[idx].name); 1087 1087 } 1088 1088 1089 - void xe_wa_dump(struct xe_gt *gt, struct drm_printer *p) 1089 + /** 1090 + * xe_wa_gt_dump() - Dump GT workarounds into a drm printer. 1091 + * @gt: the &xe_gt 1092 + * @p: the &drm_printer 1093 + * 1094 + * Return: always 0. 1095 + */ 1096 + int xe_wa_gt_dump(struct xe_gt *gt, struct drm_printer *p) 1090 1097 { 1091 1098 size_t idx; 1092 1099 ··· 1101 1094 for_each_set_bit(idx, gt->wa_active.gt, ARRAY_SIZE(gt_was)) 1102 1095 drm_printf_indent(p, 1, "%s\n", gt_was[idx].name); 1103 1096 1104 - drm_printf(p, "\nEngine Workarounds\n"); 1097 + drm_puts(p, "\n"); 1098 + drm_printf(p, "Engine Workarounds\n"); 1105 1099 for_each_set_bit(idx, gt->wa_active.engine, ARRAY_SIZE(engine_was)) 1106 1100 drm_printf_indent(p, 1, "%s\n", engine_was[idx].name); 1107 1101 1108 - drm_printf(p, "\nLRC Workarounds\n"); 1102 + drm_puts(p, "\n"); 1103 + drm_printf(p, "LRC Workarounds\n"); 1109 1104 for_each_set_bit(idx, gt->wa_active.lrc, ARRAY_SIZE(lrc_was)) 1110 1105 drm_printf_indent(p, 1, "%s\n", lrc_was[idx].name); 1111 1106 1112 - drm_printf(p, "\nOOB Workarounds\n"); 1107 + drm_puts(p, "\n"); 1108 + drm_printf(p, "OOB Workarounds\n"); 1113 1109 for_each_set_bit(idx, gt->wa_active.oob, ARRAY_SIZE(oob_was)) 1114 1110 if (oob_was[idx].name) 1115 1111 drm_printf_indent(p, 1, "%s\n", oob_was[idx].name); 1112 + return 0; 1116 1113 } 1117 1114 1118 1115 /* ··· 1138 1127 if (IS_SRIOV_VF(tile->xe)) 1139 1128 return; 1140 1129 1141 - if (XE_GT_WA(tile->primary_gt, 22010954014)) 1130 + if (XE_DEVICE_WA(tile->xe, 22010954014)) 1142 1131 xe_mmio_rmw32(mmio, XEHP_CLOCK_GATE_DIS, 0, SGSI_SIDECLK_DIS); 1143 1132 }
+1 -1
drivers/gpu/drm/xe/xe_wa.h
··· 22 22 void xe_wa_process_lrc(struct xe_hw_engine *hwe); 23 23 void xe_wa_apply_tile_workarounds(struct xe_tile *tile); 24 24 void xe_wa_device_dump(struct xe_device *xe, struct drm_printer *p); 25 - void xe_wa_dump(struct xe_gt *gt, struct drm_printer *p); 25 + int xe_wa_gt_dump(struct xe_gt *gt, struct drm_printer *p); 26 26 27 27 /** 28 28 * XE_GT_WA - Out-of-band GT workarounds, to be queried and called as needed.
+6 -11
drivers/gpu/drm/xe/xe_wa_oob.rules
··· 11 11 18020744125 PLATFORM(PVC) 12 12 1509372804 PLATFORM(PVC), GRAPHICS_STEP(A0, C0) 13 13 1409600907 GRAPHICS_VERSION_RANGE(1200, 1250) 14 - 14016763929 SUBPLATFORM(DG2, G10) 14 + 22014953428 SUBPLATFORM(DG2, G10) 15 15 SUBPLATFORM(DG2, G12) 16 16 16017236439 PLATFORM(PVC) 17 - 22010954014 PLATFORM(DG2) 18 17 14019821291 MEDIA_VERSION_RANGE(1300, 2000) 19 18 14015076503 MEDIA_VERSION(1300) 20 19 16020292621 GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0) ··· 33 34 13011645652 GRAPHICS_VERSION(2004) 34 35 GRAPHICS_VERSION_RANGE(3000, 3001) 35 36 GRAPHICS_VERSION(3003) 37 + GRAPHICS_VERSION_RANGE(3004, 3005) 36 38 14022293748 GRAPHICS_VERSION_RANGE(2001, 2002) 37 39 GRAPHICS_VERSION(2004) 38 - GRAPHICS_VERSION_RANGE(3000, 3001) 39 - GRAPHICS_VERSION(3003) 40 + GRAPHICS_VERSION_RANGE(3000, 3005) 40 41 22019794406 GRAPHICS_VERSION_RANGE(2001, 2002) 41 42 GRAPHICS_VERSION(2004) 42 43 GRAPHICS_VERSION_RANGE(3000, 3001) 43 44 GRAPHICS_VERSION(3003) 45 + GRAPHICS_VERSION_RANGE(3004, 3005) 44 46 22019338487 MEDIA_VERSION(2000) 45 47 GRAPHICS_VERSION(2001), FUNC(xe_rtp_match_not_sriov_vf) 46 48 MEDIA_VERSION(3000), MEDIA_STEP(A0, B0), FUNC(xe_rtp_match_not_sriov_vf) 47 - 22019338487_display PLATFORM(LUNARLAKE) 48 49 16023588340 GRAPHICS_VERSION(2001), FUNC(xe_rtp_match_not_sriov_vf) 49 50 14019789679 GRAPHICS_VERSION(1255) 50 51 GRAPHICS_VERSION_RANGE(1270, 2004) ··· 62 63 16023105232 GRAPHICS_VERSION_RANGE(2001, 3001) 63 64 MEDIA_VERSION_RANGE(1301, 3000) 64 65 MEDIA_VERSION(3002) 65 - GRAPHICS_VERSION(3003) 66 + GRAPHICS_VERSION_RANGE(3003, 3005) 66 67 16026508708 GRAPHICS_VERSION_RANGE(1200, 3001) 67 68 MEDIA_VERSION_RANGE(1300, 3000) 68 69 MEDIA_VERSION(3002) 69 - GRAPHICS_VERSION(3003) 70 + GRAPHICS_VERSION_RANGE(3003, 3005) 70 71 14020001231 GRAPHICS_VERSION_RANGE(2001,2004), FUNC(xe_rtp_match_psmi_enabled) 71 72 MEDIA_VERSION(2000), FUNC(xe_rtp_match_psmi_enabled) 72 73 MEDIA_VERSION(3000), FUNC(xe_rtp_match_psmi_enabled) 73 74 MEDIA_VERSION(3002), FUNC(xe_rtp_match_psmi_enabled) 74 75 16023683509 MEDIA_VERSION(2000), FUNC(xe_rtp_match_psmi_enabled) 75 76 MEDIA_VERSION(3000), MEDIA_STEP(A0, B0), FUNC(xe_rtp_match_psmi_enabled) 76 - 77 - # SoC workaround - currently applies to all platforms with the following 78 - # primary GT GMDID 79 - 14022085890 GRAPHICS_VERSION(2001) 80 77 81 78 15015404425_disable PLATFORM(PANTHERLAKE), MEDIA_STEP(B0, FOREVER) 82 79 16026007364 MEDIA_VERSION(3000)
+4
include/drm/drm_gpusvm.h
··· 235 235 * @read_only: operating on read-only memory 236 236 * @devmem_possible: possible to use device memory 237 237 * @devmem_only: use only device memory 238 + * @allow_mixed: Allow mixed mappings in get pages. Mixing between system and 239 + * single dpagemap is supported, mixing between multiple dpagemap 240 + * is unsupported. 238 241 * 239 242 * Context that is DRM GPUSVM is operating in (i.e. user arguments). 240 243 */ ··· 249 246 unsigned int read_only :1; 250 247 unsigned int devmem_possible :1; 251 248 unsigned int devmem_only :1; 249 + unsigned int allow_mixed :1; 252 250 }; 253 251 254 252 int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
+14 -2
include/drm/intel/pciids.h
··· 849 849 MACRO__(0x64B0, ## __VA_ARGS__) 850 850 851 851 /* BMG */ 852 - #define INTEL_BMG_IDS(MACRO__, ...) \ 852 + #define INTEL_BMG_G21_IDS(MACRO__, ...) \ 853 853 MACRO__(0xE202, ## __VA_ARGS__), \ 854 854 MACRO__(0xE209, ## __VA_ARGS__), \ 855 855 MACRO__(0xE20B, ## __VA_ARGS__), \ ··· 858 858 MACRO__(0xE210, ## __VA_ARGS__), \ 859 859 MACRO__(0xE211, ## __VA_ARGS__), \ 860 860 MACRO__(0xE212, ## __VA_ARGS__), \ 861 - MACRO__(0xE216, ## __VA_ARGS__), \ 861 + MACRO__(0xE216, ## __VA_ARGS__) 862 + 863 + #define INTEL_BMG_IDS(MACRO__, ...) \ 864 + INTEL_BMG_G21_IDS(MACRO__, __VA_ARGS__), \ 862 865 MACRO__(0xE220, ## __VA_ARGS__), \ 863 866 MACRO__(0xE221, ## __VA_ARGS__), \ 864 867 MACRO__(0xE222, ## __VA_ARGS__), \ ··· 883 880 MACRO__(0xB0B0, ## __VA_ARGS__), \ 884 881 MACRO__(0xFD80, ## __VA_ARGS__), \ 885 882 MACRO__(0xFD81, ## __VA_ARGS__) 883 + 884 + /* NVL-S */ 885 + #define INTEL_NVLS_IDS(MACRO__, ...) \ 886 + MACRO__(0xD740, ## __VA_ARGS__), \ 887 + MACRO__(0xD741, ## __VA_ARGS__), \ 888 + MACRO__(0xD742, ## __VA_ARGS__), \ 889 + MACRO__(0xD743, ## __VA_ARGS__), \ 890 + MACRO__(0xD744, ## __VA_ARGS__), \ 891 + MACRO__(0xD745, ## __VA_ARGS__) 886 892 887 893 #endif /* __PCIIDS_H__ */
+20 -1
include/uapi/drm/xe_drm.h
··· 771 771 * until the object is either bound to a virtual memory region via 772 772 * VM_BIND or accessed by the CPU. As a result, no backing memory is 773 773 * reserved at the time of GEM object creation. 774 - * - %DRM_XE_GEM_CREATE_FLAG_SCANOUT 774 + * - %DRM_XE_GEM_CREATE_FLAG_SCANOUT - Indicates that the GEM object is 775 + * intended for scanout via the display engine. When set, kernel ensures 776 + * that the allocation is placed in a memory region compatible with the 777 + * display engine requirements. This may impose restrictions on tiling, 778 + * alignment, and memory placement to guarantee proper display functionality. 775 779 * - %DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM - When using VRAM as a 776 780 * possible placement, ensure that the corresponding VRAM allocation 777 781 * will always use the CPU accessible part of VRAM. This is important ··· 1017 1013 * valid on VMs with DRM_XE_VM_CREATE_FLAG_FAULT_MODE set. The CPU address 1018 1014 * mirror flag are only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO 1019 1015 * handle MBZ, and the BO offset MBZ. 1016 + * - %DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET - Can be used in combination with 1017 + * %DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR to reset madvises when the underlying 1018 + * CPU address space range is unmapped (typically with munmap(2) or brk(2)). 1019 + * The madvise values set with &DRM_IOCTL_XE_MADVISE are reset to the values 1020 + * that were present immediately after the &DRM_IOCTL_XE_VM_BIND. 1021 + * The reset GPU virtual address range is the intersection of the range bound 1022 + * using &DRM_IOCTL_XE_VM_BIND and the virtual CPU address space range 1023 + * unmapped. 1024 + * This functionality is present to mimic the behaviour of CPU address space 1025 + * madvises set using madvise(2), which are typically reset on unmap. 1026 + * Note: free(3) may or may not call munmap(2) and/or brk(2), and may thus 1027 + * not invoke autoreset. Neither will stack variables going out of scope. 1028 + * Therefore it's recommended to always explicitly reset the madvises when 1029 + * freeing the memory backing a region used in a &DRM_IOCTL_XE_MADVISE call. 1020 1030 * 1021 1031 * The @prefetch_mem_region_instance for %DRM_XE_VM_BIND_OP_PREFETCH can also be: 1022 1032 * - %DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, which ensures prefetching occurs in ··· 1137 1119 #define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) 1138 1120 #define DRM_XE_VM_BIND_FLAG_CHECK_PXP (1 << 4) 1139 1121 #define DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR (1 << 5) 1122 + #define DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET (1 << 6) 1140 1123 /** @flags: Bind flags */ 1141 1124 __u32 flags; 1142 1125