UAPI Changes: - Remove unused KEEP_ACTIVE flag in the new multi queue uAPI (Niranjana) - Expose new temperature attributes in HWMON (Karthik) Driver Changes: - Force i2c into polling mode when in survivability (Raag) - Validate preferred system memory placement in xe_svm_range_validate (Brost) - Adjust page count tracepoints in shrinker (Brost) - Fix a couple drm_pagemap issues with multi-GPU (Brost) - Define GuC firmware for NVL-S (Roper) - Handle GT resume failure (Raag) - Improve wedged mode handling (Lukasz) - Add missing newlines to drm_warn messages (Osama) - Fix WQ_MEM_RECLAIM passed as max_active to alloc_workqueue (Marco) - Page-reclaim fixes and PRL stats addition (Brian) - Fix struct guc_lfd_file_header kernel-doc (Jani) - Allow compressible surfaces to be 1-way coherent (Xin) - Fix DRM scheduler layering violations in Xe (Brost) - Minor improvements to MERT code (Michal) - Privatize struct xe_ggtt_node (Maarten) - Convert wait for lmem init into an assert (Bala) - Enable GSC loading and PXP for PTL (Daniele) - Replace use of system_wq with tlb_inval->timeout_wq (Marco) - VRAM addr range bit expansion (Fei) - Cleanup unused header includes (Roper) Signed-off-by: Dave Airlie <airlied@redhat.com>
Unified · Split
| @@ -109,6 +109,22 @@ Description: RO. Package current voltage in millivolt. · 108 unmodified lines | ||
| 109 | 109 | |
| 110 | 110 | Only supported for particular Intel Xe graphics platforms. |
| 111 | 111 | |
| 112 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_crit | |
| 113 | +Date: January 2026 | |
| 114 | +KernelVersion: 7.0 | |
| 115 | +Contact: intel-xe@lists.freedesktop.org | |
| 116 | +Description: RO. Package critical temperature in millidegree Celsius. | |
| 117 | + | |
| 118 | + Only supported for particular Intel Xe graphics platforms. | |
| 119 | + | |
| 120 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_emergency | |
| 121 | +Date: January 2026 | |
| 122 | +KernelVersion: 7.0 | |
| 123 | +Contact: intel-xe@lists.freedesktop.org | |
| 124 | +Description: RO. Package shutdown temperature in millidegree Celsius. | |
| 125 | + | |
| 126 | + Only supported for particular Intel Xe graphics platforms. | |
| 127 | + | |
| 112 | 128 | What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_input |
| 113 | 129 | Date: March 2025 |
| 114 | 130 | KernelVersion: 6.15 |
| @@ -117,6 +133,30 @@ Description: RO. Package temperature in millidegree Celsius. · 2 unmodified lines | ||
| 117 | 133 | |
| 118 | 134 | Only supported for particular Intel Xe graphics platforms. |
| 119 | 135 | |
| 136 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp2_max | |
| 137 | +Date: January 2026 | |
| 138 | +KernelVersion: 7.0 | |
| 139 | +Contact: intel-xe@lists.freedesktop.org | |
| 140 | +Description: RO. Package maximum temperature limit in millidegree Celsius. | |
| 141 | + | |
| 142 | + Only supported for particular Intel Xe graphics platforms. | |
| 143 | + | |
| 144 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_crit | |
| 145 | +Date: January 2026 | |
| 146 | +KernelVersion: 7.0 | |
| 147 | +Contact: intel-xe@lists.freedesktop.org | |
| 148 | +Description: RO. VRAM critical temperature in millidegree Celsius. | |
| 149 | + | |
| 150 | + Only supported for particular Intel Xe graphics platforms. | |
| 151 | + | |
| 152 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_emergency | |
| 153 | +Date: January 2026 | |
| 154 | +KernelVersion: 7.0 | |
| 155 | +Contact: intel-xe@lists.freedesktop.org | |
| 156 | +Description: RO. VRAM shutdown temperature in millidegree Celsius. | |
| 157 | + | |
| 158 | + Only supported for particular Intel Xe graphics platforms. | |
| 159 | + | |
| 120 | 160 | What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp3_input |
| 121 | 161 | Date: March 2025 |
| 122 | 162 | KernelVersion: 6.15 |
| @@ -125,6 +165,76 @@ Description: RO. VRAM temperature in millidegree Celsius. · 2 unmodified lines | ||
| 125 | 165 | |
| 126 | 166 | Only supported for particular Intel Xe graphics platforms. |
| 127 | 167 | |
| 168 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp4_crit | |
| 169 | +Date: January 2026 | |
| 170 | +KernelVersion: 7.0 | |
| 171 | +Contact: intel-xe@lists.freedesktop.org | |
| 172 | +Description: RO. Memory controller critical temperature in millidegree Celsius. | |
| 173 | + | |
| 174 | + Only supported for particular Intel Xe graphics platforms. | |
| 175 | + | |
| 176 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp4_emergency | |
| 177 | +Date: January 2026 | |
| 178 | +KernelVersion: 7.0 | |
| 179 | +Contact: intel-xe@lists.freedesktop.org | |
| 180 | +Description: RO. Memory controller shutdown temperature in millidegree Celsius. | |
| 181 | + | |
| 182 | + Only supported for particular Intel Xe graphics platforms. | |
| 183 | + | |
| 184 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp4_input | |
| 185 | +Date: January 2026 | |
| 186 | +KernelVersion: 7.0 | |
| 187 | +Contact: intel-xe@lists.freedesktop.org | |
| 188 | +Description: RO. Memory controller average temperature in millidegree Celsius. | |
| 189 | + | |
| 190 | + Only supported for particular Intel Xe graphics platforms. | |
| 191 | + | |
| 192 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp5_crit | |
| 193 | +Date: January 2026 | |
| 194 | +KernelVersion: 7.0 | |
| 195 | +Contact: intel-xe@lists.freedesktop.org | |
| 196 | +Description: RO. GPU PCIe critical temperature in millidegree Celsius. | |
| 197 | + | |
| 198 | + Only supported for particular Intel Xe graphics platforms. | |
| 199 | + | |
| 200 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp5_emergency | |
| 201 | +Date: January 2026 | |
| 202 | +KernelVersion: 7.0 | |
| 203 | +Contact: intel-xe@lists.freedesktop.org | |
| 204 | +Description: RO. GPU PCIe shutdown temperature in millidegree Celsius. | |
| 205 | + | |
| 206 | + Only supported for particular Intel Xe graphics platforms. | |
| 207 | + | |
| 208 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp5_input | |
| 209 | +Date: January 2026 | |
| 210 | +KernelVersion: 7.0 | |
| 211 | +Contact: intel-xe@lists.freedesktop.org | |
| 212 | +Description: RO. GPU PCIe temperature in millidegree Celsius. | |
| 213 | + | |
| 214 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp[6-21]_crit | |
| 215 | +Date: January 2026 | |
| 216 | +KernelVersion: 7.0 | |
| 217 | +Contact: intel-xe@lists.freedesktop.org | |
| 218 | +Description: RO. VRAM channel critical temperature in millidegree Celsius. | |
| 219 | + | |
| 220 | + Only supported for particular Intel Xe graphics platforms. | |
| 221 | + | |
| 222 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp[6-21]_emergency | |
| 223 | +Date: January 2026 | |
| 224 | +KernelVersion: 7.0 | |
| 225 | +Contact: intel-xe@lists.freedesktop.org | |
| 226 | +Description: RO. VRAM channel shutdown temperature in millidegree Celsius. | |
| 227 | + | |
| 228 | + Only supported for particular Intel Xe graphics platforms. | |
| 229 | + | |
| 230 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/temp[6-21]_input | |
| 231 | +Date: January 2026 | |
| 232 | +KernelVersion: 7.0 | |
| 233 | +Contact: intel-xe@lists.freedesktop.org | |
| 234 | +Description: RO. VRAM channel temperature in millidegree Celsius. | |
| 235 | + | |
| 236 | + Only supported for particular Intel Xe graphics platforms. | |
| 237 | + | |
| 128 | 238 | What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan1_input |
| 129 | 239 | Date: March 2025 |
| 130 | 240 | KernelVersion: 6.16 |
| @@ -480,8 +480,18 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation, · 479 unmodified lines | ||
| 480 | 480 | .start = start, |
| 481 | 481 | .end = end, |
| 482 | 482 | .pgmap_owner = pagemap->owner, |
| 483 | − .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT | | |
| 484 | − MIGRATE_VMA_SELECT_DEVICE_PRIVATE, | |
| 483 | + /* | |
| 484 | + * FIXME: MIGRATE_VMA_SELECT_DEVICE_PRIVATE intermittently | |
| 485 | + * causes 'xe_exec_system_allocator --r *race*no*' to trigger aa | |
| 486 | + * engine reset and a hard hang due to getting stuck on a folio | |
| 487 | + * lock. This should work and needs to be root-caused. The only | |
| 488 | + * downside of not selecting MIGRATE_VMA_SELECT_DEVICE_PRIVATE | |
| 489 | + * is that device-to-device migrations won’t work; instead, | |
| 490 | + * memory will bounce through system memory. This path should be | |
| 491 | + * rare and only occur when the madvise attributes of memory are | |
| 492 | + * changed or atomics are being used. | |
| 493 | + */ | |
| 494 | + .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT, | |
| 485 | 495 | }; |
| 486 | 496 | unsigned long i, npages = npages_in_range(start, end); |
| 487 | 497 | unsigned long own_pages = 0, migrated_pages = 0; |
| @@ -582,7 +592,7 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation, · 94 unmodified lines | ||
| 582 | 592 | |
| 583 | 593 | err = ops->populate_devmem_pfn(devmem_allocation, npages, migrate.dst); |
| 584 | 594 | if (err) |
| 585 | − goto err_finalize; | |
| 595 | + goto err_aborted_migration; | |
| 586 | 596 | |
| 587 | 597 | own_pages = 0; |
| 588 | 598 | |
| @@ -621,8 +631,10 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation, · 32 unmodified lines | ||
| 621 | 631 | err = drm_pagemap_migrate_range(devmem_allocation, migrate.src, migrate.dst, |
| 622 | 632 | pages, pagemap_addr, &last, &cur, |
| 623 | 633 | mdetails); |
| 624 | − if (err) | |
| 634 | + if (err) { | |
| 635 | + npages = i + 1; | |
| 625 | 636 | goto err_finalize; |
| 637 | + } | |
| 626 | 638 | } |
| 627 | 639 | cur.start = npages; |
| 628 | 640 | cur.ops = NULL; /* Force migration */ |
| @@ -646,7 +658,7 @@ err_finalize: · 17 unmodified lines | ||
| 646 | 658 | err_aborted_migration: |
| 647 | 659 | migrate_vma_pages(&migrate); |
| 648 | 660 | |
| 649 | − for (i = 0; i < npages;) { | |
| 661 | + for (i = 0; !err && i < npages;) { | |
| 650 | 662 | struct page *page = migrate_pfn_to_page(migrate.src[i]); |
| 651 | 663 | unsigned long nr_pages = page ? NR_PAGES(folio_order(page_folio(page))) : 1; |
| 652 | 664 | |
| @@ -370,7 +370,8 @@ always-$(CONFIG_DRM_XE_WERROR) += \ · 369 unmodified lines | ||
| 370 | 370 | $(patsubst %.h,%.hdrtest, $(shell cd $(src) && find * -name '*.h' $(hdrtest_find_args))) |
| 371 | 371 | |
| 372 | 372 | quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) |
| 373 | − cmd_hdrtest = $(CC) -DHDRTEST $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@ | |
| 373 | + cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $< -include $<; \ | |
| 374 | + $(srctree)/scripts/kernel-doc -none -Werror $<; touch $@ | |
| 374 | 375 | |
| 375 | 376 | $(obj)/%.hdrtest: $(src)/%.h FORCE |
| 376 | 377 | $(call if_changed_dep,hdrtest) |
| @@ -148,7 +148,7 @@ struct guc_lfd_data_os_info { · 147 unmodified lines | ||
| 148 | 148 | } __packed; |
| 149 | 149 | |
| 150 | 150 | /** |
| 151 | − * struct guc_logfile_header - Header of GuC Log Streaming-LFD-File Format. | |
| 151 | + * struct guc_lfd_file_header - Header of GuC Log Streaming-LFD-File Format. | |
| 152 | 152 | * This structure encapsulates the layout of the guc-log-file format |
| 153 | 153 | */ |
| 154 | 154 | struct guc_lfd_file_header { |
| @@ -163,8 +163,7 @@ struct guc_lfd_file_header { · 8 unmodified lines | ||
| 163 | 163 | #define GUC_LFD_FILE_HEADER_VERSION_MASK_MAJOR GENMASK(31, 16) |
| 164 | 164 | #define GUC_LFD_FILE_HEADER_VERSION_MASK_MINOR GENMASK(15, 0) |
| 165 | 165 | |
| 166 | − /** @stream: A stream of one or more guc_lfd_data LFD blocks | |
| 167 | − */ | |
| 166 | + /** @stream: A stream of one or more guc_lfd_data LFD blocks */ | |
| 168 | 167 | u32 stream[]; |
| 169 | 168 | } __packed; |
| 170 | 169 | |
| @@ -8,7 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #include <uapi/drm/i915_drm.h> |
| 10 | 10 | |
| 11 | −#include "xe_ggtt_types.h" | |
| 11 | +#include "xe_ggtt.h" | |
| 12 | 12 | |
| 13 | 13 | #include <linux/refcount.h> |
| 14 | 14 | |
| @@ -30,7 +30,7 @@ struct i915_vma { · 15 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | static inline u32 i915_ggtt_offset(const struct i915_vma *vma) |
| 32 | 32 | { |
| 33 | − return vma->node->base.start; | |
| 33 | + return xe_ggtt_node_addr(vma->node); | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | #endif |
| @@ -171,12 +171,13 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, · 170 unmodified lines | ||
| 171 | 171 | } |
| 172 | 172 | |
| 173 | 173 | static void |
| 174 | −write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo_ofs, | |
| 174 | +write_ggtt_rotated(struct xe_ggtt *ggtt, u32 *ggtt_ofs, | |
| 175 | + u64 pte_flags, | |
| 176 | + xe_ggtt_set_pte_fn write_pte, | |
| 177 | + struct xe_bo *bo, u32 bo_ofs, | |
| 175 | 178 | u32 width, u32 height, u32 src_stride, u32 dst_stride) |
| 176 | 179 | { |
| 177 | − struct xe_device *xe = xe_bo_device(bo); | |
| 178 | 180 | u32 column, row; |
| 179 | − u64 pte = ggtt->pt_ops->pte_encode_flags(bo, xe->pat.idx[XE_CACHE_NONE]); | |
| 180 | 181 | |
| 181 | 182 | for (column = 0; column < width; column++) { |
| 182 | 183 | u32 src_idx = src_stride * (height - 1) + column + bo_ofs; |
| @@ -184,7 +185,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo · 1 unmodified line | ||
| 184 | 185 | for (row = 0; row < height; row++) { |
| 185 | 186 | u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, XE_PAGE_SIZE); |
| 186 | 187 | |
| 187 | − ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte | addr); | |
| 188 | + write_pte(ggtt, *ggtt_ofs, pte_flags | addr); | |
| 188 | 189 | *ggtt_ofs += XE_PAGE_SIZE; |
| 189 | 190 | src_idx -= src_stride; |
| 190 | 191 | } |
| @@ -194,6 +195,28 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo · 3 unmodified lines | ||
| 194 | 195 | } |
| 195 | 196 | } |
| 196 | 197 | |
| 198 | +struct fb_rotate_args { | |
| 199 | + const struct i915_gtt_view *view; | |
| 200 | + struct xe_bo *bo; | |
| 201 | +}; | |
| 202 | + | |
| 203 | +static void write_ggtt_rotated_node(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, | |
| 204 | + u64 pte_flags, xe_ggtt_set_pte_fn write_pte, void *data) | |
| 205 | +{ | |
| 206 | + struct fb_rotate_args *args = data; | |
| 207 | + struct xe_bo *bo = args->bo; | |
| 208 | + const struct intel_rotation_info *rot_info = &args->view->rotated; | |
| 209 | + u32 ggtt_ofs = xe_ggtt_node_addr(node); | |
| 210 | + | |
| 211 | + for (u32 i = 0; i < ARRAY_SIZE(rot_info->plane); i++) | |
| 212 | + write_ggtt_rotated(ggtt, &ggtt_ofs, pte_flags, write_pte, | |
| 213 | + bo, rot_info->plane[i].offset, | |
| 214 | + rot_info->plane[i].width, | |
| 215 | + rot_info->plane[i].height, | |
| 216 | + rot_info->plane[i].src_stride, | |
| 217 | + rot_info->plane[i].dst_stride); | |
| 218 | +} | |
| 219 | + | |
| 197 | 220 | static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, |
| 198 | 221 | const struct i915_gtt_view *view, |
| 199 | 222 | struct i915_vma *vma, |
| @@ -204,66 +227,43 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, · 4 unmodified lines | ||
| 204 | 227 | struct xe_device *xe = to_xe_device(fb->base.dev); |
| 205 | 228 | struct xe_tile *tile0 = xe_device_get_root_tile(xe); |
| 206 | 229 | struct xe_ggtt *ggtt = tile0->mem.ggtt; |
| 230 | + u64 pte, size; | |
| 207 | 231 | u32 align; |
| 208 | − int ret; | |
| 232 | + int ret = 0; | |
| 209 | 233 | |
| 210 | 234 | /* TODO: Consider sharing framebuffer mapping? |
| 211 | 235 | * embed i915_vma inside intel_framebuffer |
| 212 | 236 | */ |
| 213 | 237 | guard(xe_pm_runtime_noresume)(xe); |
| 214 | − ACQUIRE(mutex_intr, lock)(&ggtt->lock); | |
| 215 | − ret = ACQUIRE_ERR(mutex_intr, &lock); | |
| 216 | − if (ret) | |
| 217 | − return ret; | |
| 218 | 238 | |
| 219 | 239 | align = XE_PAGE_SIZE; |
| 220 | − if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) | |
| 221 | − align = max_t(u32, align, SZ_64K); | |
| 240 | + if (xe_bo_is_vram(bo) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) | |
| 241 | + align = max(align, SZ_64K); | |
| 222 | 242 | |
| 243 | + /* Fast case, preallocated GGTT view? */ | |
| 223 | 244 | if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) { |
| 224 | 245 | vma->node = bo->ggtt_node[tile0->id]; |
| 225 | − } else if (view->type == I915_GTT_VIEW_NORMAL) { | |
| 226 | − vma->node = xe_ggtt_node_init(ggtt); | |
| 227 | − if (IS_ERR(vma->node)) | |
| 228 | − return PTR_ERR(vma->node); | |
| 229 | − | |
| 230 | − ret = xe_ggtt_node_insert_locked(vma->node, xe_bo_size(bo), align, 0); | |
| 231 | − if (ret) { | |
| 232 | − xe_ggtt_node_fini(vma->node); | |
| 233 | − return ret; | |
| 234 | − } | |
| 235 | − | |
| 236 | − xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]); | |
| 237 | − } else { | |
| 238 | − u32 i, ggtt_ofs; | |
| 239 | − const struct intel_rotation_info *rot_info = &view->rotated; | |
| 240 | − | |
| 241 | − /* display seems to use tiles instead of bytes here, so convert it back.. */ | |
| 242 | − u32 size = intel_rotation_info_size(rot_info) * XE_PAGE_SIZE; | |
| 243 | − | |
| 244 | − vma->node = xe_ggtt_node_init(ggtt); | |
| 245 | − if (IS_ERR(vma->node)) { | |
| 246 | − ret = PTR_ERR(vma->node); | |
| 247 | − return ret; | |
| 248 | − } | |
| 249 | − | |
| 250 | − ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0); | |
| 251 | − if (ret) { | |
| 252 | − xe_ggtt_node_fini(vma->node); | |
| 253 | − return ret; | |
| 254 | − } | |
| 255 | − | |
| 256 | − ggtt_ofs = vma->node->base.start; | |
| 257 | − | |
| 258 | − for (i = 0; i < ARRAY_SIZE(rot_info->plane); i++) | |
| 259 | − write_ggtt_rotated(bo, ggtt, &ggtt_ofs, | |
| 260 | − rot_info->plane[i].offset, | |
| 261 | − rot_info->plane[i].width, | |
| 262 | − rot_info->plane[i].height, | |
| 263 | − rot_info->plane[i].src_stride, | |
| 264 | − rot_info->plane[i].dst_stride); | |
| 246 | + return 0; | |
| 265 | 247 | } |
| 266 | 248 | |
| 249 | + /* TODO: Consider sharing framebuffer mapping? | |
| 250 | + * embed i915_vma inside intel_framebuffer | |
| 251 | + */ | |
| 252 | + if (view->type == I915_GTT_VIEW_NORMAL) | |
| 253 | + size = xe_bo_size(bo); | |
| 254 | + else | |
| 255 | + /* display uses tiles instead of bytes here, so convert it back.. */ | |
| 256 | + size = intel_rotation_info_size(&view->rotated) * XE_PAGE_SIZE; | |
| 257 | + | |
| 258 | + pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); | |
| 259 | + vma->node = xe_ggtt_node_insert_transform(ggtt, bo, pte, | |
| 260 | + ALIGN(size, align), align, | |
| 261 | + view->type == I915_GTT_VIEW_NORMAL ? | |
| 262 | + NULL : write_ggtt_rotated_node, | |
| 263 | + &(struct fb_rotate_args){view, bo}); | |
| 264 | + if (IS_ERR(vma->node)) | |
| 265 | + ret = PTR_ERR(vma->node); | |
| 266 | + | |
| 267 | 267 | return ret; |
| 268 | 268 | } |
| 269 | 269 | |
| @@ -353,7 +353,7 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) · 83 unmodified lines | ||
| 353 | 353 | if (vma->dpt) |
| 354 | 354 | xe_bo_unpin_map_no_vm(vma->dpt); |
| 355 | 355 | else if (!xe_ggtt_node_allocated(vma->bo->ggtt_node[tile_id]) || |
| 356 | − vma->bo->ggtt_node[tile_id]->base.start != vma->node->base.start) | |
| 356 | + vma->bo->ggtt_node[tile_id] != vma->node) | |
| 357 | 357 | xe_ggtt_node_remove(vma->node, false); |
| 358 | 358 | |
| 359 | 359 | ttm_bo_reserve(&vma->bo->ttm, false, false, NULL); |
| @@ -39,7 +39,7 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm) · 38 unmodified lines | ||
| 39 | 39 | struct xe_gt *gt = tile->media_gt; |
| 40 | 40 | struct xe_gsc *gsc = >->uc.gsc; |
| 41 | 41 | |
| 42 | − if (!gsc || !xe_uc_fw_is_enabled(&gsc->fw)) { | |
| 42 | + if (!gsc || !xe_uc_fw_is_available(&gsc->fw)) { | |
| 43 | 43 | drm_dbg_kms(&xe->drm, |
| 44 | 44 | "GSC Components not ready for HDCP2.x\n"); |
| 45 | 45 | return false; |
| @@ -78,7 +78,7 @@ static u64 xe_stolen_node_address(const struct intel_stolen_node *node) · 77 unmodified lines | ||
| 78 | 78 | |
| 79 | 79 | static u64 xe_stolen_node_size(const struct intel_stolen_node *node) |
| 80 | 80 | { |
| 81 | − return node->bo->ttm.base.size; | |
| 81 | + return xe_bo_size(node->bo); | |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | static struct intel_stolen_node *xe_stolen_node_alloc(struct drm_device *drm) |
| @@ -89,6 +89,7 @@ · 88 unmodified lines | ||
| 89 | 89 | #define UNIFIED_COMPRESSION_FORMAT REG_GENMASK(3, 0) |
| 90 | 90 | |
| 91 | 91 | #define XE2_GAMREQSTRM_CTRL XE_REG_MCR(0x4194) |
| 92 | +#define EN_CMP_1WCOH REG_BIT(15) | |
| 92 | 93 | #define CG_DIS_CNTLBUS REG_BIT(6) |
| 93 | 94 | |
| 94 | 95 | #define CCS_AUX_INV XE_REG(0x4208) |
| @@ -101,6 +102,11 @@ · 6 unmodified lines | ||
| 101 | 102 | |
| 102 | 103 | #define XE2_LMEM_CFG XE_REG(0x48b0) |
| 103 | 104 | |
| 105 | +#define XE2_GAMWALK_CTRL 0x47e4 | |
| 106 | +#define XE2_GAMWALK_CTRL_MEDIA XE_REG(XE2_GAMWALK_CTRL + MEDIA_GT_GSI_OFFSET) | |
| 107 | +#define XE2_GAMWALK_CTRL_3D XE_REG_MCR(XE2_GAMWALK_CTRL) | |
| 108 | +#define EN_CMP_1WCOH_GW REG_BIT(14) | |
| 109 | + | |
| 104 | 110 | #define XEHP_FLAT_CCS_BASE_ADDR XE_REG_MCR(0x4910) |
| 105 | 111 | #define XEHP_FLAT_CCS_PTR REG_GENMASK(31, 8) |
| 106 | 112 | |
| @@ -11,11 +11,13 @@ · 10 unmodified lines | ||
| 11 | 11 | #define MERT_LMEM_CFG XE_REG(0x1448b0) |
| 12 | 12 | |
| 13 | 13 | #define MERT_TLB_CT_INTR_ERR_ID_PORT XE_REG(0x145190) |
| 14 | −#define MERT_TLB_CT_VFID_MASK REG_GENMASK(16, 9) | |
| 15 | −#define MERT_TLB_CT_ERROR_MASK REG_GENMASK(5, 0) | |
| 16 | −#define MERT_TLB_CT_LMTT_FAULT 0x05 | |
| 14 | +#define CATERR_VFID REG_GENMASK(16, 9) | |
| 15 | +#define CATERR_CODES REG_GENMASK(5, 0) | |
| 16 | +#define CATERR_NO_ERROR 0x00 | |
| 17 | +#define CATERR_UNMAPPED_GGTT 0x01 | |
| 18 | +#define CATERR_LMTT_FAULT 0x05 | |
| 17 | 19 | |
| 18 | 20 | #define MERT_TLB_INV_DESC_A XE_REG(0x14cf7c) |
| 19 | 21 | #define MERT_TLB_INV_DESC_A_VALID REG_BIT(0) |
| 20 | 22 | |
| 21 | −#endif /* _XE_MERT_REGS_H_ */ | |
| 23 | +#endif | |
| @@ -21,7 +21,10 @@ · 20 unmodified lines | ||
| 21 | 21 | #define BMG_FAN_1_SPEED XE_REG(0x138140) |
| 22 | 22 | #define BMG_FAN_2_SPEED XE_REG(0x138170) |
| 23 | 23 | #define BMG_FAN_3_SPEED XE_REG(0x1381a0) |
| 24 | +#define BMG_VRAM_TEMPERATURE_N(n) XE_REG(0x138260 + ((n) * (sizeof(u32)))) | |
| 24 | 25 | #define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0) |
| 26 | +#define TEMP_MASK_VRAM_N REG_GENMASK(30, 8) | |
| 27 | +#define TEMP_SIGN_MASK REG_BIT(31) | |
| 25 | 28 | #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) |
| 26 | 29 | |
| 27 | 30 | #endif /* _XE_PCODE_REGS_H_ */ |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "tests/xe_test.h" |
| 19 | 19 | |
| 20 | 20 | #include "xe_bo_evict.h" |
| 21 | +#include "xe_gt.h" | |
| 21 | 22 | #include "xe_pci.h" |
| 22 | 23 | #include "xe_pm.h" |
| 23 | 24 | |
| @@ -67,7 +67,7 @@ static int guc_buf_test_init(struct kunit *test) · 66 unmodified lines | ||
| 67 | 67 | |
| 68 | 68 | KUNIT_ASSERT_EQ(test, 0, |
| 69 | 69 | xe_ggtt_init_kunit(ggtt, DUT_GGTT_START, |
| 70 | − DUT_GGTT_START + DUT_GGTT_SIZE)); | |
| 70 | + DUT_GGTT_SIZE)); | |
| 71 | 71 | |
| 72 | 72 | kunit_activate_static_stub(test, xe_managed_bo_create_pin_map, |
| 73 | 73 | replacement_xe_managed_bo_create_pin_map); |
| @@ -7,10 +7,9 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include "instructions/xe_mi_commands.h" |
| 9 | 9 | #include "xe_assert.h" |
| 10 | −#include "xe_device.h" | |
| 10 | +#include "xe_device_types.h" | |
| 11 | 11 | #include "xe_exec_queue_types.h" |
| 12 | 12 | #include "xe_gt.h" |
| 13 | −#include "xe_hw_fence.h" | |
| 14 | 13 | #include "xe_sa.h" |
| 15 | 14 | #include "xe_sched_job.h" |
| 16 | 15 | #include "xe_vm_types.h" |
| @@ -26,9 +26,9 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "xe_dma_buf.h" |
| 27 | 27 | #include "xe_drm_client.h" |
| 28 | 28 | #include "xe_ggtt.h" |
| 29 | −#include "xe_gt.h" | |
| 30 | 29 | #include "xe_map.h" |
| 31 | 30 | #include "xe_migrate.h" |
| 31 | +#include "xe_pat.h" | |
| 32 | 32 | #include "xe_pm.h" |
| 33 | 33 | #include "xe_preempt_fence.h" |
| 34 | 34 | #include "xe_pxp.h" |
| @@ -1054,6 +1054,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, · 1019 unmodified lines | ||
| 1054 | 1054 | unsigned long *scanned) |
| 1055 | 1055 | { |
| 1056 | 1056 | struct xe_device *xe = ttm_to_xe_device(bo->bdev); |
| 1057 | + struct ttm_tt *tt = bo->ttm; | |
| 1057 | 1058 | long lret; |
| 1058 | 1059 | |
| 1059 | 1060 | /* Fake move to system, without copying data. */ |
| @@ -1078,8 +1079,10 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx, · 18 unmodified lines | ||
| 1078 | 1079 | .writeback = false, |
| 1079 | 1080 | .allow_move = false}); |
| 1080 | 1081 | |
| 1081 | − if (lret > 0) | |
| 1082 | + if (lret > 0) { | |
| 1082 | 1083 | xe_ttm_tt_account_subtract(xe, bo->ttm); |
| 1084 | + update_global_total_pages(bo->bdev, -(long)tt->num_pages); | |
| 1085 | + } | |
| 1083 | 1086 | |
| 1084 | 1087 | return lret; |
| 1085 | 1088 | } |
| @@ -1165,8 +1168,10 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, · 79 unmodified lines | ||
| 1165 | 1168 | if (needs_rpm) |
| 1166 | 1169 | xe_pm_runtime_put(xe); |
| 1167 | 1170 | |
| 1168 | − if (lret > 0) | |
| 1171 | + if (lret > 0) { | |
| 1169 | 1172 | xe_ttm_tt_account_subtract(xe, tt); |
| 1173 | + update_global_total_pages(bo->bdev, -(long)tt->num_pages); | |
| 1174 | + } | |
| 1170 | 1175 | |
| 1171 | 1176 | out_unref: |
| 1172 | 1177 | xe_bo_put(xe_bo); |
| @@ -1709,7 +1714,7 @@ static void xe_ttm_bo_destroy(struct ttm_buffer_object *ttm_bo) · 536 unmodified lines | ||
| 1709 | 1714 | xe_assert(xe, list_empty(&ttm_bo->base.gpuva.list)); |
| 1710 | 1715 | |
| 1711 | 1716 | for_each_tile(tile, xe, id) |
| 1712 | − if (bo->ggtt_node[id] && bo->ggtt_node[id]->base.size) | |
| 1717 | + if (bo->ggtt_node[id]) | |
| 1713 | 1718 | xe_ggtt_remove_bo(tile->mem.ggtt, bo); |
| 1714 | 1719 | |
| 1715 | 1720 | #ifdef CONFIG_PROC_FS |
| @@ -3517,16 +3522,16 @@ bool xe_bo_needs_ccs_pages(struct xe_bo *bo) · 1801 unmodified lines | ||
| 3517 | 3522 | if (IS_DGFX(xe) && (bo->flags & XE_BO_FLAG_SYSTEM)) |
| 3518 | 3523 | return false; |
| 3519 | 3524 | |
| 3525 | + /* Check if userspace explicitly requested no compression */ | |
| 3526 | + if (bo->flags & XE_BO_FLAG_NO_COMPRESSION) | |
| 3527 | + return false; | |
| 3528 | + | |
| 3520 | 3529 | /* |
| 3521 | − * Compression implies coh_none, therefore we know for sure that WB | |
| 3522 | − * memory can't currently use compression, which is likely one of the | |
| 3523 | − * common cases. | |
| 3524 | − * Additionally, userspace may explicitly request no compression via the | |
| 3525 | − * DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION flag, which should also disable | |
| 3526 | − * CCS usage. | |
| 3530 | + * For WB (Write-Back) CPU caching mode, check if the device | |
| 3531 | + * supports WB compression with coherency. | |
| 3527 | 3532 | */ |
| 3528 | − if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB || | |
| 3529 | − bo->flags & XE_BO_FLAG_NO_COMPRESSION) | |
| 3533 | + if (bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB && | |
| 3534 | + xe->pat.idx[XE_CACHE_WB_COMPRESSION] == XE_PAT_INVALID_IDX) | |
| 3530 | 3535 | return false; |
| 3531 | 3536 | |
| 3532 | 3537 | return true; |
| @@ -3603,8 +3608,8 @@ void xe_bo_put(struct xe_bo *bo) · 70 unmodified lines | ||
| 3603 | 3608 | might_lock(&bo->client->bos_lock); |
| 3604 | 3609 | #endif |
| 3605 | 3610 | for_each_tile(tile, xe_bo_device(bo), id) |
| 3606 | − if (bo->ggtt_node[id] && bo->ggtt_node[id]->ggtt) | |
| 3607 | − xe_ggtt_might_lock(bo->ggtt_node[id]->ggtt); | |
| 3611 | + if (bo->ggtt_node[id]) | |
| 3612 | + xe_ggtt_might_lock(tile->mem.ggtt); | |
| 3608 | 3613 | drm_gem_object_put(&bo->ttm.base); |
| 3609 | 3614 | } |
| 3610 | 3615 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <drm/ttm/ttm_tt.h> |
| 10 | 10 | |
| 11 | 11 | #include "xe_bo_types.h" |
| 12 | +#include "xe_ggtt.h" | |
| 12 | 13 | #include "xe_macros.h" |
| 13 | 14 | #include "xe_validation.h" |
| 14 | 15 | #include "xe_vm_types.h" |
| @@ -252,13 +253,14 @@ static inline u32 · 237 unmodified lines | ||
| 252 | 253 | __xe_bo_ggtt_addr(struct xe_bo *bo, u8 tile_id) |
| 253 | 254 | { |
| 254 | 255 | struct xe_ggtt_node *ggtt_node = bo->ggtt_node[tile_id]; |
| 256 | + u64 offset; | |
| 255 | 257 | |
| 256 | 258 | if (XE_WARN_ON(!ggtt_node)) |
| 257 | 259 | return 0; |
| 258 | 260 | |
| 259 | − XE_WARN_ON(ggtt_node->base.size > xe_bo_size(bo)); | |
| 260 | − XE_WARN_ON(ggtt_node->base.start + ggtt_node->base.size > (1ull << 32)); | |
| 261 | − return ggtt_node->base.start; | |
| 261 | + offset = xe_ggtt_node_addr(ggtt_node); | |
| 262 | + XE_WARN_ON(offset + xe_bo_size(bo) > (1ull << 32)); | |
| 263 | + return offset; | |
| 262 | 264 | } |
| 263 | 265 | |
| 264 | 266 | static inline u32 |
| @@ -254,36 +254,81 @@ static ssize_t wedged_mode_show(struct file *f, char __user *ubuf, · 253 unmodified lines | ||
| 254 | 254 | return simple_read_from_buffer(ubuf, size, pos, buf, len); |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | +static int __wedged_mode_set_reset_policy(struct xe_gt *gt, enum xe_wedged_mode mode) | |
| 258 | +{ | |
| 259 | + bool enable_engine_reset; | |
| 260 | + int ret; | |
| 261 | + | |
| 262 | + enable_engine_reset = (mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET); | |
| 263 | + ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads, | |
| 264 | + enable_engine_reset); | |
| 265 | + if (ret) | |
| 266 | + xe_gt_err(gt, "Failed to update GuC ADS scheduler policy (%pe)\n", ERR_PTR(ret)); | |
| 267 | + | |
| 268 | + return ret; | |
| 269 | +} | |
| 270 | + | |
| 271 | +static int wedged_mode_set_reset_policy(struct xe_device *xe, enum xe_wedged_mode mode) | |
| 272 | +{ | |
| 273 | + struct xe_gt *gt; | |
| 274 | + int ret; | |
| 275 | + u8 id; | |
| 276 | + | |
| 277 | + guard(xe_pm_runtime)(xe); | |
| 278 | + for_each_gt(gt, xe, id) { | |
| 279 | + ret = __wedged_mode_set_reset_policy(gt, mode); | |
| 280 | + if (ret) { | |
| 281 | + if (id > 0) { | |
| 282 | + xe->wedged.inconsistent_reset = true; | |
| 283 | + drm_err(&xe->drm, "Inconsistent reset policy state between GTs\n"); | |
| 284 | + } | |
| 285 | + return ret; | |
| 286 | + } | |
| 287 | + } | |
| 288 | + | |
| 289 | + xe->wedged.inconsistent_reset = false; | |
| 290 | + | |
| 291 | + return 0; | |
| 292 | +} | |
| 293 | + | |
| 294 | +static bool wedged_mode_needs_policy_update(struct xe_device *xe, enum xe_wedged_mode mode) | |
| 295 | +{ | |
| 296 | + if (xe->wedged.inconsistent_reset) | |
| 297 | + return true; | |
| 298 | + | |
| 299 | + if (xe->wedged.mode == mode) | |
| 300 | + return false; | |
| 301 | + | |
| 302 | + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET || | |
| 303 | + mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) | |
| 304 | + return true; | |
| 305 | + | |
| 306 | + return false; | |
| 307 | +} | |
| 308 | + | |
| 257 | 309 | static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, |
| 258 | 310 | size_t size, loff_t *pos) |
| 259 | 311 | { |
| 260 | 312 | struct xe_device *xe = file_inode(f)->i_private; |
| 261 | − struct xe_gt *gt; | |
| 262 | 313 | u32 wedged_mode; |
| 263 | 314 | ssize_t ret; |
| 264 | − u8 id; | |
| 265 | 315 | |
| 266 | 316 | ret = kstrtouint_from_user(ubuf, size, 0, &wedged_mode); |
| 267 | 317 | if (ret) |
| 268 | 318 | return ret; |
| 269 | 319 | |
| 270 | − if (wedged_mode > 2) | |
| 271 | − return -EINVAL; | |
| 320 | + ret = xe_device_validate_wedged_mode(xe, wedged_mode); | |
| 321 | + if (ret) | |
| 322 | + return ret; | |
| 272 | 323 | |
| 273 | − if (xe->wedged.mode == wedged_mode) | |
| 274 | − return size; | |
| 324 | + if (wedged_mode_needs_policy_update(xe, wedged_mode)) { | |
| 325 | + ret = wedged_mode_set_reset_policy(xe, wedged_mode); | |
| 326 | + if (ret) | |
| 327 | + return ret; | |
| 328 | + } | |
| 275 | 329 | |
| 276 | 330 | xe->wedged.mode = wedged_mode; |
| 277 | 331 | |
| 278 | − guard(xe_pm_runtime)(xe); | |
| 279 | − for_each_gt(gt, xe, id) { | |
| 280 | − ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads); | |
| 281 | − if (ret) { | |
| 282 | − xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); | |
| 283 | − return -EIO; | |
| 284 | − } | |
| 285 | − } | |
| 286 | − | |
| 287 | 332 | return size; |
| 288 | 333 | } |
| 289 | 334 | |
| @@ -15,14 +15,13 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "xe_device.h" |
| 16 | 16 | #include "xe_exec_queue.h" |
| 17 | 17 | #include "xe_force_wake.h" |
| 18 | −#include "xe_gt.h" | |
| 19 | 18 | #include "xe_gt_printk.h" |
| 19 | +#include "xe_gt_types.h" | |
| 20 | 20 | #include "xe_guc_capture.h" |
| 21 | 21 | #include "xe_guc_ct.h" |
| 22 | 22 | #include "xe_guc_log.h" |
| 23 | 23 | #include "xe_guc_submit.h" |
| 24 | 24 | #include "xe_hw_engine.h" |
| 25 | −#include "xe_module.h" | |
| 26 | 25 | #include "xe_pm.h" |
| 27 | 26 | #include "xe_sched_job.h" |
| 28 | 27 | #include "xe_vm.h" |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/aperture.h> |
| 9 | 9 | #include <linux/delay.h> |
| 10 | 10 | #include <linux/fault-inject.h> |
| 11 | −#include <linux/iopoll.h> | |
| 12 | 11 | #include <linux/units.h> |
| 13 | 12 | |
| 14 | 13 | #include <drm/drm_atomic_helper.h> |
| @@ -36,7 +35,6 @@ · 21 unmodified lines | ||
| 36 | 35 | #include "xe_exec_queue.h" |
| 37 | 36 | #include "xe_force_wake.h" |
| 38 | 37 | #include "xe_ggtt.h" |
| 39 | −#include "xe_gsc_proxy.h" | |
| 40 | 38 | #include "xe_gt.h" |
| 41 | 39 | #include "xe_gt_mcr.h" |
| 42 | 40 | #include "xe_gt_printk.h" |
| @@ -180,12 +178,7 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) · 137 unmodified lines | ||
| 180 | 178 | xa_for_each(&xef->exec_queue.xa, idx, q) { |
| 181 | 179 | if (q->vm && q->hwe->hw_engine_group) |
| 182 | 180 | xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); |
| 183 | − | |
| 184 | − if (xe_exec_queue_is_multi_queue_primary(q)) | |
| 185 | − xe_exec_queue_group_kill_put(q->multi_queue.group); | |
| 186 | − else | |
| 187 | − xe_exec_queue_kill(q); | |
| 188 | − | |
| 181 | + xe_exec_queue_kill(q); | |
| 189 | 182 | xe_exec_queue_put(q); |
| 190 | 183 | } |
| 191 | 184 | xa_for_each(&xef->vm.xa, idx, vm) |
| @@ -659,62 +652,14 @@ mask_err: · 467 unmodified lines | ||
| 659 | 652 | return err; |
| 660 | 653 | } |
| 661 | 654 | |
| 662 | −static int lmem_initializing(struct xe_device *xe) | |
| 655 | +static void assert_lmem_ready(struct xe_device *xe) | |
| 663 | 656 | { |
| 664 | − if (xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & LMEM_INIT) | |
| 665 | − return 0; | |
| 666 | − | |
| 667 | − if (signal_pending(current)) | |
| 668 | − return -EINTR; | |
| 669 | − | |
| 670 | − return 1; | |
| 671 | −} | |
| 672 | − | |
| 673 | −static int wait_for_lmem_ready(struct xe_device *xe) | |
| 674 | −{ | |
| 675 | − const unsigned long TIMEOUT_SEC = 60; | |
| 676 | − unsigned long prev_jiffies; | |
| 677 | − int initializing; | |
| 678 | − | |
| 679 | − if (!IS_DGFX(xe)) | |
| 680 | − return 0; | |
| 681 | − | |
| 682 | − if (IS_SRIOV_VF(xe)) | |
| 683 | − return 0; | |
| 684 | − | |
| 685 | − if (!lmem_initializing(xe)) | |
| 686 | − return 0; | |
| 687 | − | |
| 688 | − drm_dbg(&xe->drm, "Waiting for lmem initialization\n"); | |
| 689 | − prev_jiffies = jiffies; | |
| 690 | − | |
| 691 | − /* | |
| 692 | − * The boot firmware initializes local memory and | |
| 693 | − * assesses its health. If memory training fails, | |
| 694 | − * the punit will have been instructed to keep the GT powered | |
| 695 | − * down.we won't be able to communicate with it | |
| 696 | − * | |
| 697 | − * If the status check is done before punit updates the register, | |
| 698 | − * it can lead to the system being unusable. | |
| 699 | − * use a timeout and defer the probe to prevent this. | |
| 700 | − */ | |
| 701 | − poll_timeout_us(initializing = lmem_initializing(xe), | |
| 702 | − initializing <= 0, | |
| 703 | − 20 * USEC_PER_MSEC, TIMEOUT_SEC * USEC_PER_SEC, true); | |
| 704 | − if (initializing < 0) | |
| 705 | − return initializing; | |
| 706 | − | |
| 707 | − if (initializing) { | |
| 708 | − drm_dbg(&xe->drm, "lmem not initialized by firmware\n"); | |
| 709 | − return -EPROBE_DEFER; | |
| 710 | − } | |
| 711 | − | |
| 712 | − drm_dbg(&xe->drm, "lmem ready after %ums", | |
| 713 | − jiffies_to_msecs(jiffies - prev_jiffies)); | |
| 657 | + if (!IS_DGFX(xe) || IS_SRIOV_VF(xe)) | |
| 658 | + return; | |
| 714 | 659 | |
| 715 | − return 0; | |
| 660 | + xe_assert(xe, xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & | |
| 661 | + LMEM_INIT); | |
| 716 | 662 | } |
| 717 | −ALLOW_ERROR_INJECTION(wait_for_lmem_ready, ERRNO); /* See xe_pci_probe() */ | |
| 718 | 663 | |
| 719 | 664 | static void vf_update_device_info(struct xe_device *xe) |
| 720 | 665 | { |
| @@ -769,6 +714,11 @@ int xe_device_probe_early(struct xe_device *xe) · 48 unmodified lines | ||
| 769 | 714 | if (IS_SRIOV_VF(xe)) |
| 770 | 715 | vf_update_device_info(xe); |
| 771 | 716 | |
| 717 | + /* | |
| 718 | + * Check for pcode uncore_init status to confirm if the SoC | |
| 719 | + * initialization is complete. Until done, any MMIO or lmem access from | |
| 720 | + * the driver will be blocked | |
| 721 | + */ | |
| 772 | 722 | err = xe_pcode_probe_early(xe); |
| 773 | 723 | if (err || xe_survivability_mode_is_requested(xe)) { |
| 774 | 724 | int save_err = err; |
| @@ -785,11 +735,17 @@ int xe_device_probe_early(struct xe_device *xe) · 10 unmodified lines | ||
| 785 | 735 | return save_err; |
| 786 | 736 | } |
| 787 | 737 | |
| 788 | − err = wait_for_lmem_ready(xe); | |
| 789 | − if (err) | |
| 790 | − return err; | |
| 738 | + /* | |
| 739 | + * Make sure the lmem is initialized and ready to use. xe_pcode_ready() | |
| 740 | + * is flagged after full initialization is complete. Assert if lmem is | |
| 741 | + * not initialized. | |
| 742 | + */ | |
| 743 | + assert_lmem_ready(xe); | |
| 791 | 744 | |
| 792 | − xe->wedged.mode = xe_modparam.wedged_mode; | |
| 745 | + xe->wedged.mode = xe_device_validate_wedged_mode(xe, xe_modparam.wedged_mode) ? | |
| 746 | + XE_WEDGED_MODE_DEFAULT : xe_modparam.wedged_mode; | |
| 747 | + drm_dbg(&xe->drm, "wedged_mode: setting mode (%u) %s\n", | |
| 748 | + xe->wedged.mode, xe_wedged_mode_to_string(xe->wedged.mode)); | |
| 793 | 749 | |
| 794 | 750 | err = xe_device_vram_alloc(xe); |
| 795 | 751 | if (err) |
| @@ -1272,10 +1228,10 @@ static void xe_device_wedged_fini(struct drm_device *drm, void *arg) · 476 unmodified lines | ||
| 1272 | 1228 | * DOC: Xe Device Wedging |
| 1273 | 1229 | * |
| 1274 | 1230 | * Xe driver uses drm device wedged uevent as documented in Documentation/gpu/drm-uapi.rst. |
| 1275 | − * When device is in wedged state, every IOCTL will be blocked and GT cannot be | |
| 1276 | − * used. Certain critical errors like gt reset failure, firmware failures can cause | |
| 1277 | − * the device to be wedged. The default recovery method for a wedged state | |
| 1278 | − * is rebind/bus-reset. | |
| 1231 | + * When device is in wedged state, every IOCTL will be blocked and GT cannot | |
| 1232 | + * be used. The conditions under which the driver declares the device wedged | |
| 1233 | + * depend on the wedged mode configuration (see &enum xe_wedged_mode). The | |
| 1234 | + * default recovery method for a wedged state is rebind/bus-reset. | |
| 1279 | 1235 | * |
| 1280 | 1236 | * Another recovery method is vendor-specific. Below are the cases that send |
| 1281 | 1237 | * ``WEDGED=vendor-specific`` recovery method in drm device wedged uevent. |
| @@ -1340,7 +1296,7 @@ void xe_device_declare_wedged(struct xe_device *xe) · 58 unmodified lines | ||
| 1340 | 1296 | struct xe_gt *gt; |
| 1341 | 1297 | u8 id; |
| 1342 | 1298 | |
| 1343 | − if (xe->wedged.mode == 0) { | |
| 1299 | + if (xe->wedged.mode == XE_WEDGED_MODE_NEVER) { | |
| 1344 | 1300 | drm_dbg(&xe->drm, "Wedged mode is forcibly disabled\n"); |
| 1345 | 1301 | return; |
| 1346 | 1302 | } |
| @@ -1374,3 +1330,48 @@ void xe_device_declare_wedged(struct xe_device *xe) · 27 unmodified lines | ||
| 1374 | 1330 | drm_dev_wedged_event(&xe->drm, xe->wedged.method, NULL); |
| 1375 | 1331 | } |
| 1376 | 1332 | } |
| 1333 | + | |
| 1334 | +/** | |
| 1335 | + * xe_device_validate_wedged_mode - Check if given mode is supported | |
| 1336 | + * @xe: the &xe_device | |
| 1337 | + * @mode: requested mode to validate | |
| 1338 | + * | |
| 1339 | + * Check whether the provided wedged mode is supported. | |
| 1340 | + * | |
| 1341 | + * Return: 0 if mode is supported, error code otherwise. | |
| 1342 | + */ | |
| 1343 | +int xe_device_validate_wedged_mode(struct xe_device *xe, unsigned int mode) | |
| 1344 | +{ | |
| 1345 | + if (mode > XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) { | |
| 1346 | + drm_dbg(&xe->drm, "wedged_mode: invalid value (%u)\n", mode); | |
| 1347 | + return -EINVAL; | |
| 1348 | + } else if (mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET && (IS_SRIOV_VF(xe) || | |
| 1349 | + (IS_SRIOV_PF(xe) && !IS_ENABLED(CONFIG_DRM_XE_DEBUG)))) { | |
| 1350 | + drm_dbg(&xe->drm, "wedged_mode: (%u) %s mode is not supported for %s\n", | |
| 1351 | + mode, xe_wedged_mode_to_string(mode), | |
| 1352 | + xe_sriov_mode_to_string(xe_device_sriov_mode(xe))); | |
| 1353 | + return -EPERM; | |
| 1354 | + } | |
| 1355 | + | |
| 1356 | + return 0; | |
| 1357 | +} | |
| 1358 | + | |
| 1359 | +/** | |
| 1360 | + * xe_wedged_mode_to_string - Convert enum value to string. | |
| 1361 | + * @mode: the &xe_wedged_mode to convert | |
| 1362 | + * | |
| 1363 | + * Returns: wedged mode as a user friendly string. | |
| 1364 | + */ | |
| 1365 | +const char *xe_wedged_mode_to_string(enum xe_wedged_mode mode) | |
| 1366 | +{ | |
| 1367 | + switch (mode) { | |
| 1368 | + case XE_WEDGED_MODE_NEVER: | |
| 1369 | + return "never"; | |
| 1370 | + case XE_WEDGED_MODE_UPON_CRITICAL_ERROR: | |
| 1371 | + return "upon-critical-error"; | |
| 1372 | + case XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET: | |
| 1373 | + return "upon-any-hang-no-reset"; | |
| 1374 | + default: | |
| 1375 | + return "<invalid>"; | |
| 1376 | + } | |
| 1377 | +} | |
| @@ -194,6 +194,8 @@ static inline bool xe_device_wedged(struct xe_device *xe) · 193 unmodified lines | ||
| 194 | 194 | |
| 195 | 195 | void xe_device_set_wedged_method(struct xe_device *xe, unsigned long method); |
| 196 | 196 | void xe_device_declare_wedged(struct xe_device *xe); |
| 197 | +int xe_device_validate_wedged_mode(struct xe_device *xe, unsigned int mode); | |
| 198 | +const char *xe_wedged_mode_to_string(enum xe_wedged_mode mode); | |
| 197 | 199 | |
| 198 | 200 | struct xe_file *xe_file_get(struct xe_file *xef); |
| 199 | 201 | void xe_file_put(struct xe_file *xef); |
| @@ -46,6 +46,25 @@ struct xe_pat_ops; · 45 unmodified lines | ||
| 46 | 46 | struct xe_pxp; |
| 47 | 47 | struct xe_vram_region; |
| 48 | 48 | |
| 49 | +/** | |
| 50 | + * enum xe_wedged_mode - possible wedged modes | |
| 51 | + * @XE_WEDGED_MODE_NEVER: Device will never be declared wedged. | |
| 52 | + * @XE_WEDGED_MODE_UPON_CRITICAL_ERROR: Device will be declared wedged only | |
| 53 | + * when critical error occurs like GT reset failure or firmware failure. | |
| 54 | + * This is the default mode. | |
| 55 | + * @XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET: Device will be declared wedged on | |
| 56 | + * any hang. In this mode, engine resets are disabled to avoid automatic | |
| 57 | + * recovery attempts. This mode is primarily intended for debugging hangs. | |
| 58 | + */ | |
| 59 | +enum xe_wedged_mode { | |
| 60 | + XE_WEDGED_MODE_NEVER = 0, | |
| 61 | + XE_WEDGED_MODE_UPON_CRITICAL_ERROR = 1, | |
| 62 | + XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET = 2, | |
| 63 | +}; | |
| 64 | + | |
| 65 | +#define XE_WEDGED_MODE_DEFAULT XE_WEDGED_MODE_UPON_CRITICAL_ERROR | |
| 66 | +#define XE_WEDGED_MODE_DEFAULT_STR "upon-critical-error" | |
| 67 | + | |
| 49 | 68 | #define XE_BO_INVALID_OFFSET LONG_MAX |
| 50 | 69 | |
| 51 | 70 | #define GRAPHICS_VER(xe) ((xe)->info.graphics_verx100 / 100) |
| @@ -322,6 +341,8 @@ struct xe_device { · 270 unmodified lines | ||
| 322 | 341 | * pcode mailbox commands. |
| 323 | 342 | */ |
| 324 | 343 | u8 has_mbx_power_limits:1; |
| 344 | + /** @info.has_mbx_thermal_info: Device supports thermal mailbox commands */ | |
| 345 | + u8 has_mbx_thermal_info:1; | |
| 325 | 346 | /** @info.has_mem_copy_instr: Device supports MEM_COPY instruction */ |
| 326 | 347 | u8 has_mem_copy_instr:1; |
| 327 | 348 | /** @info.has_mert: Device has standalone MERT */ |
| @@ -626,9 +647,11 @@ struct xe_device { · 298 unmodified lines | ||
| 626 | 647 | /** @wedged.flag: Xe device faced a critical error and is now blocked. */ |
| 627 | 648 | atomic_t flag; |
| 628 | 649 | /** @wedged.mode: Mode controlled by kernel parameter and debugfs */ |
| 629 | − int mode; | |
| 650 | + enum xe_wedged_mode mode; | |
| 630 | 651 | /** @wedged.method: Recovery method to be sent in the drm device wedged uevent */ |
| 631 | 652 | unsigned long method; |
| 653 | + /** @wedged.inconsistent_reset: Inconsistent reset policy state between GTs */ | |
| 654 | + bool inconsistent_reset; | |
| 632 | 655 | } wedged; |
| 633 | 656 | |
| 634 | 657 | /** @bo_device: Struct to control async free of BOs */ |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <uapi/drm/xe_drm.h> |
| 12 | 12 | #include <linux/delay.h> |
| 13 | 13 | |
| 14 | −#include "xe_bo.h" | |
| 15 | 14 | #include "xe_device.h" |
| 16 | 15 | #include "xe_exec_queue.h" |
| 17 | 16 | #include "xe_hw_engine_group.h" |
| @@ -21,13 +21,11 @@ · 20 unmodified lines | ||
| 21 | 21 | #include "xe_gt_sriov_vf.h" |
| 22 | 22 | #include "xe_hw_engine_class_sysfs.h" |
| 23 | 23 | #include "xe_hw_engine_group.h" |
| 24 | −#include "xe_hw_fence.h" | |
| 25 | 24 | #include "xe_irq.h" |
| 26 | 25 | #include "xe_lrc.h" |
| 27 | 26 | #include "xe_macros.h" |
| 28 | 27 | #include "xe_migrate.h" |
| 29 | 28 | #include "xe_pm.h" |
| 30 | −#include "xe_ring_ops_types.h" | |
| 31 | 29 | #include "xe_trace.h" |
| 32 | 30 | #include "xe_vm.h" |
| 33 | 31 | #include "xe_pxp.h" |
| @@ -84,9 +82,8 @@ · 50 unmodified lines | ||
| 84 | 82 | * group is destroyed. The secondary queues hold a reference to the primary |
| 85 | 83 | * queue thus preventing the group from being destroyed when user destroys |
| 86 | 84 | * the primary queue. Once the primary queue is destroyed, secondary queues |
| 87 | − * can't be added to the queue group, but they can continue to submit the | |
| 88 | − * jobs if the DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag is set during the multi | |
| 89 | − * queue group creation. | |
| 85 | + * can't be added to the queue group and new job submissions on existing | |
| 86 | + * secondary queues are not allowed. | |
| 90 | 87 | * |
| 91 | 88 | * The queues of a multi queue group can set their priority within the group |
| 92 | 89 | * through the DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY property. |
| @@ -467,26 +464,6 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe, · 374 unmodified lines | ||
| 467 | 464 | } |
| 468 | 465 | ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO); |
| 469 | 466 | |
| 470 | −static void xe_exec_queue_group_kill(struct kref *ref) | |
| 471 | −{ | |
| 472 | − struct xe_exec_queue_group *group = container_of(ref, struct xe_exec_queue_group, | |
| 473 | − kill_refcount); | |
| 474 | − xe_exec_queue_kill(group->primary); | |
| 475 | −} | |
| 476 | − | |
| 477 | −static inline void xe_exec_queue_group_kill_get(struct xe_exec_queue_group *group) | |
| 478 | −{ | |
| 479 | − kref_get(&group->kill_refcount); | |
| 480 | −} | |
| 481 | − | |
| 482 | −void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group) | |
| 483 | −{ | |
| 484 | − if (!group) | |
| 485 | − return; | |
| 486 | − | |
| 487 | − kref_put(&group->kill_refcount, xe_exec_queue_group_kill); | |
| 488 | −} | |
| 489 | − | |
| 490 | 467 | void xe_exec_queue_destroy(struct kref *ref) |
| 491 | 468 | { |
| 492 | 469 | struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount); |
| @@ -716,7 +693,6 @@ static int xe_exec_queue_group_init(struct xe_device *xe, struct xe_exec_queue * · 223 unmodified lines | ||
| 716 | 693 | group->primary = q; |
| 717 | 694 | group->cgp_bo = bo; |
| 718 | 695 | INIT_LIST_HEAD(&group->list); |
| 719 | − kref_init(&group->kill_refcount); | |
| 720 | 696 | xa_init_flags(&group->xa, XA_FLAGS_ALLOC1); |
| 721 | 697 | mutex_init(&group->list_lock); |
| 722 | 698 | q->multi_queue.group = group; |
| @@ -792,11 +768,6 @@ static int xe_exec_queue_group_add(struct xe_device *xe, struct xe_exec_queue *q · 69 unmodified lines | ||
| 792 | 768 | |
| 793 | 769 | q->multi_queue.pos = pos; |
| 794 | 770 | |
| 795 | − if (group->primary->multi_queue.keep_active) { | |
| 796 | − xe_exec_queue_group_kill_get(group); | |
| 797 | − q->multi_queue.keep_active = true; | |
| 798 | − } | |
| 799 | − | |
| 800 | 771 | return 0; |
| 801 | 772 | } |
| 802 | 773 | |
| @@ -810,11 +781,6 @@ static void xe_exec_queue_group_delete(struct xe_device *xe, struct xe_exec_queu · 7 unmodified lines | ||
| 810 | 781 | lrc = xa_erase(&group->xa, q->multi_queue.pos); |
| 811 | 782 | xe_assert(xe, lrc); |
| 812 | 783 | xe_lrc_put(lrc); |
| 813 | − | |
| 814 | − if (q->multi_queue.keep_active) { | |
| 815 | − xe_exec_queue_group_kill_put(group); | |
| 816 | − q->multi_queue.keep_active = false; | |
| 817 | − } | |
| 818 | 784 | } |
| 819 | 785 | |
| 820 | 786 | static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue *q, |
| @@ -836,24 +802,12 @@ static int exec_queue_set_multi_group(struct xe_device *xe, struct xe_exec_queue · 15 unmodified lines | ||
| 836 | 802 | return -EINVAL; |
| 837 | 803 | |
| 838 | 804 | if (value & DRM_XE_MULTI_GROUP_CREATE) { |
| 839 | − if (XE_IOCTL_DBG(xe, value & ~(DRM_XE_MULTI_GROUP_CREATE | | |
| 840 | − DRM_XE_MULTI_GROUP_KEEP_ACTIVE))) | |
| 841 | − return -EINVAL; | |
| 842 | − | |
| 843 | − /* | |
| 844 | − * KEEP_ACTIVE is not supported in preempt fence mode as in that mode, | |
| 845 | − * VM_DESTROY ioctl expects all exec queues of that VM are already killed. | |
| 846 | − */ | |
| 847 | − if (XE_IOCTL_DBG(xe, (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) && | |
| 848 | − xe_vm_in_preempt_fence_mode(q->vm))) | |
| 805 | + if (XE_IOCTL_DBG(xe, value & ~DRM_XE_MULTI_GROUP_CREATE)) | |
| 849 | 806 | return -EINVAL; |
| 850 | 807 | |
| 851 | 808 | q->multi_queue.valid = true; |
| 852 | 809 | q->multi_queue.is_primary = true; |
| 853 | 810 | q->multi_queue.pos = 0; |
| 854 | − if (value & DRM_XE_MULTI_GROUP_KEEP_ACTIVE) | |
| 855 | − q->multi_queue.keep_active = true; | |
| 856 | − | |
| 857 | 811 | return 0; |
| 858 | 812 | } |
| 859 | 813 | |
| @@ -1419,11 +1373,6 @@ void xe_exec_queue_kill(struct xe_exec_queue *q) · 559 unmodified lines | ||
| 1419 | 1373 | |
| 1420 | 1374 | q->ops->kill(q); |
| 1421 | 1375 | xe_vm_remove_compute_exec_queue(q->vm, q); |
| 1422 | − | |
| 1423 | − if (!xe_exec_queue_is_multi_queue_primary(q) && q->multi_queue.keep_active) { | |
| 1424 | − xe_exec_queue_group_kill_put(q->multi_queue.group); | |
| 1425 | − q->multi_queue.keep_active = false; | |
| 1426 | − } | |
| 1427 | 1376 | } |
| 1428 | 1377 | |
| 1429 | 1378 | int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data, |
| @@ -1450,10 +1399,7 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data, · 20 unmodified lines | ||
| 1450 | 1399 | if (q->vm && q->hwe->hw_engine_group) |
| 1451 | 1400 | xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); |
| 1452 | 1401 | |
| 1453 | − if (xe_exec_queue_is_multi_queue_primary(q)) | |
| 1454 | − xe_exec_queue_group_kill_put(q->multi_queue.group); | |
| 1455 | − else | |
| 1456 | − xe_exec_queue_kill(q); | |
| 1402 | + xe_exec_queue_kill(q); | |
| 1457 | 1403 | |
| 1458 | 1404 | trace_xe_exec_queue_close(q); |
| 1459 | 1405 | xe_exec_queue_put(q); |
| @@ -113,8 +113,6 @@ static inline struct xe_exec_queue *xe_exec_queue_multi_queue_primary(struct xe_ · 112 unmodified lines | ||
| 113 | 113 | return xe_exec_queue_is_multi_queue(q) ? q->multi_queue.group->primary : q; |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | −void xe_exec_queue_group_kill_put(struct xe_exec_queue_group *group); | |
| 117 | − | |
| 118 | 116 | bool xe_exec_queue_is_lr(struct xe_exec_queue *q); |
| 119 | 117 | |
| 120 | 118 | bool xe_exec_queue_is_idle(struct xe_exec_queue *q); |
| @@ -62,8 +62,6 @@ struct xe_exec_queue_group { · 61 unmodified lines | ||
| 62 | 62 | struct list_head list; |
| 63 | 63 | /** @list_lock: Secondary queue list lock */ |
| 64 | 64 | struct mutex list_lock; |
| 65 | − /** @kill_refcount: ref count to kill primary queue */ | |
| 66 | − struct kref kill_refcount; | |
| 67 | 65 | /** @sync_pending: CGP_SYNC_DONE g2h response pending */ |
| 68 | 66 | bool sync_pending; |
| 69 | 67 | /** @banned: Group banned */ |
| @@ -163,8 +161,6 @@ struct xe_exec_queue { · 93 unmodified lines | ||
| 163 | 161 | u8 valid:1; |
| 164 | 162 | /** @multi_queue.is_primary: Is primary queue (Q0) of the group */ |
| 165 | 163 | u8 is_primary:1; |
| 166 | − /** @multi_queue.keep_active: Keep the group active after primary is destroyed */ | |
| 167 | − u8 keep_active:1; | |
| 168 | 164 | } multi_queue; |
| 169 | 165 | |
| 170 | 166 | /** @sched_props: scheduling properties */ |
| @@ -15,8 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "xe_bo.h" |
| 16 | 16 | #include "xe_device.h" |
| 17 | 17 | #include "xe_exec_queue.h" |
| 18 | −#include "xe_gt.h" | |
| 19 | −#include "xe_hw_fence.h" | |
| 18 | +#include "xe_gt_types.h" | |
| 20 | 19 | #include "xe_irq.h" |
| 21 | 20 | #include "xe_lrc.h" |
| 22 | 21 | #include "xe_macros.h" |
| @@ -20,9 +20,8 @@ · 19 unmodified lines | ||
| 20 | 20 | #include "regs/xe_regs.h" |
| 21 | 21 | #include "xe_assert.h" |
| 22 | 22 | #include "xe_bo.h" |
| 23 | −#include "xe_device.h" | |
| 24 | −#include "xe_gt.h" | |
| 25 | 23 | #include "xe_gt_printk.h" |
| 24 | +#include "xe_gt_types.h" | |
| 26 | 25 | #include "xe_map.h" |
| 27 | 26 | #include "xe_mmio.h" |
| 28 | 27 | #include "xe_pm.h" |
| @@ -67,6 +66,24 @@ · 38 unmodified lines | ||
| 67 | 66 | * give us the correct placement for free. |
| 68 | 67 | */ |
| 69 | 68 | |
| 69 | +/** | |
| 70 | + * struct xe_ggtt_node - A node in GGTT. | |
| 71 | + * | |
| 72 | + * This struct needs to be initialized (only-once) with xe_ggtt_node_init() before any node | |
| 73 | + * insertion, reservation, or 'ballooning'. | |
| 74 | + * It will, then, be finalized by either xe_ggtt_node_remove() or xe_ggtt_node_deballoon(). | |
| 75 | + */ | |
| 76 | +struct xe_ggtt_node { | |
| 77 | + /** @ggtt: Back pointer to xe_ggtt where this region will be inserted at */ | |
| 78 | + struct xe_ggtt *ggtt; | |
| 79 | + /** @base: A drm_mm_node */ | |
| 80 | + struct drm_mm_node base; | |
| 81 | + /** @delayed_removal_work: The work struct for the delayed removal */ | |
| 82 | + struct work_struct delayed_removal_work; | |
| 83 | + /** @invalidate_on_remove: If it needs invalidation upon removal */ | |
| 84 | + bool invalidate_on_remove; | |
| 85 | +}; | |
| 86 | + | |
| 70 | 87 | static u64 xelp_ggtt_pte_flags(struct xe_bo *bo, u16 pat_index) |
| 71 | 88 | { |
| 72 | 89 | u64 pte = XE_PAGE_PRESENT; |
| @@ -137,10 +154,32 @@ static void ggtt_update_access_counter(struct xe_ggtt *ggtt) · 64 unmodified lines | ||
| 137 | 154 | } |
| 138 | 155 | } |
| 139 | 156 | |
| 157 | +/** | |
| 158 | + * xe_ggtt_start - Get starting offset of GGTT. | |
| 159 | + * @ggtt: &xe_ggtt | |
| 160 | + * | |
| 161 | + * Returns: Starting offset for this &xe_ggtt. | |
| 162 | + */ | |
| 163 | +u64 xe_ggtt_start(struct xe_ggtt *ggtt) | |
| 164 | +{ | |
| 165 | + return ggtt->start; | |
| 166 | +} | |
| 167 | + | |
| 168 | +/** | |
| 169 | + * xe_ggtt_size - Get size of GGTT. | |
| 170 | + * @ggtt: &xe_ggtt | |
| 171 | + * | |
| 172 | + * Returns: Total usable size of this &xe_ggtt. | |
| 173 | + */ | |
| 174 | +u64 xe_ggtt_size(struct xe_ggtt *ggtt) | |
| 175 | +{ | |
| 176 | + return ggtt->size; | |
| 177 | +} | |
| 178 | + | |
| 140 | 179 | static void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte) |
| 141 | 180 | { |
| 142 | 181 | xe_tile_assert(ggtt->tile, !(addr & XE_PTE_MASK)); |
| 143 | − xe_tile_assert(ggtt->tile, addr < ggtt->size); | |
| 182 | + xe_tile_assert(ggtt->tile, addr < ggtt->start + ggtt->size); | |
| 144 | 183 | |
| 145 | 184 | writeq(pte, &ggtt->gsm[addr >> XE_PTE_SHIFT]); |
| 146 | 185 | } |
| @@ -256,16 +295,16 @@ static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { · 109 unmodified lines | ||
| 256 | 295 | .ggtt_get_pte = xe_ggtt_get_pte, |
| 257 | 296 | }; |
| 258 | 297 | |
| 259 | −static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u32 reserved) | |
| 298 | +static void __xe_ggtt_init_early(struct xe_ggtt *ggtt, u64 start, u64 size) | |
| 260 | 299 | { |
| 261 | − drm_mm_init(&ggtt->mm, reserved, | |
| 262 | − ggtt->size - reserved); | |
| 300 | + ggtt->start = start; | |
| 301 | + ggtt->size = size; | |
| 302 | + drm_mm_init(&ggtt->mm, start, size); | |
| 263 | 303 | } |
| 264 | 304 | |
| 265 | −int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 reserved, u32 size) | |
| 305 | +int xe_ggtt_init_kunit(struct xe_ggtt *ggtt, u32 start, u32 size) | |
| 266 | 306 | { |
| 267 | − ggtt->size = size; | |
| 268 | − __xe_ggtt_init_early(ggtt, reserved); | |
| 307 | + __xe_ggtt_init_early(ggtt, start, size); | |
| 269 | 308 | return 0; |
| 270 | 309 | } |
| 271 | 310 | EXPORT_SYMBOL_IF_KUNIT(xe_ggtt_init_kunit); |
| @@ -293,26 +332,32 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) · 21 unmodified lines | ||
| 293 | 332 | struct xe_device *xe = tile_to_xe(ggtt->tile); |
| 294 | 333 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); |
| 295 | 334 | unsigned int gsm_size; |
| 335 | + u64 ggtt_start, wopcm = xe_wopcm_size(xe), ggtt_size; | |
| 296 | 336 | int err; |
| 297 | 337 | |
| 298 | − if (IS_SRIOV_VF(xe) || GRAPHICS_VERx100(xe) >= 1250) | |
| 299 | − gsm_size = SZ_8M; /* GGTT is expected to be 4GiB */ | |
| 300 | − else | |
| 301 | − gsm_size = probe_gsm_size(pdev); | |
| 302 | − | |
| 303 | − if (gsm_size == 0) { | |
| 304 | − xe_tile_err(ggtt->tile, "Hardware reported no preallocated GSM\n"); | |
| 305 | − return -ENOMEM; | |
| 338 | + if (!IS_SRIOV_VF(xe)) { | |
| 339 | + if (GRAPHICS_VERx100(xe) >= 1250) | |
| 340 | + gsm_size = SZ_8M; /* GGTT is expected to be 4GiB */ | |
| 341 | + else | |
| 342 | + gsm_size = probe_gsm_size(pdev); | |
| 343 | + if (gsm_size == 0) { | |
| 344 | + xe_tile_err(ggtt->tile, "Hardware reported no preallocated GSM\n"); | |
| 345 | + return -ENOMEM; | |
| 346 | + } | |
| 347 | + ggtt_start = wopcm; | |
| 348 | + ggtt_size = (gsm_size / 8) * (u64)XE_PAGE_SIZE - ggtt_start; | |
| 349 | + } else { | |
| 350 | + /* GGTT is expected to be 4GiB */ | |
| 351 | + ggtt_start = wopcm; | |
| 352 | + ggtt_size = SZ_4G - ggtt_start; | |
| 306 | 353 | } |
| 307 | 354 | |
| 308 | 355 | ggtt->gsm = ggtt->tile->mmio.regs + SZ_8M; |
| 309 | − ggtt->size = (gsm_size / 8) * (u64) XE_PAGE_SIZE; | |
| 310 | − | |
| 311 | 356 | if (IS_DGFX(xe) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) |
| 312 | 357 | ggtt->flags |= XE_GGTT_FLAGS_64K; |
| 313 | 358 | |
| 314 | − if (ggtt->size > GUC_GGTT_TOP) | |
| 315 | − ggtt->size = GUC_GGTT_TOP; | |
| 359 | + if (ggtt_size + ggtt_start > GUC_GGTT_TOP) | |
| 360 | + ggtt_size = GUC_GGTT_TOP - ggtt_start; | |
| 316 | 361 | |
| 317 | 362 | if (GRAPHICS_VERx100(xe) >= 1270) |
| 318 | 363 | ggtt->pt_ops = |
| @@ -322,11 +367,11 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) · 3 unmodified lines | ||
| 322 | 367 | else |
| 323 | 368 | ggtt->pt_ops = &xelp_pt_ops; |
| 324 | 369 | |
| 325 | − ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM); | |
| 370 | + ggtt->wq = alloc_workqueue("xe-ggtt-wq", WQ_MEM_RECLAIM, 0); | |
| 326 | 371 | if (!ggtt->wq) |
| 327 | 372 | return -ENOMEM; |
| 328 | 373 | |
| 329 | − __xe_ggtt_init_early(ggtt, xe_wopcm_size(xe)); | |
| 374 | + __xe_ggtt_init_early(ggtt, ggtt_start, ggtt_size); | |
| 330 | 375 | |
| 331 | 376 | err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); |
| 332 | 377 | if (err) |
| @@ -563,11 +608,9 @@ void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) · 230 unmodified lines | ||
| 563 | 608 | static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size) |
| 564 | 609 | { |
| 565 | 610 | struct xe_tile *tile = ggtt->tile; |
| 566 | − struct xe_device *xe = tile_to_xe(tile); | |
| 567 | − u64 __maybe_unused wopcm = xe_wopcm_size(xe); | |
| 568 | 611 | |
| 569 | − xe_tile_assert(tile, start >= wopcm); | |
| 570 | − xe_tile_assert(tile, start + size < ggtt->size - wopcm); | |
| 612 | + xe_tile_assert(tile, start >= ggtt->start); | |
| 613 | + xe_tile_assert(tile, start + size <= ggtt->start + ggtt->size); | |
| 571 | 614 | } |
| 572 | 615 | |
| 573 | 616 | /** |
| @@ -610,20 +653,8 @@ void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift) · 36 unmodified lines | ||
| 610 | 653 | } |
| 611 | 654 | } |
| 612 | 655 | |
| 613 | −/** | |
| 614 | − * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT | |
| 615 | − * @node: the &xe_ggtt_node to be inserted | |
| 616 | − * @size: size of the node | |
| 617 | − * @align: alignment constrain of the node | |
| 618 | − * @mm_flags: flags to control the node behavior | |
| 619 | − * | |
| 620 | − * It cannot be called without first having called xe_ggtt_init() once. | |
| 621 | − * To be used in cases where ggtt->lock is already taken. | |
| 622 | − * | |
| 623 | − * Return: 0 on success or a negative error code on failure. | |
| 624 | − */ | |
| 625 | −int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, | |
| 626 | − u32 size, u32 align, u32 mm_flags) | |
| 656 | +static int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, | |
| 657 | + u32 size, u32 align, u32 mm_flags) | |
| 627 | 658 | { |
| 628 | 659 | return drm_mm_insert_node_generic(&node->ggtt->mm, &node->base, size, align, 0, |
| 629 | 660 | mm_flags); |
| @@ -661,9 +692,11 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align) · 31 unmodified lines | ||
| 661 | 692 | * This function will allocate the struct %xe_ggtt_node and return its pointer. |
| 662 | 693 | * This struct will then be freed after the node removal upon xe_ggtt_node_remove() |
| 663 | 694 | * or xe_ggtt_node_remove_balloon_locked(). |
| 664 | − * Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated | |
| 665 | − * in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), | |
| 666 | − * xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved in GGTT. | |
| 695 | + * | |
| 696 | + * Having %xe_ggtt_node struct allocated doesn't mean that the node is already | |
| 697 | + * allocated in GGTT. Only xe_ggtt_node_insert(), allocation through | |
| 698 | + * xe_ggtt_node_insert_transform(), or xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved | |
| 699 | + * in GGTT. | |
| 667 | 700 | * |
| 668 | 701 | * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. |
| 669 | 702 | **/ |
| @@ -726,13 +759,12 @@ size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node) · 56 unmodified lines | ||
| 726 | 759 | * @ggtt: the &xe_ggtt where node will be mapped |
| 727 | 760 | * @node: the &xe_ggtt_node where this BO is mapped |
| 728 | 761 | * @bo: the &xe_bo to be mapped |
| 729 | − * @pat_index: Which pat_index to use. | |
| 762 | + * @pte: The pte flags to append. | |
| 730 | 763 | */ |
| 731 | −void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, | |
| 732 | − struct xe_bo *bo, u16 pat_index) | |
| 764 | +static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, | |
| 765 | + struct xe_bo *bo, u64 pte) | |
| 733 | 766 | { |
| 734 | − | |
| 735 | − u64 start, pte, end; | |
| 767 | + u64 start, end; | |
| 736 | 768 | struct xe_res_cursor cur; |
| 737 | 769 | |
| 738 | 770 | if (XE_WARN_ON(!node)) |
| @@ -741,7 +773,6 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, · 2 unmodified lines | ||
| 741 | 773 | start = node->base.start; |
| 742 | 774 | end = start + xe_bo_size(bo); |
| 743 | 775 | |
| 744 | − pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); | |
| 745 | 776 | if (!xe_bo_is_vram(bo) && !xe_bo_is_stolen(bo)) { |
| 746 | 777 | xe_assert(xe_bo_device(bo), bo->ttm.ttm); |
| 747 | 778 | |
| @@ -771,12 +802,65 @@ void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo) · 23 unmodified lines | ||
| 771 | 802 | { |
| 772 | 803 | u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; |
| 773 | 804 | u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; |
| 805 | + u64 pte; | |
| 774 | 806 | |
| 775 | 807 | mutex_lock(&ggtt->lock); |
| 776 | − xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pat_index); | |
| 808 | + pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); | |
| 809 | + xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pte); | |
| 777 | 810 | mutex_unlock(&ggtt->lock); |
| 778 | 811 | } |
| 779 | 812 | |
| 813 | +/** | |
| 814 | + * xe_ggtt_node_insert_transform - Insert a newly allocated &xe_ggtt_node into the GGTT | |
| 815 | + * @ggtt: the &xe_ggtt where the node will inserted/reserved. | |
| 816 | + * @bo: The bo to be transformed | |
| 817 | + * @pte_flags: The extra GGTT flags to add to mapping. | |
| 818 | + * @size: size of the node | |
| 819 | + * @align: required alignment for node | |
| 820 | + * @transform: transformation function that will populate the GGTT node, or NULL for linear mapping. | |
| 821 | + * @arg: Extra argument to pass to the transformation function. | |
| 822 | + * | |
| 823 | + * This function allows inserting a GGTT node with a custom transformation function. | |
| 824 | + * This is useful for display to allow inserting rotated framebuffers to GGTT. | |
| 825 | + * | |
| 826 | + * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. | |
| 827 | + */ | |
| 828 | +struct xe_ggtt_node *xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt, | |
| 829 | + struct xe_bo *bo, u64 pte_flags, | |
| 830 | + u64 size, u32 align, | |
| 831 | + xe_ggtt_transform_cb transform, void *arg) | |
| 832 | +{ | |
| 833 | + struct xe_ggtt_node *node; | |
| 834 | + int ret; | |
| 835 | + | |
| 836 | + node = xe_ggtt_node_init(ggtt); | |
| 837 | + if (IS_ERR(node)) | |
| 838 | + return ERR_CAST(node); | |
| 839 | + | |
| 840 | + if (mutex_lock_interruptible(&ggtt->lock) < 0) { | |
| 841 | + ret = -ERESTARTSYS; | |
| 842 | + goto err; | |
| 843 | + } | |
| 844 | + | |
| 845 | + ret = xe_ggtt_node_insert_locked(node, size, align, 0); | |
| 846 | + if (ret) | |
| 847 | + goto err_unlock; | |
| 848 | + | |
| 849 | + if (transform) | |
| 850 | + transform(ggtt, node, pte_flags, ggtt->pt_ops->ggtt_set_pte, arg); | |
| 851 | + else | |
| 852 | + xe_ggtt_map_bo(ggtt, node, bo, pte_flags); | |
| 853 | + | |
| 854 | + mutex_unlock(&ggtt->lock); | |
| 855 | + return node; | |
| 856 | + | |
| 857 | +err_unlock: | |
| 858 | + mutex_unlock(&ggtt->lock); | |
| 859 | +err: | |
| 860 | + xe_ggtt_node_fini(node); | |
| 861 | + return ERR_PTR(ret); | |
| 862 | +} | |
| 863 | + | |
| 780 | 864 | static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, |
| 781 | 865 | u64 start, u64 end, struct drm_exec *exec) |
| 782 | 866 | { |
| @@ -815,8 +899,9 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, · 32 unmodified lines | ||
| 815 | 899 | } else { |
| 816 | 900 | u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; |
| 817 | 901 | u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; |
| 902 | + u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); | |
| 818 | 903 | |
| 819 | − xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pat_index); | |
| 904 | + xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte); | |
| 820 | 905 | } |
| 821 | 906 | mutex_unlock(&ggtt->lock); |
| 822 | 907 | |
| @@ -890,14 +975,12 @@ u64 xe_ggtt_largest_hole(struct xe_ggtt *ggtt, u64 alignment, u64 *spare) · 67 unmodified lines | ||
| 890 | 975 | { |
| 891 | 976 | const struct drm_mm *mm = &ggtt->mm; |
| 892 | 977 | const struct drm_mm_node *entry; |
| 893 | − u64 hole_min_start = xe_wopcm_size(tile_to_xe(ggtt->tile)); | |
| 894 | 978 | u64 hole_start, hole_end, hole_size; |
| 895 | 979 | u64 max_hole = 0; |
| 896 | 980 | |
| 897 | 981 | mutex_lock(&ggtt->lock); |
| 898 | − | |
| 899 | 982 | drm_mm_for_each_hole(entry, mm, hole_start, hole_end) { |
| 900 | − hole_start = max(hole_start, hole_min_start); | |
| 983 | + hole_start = max(hole_start, ggtt->start); | |
| 901 | 984 | hole_start = ALIGN(hole_start, alignment); |
| 902 | 985 | hole_end = ALIGN_DOWN(hole_end, alignment); |
| 903 | 986 | if (hole_start >= hole_end) |
| @@ -1069,15 +1152,13 @@ u64 xe_ggtt_print_holes(struct xe_ggtt *ggtt, u64 alignment, struct drm_printer · 165 unmodified lines | ||
| 1069 | 1152 | { |
| 1070 | 1153 | const struct drm_mm *mm = &ggtt->mm; |
| 1071 | 1154 | const struct drm_mm_node *entry; |
| 1072 | − u64 hole_min_start = xe_wopcm_size(tile_to_xe(ggtt->tile)); | |
| 1073 | 1155 | u64 hole_start, hole_end, hole_size; |
| 1074 | 1156 | u64 total = 0; |
| 1075 | 1157 | char buf[10]; |
| 1076 | 1158 | |
| 1077 | 1159 | mutex_lock(&ggtt->lock); |
| 1078 | − | |
| 1079 | 1160 | drm_mm_for_each_hole(entry, mm, hole_start, hole_end) { |
| 1080 | − hole_start = max(hole_start, hole_min_start); | |
| 1161 | + hole_start = max(hole_start, ggtt->start); | |
| 1081 | 1162 | hole_start = ALIGN(hole_start, alignment); |
| 1082 | 1163 | hole_end = ALIGN_DOWN(hole_end, alignment); |
| 1083 | 1164 | if (hole_start >= hole_end) |
| @@ -1121,3 +1202,25 @@ u64 xe_ggtt_read_pte(struct xe_ggtt *ggtt, u64 offset) · 37 unmodified lines | ||
| 1121 | 1202 | { |
| 1122 | 1203 | return ioread64(ggtt->gsm + (offset / XE_PAGE_SIZE)); |
| 1123 | 1204 | } |
| 1205 | + | |
| 1206 | +/** | |
| 1207 | + * xe_ggtt_node_addr - Get @node offset in GGTT. | |
| 1208 | + * @node: &xe_ggtt_node | |
| 1209 | + * | |
| 1210 | + * Get the GGTT offset for allocated node. | |
| 1211 | + */ | |
| 1212 | +u64 xe_ggtt_node_addr(const struct xe_ggtt_node *node) | |
| 1213 | +{ | |
| 1214 | + return node->base.start; | |
| 1215 | +} | |
| 1216 | + | |
| 1217 | +/** | |
| 1218 | + * xe_ggtt_node_size - Get @node allocation size. | |
| 1219 | + * @node: &xe_ggtt_node | |
| 1220 | + * | |
| 1221 | + * Get the allocated node's size. | |
| 1222 | + */ | |
| 1223 | +u64 xe_ggtt_node_size(const struct xe_ggtt_node *node) | |
| 1224 | +{ | |
| 1225 | + return node->base.size; | |
| 1226 | +} | |
| @@ -23,15 +23,18 @@ int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, · 22 unmodified lines | ||
| 23 | 23 | u64 start, u64 size); |
| 24 | 24 | void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); |
| 25 | 25 | void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift); |
| 26 | +u64 xe_ggtt_start(struct xe_ggtt *ggtt); | |
| 27 | +u64 xe_ggtt_size(struct xe_ggtt *ggtt); | |
| 26 | 28 | |
| 27 | 29 | int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); |
| 28 | −int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, | |
| 29 | − u32 size, u32 align, u32 mm_flags); | |
| 30 | +struct xe_ggtt_node * | |
| 31 | +xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt, | |
| 32 | + struct xe_bo *bo, u64 pte, | |
| 33 | + u64 size, u32 align, | |
| 34 | + xe_ggtt_transform_cb transform, void *arg); | |
| 30 | 35 | void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); |
| 31 | 36 | bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node); |
| 32 | 37 | size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node); |
| 33 | −void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, | |
| 34 | − struct xe_bo *bo, u16 pat_index); | |
| 35 | 38 | void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo); |
| 36 | 39 | int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo, struct drm_exec *exec); |
| 37 | 40 | int xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, |
| @@ -58,4 +61,7 @@ void xe_ggtt_might_lock(struct xe_ggtt *ggtt); · 20 unmodified lines | ||
| 58 | 61 | u64 xe_ggtt_encode_pte_flags(struct xe_ggtt *ggtt, struct xe_bo *bo, u16 pat_index); |
| 59 | 62 | u64 xe_ggtt_read_pte(struct xe_ggtt *ggtt, u64 offset); |
| 60 | 63 | |
| 64 | +u64 xe_ggtt_node_addr(const struct xe_ggtt_node *node); | |
| 65 | +u64 xe_ggtt_node_size(const struct xe_ggtt_node *node); | |
| 66 | + | |
| 61 | 67 | #endif |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "xe_pt_types.h" |
| 12 | 12 | |
| 13 | 13 | struct xe_bo; |
| 14 | +struct xe_ggtt_node; | |
| 14 | 15 | struct xe_gt; |
| 15 | 16 | |
| 16 | 17 | /** |
| @@ -22,7 +23,9 @@ struct xe_gt; · 5 unmodified lines | ||
| 22 | 23 | struct xe_ggtt { |
| 23 | 24 | /** @tile: Back pointer to tile where this GGTT belongs */ |
| 24 | 25 | struct xe_tile *tile; |
| 25 | − /** @size: Total size of this GGTT */ | |
| 26 | + /** @start: Start offset of GGTT */ | |
| 27 | + u64 start; | |
| 28 | + /** @size: Total usable size of this GGTT */ | |
| 26 | 29 | u64 size; |
| 27 | 30 | |
| 28 | 31 | #define XE_GGTT_FLAGS_64K BIT(0) |
| @@ -51,24 +54,11 @@ struct xe_ggtt { · 22 unmodified lines | ||
| 51 | 54 | struct workqueue_struct *wq; |
| 52 | 55 | }; |
| 53 | 56 | |
| 54 | −/** | |
| 55 | − * struct xe_ggtt_node - A node in GGTT. | |
| 56 | − * | |
| 57 | − * This struct needs to be initialized (only-once) with xe_ggtt_node_init() before any node | |
| 58 | − * insertion, reservation, or 'ballooning'. | |
| 59 | − * It will, then, be finalized by either xe_ggtt_node_remove() or xe_ggtt_node_deballoon(). | |
| 60 | − */ | |
| 61 | −struct xe_ggtt_node { | |
| 62 | − /** @ggtt: Back pointer to xe_ggtt where this region will be inserted at */ | |
| 63 | − struct xe_ggtt *ggtt; | |
| 64 | − /** @base: A drm_mm_node */ | |
| 65 | − struct drm_mm_node base; | |
| 66 | − /** @delayed_removal_work: The work struct for the delayed removal */ | |
| 67 | − struct work_struct delayed_removal_work; | |
| 68 | − /** @invalidate_on_remove: If it needs invalidation upon removal */ | |
| 69 | − bool invalidate_on_remove; | |
| 70 | −}; | |
| 71 | − | |
| 57 | +typedef void (*xe_ggtt_set_pte_fn)(struct xe_ggtt *ggtt, u64 addr, u64 pte); | |
| 58 | +typedef void (*xe_ggtt_transform_cb)(struct xe_ggtt *ggtt, | |
| 59 | + struct xe_ggtt_node *node, | |
| 60 | + u64 pte_flags, | |
| 61 | + xe_ggtt_set_pte_fn set_pte, void *arg); | |
| 72 | 62 | /** |
| 73 | 63 | * struct xe_ggtt_pt_ops - GGTT Page table operations |
| 74 | 64 | * Which can vary from platform to platform. |
| @@ -76,8 +66,10 @@ struct xe_ggtt_node { · 1 unmodified line | ||
| 76 | 66 | struct xe_ggtt_pt_ops { |
| 77 | 67 | /** @pte_encode_flags: Encode PTE flags for a given BO */ |
| 78 | 68 | u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index); |
| 69 | + | |
| 79 | 70 | /** @ggtt_set_pte: Directly write into GGTT's PTE */ |
| 80 | − void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte); | |
| 71 | + xe_ggtt_set_pte_fn ggtt_set_pte; | |
| 72 | + | |
| 81 | 73 | /** @ggtt_get_pte: Directly read from GGTT's PTE */ |
| 82 | 74 | u64 (*ggtt_get_pte)(struct xe_ggtt *ggtt, u64 addr); |
| 83 | 75 | }; |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | static void xe_sched_process_msg_queue(struct xe_gpu_scheduler *sched) |
| 9 | 9 | { |
| 10 | − if (!READ_ONCE(sched->base.pause_submit)) | |
| 10 | + if (!drm_sched_is_stopped(&sched->base)) | |
| 11 | 11 | queue_work(sched->base.submit_wq, &sched->work_process_msg); |
| 12 | 12 | } |
| 13 | 13 | |
| @@ -43,7 +43,7 @@ static void xe_sched_process_msg_work(struct work_struct *w) · 29 unmodified lines | ||
| 43 | 43 | container_of(w, struct xe_gpu_scheduler, work_process_msg); |
| 44 | 44 | struct xe_sched_msg *msg; |
| 45 | 45 | |
| 46 | − if (READ_ONCE(sched->base.pause_submit)) | |
| 46 | + if (drm_sched_is_stopped(&sched->base)) | |
| 47 | 47 | return; |
| 48 | 48 | |
| 49 | 49 | msg = xe_sched_get_msg(sched); |
| @@ -77,6 +77,7 @@ int xe_sched_init(struct xe_gpu_scheduler *sched, · 27 unmodified lines | ||
| 77 | 77 | }; |
| 78 | 78 | |
| 79 | 79 | sched->ops = xe_ops; |
| 80 | + spin_lock_init(&sched->msg_lock); | |
| 80 | 81 | INIT_LIST_HEAD(&sched->msgs); |
| 81 | 82 | INIT_WORK(&sched->work_process_msg, xe_sched_process_msg_work); |
| 82 | 83 | |
| @@ -117,7 +118,7 @@ void xe_sched_add_msg(struct xe_gpu_scheduler *sched, · 34 unmodified lines | ||
| 117 | 118 | void xe_sched_add_msg_locked(struct xe_gpu_scheduler *sched, |
| 118 | 119 | struct xe_sched_msg *msg) |
| 119 | 120 | { |
| 120 | − lockdep_assert_held(&sched->base.job_list_lock); | |
| 121 | + lockdep_assert_held(&sched->msg_lock); | |
| 121 | 122 | |
| 122 | 123 | list_add_tail(&msg->link, &sched->msgs); |
| 123 | 124 | xe_sched_process_msg_queue(sched); |
| @@ -131,7 +132,7 @@ void xe_sched_add_msg_locked(struct xe_gpu_scheduler *sched, · 7 unmodified lines | ||
| 131 | 132 | void xe_sched_add_msg_head(struct xe_gpu_scheduler *sched, |
| 132 | 133 | struct xe_sched_msg *msg) |
| 133 | 134 | { |
| 134 | − lockdep_assert_held(&sched->base.job_list_lock); | |
| 135 | + lockdep_assert_held(&sched->msg_lock); | |
| 135 | 136 | |
| 136 | 137 | list_add(&msg->link, &sched->msgs); |
| 137 | 138 | xe_sched_process_msg_queue(sched); |
| @@ -33,12 +33,12 @@ void xe_sched_add_msg_head(struct xe_gpu_scheduler *sched, · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | static inline void xe_sched_msg_lock(struct xe_gpu_scheduler *sched) |
| 35 | 35 | { |
| 36 | − spin_lock(&sched->base.job_list_lock); | |
| 36 | + spin_lock(&sched->msg_lock); | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | static inline void xe_sched_msg_unlock(struct xe_gpu_scheduler *sched) |
| 40 | 40 | { |
| 41 | − spin_unlock(&sched->base.job_list_lock); | |
| 41 | + spin_unlock(&sched->msg_lock); | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | static inline void xe_sched_stop(struct xe_gpu_scheduler *sched) |
| @@ -56,12 +56,9 @@ static inline void xe_sched_resubmit_jobs(struct xe_gpu_scheduler *sched) · 11 unmodified lines | ||
| 56 | 56 | struct drm_sched_job *s_job; |
| 57 | 57 | bool restore_replay = false; |
| 58 | 58 | |
| 59 | − list_for_each_entry(s_job, &sched->base.pending_list, list) { | |
| 60 | − struct drm_sched_fence *s_fence = s_job->s_fence; | |
| 61 | − struct dma_fence *hw_fence = s_fence->parent; | |
| 62 | − | |
| 59 | + drm_sched_for_each_pending_job(s_job, &sched->base, NULL) { | |
| 63 | 60 | restore_replay |= to_xe_sched_job(s_job)->restore_replay; |
| 64 | − if (restore_replay || (hw_fence && !dma_fence_is_signaled(hw_fence))) | |
| 61 | + if (restore_replay || !drm_sched_job_is_signaled(s_job)) | |
| 65 | 62 | sched->base.ops->run_job(s_job); |
| 66 | 63 | } |
| 67 | 64 | } |
| @@ -72,14 +69,6 @@ xe_sched_invalidate_job(struct xe_sched_job *job, int threshold) · 4 unmodified lines | ||
| 72 | 69 | return drm_sched_invalidate_job(&job->drm, threshold); |
| 73 | 70 | } |
| 74 | 71 | |
| 75 | −static inline void xe_sched_add_pending_job(struct xe_gpu_scheduler *sched, | |
| 76 | − struct xe_sched_job *job) | |
| 77 | −{ | |
| 78 | − spin_lock(&sched->base.job_list_lock); | |
| 79 | − list_add(&job->drm.list, &sched->base.pending_list); | |
| 80 | − spin_unlock(&sched->base.job_list_lock); | |
| 81 | −} | |
| 82 | − | |
| 83 | 72 | /** |
| 84 | 73 | * xe_sched_first_pending_job() - Find first pending job which is unsignaled |
| 85 | 74 | * @sched: Xe GPU scheduler |
| @@ -89,21 +78,13 @@ static inline void xe_sched_add_pending_job(struct xe_gpu_scheduler *sched, · 3 unmodified lines | ||
| 89 | 78 | static inline |
| 90 | 79 | struct xe_sched_job *xe_sched_first_pending_job(struct xe_gpu_scheduler *sched) |
| 91 | 80 | { |
| 92 | − struct xe_sched_job *job, *r_job = NULL; | |
| 93 | − | |
| 94 | − spin_lock(&sched->base.job_list_lock); | |
| 95 | − list_for_each_entry(job, &sched->base.pending_list, drm.list) { | |
| 96 | − struct drm_sched_fence *s_fence = job->drm.s_fence; | |
| 97 | − struct dma_fence *hw_fence = s_fence->parent; | |
| 81 | + struct drm_sched_job *job; | |
| 98 | 82 | |
| 99 | − if (hw_fence && !dma_fence_is_signaled(hw_fence)) { | |
| 100 | − r_job = job; | |
| 101 | − break; | |
| 102 | − } | |
| 103 | − } | |
| 104 | − spin_unlock(&sched->base.job_list_lock); | |
| 83 | + drm_sched_for_each_pending_job(job, &sched->base, NULL) | |
| 84 | + if (!drm_sched_job_is_signaled(job)) | |
| 85 | + return to_xe_sched_job(job); | |
| 105 | 86 | |
| 106 | − return r_job; | |
| 87 | + return NULL; | |
| 107 | 88 | } |
| 108 | 89 | |
| 109 | 90 | static inline int |
| @@ -47,6 +47,8 @@ struct xe_gpu_scheduler { · 46 unmodified lines | ||
| 47 | 47 | const struct xe_sched_backend_ops *ops; |
| 48 | 48 | /** @msgs: list of messages to be processed in @work_process_msg */ |
| 49 | 49 | struct list_head msgs; |
| 50 | + /** @msg_lock: Message lock */ | |
| 51 | + spinlock_t msg_lock; | |
| 50 | 52 | /** @work_process_msg: processes messages */ |
| 51 | 53 | struct work_struct work_process_msg; |
| 52 | 54 | }; |
| @@ -414,15 +414,16 @@ int xe_gsc_init(struct xe_gsc *gsc) · 413 unmodified lines | ||
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | /* |
| 417 | − * Some platforms can have GuC but not GSC. That would cause | |
| 418 | − * xe_uc_fw_init(gsc) to return a "not supported" failure code and abort | |
| 419 | − * all firmware loading. So check for GSC being enabled before | |
| 420 | − * propagating the failure back up. That way the higher level will keep | |
| 421 | − * going and load GuC as appropriate. | |
| 417 | + * Starting from BMG the GSC is no longer needed for MC6 entry, so the | |
| 418 | + * only missing features if the FW is lacking would be the content | |
| 419 | + * protection ones. This is acceptable, so we allow the driver load to | |
| 420 | + * continue if the GSC FW is missing. | |
| 422 | 421 | */ |
| 423 | 422 | ret = xe_uc_fw_init(&gsc->fw); |
| 424 | 423 | if (!xe_uc_fw_is_enabled(&gsc->fw)) |
| 425 | 424 | return 0; |
| 425 | + else if (gt_to_xe(gt)->info.platform >= XE_BATTLEMAGE && !xe_uc_fw_is_available(&gsc->fw)) | |
| 426 | + return 0; | |
| 426 | 427 | else if (ret) |
| 427 | 428 | goto out; |
| 428 | 429 | |
| @@ -614,7 +615,7 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) · 185 unmodified lines | ||
| 614 | 615 | |
| 615 | 616 | drm_printf(p, "\tfound security version %u\n", gsc->security_version); |
| 616 | 617 | |
| 617 | − if (!xe_uc_fw_is_enabled(&gsc->fw)) | |
| 618 | + if (!xe_uc_fw_is_available(&gsc->fw)) | |
| 618 | 619 | return; |
| 619 | 620 | |
| 620 | 621 | CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC); |
| @@ -7,11 +7,10 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <drm/drm_debugfs.h> |
| 9 | 9 | #include <drm/drm_managed.h> |
| 10 | +#include <drm/drm_print.h> | |
| 10 | 11 | |
| 11 | −#include "xe_device.h" | |
| 12 | −#include "xe_gt.h" | |
| 12 | +#include "xe_gt_types.h" | |
| 13 | 13 | #include "xe_gsc.h" |
| 14 | −#include "xe_macros.h" | |
| 15 | 14 | #include "xe_pm.h" |
| 16 | 15 | |
| 17 | 16 | static struct xe_gt * |
| @@ -18,8 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "xe_force_wake.h" |
| 19 | 19 | #include "xe_gsc.h" |
| 20 | 20 | #include "xe_gsc_submit.h" |
| 21 | −#include "xe_gt.h" | |
| 22 | 21 | #include "xe_gt_printk.h" |
| 22 | +#include "xe_gt_types.h" | |
| 23 | 23 | #include "xe_map.h" |
| 24 | 24 | #include "xe_mmio.h" |
| 25 | 25 | #include "xe_pm.h" |
| @@ -11,12 +11,10 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "xe_assert.h" |
| 12 | 12 | #include "xe_bb.h" |
| 13 | 13 | #include "xe_exec_queue.h" |
| 14 | −#include "xe_gt_printk.h" | |
| 15 | 14 | #include "xe_gt_types.h" |
| 16 | 15 | #include "xe_map.h" |
| 17 | 16 | #include "xe_sched_job.h" |
| 18 | 17 | #include "instructions/xe_gsc_commands.h" |
| 19 | −#include "regs/xe_gsc_regs.h" | |
| 20 | 18 | |
| 21 | 19 | #define GSC_HDR_SIZE (sizeof(struct intel_gsc_mtl_header)) /* shorthand define */ |
| 22 | 20 | |
| @@ -13,13 +13,11 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <generated/xe_wa_oob.h> |
| 14 | 14 | |
| 15 | 15 | #include "instructions/xe_alu_commands.h" |
| 16 | −#include "instructions/xe_gfxpipe_commands.h" | |
| 17 | 16 | #include "instructions/xe_mi_commands.h" |
| 18 | 17 | #include "regs/xe_engine_regs.h" |
| 19 | 18 | #include "regs/xe_gt_regs.h" |
| 20 | 19 | #include "xe_assert.h" |
| 21 | 20 | #include "xe_bb.h" |
| 22 | −#include "xe_bo.h" | |
| 23 | 21 | #include "xe_device.h" |
| 24 | 22 | #include "xe_eu_stall.h" |
| 25 | 23 | #include "xe_exec_queue.h" |
| @@ -140,6 +138,36 @@ static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) · 114 unmodified lines | ||
| 140 | 138 | xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); |
| 141 | 139 | } |
| 142 | 140 | |
| 141 | +static void xe_gt_enable_comp_1wcoh(struct xe_gt *gt) | |
| 142 | +{ | |
| 143 | + struct xe_device *xe = gt_to_xe(gt); | |
| 144 | + unsigned int fw_ref; | |
| 145 | + u32 reg; | |
| 146 | + | |
| 147 | + if (IS_SRIOV_VF(xe)) | |
| 148 | + return; | |
| 149 | + | |
| 150 | + if (GRAPHICS_VER(xe) >= 30 && xe->info.has_flat_ccs) { | |
| 151 | + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); | |
| 152 | + if (!fw_ref) | |
| 153 | + return; | |
| 154 | + | |
| 155 | + reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); | |
| 156 | + reg |= EN_CMP_1WCOH; | |
| 157 | + xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); | |
| 158 | + | |
| 159 | + if (xe_gt_is_media_type(gt)) { | |
| 160 | + xe_mmio_rmw32(>->mmio, XE2_GAMWALK_CTRL_MEDIA, 0, EN_CMP_1WCOH_GW); | |
| 161 | + } else { | |
| 162 | + reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMWALK_CTRL_3D); | |
| 163 | + reg |= EN_CMP_1WCOH_GW; | |
| 164 | + xe_gt_mcr_multicast_write(gt, XE2_GAMWALK_CTRL_3D, reg); | |
| 165 | + } | |
| 166 | + | |
| 167 | + xe_force_wake_put(gt_to_fw(gt), fw_ref); | |
| 168 | + } | |
| 169 | +} | |
| 170 | + | |
| 143 | 171 | static void gt_reset_worker(struct work_struct *w); |
| 144 | 172 | |
| 145 | 173 | static int emit_job_sync(struct xe_exec_queue *q, struct xe_bb *bb, |
| @@ -466,6 +494,7 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) · 320 unmodified lines | ||
| 466 | 494 | xe_gt_topology_init(gt); |
| 467 | 495 | xe_gt_mcr_init(gt); |
| 468 | 496 | xe_gt_enable_host_l2_vram(gt); |
| 497 | + xe_gt_enable_comp_1wcoh(gt); | |
| 469 | 498 | |
| 470 | 499 | if (xe_gt_is_main_type(gt)) { |
| 471 | 500 | err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt); |
| @@ -745,6 +774,7 @@ static int do_gt_restart(struct xe_gt *gt) · 273 unmodified lines | ||
| 745 | 774 | xe_pat_init(gt); |
| 746 | 775 | |
| 747 | 776 | xe_gt_enable_host_l2_vram(gt); |
| 777 | + xe_gt_enable_comp_1wcoh(gt); | |
| 748 | 778 | |
| 749 | 779 | xe_gt_mcr_set_implicit_defaults(gt); |
| 750 | 780 | xe_reg_sr_apply_mmio(>->reg_sr, gt); |
| @@ -8,12 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "xe_gt_clock.h" |
| 9 | 9 | |
| 10 | 10 | #include "regs/xe_gt_regs.h" |
| 11 | −#include "regs/xe_regs.h" | |
| 12 | −#include "xe_assert.h" | |
| 13 | −#include "xe_device.h" | |
| 14 | −#include "xe_gt.h" | |
| 11 | +#include "xe_gt_types.h" | |
| 15 | 12 | #include "xe_gt_printk.h" |
| 16 | −#include "xe_macros.h" | |
| 17 | 13 | #include "xe_mmio.h" |
| 18 | 14 | |
| 19 | 15 | #define f19_2_mhz 19200000 |
| @@ -22,7 +22,6 @@ · 21 unmodified lines | ||
| 22 | 22 | #include "xe_guc_hwconfig.h" |
| 23 | 23 | #include "xe_hw_engine.h" |
| 24 | 24 | #include "xe_lrc.h" |
| 25 | −#include "xe_macros.h" | |
| 26 | 25 | #include "xe_mocs.h" |
| 27 | 26 | #include "xe_pat.h" |
| 28 | 27 | #include "xe_pm.h" |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "xe_gt_sysfs.h" |
| 14 | 14 | #include "xe_guc_pc.h" |
| 15 | 15 | #include "regs/xe_gt_regs.h" |
| 16 | −#include "xe_macros.h" | |
| 17 | 16 | #include "xe_mmio.h" |
| 18 | 17 | #include "xe_pm.h" |
| 19 | 18 | #include "xe_sriov.h" |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include "regs/xe_gt_regs.h" |
| 9 | 9 | #include "xe_assert.h" |
| 10 | −#include "xe_gt.h" | |
| 11 | 10 | #include "xe_gt_printk.h" |
| 12 | 11 | #include "xe_gt_topology.h" |
| 13 | 12 | #include "xe_gt_types.h" |
| @@ -24,13 +24,11 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "xe_guc_buf.h" |
| 25 | 25 | #include "xe_guc_ct.h" |
| 26 | 26 | #include "xe_guc_db_mgr.h" |
| 27 | −#include "xe_guc_fwif.h" | |
| 28 | 27 | #include "xe_guc_id_mgr.h" |
| 29 | 28 | #include "xe_guc_klv_helpers.h" |
| 30 | 29 | #include "xe_guc_klv_thresholds_set.h" |
| 31 | 30 | #include "xe_guc_submit.h" |
| 32 | 31 | #include "xe_lmtt.h" |
| 33 | −#include "xe_map.h" | |
| 34 | 32 | #include "xe_migrate.h" |
| 35 | 33 | #include "xe_sriov.h" |
| 36 | 34 | #include "xe_ttm_vram_mgr.h" |
| @@ -284,7 +282,7 @@ static u32 encode_config_ggtt(u32 *cfg, const struct xe_gt_sriov_config *config, · 247 unmodified lines | ||
| 284 | 282 | if (!xe_ggtt_node_allocated(node)) |
| 285 | 283 | return 0; |
| 286 | 284 | |
| 287 | − return encode_ggtt(cfg, node->base.start, node->base.size, details); | |
| 285 | + return encode_ggtt(cfg, xe_ggtt_node_addr(node), xe_ggtt_node_size(node), details); | |
| 288 | 286 | } |
| 289 | 287 | |
| 290 | 288 | static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n, |
| @@ -393,8 +391,8 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) · 102 unmodified lines | ||
| 393 | 391 | xe_gt_assert(gt, num_dwords <= max_cfg_dwords); |
| 394 | 392 | |
| 395 | 393 | if (vfid == PFID) { |
| 396 | − u64 ggtt_start = xe_wopcm_size(gt_to_xe(gt)); | |
| 397 | − u64 ggtt_size = gt_to_tile(gt)->mem.ggtt->size - ggtt_start; | |
| 394 | + u64 ggtt_start = xe_ggtt_start(gt_to_tile(gt)->mem.ggtt); | |
| 395 | + u64 ggtt_size = xe_ggtt_size(gt_to_tile(gt)->mem.ggtt); | |
| 398 | 396 | |
| 399 | 397 | /* plain PF config data will never include a real GGTT region */ |
| 400 | 398 | xe_gt_assert(gt, !encode_config_ggtt(cfg + num_dwords, config, true)); |
| @@ -545,9 +543,9 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size) · 144 unmodified lines | ||
| 545 | 543 | |
| 546 | 544 | xe_ggtt_assign(node, vfid); |
| 547 | 545 | xe_gt_sriov_dbg_verbose(gt, "VF%u assigned GGTT %llx-%llx\n", |
| 548 | − vfid, node->base.start, node->base.start + node->base.size - 1); | |
| 546 | + vfid, xe_ggtt_node_addr(node), xe_ggtt_node_addr(node) + size - 1); | |
| 549 | 547 | |
| 550 | − err = pf_distribute_config_ggtt(gt->tile, vfid, node->base.start, node->base.size); | |
| 548 | + err = pf_distribute_config_ggtt(gt->tile, vfid, xe_ggtt_node_addr(node), size); | |
| 551 | 549 | if (unlikely(err)) |
| 552 | 550 | goto err; |
| 553 | 551 | |
| @@ -564,7 +562,7 @@ static u64 pf_get_vf_config_ggtt(struct xe_gt *gt, unsigned int vfid) · 10 unmodified lines | ||
| 564 | 562 | struct xe_ggtt_node *node = config->ggtt_region; |
| 565 | 563 | |
| 566 | 564 | xe_gt_assert(gt, xe_gt_is_main_type(gt)); |
| 567 | − return xe_ggtt_node_allocated(node) ? node->base.size : 0; | |
| 565 | + return xe_ggtt_node_allocated(node) ? xe_ggtt_node_size(node) : 0; | |
| 568 | 566 | } |
| 569 | 567 | |
| 570 | 568 | /** |
| @@ -3040,11 +3038,12 @@ int xe_gt_sriov_pf_config_print_ggtt(struct xe_gt *gt, struct drm_printer *p) · 2469 unmodified lines | ||
| 3040 | 3038 | if (!xe_ggtt_node_allocated(config->ggtt_region)) |
| 3041 | 3039 | continue; |
| 3042 | 3040 | |
| 3043 | − string_get_size(config->ggtt_region->base.size, 1, STRING_UNITS_2, | |
| 3041 | + string_get_size(xe_ggtt_node_size(config->ggtt_region), 1, STRING_UNITS_2, | |
| 3044 | 3042 | buf, sizeof(buf)); |
| 3045 | 3043 | drm_printf(p, "VF%u:\t%#0llx-%#llx\t(%s)\n", |
| 3046 | − n, config->ggtt_region->base.start, | |
| 3047 | − config->ggtt_region->base.start + config->ggtt_region->base.size - 1, | |
| 3044 | + n, xe_ggtt_node_addr(config->ggtt_region), | |
| 3045 | + xe_ggtt_node_addr(config->ggtt_region) + | |
| 3046 | + xe_ggtt_node_size(config->ggtt_region) - 1, | |
| 3048 | 3047 | buf); |
| 3049 | 3048 | } |
| 3050 | 3049 | |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <drm/drm_print.h> |
| 9 | 9 | #include <drm/drm_debugfs.h> |
| 10 | 10 | |
| 11 | −#include "xe_bo.h" | |
| 12 | 11 | #include "xe_debugfs.h" |
| 13 | 12 | #include "xe_device.h" |
| 14 | 13 | #include "xe_gt.h" |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include "xe_gt_sriov_pf.h" |
| 15 | 15 | #include "xe_gt_sriov_pf_config.h" |
| 16 | 16 | #include "xe_gt_sriov_pf_control.h" |
| 17 | −#include "xe_gt_sriov_pf_helpers.h" | |
| 18 | 17 | #include "xe_gt_sriov_pf_migration.h" |
| 19 | 18 | #include "xe_gt_sriov_printk.h" |
| 20 | 19 | #include "xe_guc.h" |
| @@ -25,6 +24,7 @@ · 4 unmodified lines | ||
| 25 | 24 | #include "xe_sriov.h" |
| 26 | 25 | #include "xe_sriov_packet.h" |
| 27 | 26 | #include "xe_sriov_packet_types.h" |
| 27 | +#include "xe_sriov_pf_helpers.h" | |
| 28 | 28 | #include "xe_sriov_pf_migration.h" |
| 29 | 29 | |
| 30 | 30 | #define XE_GT_SRIOV_PF_MIGRATION_RING_SIZE 5 |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include "abi/guc_actions_sriov_abi.h" |
| 9 | 9 | |
| 10 | −#include "xe_bo.h" | |
| 11 | 10 | #include "xe_gt.h" |
| 12 | 11 | #include "xe_gt_sriov_pf_helpers.h" |
| 13 | 12 | #include "xe_gt_sriov_pf_policy.h" |
| @@ -5,20 +5,19 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #include <drm/drm_managed.h> |
| 7 | 7 | |
| 8 | −#include "abi/guc_actions_sriov_abi.h" | |
| 9 | 8 | #include "abi/guc_relay_actions_abi.h" |
| 10 | 9 | |
| 11 | 10 | #include "regs/xe_gt_regs.h" |
| 12 | 11 | #include "regs/xe_guc_regs.h" |
| 13 | −#include "regs/xe_regs.h" | |
| 14 | 12 | |
| 13 | +#include "xe_assert.h" | |
| 15 | 14 | #include "xe_mmio.h" |
| 16 | 15 | #include "xe_gt_sriov_printk.h" |
| 17 | −#include "xe_gt_sriov_pf_helpers.h" | |
| 18 | 16 | #include "xe_gt_sriov_pf_service.h" |
| 19 | 17 | #include "xe_gt_sriov_pf_service_types.h" |
| 20 | 18 | #include "xe_guc_ct.h" |
| 21 | 19 | #include "xe_guc_hxg_helpers.h" |
| 20 | +#include "xe_sriov.h" | |
| 22 | 21 | #include "xe_sriov_pf_service.h" |
| 23 | 22 | |
| 24 | 23 | static const struct xe_reg tgl_runtime_regs[] = { |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "abi/guc_klvs_abi.h" |
| 16 | 16 | #include "abi/guc_relay_actions_abi.h" |
| 17 | 17 | #include "regs/xe_gt_regs.h" |
| 18 | −#include "regs/xe_gtt_defs.h" | |
| 19 | 18 | |
| 20 | 19 | #include "xe_assert.h" |
| 21 | 20 | #include "xe_device.h" |
| @@ -43,10 +43,10 @@ struct xe_gt_sriov_vf_runtime { · 42 unmodified lines | ||
| 43 | 43 | }; |
| 44 | 44 | |
| 45 | 45 | /** |
| 46 | − * xe_gt_sriov_vf_migration - VF migration data. | |
| 46 | + * struct xe_gt_sriov_vf_migration - VF migration data. | |
| 47 | 47 | */ |
| 48 | 48 | struct xe_gt_sriov_vf_migration { |
| 49 | − /** @migration: VF migration recovery worker */ | |
| 49 | + /** @worker: VF migration recovery worker */ | |
| 50 | 50 | struct work_struct worker; |
| 51 | 51 | /** @lock: Protects recovery_queued, teardown */ |
| 52 | 52 | spinlock_t lock; |
| @@ -7,8 +7,8 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <drm/drm_print.h> |
| 9 | 9 | |
| 10 | −#include "xe_gt.h" | |
| 11 | 10 | #include "xe_gt_stats.h" |
| 11 | +#include "xe_gt_types.h" | |
| 12 | 12 | |
| 13 | 13 | /** |
| 14 | 14 | * xe_gt_stats_incr - Increments the specified stats counter |
| @@ -76,6 +76,11 @@ static const char *const stat_description[__XE_GT_STATS_NUM_IDS] = { · 61 unmodified lines | ||
| 76 | 76 | "hw_engine_group_suspend_lr_queue_us"), |
| 77 | 77 | DEF_STAT_STR(HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US, |
| 78 | 78 | "hw_engine_group_wait_dma_queue_us"), |
| 79 | + DEF_STAT_STR(PRL_4K_ENTRY_COUNT, "prl_4k_entry_count"), | |
| 80 | + DEF_STAT_STR(PRL_64K_ENTRY_COUNT, "prl_64k_entry_count"), | |
| 81 | + DEF_STAT_STR(PRL_2M_ENTRY_COUNT, "prl_2m_entry_count"), | |
| 82 | + DEF_STAT_STR(PRL_ISSUED_COUNT, "prl_issued_count"), | |
| 83 | + DEF_STAT_STR(PRL_ABORTED_COUNT, "prl_aborted_count"), | |
| 79 | 84 | }; |
| 80 | 85 | |
| 81 | 86 | /** |
| @@ -49,6 +49,11 @@ enum xe_gt_stats_id { · 48 unmodified lines | ||
| 49 | 49 | XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT, |
| 50 | 50 | XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US, |
| 51 | 51 | XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US, |
| 52 | + XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, | |
| 53 | + XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, | |
| 54 | + XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, | |
| 55 | + XE_GT_STATS_ID_PRL_ISSUED_COUNT, | |
| 56 | + XE_GT_STATS_ID_PRL_ABORTED_COUNT, | |
| 52 | 57 | /* must be the last entry */ |
| 53 | 58 | __XE_GT_STATS_NUM_IDS, |
| 54 | 59 | }; |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <drm/drm_managed.h> |
| 12 | 12 | |
| 13 | −#include "xe_gt.h" | |
| 13 | +#include "xe_gt_types.h" | |
| 14 | 14 | |
| 15 | 15 | static void xe_gt_sysfs_kobj_release(struct kobject *kobj) |
| 16 | 16 | { |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <drm/drm_managed.h> |
| 7 | 7 | |
| 8 | 8 | #include <regs/xe_gt_regs.h> |
| 9 | −#include "xe_device.h" | |
| 9 | +#include "xe_device_types.h" | |
| 10 | 10 | #include "xe_gt.h" |
| 11 | 11 | #include "xe_gt_sysfs.h" |
| 12 | 12 | #include "xe_gt_throttle.h" |
| @@ -28,8 +28,6 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "xe_lrc.h" |
| 29 | 29 | #include "xe_map.h" |
| 30 | 30 | #include "xe_mmio.h" |
| 31 | −#include "xe_platform_types.h" | |
| 32 | −#include "xe_uc_fw.h" | |
| 33 | 31 | #include "xe_wa.h" |
| 34 | 32 | |
| 35 | 33 | /* Slack of a few additional entries per engine */ |
| @@ -451,7 +449,7 @@ static void guc_policies_init(struct xe_guc_ads *ads) · 415 unmodified lines | ||
| 451 | 449 | ads_blob_write(ads, policies.max_num_work_items, |
| 452 | 450 | GLOBAL_POLICY_MAX_NUM_WI); |
| 453 | 451 | |
| 454 | − if (xe->wedged.mode == 2) | |
| 452 | + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) | |
| 455 | 453 | global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; |
| 456 | 454 | |
| 457 | 455 | ads_blob_write(ads, policies.global_flags, global_flags); |
| @@ -983,16 +981,17 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off · 525 unmodified lines | ||
| 983 | 981 | /** |
| 984 | 982 | * xe_guc_ads_scheduler_policy_toggle_reset - Toggle reset policy |
| 985 | 983 | * @ads: Additional data structures object |
| 984 | + * @enable_engine_reset: true to enable engine resets, false otherwise | |
| 986 | 985 | * |
| 987 | − * This function update the GuC's engine reset policy based on wedged.mode. | |
| 986 | + * This function update the GuC's engine reset policy. | |
| 988 | 987 | * |
| 989 | 988 | * Return: 0 on success, and negative error code otherwise. |
| 990 | 989 | */ |
| 991 | −int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) | |
| 990 | +int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads, | |
| 991 | + bool enable_engine_reset) | |
| 992 | 992 | { |
| 993 | 993 | struct guc_policies *policies; |
| 994 | 994 | struct xe_guc *guc = ads_to_guc(ads); |
| 995 | − struct xe_device *xe = ads_to_xe(ads); | |
| 996 | 995 | CLASS(xe_guc_buf, buf)(&guc->buf, sizeof(*policies)); |
| 997 | 996 | |
| 998 | 997 | if (!xe_guc_buf_is_valid(buf)) |
| @@ -1004,10 +1003,11 @@ int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) · 5 unmodified lines | ||
| 1004 | 1003 | policies->dpc_promote_time = ads_blob_read(ads, policies.dpc_promote_time); |
| 1005 | 1004 | policies->max_num_work_items = ads_blob_read(ads, policies.max_num_work_items); |
| 1006 | 1005 | policies->is_valid = 1; |
| 1007 | − if (xe->wedged.mode == 2) | |
| 1008 | − policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; | |
| 1009 | − else | |
| 1006 | + | |
| 1007 | + if (enable_engine_reset) | |
| 1010 | 1008 | policies->global_flags &= ~GLOBAL_POLICY_DISABLE_ENGINE_RESET; |
| 1009 | + else | |
| 1010 | + policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; | |
| 1011 | 1011 | |
| 1012 | 1012 | return guc_ads_action_update_policies(ads, xe_guc_buf_flush(buf)); |
| 1013 | 1013 | } |
| @@ -6,6 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | #ifndef _XE_GUC_ADS_H_ |
| 7 | 7 | #define _XE_GUC_ADS_H_ |
| 8 | 8 | |
| 9 | +#include <linux/types.h> | |
| 10 | + | |
| 9 | 11 | struct xe_guc_ads; |
| 10 | 12 | |
| 11 | 13 | int xe_guc_ads_init(struct xe_guc_ads *ads); |
| @@ -13,6 +15,7 @@ int xe_guc_ads_init_post_hwconfig(struct xe_guc_ads *ads); · 1 unmodified line | ||
| 13 | 15 | void xe_guc_ads_populate(struct xe_guc_ads *ads); |
| 14 | 16 | void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads); |
| 15 | 17 | void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads); |
| 16 | −int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads); | |
| 18 | +int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads, | |
| 19 | + bool enable_engine_reset); | |
| 17 | 20 | |
| 18 | 21 | #endif |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/cleanup.h> |
| 7 | 7 | #include <drm/drm_managed.h> |
| 8 | 8 | |
| 9 | −#include "xe_assert.h" | |
| 10 | 9 | #include "xe_bo.h" |
| 11 | 10 | #include "xe_gt_printk.h" |
| 12 | 11 | #include "xe_guc.h" |
| @@ -13,17 +13,14 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "abi/guc_log_abi.h" |
| 14 | 14 | #include "regs/xe_engine_regs.h" |
| 15 | 15 | #include "regs/xe_gt_regs.h" |
| 16 | −#include "regs/xe_guc_regs.h" | |
| 17 | −#include "regs/xe_regs.h" | |
| 18 | 16 | |
| 19 | −#include "xe_bo.h" | |
| 17 | +#include "xe_bo_types.h" | |
| 20 | 18 | #include "xe_device.h" |
| 21 | 19 | #include "xe_exec_queue_types.h" |
| 22 | 20 | #include "xe_gt.h" |
| 23 | 21 | #include "xe_gt_mcr.h" |
| 24 | 22 | #include "xe_gt_printk.h" |
| 25 | 23 | #include "xe_guc.h" |
| 26 | −#include "xe_guc_ads.h" | |
| 27 | 24 | #include "xe_guc_capture.h" |
| 28 | 25 | #include "xe_guc_capture_types.h" |
| 29 | 26 | #include "xe_guc_ct.h" |
| @@ -1889,7 +1886,14 @@ xe_guc_capture_get_matching_and_lock(struct xe_exec_queue *q) · 1859 unmodified lines | ||
| 1889 | 1886 | return NULL; |
| 1890 | 1887 | |
| 1891 | 1888 | xe = gt_to_xe(q->gt); |
| 1892 | − if (xe->wedged.mode >= 2 || !xe_device_uc_enabled(xe) || IS_SRIOV_VF(xe)) | |
| 1889 | + | |
| 1890 | + if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) | |
| 1891 | + return NULL; | |
| 1892 | + | |
| 1893 | + if (!xe_device_uc_enabled(xe)) | |
| 1894 | + return NULL; | |
| 1895 | + | |
| 1896 | + if (IS_SRIOV_VF(xe)) | |
| 1893 | 1897 | return NULL; |
| 1894 | 1898 | |
| 1895 | 1899 | ss = &xe->devcoredump.snapshot; |
| @@ -8,13 +8,12 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <drm/drm_debugfs.h> |
| 9 | 9 | #include <drm/drm_managed.h> |
| 10 | 10 | |
| 11 | −#include "xe_device.h" | |
| 12 | −#include "xe_gt.h" | |
| 11 | +#include "xe_device_types.h" | |
| 12 | +#include "xe_gt_types.h" | |
| 13 | 13 | #include "xe_guc.h" |
| 14 | 14 | #include "xe_guc_ct.h" |
| 15 | 15 | #include "xe_guc_log.h" |
| 16 | 16 | #include "xe_guc_pc.h" |
| 17 | −#include "xe_macros.h" | |
| 18 | 17 | #include "xe_pm.h" |
| 19 | 18 | |
| 20 | 19 | /* |
| @@ -33,8 +33,6 @@ struct xe_guc_exec_queue { · 32 unmodified lines | ||
| 33 | 33 | */ |
| 34 | 34 | #define MAX_STATIC_MSG_TYPE 3 |
| 35 | 35 | struct xe_sched_msg static_msgs[MAX_STATIC_MSG_TYPE]; |
| 36 | − /** @lr_tdr: long running TDR worker */ | |
| 37 | − struct work_struct lr_tdr; | |
| 38 | 36 | /** @destroy_async: do final destroy async from this worker */ |
| 39 | 37 | struct work_struct destroy_async; |
| 40 | 38 | /** @resume_time: time of last resume */ |
| @@ -10,8 +10,8 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include "abi/guc_actions_abi.h" |
| 12 | 12 | #include "xe_bo.h" |
| 13 | −#include "xe_device.h" | |
| 14 | −#include "xe_gt.h" | |
| 13 | +#include "xe_device_types.h" | |
| 14 | +#include "xe_gt_types.h" | |
| 15 | 15 | #include "xe_guc.h" |
| 16 | 16 | #include "xe_map.h" |
| 17 | 17 | |
| @@ -15,8 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "xe_bo.h" |
| 16 | 16 | #include "xe_devcoredump.h" |
| 17 | 17 | #include "xe_force_wake.h" |
| 18 | −#include "xe_gt.h" | |
| 19 | 18 | #include "xe_gt_printk.h" |
| 19 | +#include "xe_gt_types.h" | |
| 20 | 20 | #include "xe_map.h" |
| 21 | 21 | #include "xe_mmio.h" |
| 22 | 22 | #include "xe_module.h" |
| @@ -17,8 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "abi/guc_relay_communication_abi.h" |
| 18 | 18 | |
| 19 | 19 | #include "xe_assert.h" |
| 20 | −#include "xe_device.h" | |
| 21 | −#include "xe_gt.h" | |
| 20 | +#include "xe_device_types.h" | |
| 22 | 21 | #include "xe_gt_sriov_printk.h" |
| 23 | 22 | #include "xe_gt_sriov_pf_service.h" |
| 24 | 23 | #include "xe_guc.h" |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "abi/guc_actions_abi.h" |
| 18 | 18 | #include "abi/guc_actions_slpc_abi.h" |
| 19 | 19 | #include "abi/guc_klvs_abi.h" |
| 20 | −#include "regs/xe_lrc_layout.h" | |
| 21 | 20 | #include "xe_assert.h" |
| 22 | 21 | #include "xe_bo.h" |
| 23 | 22 | #include "xe_devcoredump.h" |
| @@ -36,7 +35,6 @@ · 12 unmodified lines | ||
| 36 | 35 | #include "xe_guc_klv_helpers.h" |
| 37 | 36 | #include "xe_guc_submit_types.h" |
| 38 | 37 | #include "xe_hw_engine.h" |
| 39 | −#include "xe_hw_fence.h" | |
| 40 | 38 | #include "xe_lrc.h" |
| 41 | 39 | #include "xe_macros.h" |
| 42 | 40 | #include "xe_map.h" |
| @@ -71,11 +69,8 @@ exec_queue_to_guc(struct xe_exec_queue *q) · 28 unmodified lines | ||
| 71 | 69 | #define EXEC_QUEUE_STATE_KILLED (1 << 7) |
| 72 | 70 | #define EXEC_QUEUE_STATE_WEDGED (1 << 8) |
| 73 | 71 | #define EXEC_QUEUE_STATE_BANNED (1 << 9) |
| 74 | −#define EXEC_QUEUE_STATE_CHECK_TIMEOUT (1 << 10) | |
| 75 | −#define EXEC_QUEUE_STATE_EXTRA_REF (1 << 11) | |
| 76 | −#define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 12) | |
| 77 | −#define EXEC_QUEUE_STATE_PENDING_TDR_EXIT (1 << 13) | |
| 78 | −#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 14) | |
| 72 | +#define EXEC_QUEUE_STATE_PENDING_RESUME (1 << 10) | |
| 73 | +#define EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND (1 << 11) | |
| 79 | 74 | |
| 80 | 75 | static bool exec_queue_registered(struct xe_exec_queue *q) |
| 81 | 76 | { |
| @@ -207,36 +202,6 @@ static void set_exec_queue_wedged(struct xe_exec_queue *q) · 125 unmodified lines | ||
| 207 | 202 | atomic_or(EXEC_QUEUE_STATE_WEDGED, &q->guc->state); |
| 208 | 203 | } |
| 209 | 204 | |
| 210 | −static bool exec_queue_check_timeout(struct xe_exec_queue *q) | |
| 211 | −{ | |
| 212 | − return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_CHECK_TIMEOUT; | |
| 213 | −} | |
| 214 | − | |
| 215 | −static void set_exec_queue_check_timeout(struct xe_exec_queue *q) | |
| 216 | −{ | |
| 217 | − atomic_or(EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state); | |
| 218 | −} | |
| 219 | − | |
| 220 | −static void clear_exec_queue_check_timeout(struct xe_exec_queue *q) | |
| 221 | −{ | |
| 222 | − atomic_and(~EXEC_QUEUE_STATE_CHECK_TIMEOUT, &q->guc->state); | |
| 223 | −} | |
| 224 | − | |
| 225 | −static bool exec_queue_extra_ref(struct xe_exec_queue *q) | |
| 226 | −{ | |
| 227 | − return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_EXTRA_REF; | |
| 228 | −} | |
| 229 | − | |
| 230 | −static void set_exec_queue_extra_ref(struct xe_exec_queue *q) | |
| 231 | −{ | |
| 232 | − atomic_or(EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); | |
| 233 | −} | |
| 234 | − | |
| 235 | −static void clear_exec_queue_extra_ref(struct xe_exec_queue *q) | |
| 236 | −{ | |
| 237 | − atomic_and(~EXEC_QUEUE_STATE_EXTRA_REF, &q->guc->state); | |
| 238 | −} | |
| 239 | − | |
| 240 | 205 | static bool exec_queue_pending_resume(struct xe_exec_queue *q) |
| 241 | 206 | { |
| 242 | 207 | return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_RESUME; |
| @@ -252,21 +217,6 @@ static void clear_exec_queue_pending_resume(struct xe_exec_queue *q) · 9 unmodified lines | ||
| 252 | 217 | atomic_and(~EXEC_QUEUE_STATE_PENDING_RESUME, &q->guc->state); |
| 253 | 218 | } |
| 254 | 219 | |
| 255 | −static bool exec_queue_pending_tdr_exit(struct xe_exec_queue *q) | |
| 256 | −{ | |
| 257 | − return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_PENDING_TDR_EXIT; | |
| 258 | −} | |
| 259 | − | |
| 260 | −static void set_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) | |
| 261 | −{ | |
| 262 | − atomic_or(EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); | |
| 263 | −} | |
| 264 | − | |
| 265 | −static void clear_exec_queue_pending_tdr_exit(struct xe_exec_queue *q) | |
| 266 | −{ | |
| 267 | − atomic_and(~EXEC_QUEUE_STATE_PENDING_TDR_EXIT, &q->guc->state); | |
| 268 | −} | |
| 269 | − | |
| 270 | 220 | static bool exec_queue_idle_skip_suspend(struct xe_exec_queue *q) |
| 271 | 221 | { |
| 272 | 222 | return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_IDLE_SKIP_SUSPEND; |
| @@ -603,10 +553,7 @@ static void xe_guc_exec_queue_trigger_cleanup(struct xe_exec_queue *q) · 330 unmodified lines | ||
| 603 | 553 | /** to wakeup xe_wait_user_fence ioctl if exec queue is reset */ |
| 604 | 554 | wake_up_all(&xe->ufence_wq); |
| 605 | 555 | |
| 606 | − if (xe_exec_queue_is_lr(q)) | |
| 607 | − queue_work(guc_to_gt(guc)->ordered_wq, &q->guc->lr_tdr); | |
| 608 | − else | |
| 609 | − xe_sched_tdr_queue_imm(&q->guc->sched); | |
| 556 | + xe_sched_tdr_queue_imm(&q->guc->sched); | |
| 610 | 557 | } |
| 611 | 558 | |
| 612 | 559 | static void xe_guc_exec_queue_group_trigger_cleanup(struct xe_exec_queue *q) |
| @@ -639,19 +586,19 @@ static void xe_guc_exec_queue_reset_trigger_cleanup(struct xe_exec_queue *q) · 26 unmodified lines | ||
| 639 | 586 | WRITE_ONCE(group->banned, true); |
| 640 | 587 | |
| 641 | 588 | set_exec_queue_reset(primary); |
| 642 | − if (!exec_queue_banned(primary) && !exec_queue_check_timeout(primary)) | |
| 589 | + if (!exec_queue_banned(primary)) | |
| 643 | 590 | xe_guc_exec_queue_trigger_cleanup(primary); |
| 644 | 591 | |
| 645 | 592 | mutex_lock(&group->list_lock); |
| 646 | 593 | list_for_each_entry(eq, &group->list, multi_queue.link) { |
| 647 | 594 | set_exec_queue_reset(eq); |
| 648 | − if (!exec_queue_banned(eq) && !exec_queue_check_timeout(eq)) | |
| 595 | + if (!exec_queue_banned(eq)) | |
| 649 | 596 | xe_guc_exec_queue_trigger_cleanup(eq); |
| 650 | 597 | } |
| 651 | 598 | mutex_unlock(&group->list_lock); |
| 652 | 599 | } else { |
| 653 | 600 | set_exec_queue_reset(q); |
| 654 | − if (!exec_queue_banned(q) && !exec_queue_check_timeout(q)) | |
| 601 | + if (!exec_queue_banned(q)) | |
| 655 | 602 | xe_guc_exec_queue_trigger_cleanup(q); |
| 656 | 603 | } |
| 657 | 604 | } |
| @@ -994,14 +941,6 @@ static void register_exec_queue(struct xe_exec_queue *q, int ctx_type) · 336 unmodified lines | ||
| 994 | 941 | parallel_write(xe, map, wq_desc.wq_status, WQ_STATUS_ACTIVE); |
| 995 | 942 | } |
| 996 | 943 | |
| 997 | − /* | |
| 998 | − * We must keep a reference for LR engines if engine is registered with | |
| 999 | − * the GuC as jobs signal immediately and can't destroy an engine if the | |
| 1000 | − * GuC has a reference to it. | |
| 1001 | − */ | |
| 1002 | − if (xe_exec_queue_is_lr(q)) | |
| 1003 | − xe_exec_queue_get(q); | |
| 1004 | − | |
| 1005 | 944 | set_exec_queue_registered(q); |
| 1006 | 945 | trace_xe_exec_queue_register(q); |
| 1007 | 946 | if (xe_exec_queue_is_multi_queue_primary(q)) |
| @@ -1202,7 +1141,7 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) · 194 unmodified lines | ||
| 1202 | 1141 | struct xe_sched_job *job = to_xe_sched_job(drm_job); |
| 1203 | 1142 | struct xe_exec_queue *q = job->q; |
| 1204 | 1143 | struct xe_guc *guc = exec_queue_to_guc(q); |
| 1205 | − bool lr = xe_exec_queue_is_lr(q), killed_or_banned_or_wedged = | |
| 1144 | + bool killed_or_banned_or_wedged = | |
| 1206 | 1145 | exec_queue_killed_or_banned_or_wedged(q); |
| 1207 | 1146 | |
| 1208 | 1147 | xe_gt_assert(guc_to_gt(guc), !(exec_queue_destroyed(q) || exec_queue_pending_disable(q)) || |
| @@ -1232,14 +1171,6 @@ guc_exec_queue_run_job(struct drm_sched_job *drm_job) · 23 unmodified lines | ||
| 1232 | 1171 | } |
| 1233 | 1172 | |
| 1234 | 1173 | run_job_out: |
| 1235 | − /* | |
| 1236 | − * We don't care about job-fence ordering in LR VMs because these fences | |
| 1237 | − * are never exported; they are used solely to keep jobs on the pending | |
| 1238 | − * list. Once a queue enters an error state, there's no need to track | |
| 1239 | − * them. | |
| 1240 | − */ | |
| 1241 | − if (killed_or_banned_or_wedged && lr) | |
| 1242 | − xe_sched_job_set_error(job, -ECANCELED); | |
| 1243 | 1174 | |
| 1244 | 1175 | return job->fence; |
| 1245 | 1176 | } |
| @@ -1291,8 +1222,7 @@ static void disable_scheduling_deregister(struct xe_guc *guc, · 45 unmodified lines | ||
| 1291 | 1222 | xe_gt_warn(q->gt, "Pending enable/disable failed to respond\n"); |
| 1292 | 1223 | xe_sched_submission_start(sched); |
| 1293 | 1224 | xe_gt_reset_async(q->gt); |
| 1294 | − if (!xe_exec_queue_is_lr(q)) | |
| 1295 | − xe_sched_tdr_queue_imm(sched); | |
| 1225 | + xe_sched_tdr_queue_imm(sched); | |
| 1296 | 1226 | return; |
| 1297 | 1227 | } |
| 1298 | 1228 | |
| @@ -1339,8 +1269,9 @@ void xe_guc_submit_wedge(struct xe_guc *guc) · 40 unmodified lines | ||
| 1339 | 1269 | err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, |
| 1340 | 1270 | guc_submit_wedged_fini, guc); |
| 1341 | 1271 | if (err) { |
| 1342 | − xe_gt_err(gt, "Failed to register clean-up on wedged.mode=2; " | |
| 1343 | − "Although device is wedged.\n"); | |
| 1272 | + xe_gt_err(gt, "Failed to register clean-up in wedged.mode=%s; " | |
| 1273 | + "Although device is wedged.\n", | |
| 1274 | + xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)); | |
| 1344 | 1275 | return; |
| 1345 | 1276 | } |
| 1346 | 1277 | |
| @@ -1355,7 +1286,7 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc) · 8 unmodified lines | ||
| 1355 | 1286 | { |
| 1356 | 1287 | struct xe_device *xe = guc_to_xe(guc); |
| 1357 | 1288 | |
| 1358 | − if (xe->wedged.mode != 2) | |
| 1289 | + if (xe->wedged.mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) | |
| 1359 | 1290 | return false; |
| 1360 | 1291 | |
| 1361 | 1292 | if (xe_device_wedged(xe)) |
| @@ -1366,84 +1297,6 @@ static bool guc_submit_hint_wedged(struct xe_guc *guc) · 4 unmodified lines | ||
| 1366 | 1297 | return true; |
| 1367 | 1298 | } |
| 1368 | 1299 | |
| 1369 | −static void xe_guc_exec_queue_lr_cleanup(struct work_struct *w) | |
| 1370 | −{ | |
| 1371 | − struct xe_guc_exec_queue *ge = | |
| 1372 | − container_of(w, struct xe_guc_exec_queue, lr_tdr); | |
| 1373 | − struct xe_exec_queue *q = ge->q; | |
| 1374 | − struct xe_guc *guc = exec_queue_to_guc(q); | |
| 1375 | − struct xe_gpu_scheduler *sched = &ge->sched; | |
| 1376 | − struct xe_sched_job *job; | |
| 1377 | − bool wedged = false; | |
| 1378 | − | |
| 1379 | − xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_lr(q)); | |
| 1380 | − | |
| 1381 | − if (vf_recovery(guc)) | |
| 1382 | − return; | |
| 1383 | − | |
| 1384 | − trace_xe_exec_queue_lr_cleanup(q); | |
| 1385 | − | |
| 1386 | − if (!exec_queue_killed(q)) | |
| 1387 | − wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); | |
| 1388 | − | |
| 1389 | − /* Kill the run_job / process_msg entry points */ | |
| 1390 | − xe_sched_submission_stop(sched); | |
| 1391 | − | |
| 1392 | − /* | |
| 1393 | − * Engine state now mostly stable, disable scheduling / deregister if | |
| 1394 | − * needed. This cleanup routine might be called multiple times, where | |
| 1395 | − * the actual async engine deregister drops the final engine ref. | |
| 1396 | − * Calling disable_scheduling_deregister will mark the engine as | |
| 1397 | − * destroyed and fire off the CT requests to disable scheduling / | |
| 1398 | − * deregister, which we only want to do once. We also don't want to mark | |
| 1399 | − * the engine as pending_disable again as this may race with the | |
| 1400 | − * xe_guc_deregister_done_handler() which treats it as an unexpected | |
| 1401 | − * state. | |
| 1402 | − */ | |
| 1403 | − if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) { | |
| 1404 | − struct xe_guc *guc = exec_queue_to_guc(q); | |
| 1405 | − int ret; | |
| 1406 | − | |
| 1407 | − set_exec_queue_banned(q); | |
| 1408 | − disable_scheduling_deregister(guc, q); | |
| 1409 | − | |
| 1410 | − /* | |
| 1411 | − * Must wait for scheduling to be disabled before signalling | |
| 1412 | − * any fences, if GT broken the GT reset code should signal us. | |
| 1413 | − */ | |
| 1414 | − ret = wait_event_timeout(guc->ct.wq, | |
| 1415 | − !exec_queue_pending_disable(q) || | |
| 1416 | − xe_guc_read_stopped(guc) || | |
| 1417 | − vf_recovery(guc), HZ * 5); | |
| 1418 | − if (vf_recovery(guc)) | |
| 1419 | − return; | |
| 1420 | − | |
| 1421 | − if (!ret) { | |
| 1422 | − xe_gt_warn(q->gt, "Schedule disable failed to respond, guc_id=%d\n", | |
| 1423 | − q->guc->id); | |
| 1424 | − xe_devcoredump(q, NULL, "Schedule disable failed to respond, guc_id=%d\n", | |
| 1425 | − q->guc->id); | |
| 1426 | − xe_sched_submission_start(sched); | |
| 1427 | − xe_gt_reset_async(q->gt); | |
| 1428 | − return; | |
| 1429 | − } | |
| 1430 | − } | |
| 1431 | − | |
| 1432 | − if (!exec_queue_killed(q) && !xe_lrc_ring_is_idle(q->lrc[0])) | |
| 1433 | − xe_devcoredump(q, NULL, "LR job cleanup, guc_id=%d", q->guc->id); | |
| 1434 | − | |
| 1435 | − xe_hw_fence_irq_stop(q->fence_irq); | |
| 1436 | − | |
| 1437 | − xe_sched_submission_start(sched); | |
| 1438 | − | |
| 1439 | − spin_lock(&sched->base.job_list_lock); | |
| 1440 | − list_for_each_entry(job, &sched->base.pending_list, drm.list) | |
| 1441 | − xe_sched_job_set_error(job, -ECANCELED); | |
| 1442 | − spin_unlock(&sched->base.job_list_lock); | |
| 1443 | − | |
| 1444 | − xe_hw_fence_irq_start(q->fence_irq); | |
| 1445 | −} | |
| 1446 | − | |
| 1447 | 1300 | #define ADJUST_FIVE_PERCENT(__t) mul_u64_u32_div(__t, 105, 100) |
| 1448 | 1301 | |
| 1449 | 1302 | static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) |
| @@ -1462,7 +1315,16 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) · 12 unmodified lines | ||
| 1462 | 1315 | return xe_sched_invalidate_job(job, 2); |
| 1463 | 1316 | } |
| 1464 | 1317 | |
| 1465 | − ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0])); | |
| 1318 | + ctx_timestamp = lower_32_bits(xe_lrc_timestamp(q->lrc[0])); | |
| 1319 | + if (ctx_timestamp == job->sample_timestamp) { | |
| 1320 | + xe_gt_warn(gt, "Check job timeout: seqno=%u, lrc_seqno=%u, guc_id=%d, timestamp stuck", | |
| 1321 | + xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job), | |
| 1322 | + q->guc->id); | |
| 1323 | + | |
| 1324 | + return xe_sched_invalidate_job(job, 0); | |
| 1325 | + } | |
| 1326 | + | |
| 1327 | + job->sample_timestamp = ctx_timestamp; | |
| 1466 | 1328 | ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); |
| 1467 | 1329 | |
| 1468 | 1330 | /* |
| @@ -1516,8 +1378,7 @@ static void enable_scheduling(struct xe_exec_queue *q) · 47 unmodified lines | ||
| 1516 | 1378 | xe_gt_warn(guc_to_gt(guc), "Schedule enable failed to respond"); |
| 1517 | 1379 | set_exec_queue_banned(q); |
| 1518 | 1380 | xe_gt_reset_async(q->gt); |
| 1519 | − if (!xe_exec_queue_is_lr(q)) | |
| 1520 | − xe_sched_tdr_queue_imm(&q->guc->sched); | |
| 1381 | + xe_sched_tdr_queue_imm(&q->guc->sched); | |
| 1521 | 1382 | } |
| 1522 | 1383 | } |
| 1523 | 1384 | |
| @@ -1543,33 +1404,11 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate) · 19 unmodified lines | ||
| 1543 | 1404 | G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1); |
| 1544 | 1405 | } |
| 1545 | 1406 | |
| 1546 | −static void __deregister_exec_queue(struct xe_guc *guc, struct xe_exec_queue *q) | |
| 1547 | −{ | |
| 1548 | − u32 action[] = { | |
| 1549 | − XE_GUC_ACTION_DEREGISTER_CONTEXT, | |
| 1550 | − q->guc->id, | |
| 1551 | − }; | |
| 1552 | − | |
| 1553 | − xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); | |
| 1554 | − xe_gt_assert(guc_to_gt(guc), exec_queue_registered(q)); | |
| 1555 | − xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_enable(q)); | |
| 1556 | − xe_gt_assert(guc_to_gt(guc), !exec_queue_pending_disable(q)); | |
| 1557 | − | |
| 1558 | − set_exec_queue_destroyed(q); | |
| 1559 | − trace_xe_exec_queue_deregister(q); | |
| 1560 | − | |
| 1561 | − if (xe_exec_queue_is_multi_queue_secondary(q)) | |
| 1562 | − handle_deregister_done(guc, q); | |
| 1563 | − else | |
| 1564 | − xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), | |
| 1565 | − G2H_LEN_DW_DEREGISTER_CONTEXT, 1); | |
| 1566 | −} | |
| 1567 | − | |
| 1568 | 1407 | static enum drm_gpu_sched_stat |
| 1569 | 1408 | guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) |
| 1570 | 1409 | { |
| 1571 | 1410 | struct xe_sched_job *job = to_xe_sched_job(drm_job); |
| 1572 | − struct xe_sched_job *tmp_job; | |
| 1411 | + struct drm_sched_job *tmp_job; | |
| 1573 | 1412 | struct xe_exec_queue *q = job->q; |
| 1574 | 1413 | struct xe_gpu_scheduler *sched = &q->guc->sched; |
| 1575 | 1414 | struct xe_guc *guc = exec_queue_to_guc(q); |
| @@ -1577,10 +1416,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 1 unmodified line | ||
| 1577 | 1416 | struct xe_device *xe = guc_to_xe(guc); |
| 1578 | 1417 | int err = -ETIME; |
| 1579 | 1418 | pid_t pid = -1; |
| 1580 | − int i = 0; | |
| 1581 | 1419 | bool wedged = false, skip_timeout_check; |
| 1582 | 1420 | |
| 1583 | − xe_gt_assert(guc_to_gt(guc), !xe_exec_queue_is_lr(q)); | |
| 1421 | + xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q)); | |
| 1584 | 1422 | |
| 1585 | 1423 | /* |
| 1586 | 1424 | * TDR has fired before free job worker. Common if exec queue |
| @@ -1597,14 +1435,17 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 10 unmodified lines | ||
| 1597 | 1435 | |
| 1598 | 1436 | /* Must check all state after stopping scheduler */ |
| 1599 | 1437 | skip_timeout_check = exec_queue_reset(q) || |
| 1600 | − exec_queue_killed_or_banned_or_wedged(q) || | |
| 1601 | − exec_queue_destroyed(q); | |
| 1438 | + exec_queue_killed_or_banned_or_wedged(q); | |
| 1602 | 1439 | |
| 1603 | 1440 | /* Skip timeout check if multi-queue group is banned */ |
| 1604 | 1441 | if (xe_exec_queue_is_multi_queue(q) && |
| 1605 | 1442 | READ_ONCE(q->multi_queue.group->banned)) |
| 1606 | 1443 | skip_timeout_check = true; |
| 1607 | 1444 | |
| 1445 | + /* LR jobs can only get here if queue has been killed or hit an error */ | |
| 1446 | + if (xe_exec_queue_is_lr(q)) | |
| 1447 | + xe_gt_assert(guc_to_gt(guc), skip_timeout_check); | |
| 1448 | + | |
| 1608 | 1449 | /* |
| 1609 | 1450 | * FIXME: In multi-queue scenario, the TDR must ensure that the whole |
| 1610 | 1451 | * multi-queue group is off the HW before signaling the fences to avoid |
| @@ -1628,23 +1469,24 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 17 unmodified lines | ||
| 1628 | 1469 | } |
| 1629 | 1470 | |
| 1630 | 1471 | /* |
| 1631 | − * XXX: Sampling timeout doesn't work in wedged mode as we have to | |
| 1632 | − * modify scheduling state to read timestamp. We could read the | |
| 1633 | − * timestamp from a register to accumulate current running time but this | |
| 1634 | − * doesn't work for SRIOV. For now assuming timeouts in wedged mode are | |
| 1635 | − * genuine timeouts. | |
| 1472 | + * Check if job is actually timed out, if so restart job execution and TDR | |
| 1636 | 1473 | */ |
| 1474 | + if (!skip_timeout_check && !check_timeout(q, job)) | |
| 1475 | + goto rearm; | |
| 1476 | + | |
| 1637 | 1477 | if (!exec_queue_killed(q)) |
| 1638 | 1478 | wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); |
| 1639 | 1479 | |
| 1640 | − /* Engine state now stable, disable scheduling to check timestamp */ | |
| 1641 | − if (!wedged && exec_queue_registered(q)) { | |
| 1480 | + set_exec_queue_banned(q); | |
| 1481 | + | |
| 1482 | + /* Kick job / queue off hardware */ | |
| 1483 | + if (!wedged && (exec_queue_enabled(q) || exec_queue_pending_disable(q))) { | |
| 1642 | 1484 | int ret; |
| 1643 | 1485 | |
| 1644 | 1486 | if (exec_queue_reset(q)) |
| 1645 | 1487 | err = -EIO; |
| 1646 | 1488 | |
| 1647 | − if (!exec_queue_destroyed(q)) { | |
| 1489 | + if (xe_uc_fw_is_running(&guc->fw)) { | |
| 1648 | 1490 | /* |
| 1649 | 1491 | * Wait for any pending G2H to flush out before |
| 1650 | 1492 | * modifying state |
| @@ -1659,13 +1501,6 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 8 unmodified lines | ||
| 1659 | 1501 | if (!ret || xe_guc_read_stopped(guc)) |
| 1660 | 1502 | goto trigger_reset; |
| 1661 | 1503 | |
| 1662 | − /* | |
| 1663 | − * Flag communicates to G2H handler that schedule | |
| 1664 | − * disable originated from a timeout check. The G2H then | |
| 1665 | − * avoid triggering cleanup or deregistering the exec | |
| 1666 | − * queue. | |
| 1667 | − */ | |
| 1668 | − set_exec_queue_check_timeout(q); | |
| 1669 | 1504 | disable_scheduling(q, skip_timeout_check); |
| 1670 | 1505 | } |
| 1671 | 1506 | |
| @@ -1679,6 +1514,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) · 7 unmodified lines | ||
| 1679 | 1514 | */ |
| 1680 | 1515 | smp_rmb(); |
| 1681 | 1516 | ret = wait_event_timeout(guc->ct.wq, |
| 1517 | + !xe_uc_fw_is_running(&guc->fw) || | |
| 1682 | 1518 | !exec_queue_pending_disable(q) || |
| 1683 | 1519 | xe_guc_read_stopped(guc) || |
| 1684 | 1520 | vf_recovery(guc), HZ * 5); |
| @@ -1693,24 +1529,12 @@ trigger_reset: · 8 unmodified lines | ||
| 1693 | 1529 | xe_devcoredump(q, job, |
| 1694 | 1530 | "Schedule disable failed to respond, guc_id=%d, ret=%d, guc_read=%d", |
| 1695 | 1531 | q->guc->id, ret, xe_guc_read_stopped(guc)); |
| 1696 | − set_exec_queue_extra_ref(q); | |
| 1697 | − xe_exec_queue_get(q); /* GT reset owns this */ | |
| 1698 | − set_exec_queue_banned(q); | |
| 1699 | 1532 | xe_gt_reset_async(q->gt); |
| 1700 | 1533 | xe_sched_tdr_queue_imm(sched); |
| 1701 | 1534 | goto rearm; |
| 1702 | 1535 | } |
| 1703 | 1536 | } |
| 1704 | 1537 | |
| 1705 | − /* | |
| 1706 | − * Check if job is actually timed out, if so restart job execution and TDR | |
| 1707 | − */ | |
| 1708 | − if (!wedged && !skip_timeout_check && !check_timeout(q, job) && | |
| 1709 | − !exec_queue_reset(q) && exec_queue_registered(q)) { | |
| 1710 | − clear_exec_queue_check_timeout(q); | |
| 1711 | − goto sched_enable; | |
| 1712 | − } | |
| 1713 | − | |
| 1714 | 1538 | if (q->vm && q->vm->xef) { |
| 1715 | 1539 | process_name = q->vm->xef->process_name; |
| 1716 | 1540 | pid = q->vm->xef->pid; |
| @@ -1741,28 +1565,16 @@ trigger_reset: · 24 unmodified lines | ||
| 1741 | 1565 | if (!wedged && (q->flags & EXEC_QUEUE_FLAG_KERNEL || |
| 1742 | 1566 | (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)))) { |
| 1743 | 1567 | if (!xe_sched_invalidate_job(job, 2)) { |
| 1744 | − clear_exec_queue_check_timeout(q); | |
| 1745 | 1568 | xe_gt_reset_async(q->gt); |
| 1746 | 1569 | goto rearm; |
| 1747 | 1570 | } |
| 1748 | 1571 | } |
| 1749 | 1572 | |
| 1750 | − /* Finish cleaning up exec queue via deregister */ | |
| 1751 | − set_exec_queue_banned(q); | |
| 1752 | − if (!wedged && exec_queue_registered(q) && !exec_queue_destroyed(q)) { | |
| 1753 | − set_exec_queue_extra_ref(q); | |
| 1754 | − xe_exec_queue_get(q); | |
| 1755 | − __deregister_exec_queue(guc, q); | |
| 1756 | − } | |
| 1757 | − | |
| 1758 | − /* Stop fence signaling */ | |
| 1759 | − xe_hw_fence_irq_stop(q->fence_irq); | |
| 1573 | + /* Mark all outstanding jobs as bad, thus completing them */ | |
| 1574 | + xe_sched_job_set_error(job, err); | |
| 1575 | + drm_sched_for_each_pending_job(tmp_job, &sched->base, NULL) | |
| 1576 | + xe_sched_job_set_error(to_xe_sched_job(tmp_job), -ECANCELED); | |
| 1760 | 1577 | |
| 1761 | − /* | |
| 1762 | − * Fence state now stable, stop / start scheduler which cleans up any | |
| 1763 | − * fences that are complete | |
| 1764 | − */ | |
| 1765 | − xe_sched_add_pending_job(sched, job); | |
| 1766 | 1578 | xe_sched_submission_start(sched); |
| 1767 | 1579 | |
| 1768 | 1580 | if (xe_exec_queue_is_multi_queue(q)) |
| @@ -1770,20 +1582,12 @@ trigger_reset: · 1 unmodified line | ||
| 1770 | 1582 | else |
| 1771 | 1583 | xe_guc_exec_queue_trigger_cleanup(q); |
| 1772 | 1584 | |
| 1773 | − /* Mark all outstanding jobs as bad, thus completing them */ | |
| 1774 | − spin_lock(&sched->base.job_list_lock); | |
| 1775 | − list_for_each_entry(tmp_job, &sched->base.pending_list, drm.list) | |
| 1776 | − xe_sched_job_set_error(tmp_job, !i++ ? err : -ECANCELED); | |
| 1777 | − spin_unlock(&sched->base.job_list_lock); | |
| 1778 | − | |
| 1779 | − /* Start fence signaling */ | |
| 1780 | − xe_hw_fence_irq_start(q->fence_irq); | |
| 1781 | − | |
| 1782 | − return DRM_GPU_SCHED_STAT_RESET; | |
| 1585 | + /* | |
| 1586 | + * We want the job added back to the pending list so it gets freed; this | |
| 1587 | + * is what DRM_GPU_SCHED_STAT_NO_HANG does. | |
| 1588 | + */ | |
| 1589 | + return DRM_GPU_SCHED_STAT_NO_HANG; | |
| 1783 | 1590 | |
| 1784 | −sched_enable: | |
| 1785 | − set_exec_queue_pending_tdr_exit(q); | |
| 1786 | − enable_scheduling(q); | |
| 1787 | 1591 | rearm: |
| 1788 | 1592 | /* |
| 1789 | 1593 | * XXX: Ideally want to adjust timeout based on current execution time |
| @@ -1829,8 +1633,6 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) · 39 unmodified lines | ||
| 1829 | 1633 | mutex_unlock(&group->list_lock); |
| 1830 | 1634 | } |
| 1831 | 1635 | |
| 1832 | − if (xe_exec_queue_is_lr(q)) | |
| 1833 | − cancel_work_sync(&ge->lr_tdr); | |
| 1834 | 1636 | /* Confirm no work left behind accessing device structures */ |
| 1835 | 1637 | cancel_delayed_work_sync(&ge->sched.base.work_tdr); |
| 1836 | 1638 | |
| @@ -2134,9 +1936,6 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) · 297 unmodified lines | ||
| 2134 | 1936 | if (err) |
| 2135 | 1937 | goto err_sched; |
| 2136 | 1938 | |
| 2137 | − if (xe_exec_queue_is_lr(q)) | |
| 2138 | − INIT_WORK(&q->guc->lr_tdr, xe_guc_exec_queue_lr_cleanup); | |
| 2139 | − | |
| 2140 | 1939 | mutex_lock(&guc->submission_state.lock); |
| 2141 | 1940 | |
| 2142 | 1941 | err = alloc_guc_id(guc, q); |
| @@ -2432,9 +2231,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) · 289 unmodified lines | ||
| 2432 | 2231 | |
| 2433 | 2232 | /* Clean up lost G2H + reset engine state */ |
| 2434 | 2233 | if (exec_queue_registered(q)) { |
| 2435 | − if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) | |
| 2436 | − xe_exec_queue_put(q); | |
| 2437 | − else if (exec_queue_destroyed(q)) | |
| 2234 | + if (exec_queue_destroyed(q)) | |
| 2438 | 2235 | __guc_exec_queue_destroy(guc, q); |
| 2439 | 2236 | } |
| 2440 | 2237 | if (q->guc->suspend_pending) { |
| @@ -2464,9 +2261,6 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) · 23 unmodified lines | ||
| 2464 | 2261 | trace_xe_sched_job_ban(job); |
| 2465 | 2262 | ban = true; |
| 2466 | 2263 | } |
| 2467 | − } else if (xe_exec_queue_is_lr(q) && | |
| 2468 | − !xe_lrc_ring_is_idle(q->lrc[0])) { | |
| 2469 | − ban = true; | |
| 2470 | 2264 | } |
| 2471 | 2265 | |
| 2472 | 2266 | if (ban) { |
| @@ -2546,11 +2340,8 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, · 73 unmodified lines | ||
| 2546 | 2340 | q->guc->id); |
| 2547 | 2341 | } |
| 2548 | 2342 | |
| 2549 | − if (pending_enable && !pending_resume && | |
| 2550 | − !exec_queue_pending_tdr_exit(q)) { | |
| 2343 | + if (pending_enable && !pending_resume) { | |
| 2551 | 2344 | clear_exec_queue_registered(q); |
| 2552 | − if (xe_exec_queue_is_lr(q)) | |
| 2553 | − xe_exec_queue_put(q); | |
| 2554 | 2345 | xe_gt_dbg(guc_to_gt(guc), "Replay REGISTER - guc_id=%d", |
| 2555 | 2346 | q->guc->id); |
| 2556 | 2347 | } |
| @@ -2558,7 +2349,6 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, · 1 unmodified line | ||
| 2558 | 2349 | if (pending_enable) { |
| 2559 | 2350 | clear_exec_queue_enabled(q); |
| 2560 | 2351 | clear_exec_queue_pending_resume(q); |
| 2561 | − clear_exec_queue_pending_tdr_exit(q); | |
| 2562 | 2352 | clear_exec_queue_pending_enable(q); |
| 2563 | 2353 | xe_gt_dbg(guc_to_gt(guc), "Replay ENABLE - guc_id=%d", |
| 2564 | 2354 | q->guc->id); |
| @@ -2566,11 +2356,7 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, · 1 unmodified line | ||
| 2566 | 2356 | |
| 2567 | 2357 | if (exec_queue_destroyed(q) && exec_queue_registered(q)) { |
| 2568 | 2358 | clear_exec_queue_destroyed(q); |
| 2569 | − if (exec_queue_extra_ref(q)) | |
| 2570 | − xe_exec_queue_put(q); | |
| 2571 | − else | |
| 2572 | − q->guc->needs_cleanup = true; | |
| 2573 | − clear_exec_queue_extra_ref(q); | |
| 2359 | + q->guc->needs_cleanup = true; | |
| 2574 | 2360 | xe_gt_dbg(guc_to_gt(guc), "Replay CLEANUP - guc_id=%d", |
| 2575 | 2361 | q->guc->id); |
| 2576 | 2362 | } |
| @@ -2588,7 +2374,6 @@ static void guc_exec_queue_revert_pending_state_change(struct xe_guc *guc, · 11 unmodified lines | ||
| 2588 | 2374 | if (!pending_enable) |
| 2589 | 2375 | set_exec_queue_enabled(q); |
| 2590 | 2376 | clear_exec_queue_pending_disable(q); |
| 2591 | − clear_exec_queue_check_timeout(q); | |
| 2592 | 2377 | xe_gt_dbg(guc_to_gt(guc), "Replay DISABLE - guc_id=%d", |
| 2593 | 2378 | q->guc->id); |
| 2594 | 2379 | } |
| @@ -2623,10 +2408,7 @@ static void guc_exec_queue_pause(struct xe_guc *guc, struct xe_exec_queue *q) · 28 unmodified lines | ||
| 2623 | 2408 | |
| 2624 | 2409 | /* Stop scheduling + flush any DRM scheduler operations */ |
| 2625 | 2410 | xe_sched_submission_stop(sched); |
| 2626 | − if (xe_exec_queue_is_lr(q)) | |
| 2627 | − cancel_work_sync(&q->guc->lr_tdr); | |
| 2628 | − else | |
| 2629 | − cancel_delayed_work_sync(&sched->base.work_tdr); | |
| 2411 | + cancel_delayed_work_sync(&sched->base.work_tdr); | |
| 2630 | 2412 | |
| 2631 | 2413 | guc_exec_queue_revert_pending_state_change(guc, q); |
| 2632 | 2414 | |
| @@ -2753,11 +2535,12 @@ static void guc_exec_queue_unpause_prepare(struct xe_guc *guc, · 120 unmodified lines | ||
| 2753 | 2535 | struct xe_exec_queue *q) |
| 2754 | 2536 | { |
| 2755 | 2537 | struct xe_gpu_scheduler *sched = &q->guc->sched; |
| 2756 | − struct xe_sched_job *job = NULL, *__job; | |
| 2538 | + struct xe_sched_job *job = NULL; | |
| 2539 | + struct drm_sched_job *s_job; | |
| 2757 | 2540 | bool restore_replay = false; |
| 2758 | 2541 | |
| 2759 | − list_for_each_entry(__job, &sched->base.pending_list, drm.list) { | |
| 2760 | − job = __job; | |
| 2542 | + drm_sched_for_each_pending_job(s_job, &sched->base, NULL) { | |
| 2543 | + job = to_xe_sched_job(s_job); | |
| 2761 | 2544 | restore_replay |= job->restore_replay; |
| 2762 | 2545 | if (restore_replay) { |
| 2763 | 2546 | xe_gt_dbg(guc_to_gt(guc), "Replay JOB - guc_id=%d, seqno=%d", |
| @@ -2881,7 +2664,7 @@ void xe_guc_submit_unpause_vf(struct xe_guc *guc) · 117 unmodified lines | ||
| 2881 | 2664 | * created after resfix done. |
| 2882 | 2665 | */ |
| 2883 | 2666 | if (q->guc->id != index || |
| 2884 | − !READ_ONCE(q->guc->sched.base.pause_submit)) | |
| 2667 | + !drm_sched_is_stopped(&q->guc->sched.base)) | |
| 2885 | 2668 | continue; |
| 2886 | 2669 | |
| 2887 | 2670 | guc_exec_queue_unpause(guc, q); |
| @@ -2967,13 +2750,10 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, · 79 unmodified lines | ||
| 2967 | 2750 | |
| 2968 | 2751 | q->guc->resume_time = ktime_get(); |
| 2969 | 2752 | clear_exec_queue_pending_resume(q); |
| 2970 | − clear_exec_queue_pending_tdr_exit(q); | |
| 2971 | 2753 | clear_exec_queue_pending_enable(q); |
| 2972 | 2754 | smp_wmb(); |
| 2973 | 2755 | wake_up_all(&guc->ct.wq); |
| 2974 | 2756 | } else { |
| 2975 | − bool check_timeout = exec_queue_check_timeout(q); | |
| 2976 | − | |
| 2977 | 2757 | xe_gt_assert(guc_to_gt(guc), runnable_state == 0); |
| 2978 | 2758 | xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q)); |
| 2979 | 2759 | |
| @@ -2981,11 +2761,11 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q, · 1 unmodified line | ||
| 2981 | 2761 | suspend_fence_signal(q); |
| 2982 | 2762 | clear_exec_queue_pending_disable(q); |
| 2983 | 2763 | } else { |
| 2984 | − if (exec_queue_banned(q) || check_timeout) { | |
| 2764 | + if (exec_queue_banned(q)) { | |
| 2985 | 2765 | smp_wmb(); |
| 2986 | 2766 | wake_up_all(&guc->ct.wq); |
| 2987 | 2767 | } |
| 2988 | − if (!check_timeout && exec_queue_destroyed(q)) { | |
| 2768 | + if (exec_queue_destroyed(q)) { | |
| 2989 | 2769 | /* |
| 2990 | 2770 | * Make sure to clear the pending_disable only |
| 2991 | 2771 | * after sampling the destroyed state. We want |
| @@ -3048,11 +2828,7 @@ static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q) · 56 unmodified lines | ||
| 3048 | 2828 | trace_xe_exec_queue_deregister_done(q); |
| 3049 | 2829 | |
| 3050 | 2830 | clear_exec_queue_registered(q); |
| 3051 | − | |
| 3052 | − if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) | |
| 3053 | − xe_exec_queue_put(q); | |
| 3054 | − else | |
| 3055 | − __guc_exec_queue_destroy(guc, q); | |
| 2831 | + __guc_exec_queue_destroy(guc, q); | |
| 3056 | 2832 | } |
| 3057 | 2833 | |
| 3058 | 2834 | int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len) |
| @@ -3386,29 +3162,6 @@ xe_guc_exec_queue_snapshot_capture(struct xe_exec_queue *q) · 327 unmodified lines | ||
| 3386 | 3162 | snapshot->multi_queue.primary = xe_exec_queue_multi_queue_primary(q)->guc->id; |
| 3387 | 3163 | snapshot->multi_queue.pos = q->multi_queue.pos; |
| 3388 | 3164 | } |
| 3389 | − spin_lock(&sched->base.job_list_lock); | |
| 3390 | − snapshot->pending_list_size = list_count_nodes(&sched->base.pending_list); | |
| 3391 | − snapshot->pending_list = kmalloc_array(snapshot->pending_list_size, | |
| 3392 | − sizeof(struct pending_list_snapshot), | |
| 3393 | − GFP_ATOMIC); | |
| 3394 | − | |
| 3395 | − if (snapshot->pending_list) { | |
| 3396 | − struct xe_sched_job *job_iter; | |
| 3397 | − | |
| 3398 | − i = 0; | |
| 3399 | − list_for_each_entry(job_iter, &sched->base.pending_list, drm.list) { | |
| 3400 | − snapshot->pending_list[i].seqno = | |
| 3401 | − xe_sched_job_seqno(job_iter); | |
| 3402 | − snapshot->pending_list[i].fence = | |
| 3403 | − dma_fence_is_signaled(job_iter->fence) ? 1 : 0; | |
| 3404 | − snapshot->pending_list[i].finished = | |
| 3405 | − dma_fence_is_signaled(&job_iter->drm.s_fence->finished) | |
| 3406 | − ? 1 : 0; | |
| 3407 | − i++; | |
| 3408 | − } | |
| 3409 | − } | |
| 3410 | − | |
| 3411 | − spin_unlock(&sched->base.job_list_lock); | |
| 3412 | 3165 | |
| 3413 | 3166 | return snapshot; |
| 3414 | 3167 | } |
| @@ -3472,13 +3225,6 @@ xe_guc_exec_queue_snapshot_print(struct xe_guc_submit_exec_queue_snapshot *snaps · 57 unmodified lines | ||
| 3472 | 3225 | drm_printf(p, "\tMulti queue primary GuC ID: %d\n", snapshot->multi_queue.primary); |
| 3473 | 3226 | drm_printf(p, "\tMulti queue position: %d\n", snapshot->multi_queue.pos); |
| 3474 | 3227 | } |
| 3475 | − | |
| 3476 | − for (i = 0; snapshot->pending_list && i < snapshot->pending_list_size; | |
| 3477 | − i++) | |
| 3478 | − drm_printf(p, "\tJob: seqno=%d, fence=%d, finished=%d\n", | |
| 3479 | − snapshot->pending_list[i].seqno, | |
| 3480 | − snapshot->pending_list[i].fence, | |
| 3481 | − snapshot->pending_list[i].finished); | |
| 3482 | 3228 | } |
| 3483 | 3229 | |
| 3484 | 3230 | /** |
| @@ -3501,7 +3247,6 @@ void xe_guc_exec_queue_snapshot_free(struct xe_guc_submit_exec_queue_snapshot *s · 16 unmodified lines | ||
| 3501 | 3247 | xe_lrc_snapshot_free(snapshot->lrc[i]); |
| 3502 | 3248 | kfree(snapshot->lrc); |
| 3503 | 3249 | } |
| 3504 | − kfree(snapshot->pending_list); | |
| 3505 | 3250 | kfree(snapshot); |
| 3506 | 3251 | } |
| 3507 | 3252 | |
| @@ -61,12 +61,6 @@ struct guc_submit_parallel_scratch { · 60 unmodified lines | ||
| 61 | 61 | u32 wq[WQ_SIZE / sizeof(u32)]; |
| 62 | 62 | }; |
| 63 | 63 | |
| 64 | −struct pending_list_snapshot { | |
| 65 | − u32 seqno; | |
| 66 | − bool fence; | |
| 67 | − bool finished; | |
| 68 | −}; | |
| 69 | − | |
| 70 | 64 | /** |
| 71 | 65 | * struct xe_guc_submit_exec_queue_snapshot - Snapshot for devcoredump |
| 72 | 66 | */ |
| @@ -147,11 +141,6 @@ struct xe_guc_submit_exec_queue_snapshot { · 74 unmodified lines | ||
| 147 | 141 | /** @valid: The exec queue is part of a multi queue group */ |
| 148 | 142 | bool valid; |
| 149 | 143 | } multi_queue; |
| 150 | − | |
| 151 | − /** @pending_list_size: Size of the pending list snapshot array */ | |
| 152 | − int pending_list_size; | |
| 153 | − /** @pending_list: snapshot of the pending list info */ | |
| 154 | − struct pending_list_snapshot *pending_list; | |
| 155 | 144 | }; |
| 156 | 145 | |
| 157 | 146 | #endif |
| @@ -97,6 +97,7 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) · 96 unmodified lines | ||
| 97 | 97 | static int send_page_reclaim(struct xe_guc *guc, u32 seqno, |
| 98 | 98 | u64 gpu_addr) |
| 99 | 99 | { |
| 100 | + struct xe_gt *gt = guc_to_gt(guc); | |
| 100 | 101 | u32 action[] = { |
| 101 | 102 | XE_GUC_ACTION_PAGE_RECLAMATION, |
| 102 | 103 | seqno, |
| @@ -104,6 +105,8 @@ static int send_page_reclaim(struct xe_guc *guc, u32 seqno, · 1 unmodified line | ||
| 104 | 105 | upper_32_bits(gpu_addr), |
| 105 | 106 | }; |
| 106 | 107 | |
| 108 | + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_ISSUED_COUNT, 1); | |
| 109 | + | |
| 107 | 110 | return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), |
| 108 | 111 | G2H_LEN_DW_PAGE_RECLAMATION, 1); |
| 109 | 112 | } |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <drm/drm_print.h> |
| 12 | 12 | |
| 13 | 13 | #include "xe_device_types.h" |
| 14 | −#include "xe_drv.h" | |
| 15 | 14 | #include "xe_heci_gsc.h" |
| 16 | 15 | #include "regs/xe_gsc_regs.h" |
| 17 | 16 | #include "xe_platform_types.h" |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include "abi/gsc_pxp_commands_abi.h" |
| 13 | 13 | #include "regs/xe_gsc_regs.h" |
| 14 | 14 | #include "regs/xe_guc_regs.h" |
| 15 | −#include "xe_assert.h" | |
| 16 | 15 | #include "xe_bo.h" |
| 17 | 16 | #include "xe_device.h" |
| 18 | 17 | #include "xe_force_wake.h" |
| @@ -7,11 +7,10 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <drm/drm_debugfs.h> |
| 9 | 9 | #include <drm/drm_managed.h> |
| 10 | +#include <drm/drm_print.h> | |
| 10 | 11 | |
| 11 | −#include "xe_device.h" | |
| 12 | −#include "xe_gt.h" | |
| 12 | +#include "xe_gt_types.h" | |
| 13 | 13 | #include "xe_huc.h" |
| 14 | −#include "xe_macros.h" | |
| 15 | 14 | #include "xe_pm.h" |
| 16 | 15 | |
| 17 | 16 | static struct xe_gt * |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | ||
| 33 | 33 | #include "xe_hw_fence.h" |
| 34 | 34 | #include "xe_irq.h" |
| 35 | 35 | #include "xe_lrc.h" |
| 36 | −#include "xe_macros.h" | |
| 37 | 36 | #include "xe_mmio.h" |
| 38 | 37 | #include "xe_reg_sr.h" |
| 39 | 38 | #include "xe_reg_whitelist.h" |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/kobject.h> |
| 8 | 8 | #include <linux/sysfs.h> |
| 9 | 9 | |
| 10 | −#include "xe_device.h" | |
| 10 | +#include "xe_device_types.h" | |
| 11 | 11 | #include "xe_gt.h" |
| 12 | 12 | #include "xe_hw_engine_class_sysfs.h" |
| 13 | 13 | #include "xe_pm.h" |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <drm/drm_managed.h> |
| 7 | 7 | |
| 8 | 8 | #include "xe_assert.h" |
| 9 | −#include "xe_device.h" | |
| 9 | +#include "xe_device_types.h" | |
| 10 | 10 | #include "xe_exec_queue.h" |
| 11 | 11 | #include "xe_gt.h" |
| 12 | 12 | #include "xe_gt_stats.h" |
| @@ -8,9 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/device.h> |
| 9 | 9 | #include <linux/slab.h> |
| 10 | 10 | |
| 11 | −#include "xe_bo.h" | |
| 12 | −#include "xe_device.h" | |
| 13 | −#include "xe_gt.h" | |
| 11 | +#include "xe_device_types.h" | |
| 14 | 12 | #include "xe_hw_engine.h" |
| 15 | 13 | #include "xe_macros.h" |
| 16 | 14 | #include "xe_map.h" |
| @@ -108,22 +106,6 @@ void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq) · 91 unmodified lines | ||
| 108 | 106 | irq_work_queue(&irq->work); |
| 109 | 107 | } |
| 110 | 108 | |
| 111 | −void xe_hw_fence_irq_stop(struct xe_hw_fence_irq *irq) | |
| 112 | −{ | |
| 113 | − spin_lock_irq(&irq->lock); | |
| 114 | − irq->enabled = false; | |
| 115 | − spin_unlock_irq(&irq->lock); | |
| 116 | −} | |
| 117 | − | |
| 118 | −void xe_hw_fence_irq_start(struct xe_hw_fence_irq *irq) | |
| 119 | −{ | |
| 120 | − spin_lock_irq(&irq->lock); | |
| 121 | − irq->enabled = true; | |
| 122 | − spin_unlock_irq(&irq->lock); | |
| 123 | − | |
| 124 | − irq_work_queue(&irq->work); | |
| 125 | −} | |
| 126 | − | |
| 127 | 109 | void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt, |
| 128 | 110 | struct xe_hw_fence_irq *irq, const char *name) |
| 129 | 111 | { |
| @@ -17,8 +17,6 @@ void xe_hw_fence_module_exit(void); · 16 unmodified lines | ||
| 17 | 17 | void xe_hw_fence_irq_init(struct xe_hw_fence_irq *irq); |
| 18 | 18 | void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq); |
| 19 | 19 | void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq); |
| 20 | −void xe_hw_fence_irq_stop(struct xe_hw_fence_irq *irq); | |
| 21 | −void xe_hw_fence_irq_start(struct xe_hw_fence_irq *irq); | |
| 22 | 20 | |
| 23 | 21 | void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt, |
| 24 | 22 | struct xe_hw_fence_irq *irq, const char *name); |
| @@ -39,10 +39,16 @@ enum xe_hwmon_reg_operation { · 38 unmodified lines | ||
| 39 | 39 | REG_READ64, |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | +#define MAX_VRAM_CHANNELS (16) | |
| 43 | + | |
| 42 | 44 | enum xe_hwmon_channel { |
| 43 | 45 | CHANNEL_CARD, |
| 44 | 46 | CHANNEL_PKG, |
| 45 | 47 | CHANNEL_VRAM, |
| 48 | + CHANNEL_MCTRL, | |
| 49 | + CHANNEL_PCIE, | |
| 50 | + CHANNEL_VRAM_N, | |
| 51 | + CHANNEL_VRAM_N_MAX = CHANNEL_VRAM_N + MAX_VRAM_CHANNELS, | |
| 46 | 52 | CHANNEL_MAX, |
| 47 | 53 | }; |
| 48 | 54 | |
| @@ -53,6 +59,15 @@ enum xe_fan_channel { · 4 unmodified lines | ||
| 53 | 59 | FAN_MAX, |
| 54 | 60 | }; |
| 55 | 61 | |
| 62 | +enum xe_temp_limit { | |
| 63 | + TEMP_LIMIT_PKG_SHUTDOWN, | |
| 64 | + TEMP_LIMIT_PKG_CRIT, | |
| 65 | + TEMP_LIMIT_MEM_SHUTDOWN, | |
| 66 | + TEMP_LIMIT_PKG_MAX, | |
| 67 | + TEMP_LIMIT_MEM_CRIT, | |
| 68 | + TEMP_LIMIT_MAX | |
| 69 | +}; | |
| 70 | + | |
| 56 | 71 | /* Attribute index for powerX_xxx_interval sysfs entries */ |
| 57 | 72 | enum sensor_attr_power { |
| 58 | 73 | SENSOR_INDEX_PSYS_PL1, |
| @@ -91,6 +106,12 @@ enum sensor_attr_power { · 32 unmodified lines | ||
| 91 | 106 | */ |
| 92 | 107 | #define PL_WRITE_MBX_TIMEOUT_MS (1) |
| 93 | 108 | |
| 109 | +/* Index of memory controller in READ_THERMAL_DATA output */ | |
| 110 | +#define TEMP_INDEX_MCTRL 2 | |
| 111 | + | |
| 112 | +/* Maximum characters in hwmon label name */ | |
| 113 | +#define MAX_LABEL_SIZE 16 | |
| 114 | + | |
| 94 | 115 | /** |
| 95 | 116 | * struct xe_hwmon_energy_info - to accumulate energy |
| 96 | 117 | */ |
| @@ -111,6 +132,24 @@ struct xe_hwmon_fan_info { · 14 unmodified lines | ||
| 111 | 132 | u64 time_prev; |
| 112 | 133 | }; |
| 113 | 134 | |
| 135 | +/** | |
| 136 | + * struct xe_hwmon_thermal_info - to store temperature data | |
| 137 | + */ | |
| 138 | +struct xe_hwmon_thermal_info { | |
| 139 | + union { | |
| 140 | + /** @limit: temperatures limits */ | |
| 141 | + u8 limit[TEMP_LIMIT_MAX]; | |
| 142 | + /** @data: temperature limits in dwords */ | |
| 143 | + u32 data[DIV_ROUND_UP(TEMP_LIMIT_MAX, sizeof(u32))]; | |
| 144 | + }; | |
| 145 | + /** @count: no of temperature sensors available for the platform */ | |
| 146 | + u8 count; | |
| 147 | + /** @value: signed value from each sensor */ | |
| 148 | + s8 value[U8_MAX]; | |
| 149 | + /** @vram_label: vram label names */ | |
| 150 | + char vram_label[MAX_VRAM_CHANNELS][MAX_LABEL_SIZE]; | |
| 151 | +}; | |
| 152 | + | |
| 114 | 153 | /** |
| 115 | 154 | * struct xe_hwmon - xe hwmon data structure |
| 116 | 155 | */ |
| @@ -137,7 +176,8 @@ struct xe_hwmon { · 20 unmodified lines | ||
| 137 | 176 | u32 pl1_on_boot[CHANNEL_MAX]; |
| 138 | 177 | /** @pl2_on_boot: power limit PL2 on boot */ |
| 139 | 178 | u32 pl2_on_boot[CHANNEL_MAX]; |
| 140 | − | |
| 179 | + /** @temp: Temperature info */ | |
| 180 | + struct xe_hwmon_thermal_info temp; | |
| 141 | 181 | }; |
| 142 | 182 | |
| 143 | 183 | static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 attr, int channel, |
| @@ -224,6 +264,8 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg · 80 unmodified lines | ||
| 224 | 264 | return BMG_PACKAGE_TEMPERATURE; |
| 225 | 265 | else if (channel == CHANNEL_VRAM) |
| 226 | 266 | return BMG_VRAM_TEMPERATURE; |
| 267 | + else if (in_range(channel, CHANNEL_VRAM_N, CHANNEL_VRAM_N_MAX)) | |
| 268 | + return BMG_VRAM_TEMPERATURE_N(channel - CHANNEL_VRAM_N); | |
| 227 | 269 | } else if (xe->info.platform == XE_DG2) { |
| 228 | 270 | if (channel == CHANNEL_PKG) |
| 229 | 271 | return PCU_CR_PACKAGE_TEMPERATURE; |
| @@ -677,8 +719,29 @@ static const struct attribute_group *hwmon_groups[] = { · 447 unmodified lines | ||
| 677 | 719 | }; |
| 678 | 720 | |
| 679 | 721 | static const struct hwmon_channel_info * const hwmon_info[] = { |
| 680 | − HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, | |
| 681 | − HWMON_T_INPUT | HWMON_T_LABEL), | |
| 722 | + HWMON_CHANNEL_INFO(temp, | |
| 723 | + HWMON_T_LABEL, | |
| 724 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL | | |
| 725 | + HWMON_T_MAX, | |
| 726 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 727 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 728 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 729 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 730 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 731 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 732 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 733 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 734 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 735 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 736 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 737 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 738 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 739 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 740 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 741 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 742 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 743 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL, | |
| 744 | + HWMON_T_CRIT | HWMON_T_EMERGENCY | HWMON_T_INPUT | HWMON_T_LABEL), | |
| 682 | 745 | HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CRIT | |
| 683 | 746 | HWMON_P_CAP, |
| 684 | 747 | HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_LABEL | HWMON_P_CAP), |
| @@ -689,6 +752,75 @@ static const struct hwmon_channel_info * const hwmon_info[] = { · 4 unmodified lines | ||
| 689 | 752 | NULL |
| 690 | 753 | }; |
| 691 | 754 | |
| 755 | +static int xe_hwmon_pcode_read_thermal_info(struct xe_hwmon *hwmon) | |
| 756 | +{ | |
| 757 | + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); | |
| 758 | + u32 config = 0; | |
| 759 | + int ret; | |
| 760 | + | |
| 761 | + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_LIMITS, 0), | |
| 762 | + &hwmon->temp.data[0], &hwmon->temp.data[1]); | |
| 763 | + if (ret) | |
| 764 | + return ret; | |
| 765 | + | |
| 766 | + drm_dbg(&hwmon->xe->drm, "thermal info read val 0x%x val1 0x%x\n", | |
| 767 | + hwmon->temp.data[0], hwmon->temp.data[1]); | |
| 768 | + | |
| 769 | + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_CONFIG, 0), | |
| 770 | + &config, NULL); | |
| 771 | + if (ret) | |
| 772 | + return ret; | |
| 773 | + | |
| 774 | + drm_dbg(&hwmon->xe->drm, "thermal config count 0x%x\n", config); | |
| 775 | + hwmon->temp.count = REG_FIELD_GET(TEMP_MASK, config); | |
| 776 | + | |
| 777 | + return ret; | |
| 778 | +} | |
| 779 | + | |
| 780 | +static int get_mc_temp(struct xe_hwmon *hwmon, long *val) | |
| 781 | +{ | |
| 782 | + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); | |
| 783 | + u32 *dword = (u32 *)hwmon->temp.value; | |
| 784 | + s32 average = 0; | |
| 785 | + int ret, i; | |
| 786 | + | |
| 787 | + for (i = 0; i < DIV_ROUND_UP(TEMP_LIMIT_MAX, sizeof(u32)); i++) { | |
| 788 | + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_DATA, i), | |
| 789 | + (dword + i), NULL); | |
| 790 | + if (ret) | |
| 791 | + return ret; | |
| 792 | + drm_dbg(&hwmon->xe->drm, "thermal data for group %d val 0x%x\n", i, dword[i]); | |
| 793 | + } | |
| 794 | + | |
| 795 | + for (i = TEMP_INDEX_MCTRL; i < hwmon->temp.count - 1; i++) | |
| 796 | + average += hwmon->temp.value[i]; | |
| 797 | + | |
| 798 | + average /= (hwmon->temp.count - TEMP_INDEX_MCTRL - 1); | |
| 799 | + *val = average * MILLIDEGREE_PER_DEGREE; | |
| 800 | + return 0; | |
| 801 | +} | |
| 802 | + | |
| 803 | +static int get_pcie_temp(struct xe_hwmon *hwmon, long *val) | |
| 804 | +{ | |
| 805 | + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); | |
| 806 | + u32 data = 0; | |
| 807 | + int ret; | |
| 808 | + | |
| 809 | + ret = xe_pcode_read(root_tile, PCODE_MBOX(PCODE_THERMAL_INFO, READ_THERMAL_DATA, | |
| 810 | + PCIE_SENSOR_GROUP_ID), &data, NULL); | |
| 811 | + if (ret) | |
| 812 | + return ret; | |
| 813 | + | |
| 814 | + /* Sensor offset is different for G21 */ | |
| 815 | + if (hwmon->xe->info.subplatform != XE_SUBPLATFORM_BATTLEMAGE_G21) | |
| 816 | + data = REG_FIELD_GET(PCIE_SENSOR_MASK, data); | |
| 817 | + | |
| 818 | + data = REG_FIELD_GET(TEMP_MASK, data); | |
| 819 | + *val = (s8)data * MILLIDEGREE_PER_DEGREE; | |
| 820 | + | |
| 821 | + return 0; | |
| 822 | +} | |
| 823 | + | |
| 692 | 824 | /* I1 is exposed as power_crit or as curr_crit depending on bit 31 */ |
| 693 | 825 | static int xe_hwmon_pcode_read_i1(const struct xe_hwmon *hwmon, u32 *uval) |
| 694 | 826 | { |
| @@ -783,13 +915,77 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu · 88 unmodified lines | ||
| 783 | 915 | *value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE); |
| 784 | 916 | } |
| 785 | 917 | |
| 918 | +static inline bool is_vram_ch_available(struct xe_hwmon *hwmon, int channel) | |
| 919 | +{ | |
| 920 | + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe); | |
| 921 | + int vram_id = channel - CHANNEL_VRAM_N; | |
| 922 | + struct xe_reg vram_reg; | |
| 923 | + | |
| 924 | + vram_reg = xe_hwmon_get_reg(hwmon, REG_TEMP, channel); | |
| 925 | + if (!xe_reg_is_valid(vram_reg) || !xe_mmio_read32(mmio, vram_reg)) | |
| 926 | + return false; | |
| 927 | + | |
| 928 | + /* Create label only for available vram channel */ | |
| 929 | + sprintf(hwmon->temp.vram_label[vram_id], "vram_ch_%d", vram_id); | |
| 930 | + return true; | |
| 931 | +} | |
| 932 | + | |
| 786 | 933 | static umode_t |
| 787 | 934 | xe_hwmon_temp_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel) |
| 788 | 935 | { |
| 789 | 936 | switch (attr) { |
| 937 | + case hwmon_temp_emergency: | |
| 938 | + switch (channel) { | |
| 939 | + case CHANNEL_PKG: | |
| 940 | + return hwmon->temp.limit[TEMP_LIMIT_PKG_SHUTDOWN] ? 0444 : 0; | |
| 941 | + case CHANNEL_VRAM: | |
| 942 | + return hwmon->temp.limit[TEMP_LIMIT_MEM_SHUTDOWN] ? 0444 : 0; | |
| 943 | + case CHANNEL_MCTRL: | |
| 944 | + case CHANNEL_PCIE: | |
| 945 | + return hwmon->temp.count ? 0444 : 0; | |
| 946 | + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: | |
| 947 | + return (is_vram_ch_available(hwmon, channel) && | |
| 948 | + hwmon->temp.limit[TEMP_LIMIT_MEM_SHUTDOWN]) ? 0444 : 0; | |
| 949 | + default: | |
| 950 | + return 0; | |
| 951 | + } | |
| 952 | + case hwmon_temp_crit: | |
| 953 | + switch (channel) { | |
| 954 | + case CHANNEL_PKG: | |
| 955 | + return hwmon->temp.limit[TEMP_LIMIT_PKG_CRIT] ? 0444 : 0; | |
| 956 | + case CHANNEL_VRAM: | |
| 957 | + return hwmon->temp.limit[TEMP_LIMIT_MEM_CRIT] ? 0444 : 0; | |
| 958 | + case CHANNEL_MCTRL: | |
| 959 | + case CHANNEL_PCIE: | |
| 960 | + return hwmon->temp.count ? 0444 : 0; | |
| 961 | + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: | |
| 962 | + return (is_vram_ch_available(hwmon, channel) && | |
| 963 | + hwmon->temp.limit[TEMP_LIMIT_MEM_CRIT]) ? 0444 : 0; | |
| 964 | + default: | |
| 965 | + return 0; | |
| 966 | + } | |
| 967 | + case hwmon_temp_max: | |
| 968 | + switch (channel) { | |
| 969 | + case CHANNEL_PKG: | |
| 970 | + return hwmon->temp.limit[TEMP_LIMIT_PKG_MAX] ? 0444 : 0; | |
| 971 | + default: | |
| 972 | + return 0; | |
| 973 | + } | |
| 790 | 974 | case hwmon_temp_input: |
| 791 | 975 | case hwmon_temp_label: |
| 792 | − return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_TEMP, channel)) ? 0444 : 0; | |
| 976 | + switch (channel) { | |
| 977 | + case CHANNEL_PKG: | |
| 978 | + case CHANNEL_VRAM: | |
| 979 | + return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_TEMP, | |
| 980 | + channel)) ? 0444 : 0; | |
| 981 | + case CHANNEL_MCTRL: | |
| 982 | + case CHANNEL_PCIE: | |
| 983 | + return hwmon->temp.count ? 0444 : 0; | |
| 984 | + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: | |
| 985 | + return is_vram_ch_available(hwmon, channel) ? 0444 : 0; | |
| 986 | + default: | |
| 987 | + return 0; | |
| 988 | + } | |
| 793 | 989 | default: |
| 794 | 990 | return 0; |
| 795 | 991 | } |
| @@ -803,11 +999,67 @@ xe_hwmon_temp_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val) · 7 unmodified lines | ||
| 803 | 999 | |
| 804 | 1000 | switch (attr) { |
| 805 | 1001 | case hwmon_temp_input: |
| 806 | − reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); | |
| 1002 | + switch (channel) { | |
| 1003 | + case CHANNEL_PKG: | |
| 1004 | + case CHANNEL_VRAM: | |
| 1005 | + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); | |
| 807 | 1006 | |
| 808 | − /* HW register value is in degrees Celsius, convert to millidegrees. */ | |
| 809 | − *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; | |
| 810 | − return 0; | |
| 1007 | + /* HW register value is in degrees Celsius, convert to millidegrees. */ | |
| 1008 | + *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; | |
| 1009 | + return 0; | |
| 1010 | + case CHANNEL_MCTRL: | |
| 1011 | + return get_mc_temp(hwmon, val); | |
| 1012 | + case CHANNEL_PCIE: | |
| 1013 | + return get_pcie_temp(hwmon, val); | |
| 1014 | + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: | |
| 1015 | + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_TEMP, channel)); | |
| 1016 | + /* | |
| 1017 | + * This temperature format is 24 bit [31:8] signed integer and 8 bit | |
| 1018 | + * [7:0] fraction. | |
| 1019 | + */ | |
| 1020 | + *val = (s32)(REG_FIELD_GET(TEMP_MASK_VRAM_N, reg_val)) * | |
| 1021 | + (REG_FIELD_GET(TEMP_SIGN_MASK, reg_val) ? -1 : 1) * | |
| 1022 | + MILLIDEGREE_PER_DEGREE; | |
| 1023 | + return 0; | |
| 1024 | + default: | |
| 1025 | + return -EOPNOTSUPP; | |
| 1026 | + } | |
| 1027 | + case hwmon_temp_emergency: | |
| 1028 | + switch (channel) { | |
| 1029 | + case CHANNEL_PKG: | |
| 1030 | + case CHANNEL_MCTRL: | |
| 1031 | + case CHANNEL_PCIE: | |
| 1032 | + *val = hwmon->temp.limit[TEMP_LIMIT_PKG_SHUTDOWN] * MILLIDEGREE_PER_DEGREE; | |
| 1033 | + return 0; | |
| 1034 | + case CHANNEL_VRAM: | |
| 1035 | + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: | |
| 1036 | + *val = hwmon->temp.limit[TEMP_LIMIT_MEM_SHUTDOWN] * MILLIDEGREE_PER_DEGREE; | |
| 1037 | + return 0; | |
| 1038 | + default: | |
| 1039 | + return -EOPNOTSUPP; | |
| 1040 | + } | |
| 1041 | + case hwmon_temp_crit: | |
| 1042 | + switch (channel) { | |
| 1043 | + case CHANNEL_PKG: | |
| 1044 | + case CHANNEL_MCTRL: | |
| 1045 | + case CHANNEL_PCIE: | |
| 1046 | + *val = hwmon->temp.limit[TEMP_LIMIT_PKG_CRIT] * MILLIDEGREE_PER_DEGREE; | |
| 1047 | + return 0; | |
| 1048 | + case CHANNEL_VRAM: | |
| 1049 | + case CHANNEL_VRAM_N...CHANNEL_VRAM_N_MAX: | |
| 1050 | + *val = hwmon->temp.limit[TEMP_LIMIT_MEM_CRIT] * MILLIDEGREE_PER_DEGREE; | |
| 1051 | + return 0; | |
| 1052 | + default: | |
| 1053 | + return -EOPNOTSUPP; | |
| 1054 | + } | |
| 1055 | + case hwmon_temp_max: | |
| 1056 | + switch (channel) { | |
| 1057 | + case CHANNEL_PKG: | |
| 1058 | + *val = hwmon->temp.limit[TEMP_LIMIT_PKG_MAX] * MILLIDEGREE_PER_DEGREE; | |
| 1059 | + return 0; | |
| 1060 | + default: | |
| 1061 | + return -EOPNOTSUPP; | |
| 1062 | + } | |
| 811 | 1063 | default: |
| 812 | 1064 | return -EOPNOTSUPP; |
| 813 | 1065 | } |
| @@ -1163,12 +1415,20 @@ static int xe_hwmon_read_label(struct device *dev, · 349 unmodified lines | ||
| 1163 | 1415 | enum hwmon_sensor_types type, |
| 1164 | 1416 | u32 attr, int channel, const char **str) |
| 1165 | 1417 | { |
| 1418 | + struct xe_hwmon *hwmon = dev_get_drvdata(dev); | |
| 1419 | + | |
| 1166 | 1420 | switch (type) { |
| 1167 | 1421 | case hwmon_temp: |
| 1168 | 1422 | if (channel == CHANNEL_PKG) |
| 1169 | 1423 | *str = "pkg"; |
| 1170 | 1424 | else if (channel == CHANNEL_VRAM) |
| 1171 | 1425 | *str = "vram"; |
| 1426 | + else if (channel == CHANNEL_MCTRL) | |
| 1427 | + *str = "mctrl"; | |
| 1428 | + else if (channel == CHANNEL_PCIE) | |
| 1429 | + *str = "pcie"; | |
| 1430 | + else if (in_range(channel, CHANNEL_VRAM_N, CHANNEL_VRAM_N_MAX)) | |
| 1431 | + *str = hwmon->temp.vram_label[channel - CHANNEL_VRAM_N]; | |
| 1172 | 1432 | return 0; |
| 1173 | 1433 | case hwmon_power: |
| 1174 | 1434 | case hwmon_energy: |
| @@ -1263,6 +1523,9 @@ xe_hwmon_get_preregistration_info(struct xe_hwmon *hwmon) · 88 unmodified lines | ||
| 1263 | 1523 | for (channel = 0; channel < FAN_MAX; channel++) |
| 1264 | 1524 | if (xe_hwmon_is_visible(hwmon, hwmon_fan, hwmon_fan_input, channel)) |
| 1265 | 1525 | xe_hwmon_fan_input_read(hwmon, channel, &fan_speed); |
| 1526 | + | |
| 1527 | + if (hwmon->xe->info.has_mbx_thermal_info && xe_hwmon_pcode_read_thermal_info(hwmon)) | |
| 1528 | + drm_warn(&hwmon->xe->drm, "Thermal mailbox not supported by card firmware\n"); | |
| 1266 | 1529 | } |
| 1267 | 1530 | |
| 1268 | 1531 | int xe_hwmon_register(struct xe_device *xe) |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * Copyright (C) 2025 Intel Corporation. |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | +#include <drm/drm_print.h> | |
| 8 | 9 | #include <linux/array_size.h> |
| 9 | 10 | #include <linux/container_of.h> |
| 10 | 11 | #include <linux/device.h> |
| @@ -26,11 +27,11 @@ · 15 unmodified lines | ||
| 26 | 27 | #include "regs/xe_i2c_regs.h" |
| 27 | 28 | #include "regs/xe_irq_regs.h" |
| 28 | 29 | |
| 29 | −#include "xe_device.h" | |
| 30 | 30 | #include "xe_device_types.h" |
| 31 | 31 | #include "xe_i2c.h" |
| 32 | 32 | #include "xe_mmio.h" |
| 33 | −#include "xe_platform_types.h" | |
| 33 | +#include "xe_sriov.h" | |
| 34 | +#include "xe_survivability_mode.h" | |
| 34 | 35 | |
| 35 | 36 | /** |
| 36 | 37 | * DOC: Xe I2C devices |
| @@ -213,11 +214,13 @@ static const struct irq_domain_ops xe_i2c_irq_ops = { · 176 unmodified lines | ||
| 213 | 214 | .map = xe_i2c_irq_map, |
| 214 | 215 | }; |
| 215 | 216 | |
| 216 | −static int xe_i2c_create_irq(struct xe_i2c *i2c) | |
| 217 | +static int xe_i2c_create_irq(struct xe_device *xe) | |
| 217 | 218 | { |
| 219 | + struct xe_i2c *i2c = xe->i2c; | |
| 218 | 220 | struct irq_domain *domain; |
| 219 | 221 | |
| 220 | − if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ)) | |
| 222 | + if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ) || | |
| 223 | + xe_survivability_mode_is_boot_enabled(xe)) | |
| 221 | 224 | return 0; |
| 222 | 225 | |
| 223 | 226 | domain = irq_domain_create_linear(dev_fwnode(i2c->drm_dev), 1, &xe_i2c_irq_ops, NULL); |
| @@ -351,7 +354,7 @@ int xe_i2c_probe(struct xe_device *xe) · 127 unmodified lines | ||
| 351 | 354 | if (ret) |
| 352 | 355 | return ret; |
| 353 | 356 | |
| 354 | − ret = xe_i2c_create_irq(i2c); | |
| 357 | + ret = xe_i2c_create_irq(xe); | |
| 355 | 358 | if (ret) |
| 356 | 359 | goto err_unregister_notifier; |
| 357 | 360 | |
| @@ -10,7 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <drm/drm_managed.h> |
| 11 | 11 | |
| 12 | 12 | #include "display/xe_display.h" |
| 13 | −#include "regs/xe_guc_regs.h" | |
| 14 | 13 | #include "regs/xe_irq_regs.h" |
| 15 | 14 | #include "xe_device.h" |
| 16 | 15 | #include "xe_drv.h" |
| @@ -15,10 +15,12 @@ · 14 unmodified lines | ||
| 15 | 15 | #define XE_LB_MAX_PAYLOAD_SIZE SZ_4K |
| 16 | 16 | |
| 17 | 17 | /** |
| 18 | − * xe_late_bind_fw_id - enum to determine late binding fw index | |
| 18 | + * enum xe_late_bind_fw_id - enum to determine late binding fw index | |
| 19 | 19 | */ |
| 20 | 20 | enum xe_late_bind_fw_id { |
| 21 | + /** @XE_LB_FW_FAN_CONTROL: Fan control */ | |
| 21 | 22 | XE_LB_FW_FAN_CONTROL = 0, |
| 23 | + /** @XE_LB_FW_MAX_ID: Number of IDs */ | |
| 22 | 24 | XE_LB_FW_MAX_ID |
| 23 | 25 | }; |
| 24 | 26 | |
| @@ -289,7 +289,7 @@ void xe_lmtt_invalidate_hw(struct xe_lmtt *lmtt) · 288 unmodified lines | ||
| 289 | 289 | ERR_PTR(err)); |
| 290 | 290 | |
| 291 | 291 | if (xe_device_has_mert(xe) && xe_tile_is_root(tile)) { |
| 292 | − err = xe_mert_invalidate_lmtt(tile); | |
| 292 | + err = xe_mert_invalidate_lmtt(xe); | |
| 293 | 293 | if (err) |
| 294 | 294 | xe_tile_sriov_err(tile, "MERT LMTT invalidation failed (%pe)", |
| 295 | 295 | ERR_PTR(err)); |
| @@ -857,7 +857,7 @@ u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc) · 856 unmodified lines | ||
| 857 | 857 | * |
| 858 | 858 | * Returns: ctx timestamp value |
| 859 | 859 | */ |
| 860 | −u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) | |
| 860 | +static u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) | |
| 861 | 861 | { |
| 862 | 862 | struct xe_device *xe = lrc_to_xe(lrc); |
| 863 | 863 | struct iosys_map map; |
| @@ -1068,6 +1068,9 @@ static ssize_t setup_utilization_wa(struct xe_lrc *lrc, · 204 unmodified lines | ||
| 1068 | 1068 | { |
| 1069 | 1069 | u32 *cmd = batch; |
| 1070 | 1070 | |
| 1071 | + if (IS_SRIOV_VF(gt_to_xe(lrc->gt))) | |
| 1072 | + return 0; | |
| 1073 | + | |
| 1071 | 1074 | if (xe_gt_WARN_ON(lrc->gt, max_len < 12)) |
| 1072 | 1075 | return -ENOSPC; |
| 1073 | 1076 | |
| @@ -2406,35 +2409,31 @@ static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts) · 1332 unmodified lines | ||
| 2406 | 2409 | } |
| 2407 | 2410 | |
| 2408 | 2411 | /** |
| 2409 | − * xe_lrc_update_timestamp() - Update ctx timestamp | |
| 2412 | + * xe_lrc_timestamp() - Current ctx timestamp | |
| 2410 | 2413 | * @lrc: Pointer to the lrc. |
| 2411 | − * @old_ts: Old timestamp value | |
| 2412 | 2414 | * |
| 2413 | − * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and | |
| 2414 | − * update saved value. With support for active contexts, the calculation may be | |
| 2415 | − * slightly racy, so follow a read-again logic to ensure that the context is | |
| 2416 | − * still active before returning the right timestamp. | |
| 2415 | + * Return latest ctx timestamp. With support for active contexts, the | |
| 2416 | + * calculation may bb slightly racy, so follow a read-again logic to ensure that | |
| 2417 | + * the context is still active before returning the right timestamp. | |
| 2417 | 2418 | * |
| 2418 | 2419 | * Returns: New ctx timestamp value |
| 2419 | 2420 | */ |
| 2420 | −u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) | |
| 2421 | +u64 xe_lrc_timestamp(struct xe_lrc *lrc) | |
| 2421 | 2422 | { |
| 2422 | − u64 lrc_ts, reg_ts; | |
| 2423 | + u64 lrc_ts, reg_ts, new_ts; | |
| 2423 | 2424 | u32 engine_id; |
| 2424 | 2425 | |
| 2425 | − *old_ts = lrc->ctx_timestamp; | |
| 2426 | − | |
| 2427 | 2426 | lrc_ts = xe_lrc_ctx_timestamp(lrc); |
| 2428 | 2427 | /* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */ |
| 2429 | 2428 | if (IS_SRIOV_VF(lrc_to_xe(lrc))) { |
| 2430 | − lrc->ctx_timestamp = lrc_ts; | |
| 2429 | + new_ts = lrc_ts; | |
| 2431 | 2430 | goto done; |
| 2432 | 2431 | } |
| 2433 | 2432 | |
| 2434 | 2433 | if (lrc_ts == CONTEXT_ACTIVE) { |
| 2435 | 2434 | engine_id = xe_lrc_engine_id(lrc); |
| 2436 | 2435 | if (!get_ctx_timestamp(lrc, engine_id, ®_ts)) |
| 2437 | − lrc->ctx_timestamp = reg_ts; | |
| 2436 | + new_ts = reg_ts; | |
| 2438 | 2437 | |
| 2439 | 2438 | /* read lrc again to ensure context is still active */ |
| 2440 | 2439 | lrc_ts = xe_lrc_ctx_timestamp(lrc); |
| @@ -2445,9 +2444,27 @@ u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) · 4 unmodified lines | ||
| 2445 | 2444 | * be a separate if condition. |
| 2446 | 2445 | */ |
| 2447 | 2446 | if (lrc_ts != CONTEXT_ACTIVE) |
| 2448 | − lrc->ctx_timestamp = lrc_ts; | |
| 2447 | + new_ts = lrc_ts; | |
| 2449 | 2448 | |
| 2450 | 2449 | done: |
| 2450 | + return new_ts; | |
| 2451 | +} | |
| 2452 | + | |
| 2453 | +/** | |
| 2454 | + * xe_lrc_update_timestamp() - Update ctx timestamp | |
| 2455 | + * @lrc: Pointer to the lrc. | |
| 2456 | + * @old_ts: Old timestamp value | |
| 2457 | + * | |
| 2458 | + * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and | |
| 2459 | + * update saved value. | |
| 2460 | + * | |
| 2461 | + * Returns: New ctx timestamp value | |
| 2462 | + */ | |
| 2463 | +u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) | |
| 2464 | +{ | |
| 2465 | + *old_ts = lrc->ctx_timestamp; | |
| 2466 | + lrc->ctx_timestamp = xe_lrc_timestamp(lrc); | |
| 2467 | + | |
| 2451 | 2468 | trace_xe_lrc_update_timestamp(lrc, *old_ts); |
| 2452 | 2469 | |
| 2453 | 2470 | return lrc->ctx_timestamp; |
| @@ -145,7 +145,6 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); · 144 unmodified lines | ||
| 145 | 145 | |
| 146 | 146 | u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc); |
| 147 | 147 | u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc); |
| 148 | −u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); | |
| 149 | 148 | u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); |
| 150 | 149 | u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); |
| 151 | 150 | int xe_lrc_setup_wa_bb_with_scratch(struct xe_lrc *lrc, struct xe_hw_engine *hwe, |
| @@ -165,4 +164,6 @@ int xe_lrc_setup_wa_bb_with_scratch(struct xe_lrc *lrc, struct xe_hw_engine *hwe · 13 unmodified lines | ||
| 165 | 164 | */ |
| 166 | 165 | u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts); |
| 167 | 166 | |
| 167 | +u64 xe_lrc_timestamp(struct xe_lrc *lrc); | |
| 168 | + | |
| 168 | 169 | #endif |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include "regs/xe_guc_regs.h" |
| 9 | 9 | #include "regs/xe_irq_regs.h" |
| 10 | −#include "regs/xe_regs.h" | |
| 11 | 10 | |
| 12 | 11 | #include "xe_assert.h" |
| 13 | 12 | #include "xe_bo.h" |
| @@ -16,7 +15,6 @@ · 2 unmodified lines | ||
| 16 | 15 | #include "xe_gt.h" |
| 17 | 16 | #include "xe_guc.h" |
| 18 | 17 | #include "xe_hw_engine.h" |
| 19 | −#include "xe_map.h" | |
| 20 | 18 | #include "xe_memirq.h" |
| 21 | 19 | #include "xe_tile_printk.h" |
| 22 | 20 | |
| @@ -9,25 +9,38 @@ · 8 unmodified lines | ||
| 9 | 9 | #include "xe_device.h" |
| 10 | 10 | #include "xe_mert.h" |
| 11 | 11 | #include "xe_mmio.h" |
| 12 | +#include "xe_sriov_printk.h" | |
| 12 | 13 | #include "xe_tile.h" |
| 13 | 14 | |
| 14 | 15 | /** |
| 15 | − * xe_mert_invalidate_lmtt - Invalidate MERT LMTT | |
| 16 | − * @tile: the &xe_tile | |
| 16 | + * xe_mert_init_early() - Initialize MERT data | |
| 17 | + * @xe: the &xe_device with MERT to init | |
| 18 | + */ | |
| 19 | +void xe_mert_init_early(struct xe_device *xe) | |
| 20 | +{ | |
| 21 | + struct xe_tile *tile = xe_device_get_root_tile(xe); | |
| 22 | + struct xe_mert *mert = &tile->mert; | |
| 23 | + | |
| 24 | + spin_lock_init(&mert->lock); | |
| 25 | + init_completion(&mert->tlb_inv_done); | |
| 26 | +} | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * xe_mert_invalidate_lmtt() - Invalidate MERT LMTT | |
| 30 | + * @xe: the &xe_device with MERT | |
| 17 | 31 | * |
| 18 | 32 | * Trigger invalidation of the MERT LMTT and wait for completion. |
| 19 | 33 | * |
| 20 | 34 | * Return: 0 on success or -ETIMEDOUT in case of a timeout. |
| 21 | 35 | */ |
| 22 | −int xe_mert_invalidate_lmtt(struct xe_tile *tile) | |
| 36 | +int xe_mert_invalidate_lmtt(struct xe_device *xe) | |
| 23 | 37 | { |
| 24 | − struct xe_device *xe = tile_to_xe(tile); | |
| 38 | + struct xe_tile *tile = xe_device_get_root_tile(xe); | |
| 25 | 39 | struct xe_mert *mert = &tile->mert; |
| 26 | 40 | const long timeout = HZ / 4; |
| 27 | 41 | unsigned long flags; |
| 28 | 42 | |
| 29 | 43 | xe_assert(xe, xe_device_has_mert(xe)); |
| 30 | − xe_assert(xe, xe_tile_is_root(tile)); | |
| 31 | 44 | |
| 32 | 45 | spin_lock_irqsave(&mert->lock, flags); |
| 33 | 46 | if (!mert->tlb_inv_triggered) { |
| @@ -43,6 +56,37 @@ int xe_mert_invalidate_lmtt(struct xe_tile *tile) · 9 unmodified lines | ||
| 43 | 56 | return 0; |
| 44 | 57 | } |
| 45 | 58 | |
| 59 | +static void mert_handle_cat_error(struct xe_device *xe) | |
| 60 | +{ | |
| 61 | + struct xe_tile *tile = xe_device_get_root_tile(xe); | |
| 62 | + u32 reg_val, vfid, code; | |
| 63 | + | |
| 64 | + reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT); | |
| 65 | + if (!reg_val) | |
| 66 | + return; | |
| 67 | + xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0); | |
| 68 | + | |
| 69 | + vfid = FIELD_GET(CATERR_VFID, reg_val); | |
| 70 | + code = FIELD_GET(CATERR_CODES, reg_val); | |
| 71 | + | |
| 72 | + switch (code) { | |
| 73 | + case CATERR_NO_ERROR: | |
| 74 | + break; | |
| 75 | + case CATERR_UNMAPPED_GGTT: | |
| 76 | + xe_sriov_err(xe, "MERT: CAT_ERR: Access to an unmapped GGTT!\n"); | |
| 77 | + xe_device_declare_wedged(xe); | |
| 78 | + break; | |
| 79 | + case CATERR_LMTT_FAULT: | |
| 80 | + xe_sriov_dbg(xe, "MERT: CAT_ERR: VF%u LMTT fault!\n", vfid); | |
| 81 | + /* XXX: track/report malicious VF activity */ | |
| 82 | + break; | |
| 83 | + default: | |
| 84 | + xe_sriov_err(xe, "MERT: Unexpected CAT_ERR code=%#x!\n", code); | |
| 85 | + xe_device_declare_wedged(xe); | |
| 86 | + break; | |
| 87 | + } | |
| 88 | +} | |
| 89 | + | |
| 46 | 90 | /** |
| 47 | 91 | * xe_mert_irq_handler - Handler for MERT interrupts |
| 48 | 92 | * @xe: the &xe_device |
| @@ -53,30 +97,22 @@ int xe_mert_invalidate_lmtt(struct xe_tile *tile) · 4 unmodified lines | ||
| 53 | 97 | void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl) |
| 54 | 98 | { |
| 55 | 99 | struct xe_tile *tile = xe_device_get_root_tile(xe); |
| 100 | + struct xe_mert *mert = &tile->mert; | |
| 56 | 101 | unsigned long flags; |
| 57 | 102 | u32 reg_val; |
| 58 | − u8 err; | |
| 59 | 103 | |
| 60 | 104 | if (!(master_ctl & SOC_H2DMEMINT_IRQ)) |
| 61 | 105 | return; |
| 62 | 106 | |
| 63 | − reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT); | |
| 64 | − xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0); | |
| 65 | − | |
| 66 | − err = FIELD_GET(MERT_TLB_CT_ERROR_MASK, reg_val); | |
| 67 | − if (err == MERT_TLB_CT_LMTT_FAULT) | |
| 68 | − drm_dbg(&xe->drm, "MERT catastrophic error: LMTT fault (VF%u)\n", | |
| 69 | − FIELD_GET(MERT_TLB_CT_VFID_MASK, reg_val)); | |
| 70 | − else if (err) | |
| 71 | − drm_dbg(&xe->drm, "MERT catastrophic error: Unexpected fault (0x%x)\n", err); | |
| 107 | + mert_handle_cat_error(xe); | |
| 72 | 108 | |
| 73 | − spin_lock_irqsave(&tile->mert.lock, flags); | |
| 74 | − if (tile->mert.tlb_inv_triggered) { | |
| 109 | + spin_lock_irqsave(&mert->lock, flags); | |
| 110 | + if (mert->tlb_inv_triggered) { | |
| 75 | 111 | reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_INV_DESC_A); |
| 76 | 112 | if (!(reg_val & MERT_TLB_INV_DESC_A_VALID)) { |
| 77 | − tile->mert.tlb_inv_triggered = false; | |
| 78 | − complete_all(&tile->mert.tlb_inv_done); | |
| 113 | + mert->tlb_inv_triggered = false; | |
| 114 | + complete_all(&mert->tlb_inv_done); | |
| 79 | 115 | } |
| 80 | 116 | } |
| 81 | − spin_unlock_irqrestore(&tile->mert.lock, flags); | |
| 117 | + spin_unlock_irqrestore(&mert->lock, flags); | |
| 82 | 118 | } |
| @@ -3,30 +3,33 @@ · 2 unmodified lines | ||
| 3 | 3 | * Copyright(c) 2025, Intel Corporation. All rights reserved. |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | −#ifndef __XE_MERT_H__ | |
| 7 | −#define __XE_MERT_H__ | |
| 6 | +#ifndef _XE_MERT_H_ | |
| 7 | +#define _XE_MERT_H_ | |
| 8 | 8 | |
| 9 | 9 | #include <linux/completion.h> |
| 10 | 10 | #include <linux/spinlock.h> |
| 11 | 11 | #include <linux/types.h> |
| 12 | 12 | |
| 13 | 13 | struct xe_device; |
| 14 | −struct xe_tile; | |
| 15 | 14 | |
| 15 | +/** | |
| 16 | + * struct xe_mert - MERT related data | |
| 17 | + */ | |
| 16 | 18 | struct xe_mert { |
| 17 | 19 | /** @lock: protects the TLB invalidation status */ |
| 18 | 20 | spinlock_t lock; |
| 19 | 21 | /** @tlb_inv_triggered: indicates if TLB invalidation was triggered */ |
| 20 | 22 | bool tlb_inv_triggered; |
| 21 | − /** @mert.tlb_inv_done: completion of TLB invalidation */ | |
| 23 | + /** @tlb_inv_done: completion of TLB invalidation */ | |
| 22 | 24 | struct completion tlb_inv_done; |
| 23 | 25 | }; |
| 24 | 26 | |
| 25 | 27 | #ifdef CONFIG_PCI_IOV |
| 26 | −int xe_mert_invalidate_lmtt(struct xe_tile *tile); | |
| 28 | +void xe_mert_init_early(struct xe_device *xe); | |
| 29 | +int xe_mert_invalidate_lmtt(struct xe_device *xe); | |
| 27 | 30 | void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl); |
| 28 | 31 | #else |
| 29 | 32 | static inline void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl) { } |
| 30 | 33 | #endif |
| 31 | 34 | |
| 32 | −#endif /* __XE_MERT_H__ */ | |
| 35 | +#endif | |
| @@ -14,12 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <drm/drm_print.h> |
| 15 | 15 | |
| 16 | 16 | #include "regs/xe_bars.h" |
| 17 | −#include "regs/xe_regs.h" | |
| 18 | 17 | #include "xe_device.h" |
| 19 | −#include "xe_gt.h" | |
| 20 | −#include "xe_gt_printk.h" | |
| 21 | 18 | #include "xe_gt_sriov_vf.h" |
| 22 | −#include "xe_macros.h" | |
| 23 | 19 | #include "xe_sriov.h" |
| 24 | 20 | #include "xe_trace.h" |
| 25 | 21 | #include "xe_wa.h" |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include "xe_mocs.h" |
| 7 | 7 | |
| 8 | 8 | #include "regs/xe_gt_regs.h" |
| 9 | −#include "xe_bo.h" | |
| 10 | 9 | #include "xe_device.h" |
| 11 | 10 | #include "xe_exec_queue.h" |
| 12 | 11 | #include "xe_force_wake.h" |
| @@ -17,7 +16,6 @@ · 4 unmodified lines | ||
| 17 | 16 | #include "xe_platform_types.h" |
| 18 | 17 | #include "xe_pm.h" |
| 19 | 18 | #include "xe_sriov.h" |
| 20 | −#include "xe_step_types.h" | |
| 21 | 19 | |
| 22 | 20 | #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) |
| 23 | 21 | #define mocs_dbg xe_gt_dbg |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <drm/drm_module.h> |
| 12 | 12 | |
| 13 | +#include "xe_device_types.h" | |
| 13 | 14 | #include "xe_drv.h" |
| 14 | 15 | #include "xe_configfs.h" |
| 15 | 16 | #include "xe_hw_fence.h" |
| @@ -29,7 +30,8 @@ · 13 unmodified lines | ||
| 29 | 30 | #define DEFAULT_FORCE_PROBE CONFIG_DRM_XE_FORCE_PROBE |
| 30 | 31 | #define DEFAULT_MAX_VFS ~0 |
| 31 | 32 | #define DEFAULT_MAX_VFS_STR "unlimited" |
| 32 | −#define DEFAULT_WEDGED_MODE 1 | |
| 33 | +#define DEFAULT_WEDGED_MODE XE_WEDGED_MODE_DEFAULT | |
| 34 | +#define DEFAULT_WEDGED_MODE_STR XE_WEDGED_MODE_DEFAULT_STR | |
| 33 | 35 | #define DEFAULT_SVM_NOTIFIER_SIZE 512 |
| 34 | 36 | |
| 35 | 37 | struct xe_modparam xe_modparam = { |
| @@ -88,10 +90,10 @@ MODULE_PARM_DESC(max_vfs, · 52 unmodified lines | ||
| 88 | 90 | "[default=" DEFAULT_MAX_VFS_STR "])"); |
| 89 | 91 | #endif |
| 90 | 92 | |
| 91 | −module_param_named_unsafe(wedged_mode, xe_modparam.wedged_mode, int, 0600); | |
| 93 | +module_param_named_unsafe(wedged_mode, xe_modparam.wedged_mode, uint, 0600); | |
| 92 | 94 | MODULE_PARM_DESC(wedged_mode, |
| 93 | − "Module's default policy for the wedged mode (0=never, 1=upon-critical-errors, 2=upon-any-hang " | |
| 94 | − "[default=" __stringify(DEFAULT_WEDGED_MODE) "])"); | |
| 95 | + "Module's default policy for the wedged mode (0=never, 1=upon-critical-error, 2=upon-any-hang-no-reset " | |
| 96 | + "[default=" DEFAULT_WEDGED_MODE_STR "])"); | |
| 95 | 97 | |
| 96 | 98 | static int xe_check_nomodeset(void) |
| 97 | 99 | { |
| @@ -21,7 +21,7 @@ struct xe_modparam { · 20 unmodified lines | ||
| 21 | 21 | #ifdef CONFIG_PCI_IOV |
| 22 | 22 | unsigned int max_vfs; |
| 23 | 23 | #endif |
| 24 | − int wedged_mode; | |
| 24 | + unsigned int wedged_mode; | |
| 25 | 25 | u32 svm_notifier_size; |
| 26 | 26 | }; |
| 27 | 27 | |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/intel_dg_nvm_aux.h> |
| 7 | 7 | #include <linux/pci.h> |
| 8 | 8 | |
| 9 | −#include "xe_device.h" | |
| 10 | 9 | #include "xe_device_types.h" |
| 11 | 10 | #include "xe_mmio.h" |
| 12 | 11 | #include "xe_nvm.h" |
| @@ -10,14 +10,11 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include "xe_page_reclaim.h" |
| 12 | 12 | |
| 13 | −#include "regs/xe_gt_regs.h" | |
| 14 | −#include "xe_assert.h" | |
| 13 | +#include "xe_gt_stats.h" | |
| 15 | 14 | #include "xe_macros.h" |
| 16 | −#include "xe_mmio.h" | |
| 17 | 15 | #include "xe_pat.h" |
| 18 | 16 | #include "xe_sa.h" |
| 19 | 17 | #include "xe_tlb_inval_types.h" |
| 20 | −#include "xe_vm.h" | |
| 21 | 18 | |
| 22 | 19 | /** |
| 23 | 20 | * xe_page_reclaim_skip() - Decide whether PRL should be skipped for a VMA |
| @@ -108,7 +105,6 @@ void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl) · 84 unmodified lines | ||
| 108 | 105 | */ |
| 109 | 106 | void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl) |
| 110 | 107 | { |
| 111 | − // xe_page_reclaim_list_invalidate(prl); | |
| 112 | 108 | prl->entries = NULL; |
| 113 | 109 | prl->num_entries = 0; |
| 114 | 110 | } |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | struct xe_tlb_inval; |
| 20 | 20 | struct xe_tlb_inval_fence; |
| 21 | 21 | struct xe_tile; |
| 22 | +struct xe_gt; | |
| 22 | 23 | struct xe_vma; |
| 23 | 24 | |
| 24 | 25 | struct xe_guc_page_reclaim_entry { |
| @@ -75,6 +76,25 @@ struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inva · 50 unmodified lines | ||
| 75 | 76 | struct xe_page_reclaim_list *prl, |
| 76 | 77 | struct xe_tlb_inval_fence *fence); |
| 77 | 78 | void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl); |
| 79 | + | |
| 80 | +/** | |
| 81 | + * xe_page_reclaim_list_abort() - Invalidate a PRL and log an abort reason | |
| 82 | + * @gt: GT owning the page reclaim request | |
| 83 | + * @prl: Page reclaim list to invalidate | |
| 84 | + * @fmt: format string for the log message with args | |
| 85 | + * | |
| 86 | + * Abort page reclaim process by invalidating PRL and doing any relevant logging. | |
| 87 | + */ | |
| 88 | +#define xe_page_reclaim_list_abort(gt, prl, fmt, ...) \ | |
| 89 | + do { \ | |
| 90 | + struct xe_gt *__gt = (gt); \ | |
| 91 | + struct xe_page_reclaim_list *__prl = (prl); \ | |
| 92 | + \ | |
| 93 | + xe_page_reclaim_list_invalidate(__prl); \ | |
| 94 | + xe_gt_stats_incr(__gt, XE_GT_STATS_ID_PRL_ABORTED_COUNT, 1); \ | |
| 95 | + vm_dbg(>_to_xe(__gt)->drm, "PRL aborted: " fmt, ##__VA_ARGS__); \ | |
| 96 | + } while (0) | |
| 97 | + | |
| 78 | 98 | void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl); |
| 79 | 99 | int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl); |
| 80 | 100 | /** |
| @@ -132,9 +132,10 @@ static const struct xe_pat_table_entry xelpg_pat_table[] = { · 131 unmodified lines | ||
| 132 | 132 | * in the table. |
| 133 | 133 | * |
| 134 | 134 | * Note: There is an implicit assumption in the driver that compression and |
| 135 | − * coh_1way+ are mutually exclusive. If this is ever not true then userptr | |
| 136 | − * and imported dma-buf from external device will have uncleared ccs state. See | |
| 137 | − * also xe_bo_needs_ccs_pages(). | |
| 135 | + * coh_1way+ are mutually exclusive for platforms prior to Xe3. Starting | |
| 136 | + * with Xe3, compression can be combined with coherency. If using compression | |
| 137 | + * with coherency, userptr and imported dma-buf from external device will | |
| 138 | + * have uncleared ccs state. See also xe_bo_needs_ccs_pages(). | |
| 138 | 139 | */ |
| 139 | 140 | #define XE2_PAT(no_promote, comp_en, l3clos, l3_policy, l4_policy, __coh_mode) \ |
| 140 | 141 | { \ |
| @@ -144,8 +145,7 @@ static const struct xe_pat_table_entry xelpg_pat_table[] = { · 3 unmodified lines | ||
| 144 | 145 | REG_FIELD_PREP(XE2_L3_POLICY, l3_policy) | \ |
| 145 | 146 | REG_FIELD_PREP(XE2_L4_POLICY, l4_policy) | \ |
| 146 | 147 | REG_FIELD_PREP(XE2_COH_MODE, __coh_mode), \ |
| 147 | − .coh_mode = (BUILD_BUG_ON_ZERO(__coh_mode && comp_en) || __coh_mode) ? \ | |
| 148 | − XE_COH_AT_LEAST_1WAY : XE_COH_NONE, \ | |
| 148 | + .coh_mode = __coh_mode ? XE_COH_AT_LEAST_1WAY : XE_COH_NONE, \ | |
| 149 | 149 | .valid = 1 \ |
| 150 | 150 | } |
| 151 | 151 | |
| @@ -181,6 +181,38 @@ static const struct xe_pat_table_entry xe2_pat_table[] = { · 29 unmodified lines | ||
| 181 | 181 | [31] = XE2_PAT( 0, 0, 3, 0, 3, 3 ), |
| 182 | 182 | }; |
| 183 | 183 | |
| 184 | +static const struct xe_pat_table_entry xe3_lpg_pat_table[] = { | |
| 185 | + [ 0] = XE2_PAT( 0, 0, 0, 0, 3, 0 ), | |
| 186 | + [ 1] = XE2_PAT( 0, 0, 0, 0, 3, 2 ), | |
| 187 | + [ 2] = XE2_PAT( 0, 0, 0, 0, 3, 3 ), | |
| 188 | + [ 3] = XE2_PAT( 0, 0, 0, 3, 3, 0 ), | |
| 189 | + [ 4] = XE2_PAT( 0, 0, 0, 3, 0, 2 ), | |
| 190 | + [ 5] = XE2_PAT( 0, 0, 0, 3, 3, 2 ), | |
| 191 | + [ 6] = XE2_PAT( 1, 0, 0, 1, 3, 0 ), | |
| 192 | + [ 7] = XE2_PAT( 0, 0, 0, 3, 0, 3 ), | |
| 193 | + [ 8] = XE2_PAT( 0, 0, 0, 3, 0, 0 ), | |
| 194 | + [ 9] = XE2_PAT( 0, 1, 0, 0, 3, 0 ), | |
| 195 | + [10] = XE2_PAT( 0, 1, 0, 3, 0, 0 ), | |
| 196 | + [11] = XE2_PAT( 1, 1, 0, 1, 3, 0 ), | |
| 197 | + [12] = XE2_PAT( 0, 1, 0, 3, 3, 0 ), | |
| 198 | + [13] = XE2_PAT( 0, 0, 0, 0, 0, 0 ), | |
| 199 | + [14] = XE2_PAT( 0, 1, 0, 0, 0, 0 ), | |
| 200 | + [15] = XE2_PAT( 1, 1, 0, 1, 1, 0 ), | |
| 201 | + [16] = XE2_PAT( 0, 1, 0, 0, 3, 2 ), | |
| 202 | + /* 17..19 are reserved; leave set to all 0's */ | |
| 203 | + [20] = XE2_PAT( 0, 0, 1, 0, 3, 0 ), | |
| 204 | + [21] = XE2_PAT( 0, 1, 1, 0, 3, 0 ), | |
| 205 | + [22] = XE2_PAT( 0, 0, 1, 0, 3, 2 ), | |
| 206 | + [23] = XE2_PAT( 0, 0, 1, 0, 3, 3 ), | |
| 207 | + [24] = XE2_PAT( 0, 0, 2, 0, 3, 0 ), | |
| 208 | + [25] = XE2_PAT( 0, 1, 2, 0, 3, 0 ), | |
| 209 | + [26] = XE2_PAT( 0, 0, 2, 0, 3, 2 ), | |
| 210 | + [27] = XE2_PAT( 0, 0, 2, 0, 3, 3 ), | |
| 211 | + [28] = XE2_PAT( 0, 0, 3, 0, 3, 0 ), | |
| 212 | + [29] = XE2_PAT( 0, 1, 3, 0, 3, 0 ), | |
| 213 | + [30] = XE2_PAT( 0, 0, 3, 0, 3, 2 ), | |
| 214 | + [31] = XE2_PAT( 0, 0, 3, 0, 3, 3 ), | |
| 215 | +}; | |
| 184 | 216 | /* Special PAT values programmed outside the main table */ |
| 185 | 217 | static const struct xe_pat_table_entry xe2_pat_ats = XE2_PAT( 0, 0, 0, 0, 3, 3 ); |
| 186 | 218 | static const struct xe_pat_table_entry xe2_pat_pta = XE2_PAT( 0, 0, 0, 0, 3, 0 ); |
| @@ -490,6 +522,7 @@ static const struct xe_pat_ops xe3p_xpc_pat_ops = { · 303 unmodified lines | ||
| 490 | 522 | |
| 491 | 523 | void xe_pat_init_early(struct xe_device *xe) |
| 492 | 524 | { |
| 525 | + xe->pat.idx[XE_CACHE_WB_COMPRESSION] = XE_PAT_INVALID_IDX; | |
| 493 | 526 | if (GRAPHICS_VERx100(xe) == 3511) { |
| 494 | 527 | xe->pat.ops = &xe3p_xpc_pat_ops; |
| 495 | 528 | xe->pat.table = xe3p_xpc_pat_table; |
| @@ -501,7 +534,12 @@ void xe_pat_init_early(struct xe_device *xe) · 5 unmodified lines | ||
| 501 | 534 | xe->pat.idx[XE_CACHE_WB] = 2; |
| 502 | 535 | } else if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) { |
| 503 | 536 | xe->pat.ops = &xe2_pat_ops; |
| 504 | − xe->pat.table = xe2_pat_table; | |
| 537 | + if (GRAPHICS_VER(xe) == 30) { | |
| 538 | + xe->pat.table = xe3_lpg_pat_table; | |
| 539 | + xe->pat.idx[XE_CACHE_WB_COMPRESSION] = 16; | |
| 540 | + } else { | |
| 541 | + xe->pat.table = xe2_pat_table; | |
| 542 | + } | |
| 505 | 543 | xe->pat.pat_ats = &xe2_pat_ats; |
| 506 | 544 | if (IS_DGFX(xe)) |
| 507 | 545 | xe->pat.pat_pta = &xe2_pat_pta; |
| @@ -658,6 +696,8 @@ int xe_pat_dump_sw_config(struct xe_gt *gt, struct drm_printer *p) · 150 unmodified lines | ||
| 658 | 696 | if (GRAPHICS_VER(xe) >= 20) { |
| 659 | 697 | drm_printf(p, "IDX[XE_CACHE_NONE_COMPRESSION] = %d\n", |
| 660 | 698 | xe->pat.idx[XE_CACHE_NONE_COMPRESSION]); |
| 699 | + drm_printf(p, "IDX[XE_CACHE_WB_COMPRESSION] = %d\n", | |
| 700 | + xe->pat.idx[XE_CACHE_WB_COMPRESSION]); | |
| 661 | 701 | } |
| 662 | 702 | |
| 663 | 703 | return 0; |
| @@ -12,6 +12,8 @@ struct drm_printer; · 11 unmodified lines | ||
| 12 | 12 | struct xe_device; |
| 13 | 13 | struct xe_gt; |
| 14 | 14 | |
| 15 | +#define XE_PAT_INVALID_IDX U16_MAX | |
| 16 | + | |
| 15 | 17 | /** |
| 16 | 18 | * struct xe_pat_table_entry - The pat_index encoding and other meta information. |
| 17 | 19 | */ |
| @@ -24,7 +24,6 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "xe_gt.h" |
| 25 | 25 | #include "xe_gt_sriov_vf.h" |
| 26 | 26 | #include "xe_guc.h" |
| 27 | −#include "xe_macros.h" | |
| 28 | 27 | #include "xe_mmio.h" |
| 29 | 28 | #include "xe_module.h" |
| 30 | 29 | #include "xe_pci_rebar.h" |
| @@ -366,6 +365,7 @@ static const struct xe_device_desc bmg_desc = { · 335 unmodified lines | ||
| 366 | 365 | .has_fan_control = true, |
| 367 | 366 | .has_flat_ccs = 1, |
| 368 | 367 | .has_mbx_power_limits = true, |
| 368 | + .has_mbx_thermal_info = true, | |
| 369 | 369 | .has_gsc_nvm = 1, |
| 370 | 370 | .has_heci_cscfi = 1, |
| 371 | 371 | .has_i2c = true, |
| @@ -392,6 +392,7 @@ static const struct xe_device_desc ptl_desc = { · 20 unmodified lines | ||
| 392 | 392 | .has_sriov = true, |
| 393 | 393 | .has_mem_copy_instr = true, |
| 394 | 394 | .has_pre_prod_wa = 1, |
| 395 | + .has_pxp = true, | |
| 395 | 396 | .max_gt_per_tile = 2, |
| 396 | 397 | .needs_scratch = true, |
| 397 | 398 | .needs_shared_vf_gt_wq = true, |
| @@ -421,6 +422,7 @@ static const struct xe_device_desc cri_desc = { · 23 unmodified lines | ||
| 421 | 422 | .has_gsc_nvm = 1, |
| 422 | 423 | .has_i2c = true, |
| 423 | 424 | .has_mbx_power_limits = true, |
| 425 | + .has_mbx_thermal_info = true, | |
| 424 | 426 | .has_mert = true, |
| 425 | 427 | .has_pre_prod_wa = 1, |
| 426 | 428 | .has_soc_remapper_sysctrl = true, |
| @@ -686,6 +688,7 @@ static int xe_info_init_early(struct xe_device *xe, · 259 unmodified lines | ||
| 686 | 688 | /* runtime fusing may force flat_ccs to disabled later */ |
| 687 | 689 | xe->info.has_flat_ccs = desc->has_flat_ccs; |
| 688 | 690 | xe->info.has_mbx_power_limits = desc->has_mbx_power_limits; |
| 691 | + xe->info.has_mbx_thermal_info = desc->has_mbx_thermal_info; | |
| 689 | 692 | xe->info.has_gsc_nvm = desc->has_gsc_nvm; |
| 690 | 693 | xe->info.has_heci_gscfi = desc->has_heci_gscfi; |
| 691 | 694 | xe->info.has_heci_cscfi = desc->has_heci_cscfi; |
| @@ -48,6 +48,7 @@ struct xe_device_desc { · 47 unmodified lines | ||
| 48 | 48 | u8 has_late_bind:1; |
| 49 | 49 | u8 has_llc:1; |
| 50 | 50 | u8 has_mbx_power_limits:1; |
| 51 | + u8 has_mbx_thermal_info:1; | |
| 51 | 52 | u8 has_mem_copy_instr:1; |
| 52 | 53 | u8 has_mert:1; |
| 53 | 54 | u8 has_pre_prod_wa:1; |
| @@ -50,6 +50,13 @@ · 49 unmodified lines | ||
| 50 | 50 | #define READ_PL_FROM_FW 0x1 |
| 51 | 51 | #define READ_PL_FROM_PCODE 0x0 |
| 52 | 52 | |
| 53 | +#define PCODE_THERMAL_INFO 0x25 | |
| 54 | +#define READ_THERMAL_LIMITS 0x0 | |
| 55 | +#define READ_THERMAL_CONFIG 0x1 | |
| 56 | +#define READ_THERMAL_DATA 0x2 | |
| 57 | +#define PCIE_SENSOR_GROUP_ID 0x2 | |
| 58 | +#define PCIE_SENSOR_MASK REG_GENMASK(31, 16) | |
| 59 | + | |
| 53 | 60 | #define PCODE_LATE_BINDING 0x5C |
| 54 | 61 | #define GET_CAPABILITY_STATUS 0x0 |
| 55 | 62 | #define V1_FAN_SUPPORTED REG_BIT(0) |
| @@ -260,10 +260,19 @@ int xe_pm_resume(struct xe_device *xe) · 259 unmodified lines | ||
| 260 | 260 | |
| 261 | 261 | xe_irq_resume(xe); |
| 262 | 262 | |
| 263 | − for_each_gt(gt, xe, id) | |
| 264 | − xe_gt_resume(gt); | |
| 263 | + for_each_gt(gt, xe, id) { | |
| 264 | + err = xe_gt_resume(gt); | |
| 265 | + if (err) | |
| 266 | + break; | |
| 267 | + } | |
| 265 | 268 | |
| 269 | + /* | |
| 270 | + * Try to bring up display before bailing from GT resume failure, | |
| 271 | + * so we don't leave the user clueless with a blank screen. | |
| 272 | + */ | |
| 266 | 273 | xe_display_pm_resume(xe); |
| 274 | + if (err) | |
| 275 | + goto err; | |
| 267 | 276 | |
| 268 | 277 | err = xe_bo_restore_late(xe); |
| 269 | 278 | if (err) |
| @@ -656,10 +665,19 @@ int xe_pm_runtime_resume(struct xe_device *xe) · 386 unmodified lines | ||
| 656 | 665 | |
| 657 | 666 | xe_irq_resume(xe); |
| 658 | 667 | |
| 659 | − for_each_gt(gt, xe, id) | |
| 660 | − xe->d3cold.allowed ? xe_gt_resume(gt) : xe_gt_runtime_resume(gt); | |
| 668 | + for_each_gt(gt, xe, id) { | |
| 669 | + err = xe->d3cold.allowed ? xe_gt_resume(gt) : xe_gt_runtime_resume(gt); | |
| 670 | + if (err) | |
| 671 | + break; | |
| 672 | + } | |
| 661 | 673 | |
| 674 | + /* | |
| 675 | + * Try to bring up display before bailing from GT resume failure, | |
| 676 | + * so we don't leave the user clueless with a blank screen. | |
| 677 | + */ | |
| 662 | 678 | xe_display_pm_runtime_resume(xe); |
| 679 | + if (err) | |
| 680 | + goto out; | |
| 663 | 681 | |
| 664 | 682 | if (xe->d3cold.allowed) { |
| 665 | 683 | err = xe_bo_restore_late(xe); |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/debugfs.h> |
| 7 | 7 | |
| 8 | 8 | #include "xe_bo.h" |
| 9 | −#include "xe_device.h" | |
| 9 | +#include "xe_device_types.h" | |
| 10 | 10 | #include "xe_configfs.h" |
| 11 | 11 | #include "xe_psmi.h" |
| 12 | 12 | |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "xe_drm_client.h" |
| 12 | 12 | #include "xe_exec_queue.h" |
| 13 | 13 | #include "xe_gt.h" |
| 14 | +#include "xe_gt_stats.h" | |
| 14 | 15 | #include "xe_migrate.h" |
| 15 | 16 | #include "xe_page_reclaim.h" |
| 16 | 17 | #include "xe_pt_types.h" |
| @@ -1576,12 +1577,6 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level, · 1559 unmodified lines | ||
| 1576 | 1577 | return false; |
| 1577 | 1578 | } |
| 1578 | 1579 | |
| 1579 | −/* Huge 2MB leaf lives directly in a level-1 table and has no children */ | |
| 1580 | −static bool is_2m_pte(struct xe_pt *pte) | |
| 1581 | −{ | |
| 1582 | − return pte->level == 1 && !pte->base.children; | |
| 1583 | −} | |
| 1584 | − | |
| 1585 | 1580 | /* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */ |
| 1586 | 1581 | #define COMPUTE_RECLAIM_ADDRESS_MASK(page_size) \ |
| 1587 | 1582 | ({ \ |
| @@ -1593,8 +1588,10 @@ static int generate_reclaim_entry(struct xe_tile *tile, · 5 unmodified lines | ||
| 1593 | 1588 | struct xe_page_reclaim_list *prl, |
| 1594 | 1589 | u64 pte, struct xe_pt *xe_child) |
| 1595 | 1590 | { |
| 1591 | + struct xe_gt *gt = tile->primary_gt; | |
| 1596 | 1592 | struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries; |
| 1597 | − u64 phys_page = (pte & XE_PTE_ADDR_MASK) >> XE_PTE_SHIFT; | |
| 1593 | + u64 phys_addr = pte & XE_PTE_ADDR_MASK; | |
| 1594 | + u64 phys_page = phys_addr >> XE_PTE_SHIFT; | |
| 1598 | 1595 | int num_entries = prl->num_entries; |
| 1599 | 1596 | u32 reclamation_size; |
| 1600 | 1597 | |
| @@ -1612,16 +1609,21 @@ static int generate_reclaim_entry(struct xe_tile *tile, · 11 unmodified lines | ||
| 1612 | 1609 | * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim |
| 1613 | 1610 | */ |
| 1614 | 1611 | if (xe_child->level == 0 && !(pte & XE_PTE_PS64)) { |
| 1612 | + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1); | |
| 1615 | 1613 | reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K); /* reclamation_size = 0 */ |
| 1614 | + xe_tile_assert(tile, phys_addr % SZ_4K == 0); | |
| 1616 | 1615 | } else if (xe_child->level == 0) { |
| 1616 | + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1); | |
| 1617 | 1617 | reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */ |
| 1618 | − } else if (is_2m_pte(xe_child)) { | |
| 1618 | + xe_tile_assert(tile, phys_addr % SZ_64K == 0); | |
| 1619 | + } else if (xe_child->level == 1 && pte & XE_PDE_PS_2M) { | |
| 1620 | + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, 1); | |
| 1619 | 1621 | reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M); /* reclamation_size = 9 */ |
| 1622 | + xe_tile_assert(tile, phys_addr % SZ_2M == 0); | |
| 1620 | 1623 | } else { |
| 1621 | − xe_page_reclaim_list_invalidate(prl); | |
| 1622 | − vm_dbg(&tile_to_xe(tile)->drm, | |
| 1623 | − "PRL invalidate: unsupported PTE level=%u pte=%#llx\n", | |
| 1624 | − xe_child->level, pte); | |
| 1624 | + xe_page_reclaim_list_abort(tile->primary_gt, prl, | |
| 1625 | + "unsupported PTE level=%u pte=%#llx", | |
| 1626 | + xe_child->level, pte); | |
| 1625 | 1627 | return -EINVAL; |
| 1626 | 1628 | } |
| 1627 | 1629 | |
| @@ -1648,20 +1650,40 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, · 20 unmodified lines | ||
| 1648 | 1650 | struct xe_pt_stage_unbind_walk *xe_walk = |
| 1649 | 1651 | container_of(walk, typeof(*xe_walk), base); |
| 1650 | 1652 | struct xe_device *xe = tile_to_xe(xe_walk->tile); |
| 1653 | + pgoff_t first = xe_pt_offset(addr, xe_child->level, walk); | |
| 1654 | + bool killed; | |
| 1651 | 1655 | |
| 1652 | 1656 | XE_WARN_ON(!*child); |
| 1653 | 1657 | XE_WARN_ON(!level); |
| 1654 | 1658 | /* Check for leaf node */ |
| 1655 | 1659 | if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && |
| 1656 | − !xe_child->base.children) { | |
| 1660 | + (!xe_child->base.children || !xe_child->base.children[first])) { | |
| 1657 | 1661 | struct iosys_map *leaf_map = &xe_child->bo->vmap; |
| 1658 | − pgoff_t first = xe_pt_offset(addr, 0, walk); | |
| 1659 | − pgoff_t count = xe_pt_num_entries(addr, next, 0, walk); | |
| 1662 | + pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk); | |
| 1660 | 1663 | |
| 1661 | 1664 | for (pgoff_t i = 0; i < count; i++) { |
| 1662 | 1665 | u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64); |
| 1663 | 1666 | int ret; |
| 1664 | 1667 | |
| 1668 | + /* | |
| 1669 | + * In rare scenarios, pte may not be written yet due to racy conditions. | |
| 1670 | + * In such cases, invalidate the PRL and fallback to full PPC invalidation. | |
| 1671 | + */ | |
| 1672 | + if (!pte) { | |
| 1673 | + xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, | |
| 1674 | + "found zero pte at addr=%#llx", addr); | |
| 1675 | + break; | |
| 1676 | + } | |
| 1677 | + | |
| 1678 | + /* Ensure it is a defined page */ | |
| 1679 | + xe_tile_assert(xe_walk->tile, | |
| 1680 | + xe_child->level == 0 || | |
| 1681 | + (pte & (XE_PTE_PS64 | XE_PDE_PS_2M | XE_PDPE_PS_1G))); | |
| 1682 | + | |
| 1683 | + /* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */ | |
| 1684 | + if (pte & XE_PTE_PS64) | |
| 1685 | + i += 15; /* Skip other 15 consecutive 4K pages in the 64K page */ | |
| 1686 | + | |
| 1665 | 1687 | /* Account for NULL terminated entry on end (-1) */ |
| 1666 | 1688 | if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) { |
| 1667 | 1689 | ret = generate_reclaim_entry(xe_walk->tile, xe_walk->prl, |
| @@ -1670,22 +1692,32 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, · 2 unmodified lines | ||
| 1670 | 1692 | break; |
| 1671 | 1693 | } else { |
| 1672 | 1694 | /* overflow, mark as invalid */ |
| 1673 | − xe_page_reclaim_list_invalidate(xe_walk->prl); | |
| 1674 | − vm_dbg(&xe->drm, | |
| 1675 | − "PRL invalidate: overflow while adding pte=%#llx", | |
| 1676 | − pte); | |
| 1695 | + xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, | |
| 1696 | + "overflow while adding pte=%#llx", | |
| 1697 | + pte); | |
| 1677 | 1698 | break; |
| 1678 | 1699 | } |
| 1679 | 1700 | } |
| 1680 | 1701 | } |
| 1681 | 1702 | |
| 1682 | − /* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */ | |
| 1683 | − if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) && | |
| 1684 | − xe_walk->prl && level > 1 && xe_child->base.children && xe_child->num_live != 0) { | |
| 1685 | − xe_page_reclaim_list_invalidate(xe_walk->prl); | |
| 1686 | − vm_dbg(&xe->drm, | |
| 1687 | − "PRL invalidate: kill at level=%u addr=%#llx next=%#llx num_live=%u\n", | |
| 1688 | − level, addr, next, xe_child->num_live); | |
| 1703 | + killed = xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk); | |
| 1704 | + | |
| 1705 | + /* | |
| 1706 | + * Verify PRL is active and if entry is not a leaf pte (base.children conditions), | |
| 1707 | + * there is a potential need to invalidate the PRL if any PTE (num_live) are dropped. | |
| 1708 | + */ | |
| 1709 | + if (xe_walk->prl && level > 1 && xe_child->num_live && | |
| 1710 | + xe_child->base.children && xe_child->base.children[first]) { | |
| 1711 | + bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base); | |
| 1712 | + | |
| 1713 | + /* | |
| 1714 | + * If aborting page walk early (kill) or page walk completes the full range | |
| 1715 | + * we need to invalidate the PRL. | |
| 1716 | + */ | |
| 1717 | + if (killed || covered) | |
| 1718 | + xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, | |
| 1719 | + "kill at level=%u addr=%#llx next=%#llx num_live=%u", | |
| 1720 | + level, addr, next, xe_child->num_live); | |
| 1689 | 1721 | } |
| 1690 | 1722 | |
| 1691 | 1723 | return 0; |
| @@ -20,6 +20,7 @@ enum xe_cache_level { · 19 unmodified lines | ||
| 20 | 20 | XE_CACHE_WT, |
| 21 | 21 | XE_CACHE_WB, |
| 22 | 22 | XE_CACHE_NONE_COMPRESSION, /*UC + COH_NONE + COMPRESSION */ |
| 23 | + XE_CACHE_WB_COMPRESSION, | |
| 23 | 24 | __XE_CACHE_LEVEL_COUNT, |
| 24 | 25 | }; |
| 25 | 26 | |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "xe_force_wake.h" |
| 16 | 16 | #include "xe_guc_submit.h" |
| 17 | 17 | #include "xe_gsc_proxy.h" |
| 18 | −#include "xe_gt.h" | |
| 19 | 18 | #include "xe_gt_types.h" |
| 20 | 19 | #include "xe_huc.h" |
| 21 | 20 | #include "xe_mmio.h" |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <drm/drm_managed.h> |
| 12 | 12 | #include <drm/drm_print.h> |
| 13 | 13 | |
| 14 | −#include "xe_device.h" | |
| 14 | +#include "xe_device_types.h" | |
| 15 | 15 | #include "xe_pxp.h" |
| 16 | 16 | #include "xe_pxp_types.h" |
| 17 | 17 | #include "regs/xe_irq_regs.h" |
| @@ -13,16 +13,13 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <drm/drm_managed.h> |
| 14 | 14 | #include <drm/drm_print.h> |
| 15 | 15 | |
| 16 | −#include "regs/xe_engine_regs.h" | |
| 17 | −#include "regs/xe_gt_regs.h" | |
| 18 | 16 | #include "xe_device.h" |
| 19 | 17 | #include "xe_device_types.h" |
| 20 | 18 | #include "xe_force_wake.h" |
| 21 | −#include "xe_gt.h" | |
| 22 | 19 | #include "xe_gt_mcr.h" |
| 23 | 20 | #include "xe_gt_printk.h" |
| 21 | +#include "xe_gt_types.h" | |
| 24 | 22 | #include "xe_hw_engine_types.h" |
| 25 | −#include "xe_macros.h" | |
| 26 | 23 | #include "xe_mmio.h" |
| 27 | 24 | #include "xe_rtp_types.h" |
| 28 | 25 | |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "regs/xe_engine_regs.h" |
| 9 | 9 | #include "regs/xe_gt_regs.h" |
| 10 | 10 | #include "regs/xe_oa_regs.h" |
| 11 | −#include "regs/xe_regs.h" | |
| 12 | 11 | #include "xe_device.h" |
| 13 | 12 | #include "xe_gt_types.h" |
| 14 | 13 | #include "xe_gt_printk.h" |
| @@ -11,11 +11,9 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "instructions/xe_mi_commands.h" |
| 12 | 12 | #include "regs/xe_engine_regs.h" |
| 13 | 13 | #include "regs/xe_gt_regs.h" |
| 14 | −#include "regs/xe_lrc_layout.h" | |
| 15 | 14 | #include "xe_exec_queue.h" |
| 16 | −#include "xe_gt.h" | |
| 15 | +#include "xe_gt_types.h" | |
| 17 | 16 | #include "xe_lrc.h" |
| 18 | −#include "xe_macros.h" | |
| 19 | 17 | #include "xe_sched_job.h" |
| 20 | 18 | #include "xe_sriov.h" |
| 21 | 19 | #include "xe_vm_types.h" |
| @@ -235,13 +233,26 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job) · 213 unmodified lines | ||
| 235 | 233 | return 0; |
| 236 | 234 | } |
| 237 | 235 | |
| 238 | −static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i) | |
| 236 | +static int emit_copy_timestamp(struct xe_device *xe, struct xe_lrc *lrc, | |
| 237 | + u32 *dw, int i) | |
| 239 | 238 | { |
| 240 | 239 | dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; |
| 241 | 240 | dw[i++] = RING_CTX_TIMESTAMP(0).addr; |
| 242 | 241 | dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); |
| 243 | 242 | dw[i++] = 0; |
| 244 | 243 | |
| 244 | + /* | |
| 245 | + * Ensure CTX timestamp >= Job timestamp during VF sampling to avoid | |
| 246 | + * arithmetic wraparound in TDR. | |
| 247 | + */ | |
| 248 | + if (IS_SRIOV_VF(xe)) { | |
| 249 | + dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | | |
| 250 | + MI_SRM_ADD_CS_OFFSET; | |
| 251 | + dw[i++] = RING_CTX_TIMESTAMP(0).addr; | |
| 252 | + dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc); | |
| 253 | + dw[i++] = 0; | |
| 254 | + } | |
| 255 | + | |
| 245 | 256 | return i; |
| 246 | 257 | } |
| 247 | 258 | |
| @@ -255,7 +266,7 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc · 7 unmodified lines | ||
| 255 | 266 | |
| 256 | 267 | *head = lrc->ring.tail; |
| 257 | 268 | |
| 258 | − i = emit_copy_timestamp(lrc, dw, i); | |
| 269 | + i = emit_copy_timestamp(gt_to_xe(gt), lrc, dw, i); | |
| 259 | 270 | |
| 260 | 271 | if (job->ring_ops_flush_tlb) { |
| 261 | 272 | dw[i++] = preparser_disable(true); |
| @@ -310,7 +321,7 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc, · 48 unmodified lines | ||
| 310 | 321 | |
| 311 | 322 | *head = lrc->ring.tail; |
| 312 | 323 | |
| 313 | − i = emit_copy_timestamp(lrc, dw, i); | |
| 324 | + i = emit_copy_timestamp(xe, lrc, dw, i); | |
| 314 | 325 | |
| 315 | 326 | dw[i++] = preparser_disable(true); |
| 316 | 327 | |
| @@ -364,7 +375,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job, · 47 unmodified lines | ||
| 364 | 375 | |
| 365 | 376 | *head = lrc->ring.tail; |
| 366 | 377 | |
| 367 | − i = emit_copy_timestamp(lrc, dw, i); | |
| 378 | + i = emit_copy_timestamp(xe, lrc, dw, i); | |
| 368 | 379 | |
| 369 | 380 | dw[i++] = preparser_disable(true); |
| 370 | 381 | if (lacks_render) |
| @@ -406,12 +417,14 @@ static void emit_migration_job_gen12(struct xe_sched_job *job, · 35 unmodified lines | ||
| 406 | 417 | struct xe_lrc *lrc, u32 *head, |
| 407 | 418 | u32 seqno) |
| 408 | 419 | { |
| 420 | + struct xe_gt *gt = job->q->gt; | |
| 421 | + struct xe_device *xe = gt_to_xe(gt); | |
| 409 | 422 | u32 saddr = xe_lrc_start_seqno_ggtt_addr(lrc); |
| 410 | 423 | u32 dw[MAX_JOB_SIZE_DW], i = 0; |
| 411 | 424 | |
| 412 | 425 | *head = lrc->ring.tail; |
| 413 | 426 | |
| 414 | − i = emit_copy_timestamp(lrc, dw, i); | |
| 427 | + i = emit_copy_timestamp(xe, lrc, dw, i); | |
| 415 | 428 | |
| 416 | 429 | i = emit_store_imm_ggtt(saddr, seqno, dw, i); |
| 417 | 430 | |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include "xe_configfs.h" |
| 13 | 13 | #include "xe_gt.h" |
| 14 | 14 | #include "xe_gt_topology.h" |
| 15 | −#include "xe_macros.h" | |
| 16 | 15 | #include "xe_reg_sr.h" |
| 17 | 16 | #include "xe_sriov.h" |
| 18 | 17 | |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <drm/drm_managed.h> |
| 11 | 11 | |
| 12 | 12 | #include "xe_bo.h" |
| 13 | −#include "xe_device.h" | |
| 13 | +#include "xe_device_types.h" | |
| 14 | 14 | #include "xe_map.h" |
| 15 | 15 | |
| 16 | 16 | static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include "xe_device.h" |
| 13 | 13 | #include "xe_exec_queue.h" |
| 14 | −#include "xe_gt.h" | |
| 14 | +#include "xe_gt_types.h" | |
| 15 | 15 | #include "xe_hw_engine_types.h" |
| 16 | 16 | #include "xe_hw_fence.h" |
| 17 | 17 | #include "xe_lrc.h" |
| @@ -110,6 +110,7 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, · 92 unmodified lines | ||
| 110 | 110 | return ERR_PTR(-ENOMEM); |
| 111 | 111 | |
| 112 | 112 | job->q = q; |
| 113 | + job->sample_timestamp = U64_MAX; | |
| 113 | 114 | kref_init(&job->refcount); |
| 114 | 115 | xe_exec_queue_get(job->q); |
| 115 | 116 | |
| @@ -59,6 +59,8 @@ struct xe_sched_job { · 58 unmodified lines | ||
| 59 | 59 | u32 lrc_seqno; |
| 60 | 60 | /** @migrate_flush_flags: Additional flush flags for migration jobs */ |
| 61 | 61 | u32 migrate_flush_flags; |
| 62 | + /** @sample_timestamp: Sampling of job timestamp in TDR */ | |
| 63 | + u64 sample_timestamp; | |
| 62 | 64 | /** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */ |
| 63 | 65 | bool ring_ops_flush_tlb; |
| 64 | 66 | /** @ggtt: mapped in ggtt. */ |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include "xe_bo.h" |
| 7 | 7 | #include "xe_device.h" |
| 8 | 8 | #include "xe_guc_klv_helpers.h" |
| 9 | −#include "xe_printk.h" | |
| 10 | 9 | #include "xe_sriov_packet.h" |
| 11 | 10 | #include "xe_sriov_packet_types.h" |
| 12 | 11 | #include "xe_sriov_pf_helpers.h" |
| @@ -90,7 +90,6 @@ bool xe_sriov_pf_readiness(struct xe_device *xe) · 89 unmodified lines | ||
| 90 | 90 | */ |
| 91 | 91 | int xe_sriov_pf_init_early(struct xe_device *xe) |
| 92 | 92 | { |
| 93 | − struct xe_mert *mert = &xe_device_get_root_tile(xe)->mert; | |
| 94 | 93 | int err; |
| 95 | 94 | |
| 96 | 95 | xe_assert(xe, IS_SRIOV_PF(xe)); |
| @@ -112,8 +111,7 @@ int xe_sriov_pf_init_early(struct xe_device *xe) · 15 unmodified lines | ||
| 112 | 111 | |
| 113 | 112 | xe_sriov_pf_service_init(xe); |
| 114 | 113 | |
| 115 | − spin_lock_init(&mert->lock); | |
| 116 | − init_completion(&mert->tlb_inv_done); | |
| 114 | + xe_mert_init_early(xe); | |
| 117 | 115 | |
| 118 | 116 | return 0; |
| 119 | 117 | } |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include "xe_sriov_pf_migration.h" |
| 17 | 17 | #include "xe_sriov_pf_provision.h" |
| 18 | 18 | #include "xe_sriov_pf_service.h" |
| 19 | −#include "xe_sriov_printk.h" | |
| 20 | 19 | #include "xe_tile_sriov_pf_debugfs.h" |
| 21 | 20 | |
| 22 | 21 | /* |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <drm/drm_debugfs.h> |
| 7 | 7 | #include <drm/drm_managed.h> |
| 8 | 8 | |
| 9 | −#include "xe_gt.h" | |
| 10 | 9 | #include "xe_gt_sriov_vf.h" |
| 11 | 10 | #include "xe_guc.h" |
| 12 | 11 | #include "xe_sriov_printk.h" |
| @@ -5,10 +5,11 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #include "xe_step.h" |
| 7 | 7 | |
| 8 | +#include <drm/drm_print.h> | |
| 8 | 9 | #include <kunit/visibility.h> |
| 9 | 10 | #include <linux/bitfield.h> |
| 10 | 11 | |
| 11 | −#include "xe_device.h" | |
| 12 | +#include "xe_device_types.h" | |
| 12 | 13 | #include "xe_platform_types.h" |
| 13 | 14 | |
| 14 | 15 | /* |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include "xe_configfs.h" |
| 14 | 14 | #include "xe_device.h" |
| 15 | −#include "xe_gt.h" | |
| 16 | 15 | #include "xe_heci_gsc.h" |
| 17 | 16 | #include "xe_i2c.h" |
| 18 | 17 | #include "xe_mmio.h" |
| @@ -321,7 +320,7 @@ static int enable_boot_survivability_mode(struct pci_dev *pdev) · 302 unmodified lines | ||
| 321 | 320 | if (ret) |
| 322 | 321 | return ret; |
| 323 | 322 | |
| 324 | − /* Make sure xe_heci_gsc_init() knows about survivability mode */ | |
| 323 | + /* Make sure xe_heci_gsc_init() and xe_i2c_probe() are aware of survivability */ | |
| 325 | 324 | survivability->mode = true; |
| 326 | 325 | |
| 327 | 326 | xe_heci_gsc_init(xe); |
| @@ -988,6 +988,8 @@ bool xe_svm_range_validate(struct xe_vm *vm, · 987 unmodified lines | ||
| 988 | 988 | ret = (range->tile_present & ~range->tile_invalidated & tile_mask) == tile_mask; |
| 989 | 989 | if (dpagemap) |
| 990 | 990 | ret = ret && xe_svm_range_has_pagemap_locked(range, dpagemap); |
| 991 | + else | |
| 992 | + ret = ret && !range->base.pages.dpagemap; | |
| 991 | 993 | |
| 992 | 994 | xe_svm_notifier_unlock(vm); |
| 993 | 995 | |
| @@ -9,9 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <drm/drm_pagemap_util.h> |
| 10 | 10 | |
| 11 | 11 | #include "xe_bo.h" |
| 12 | −#include "xe_device.h" | |
| 12 | +#include "xe_device_types.h" | |
| 13 | 13 | #include "xe_ggtt.h" |
| 14 | −#include "xe_gt.h" | |
| 15 | 14 | #include "xe_memirq.h" |
| 16 | 15 | #include "xe_migrate.h" |
| 17 | 16 | #include "xe_pcode.h" |
| @@ -5,13 +5,10 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #include <drm/drm_managed.h> |
| 7 | 7 | |
| 8 | −#include "abi/guc_actions_abi.h" | |
| 9 | −#include "xe_device.h" | |
| 8 | +#include "xe_device_types.h" | |
| 10 | 9 | #include "xe_force_wake.h" |
| 11 | −#include "xe_gt.h" | |
| 12 | −#include "xe_gt_printk.h" | |
| 13 | 10 | #include "xe_gt_stats.h" |
| 14 | −#include "xe_guc.h" | |
| 11 | +#include "xe_gt_types.h" | |
| 15 | 12 | #include "xe_guc_ct.h" |
| 16 | 13 | #include "xe_guc_tlb_inval.h" |
| 17 | 14 | #include "xe_mmio.h" |
| @@ -94,7 +91,7 @@ static void xe_tlb_inval_fence_timeout(struct work_struct *work) · 76 unmodified lines | ||
| 94 | 91 | xe_tlb_inval_fence_signal(fence); |
| 95 | 92 | } |
| 96 | 93 | if (!list_empty(&tlb_inval->pending_fences)) |
| 97 | − queue_delayed_work(system_wq, &tlb_inval->fence_tdr, | |
| 94 | + queue_delayed_work(tlb_inval->timeout_wq, &tlb_inval->fence_tdr, | |
| 98 | 95 | timeout_delay); |
| 99 | 96 | spin_unlock_irq(&tlb_inval->pending_lock); |
| 100 | 97 | } |
| @@ -146,6 +143,10 @@ int xe_gt_tlb_inval_init_early(struct xe_gt *gt) · 45 unmodified lines | ||
| 146 | 143 | if (IS_ERR(tlb_inval->job_wq)) |
| 147 | 144 | return PTR_ERR(tlb_inval->job_wq); |
| 148 | 145 | |
| 146 | + tlb_inval->timeout_wq = gt->ordered_wq; | |
| 147 | + if (IS_ERR(tlb_inval->timeout_wq)) | |
| 148 | + return PTR_ERR(tlb_inval->timeout_wq); | |
| 149 | + | |
| 149 | 150 | /* XXX: Blindly setting up backend to GuC */ |
| 150 | 151 | xe_guc_tlb_inval_init_early(>->uc.guc, tlb_inval); |
| 151 | 152 | |
| @@ -240,7 +241,7 @@ static void xe_tlb_inval_fence_prep(struct xe_tlb_inval_fence *fence) · 88 unmodified lines | ||
| 240 | 241 | list_add_tail(&fence->link, &tlb_inval->pending_fences); |
| 241 | 242 | |
| 242 | 243 | if (list_is_singular(&tlb_inval->pending_fences)) |
| 243 | − queue_delayed_work(system_wq, &tlb_inval->fence_tdr, | |
| 244 | + queue_delayed_work(tlb_inval->timeout_wq, &tlb_inval->fence_tdr, | |
| 244 | 245 | tlb_inval->ops->timeout_delay(tlb_inval)); |
| 245 | 246 | spin_unlock_irq(&tlb_inval->pending_lock); |
| 246 | 247 | |
| @@ -399,7 +400,7 @@ void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno) · 152 unmodified lines | ||
| 399 | 400 | } |
| 400 | 401 | |
| 401 | 402 | if (!list_empty(&tlb_inval->pending_fences)) |
| 402 | − mod_delayed_work(system_wq, | |
| 403 | + mod_delayed_work(tlb_inval->timeout_wq, | |
| 403 | 404 | &tlb_inval->fence_tdr, |
| 404 | 405 | tlb_inval->ops->timeout_delay(tlb_inval)); |
| 405 | 406 | else |
| @@ -109,6 +109,8 @@ struct xe_tlb_inval { · 108 unmodified lines | ||
| 109 | 109 | struct workqueue_struct *job_wq; |
| 110 | 110 | /** @tlb_inval.lock: protects TLB invalidation fences */ |
| 111 | 111 | spinlock_t lock; |
| 112 | + /** @timeout_wq: schedules TLB invalidation fence timeouts */ | |
| 113 | + struct workqueue_struct *timeout_wq; | |
| 112 | 114 | }; |
| 113 | 115 | |
| 114 | 116 | /** |
| @@ -228,11 +228,6 @@ DEFINE_EVENT(xe_exec_queue, xe_exec_queue_resubmit, · 227 unmodified lines | ||
| 228 | 228 | TP_ARGS(q) |
| 229 | 229 | ); |
| 230 | 230 | |
| 231 | −DEFINE_EVENT(xe_exec_queue, xe_exec_queue_lr_cleanup, | |
| 232 | − TP_PROTO(struct xe_exec_queue *q), | |
| 233 | − TP_ARGS(q) | |
| 234 | −); | |
| 235 | − | |
| 236 | 231 | DECLARE_EVENT_CLASS(xe_sched_job, |
| 237 | 232 | TP_PROTO(struct xe_sched_job *job), |
| 238 | 233 | TP_ARGS(job), |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "regs/xe_regs.h" |
| 18 | 18 | #include "xe_bo.h" |
| 19 | 19 | #include "xe_device.h" |
| 20 | −#include "xe_gt.h" | |
| 21 | 20 | #include "xe_gt_printk.h" |
| 22 | 21 | #include "xe_mmio.h" |
| 23 | 22 | #include "xe_res_cursor.h" |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <drm/ttm/ttm_tt.h> |
| 14 | 14 | |
| 15 | 15 | #include "xe_bo.h" |
| 16 | −#include "xe_gt.h" | |
| 17 | 16 | |
| 18 | 17 | struct xe_ttm_sys_node { |
| 19 | 18 | struct ttm_buffer_object *tbo; |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include "xe_bo.h" |
| 14 | 14 | #include "xe_device.h" |
| 15 | −#include "xe_gt.h" | |
| 16 | 15 | #include "xe_res_cursor.h" |
| 17 | 16 | #include "xe_ttm_vram_mgr.h" |
| 18 | 17 | #include "xe_vram_types.h" |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "xe_assert.h" |
| 9 | 9 | #include "xe_device.h" |
| 10 | 10 | #include "xe_gsc.h" |
| 11 | −#include "xe_gsc_proxy.h" | |
| 12 | 11 | #include "xe_gt.h" |
| 13 | 12 | #include "xe_gt_printk.h" |
| 14 | 13 | #include "xe_gt_sriov_vf.h" |
| @@ -17,7 +16,6 @@ · 2 unmodified lines | ||
| 17 | 16 | #include "xe_guc_engine_activity.h" |
| 18 | 17 | #include "xe_huc.h" |
| 19 | 18 | #include "xe_sriov.h" |
| 20 | −#include "xe_uc_fw.h" | |
| 21 | 19 | #include "xe_wopcm.h" |
| 22 | 20 | |
| 23 | 21 | static struct xe_gt * |
| @@ -7,12 +7,12 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <drm/drm_debugfs.h> |
| 9 | 9 | |
| 10 | −#include "xe_gt.h" | |
| 11 | 10 | #include "xe_gsc_debugfs.h" |
| 12 | 11 | #include "xe_guc_debugfs.h" |
| 13 | 12 | #include "xe_huc_debugfs.h" |
| 14 | 13 | #include "xe_macros.h" |
| 15 | 14 | #include "xe_uc_debugfs.h" |
| 15 | +#include "xe_uc_types.h" | |
| 16 | 16 | |
| 17 | 17 | void xe_uc_debugfs_register(struct xe_uc *uc, struct dentry *parent) |
| 18 | 18 | { |
| @@ -14,9 +14,9 @@ · 13 unmodified lines | ||
| 14 | 14 | #include "xe_device_types.h" |
| 15 | 15 | #include "xe_force_wake.h" |
| 16 | 16 | #include "xe_gsc.h" |
| 17 | −#include "xe_gt.h" | |
| 18 | 17 | #include "xe_gt_printk.h" |
| 19 | 18 | #include "xe_gt_sriov_vf.h" |
| 19 | +#include "xe_gt_types.h" | |
| 20 | 20 | #include "xe_guc.h" |
| 21 | 21 | #include "xe_map.h" |
| 22 | 22 | #include "xe_mmio.h" |
| @@ -115,6 +115,7 @@ struct fw_blobs_by_type { · 92 unmodified lines | ||
| 115 | 115 | #define XE_GT_TYPE_ANY XE_GT_TYPE_UNINITIALIZED |
| 116 | 116 | |
| 117 | 117 | #define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver) \ |
| 118 | + fw_def(NOVALAKE_S, GT_TYPE_ANY, mmp_ver(xe, guc, nvl, 70, 55, 4)) \ | |
| 118 | 119 | fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, guc, ptl, 70, 54, 0)) \ |
| 119 | 120 | fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 54, 0)) \ |
| 120 | 121 | fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 53, 0)) \ |
| @@ -140,6 +141,7 @@ struct fw_blobs_by_type { · 19 unmodified lines | ||
| 140 | 141 | |
| 141 | 142 | /* for the GSC FW we match the compatibility version and not the release one */ |
| 142 | 143 | #define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver) \ |
| 144 | + fw_def(PANTHERLAKE, GT_TYPE_ANY, major_ver(xe, gsc, ptl, 105, 1, 0)) \ | |
| 143 | 145 | fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, gsc, lnl, 104, 1, 0)) \ |
| 144 | 146 | fw_def(METEORLAKE, GT_TYPE_ANY, major_ver(i915, gsc, mtl, 102, 1, 0)) |
| 145 | 147 | |
| @@ -738,7 +740,7 @@ static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmwar · 592 unmodified lines | ||
| 738 | 740 | return 0; |
| 739 | 741 | } |
| 740 | 742 | |
| 741 | − err = request_firmware(&fw, uc_fw->path, dev); | |
| 743 | + err = firmware_request_nowarn(&fw, uc_fw->path, dev); | |
| 742 | 744 | if (err) |
| 743 | 745 | goto fail; |
| 744 | 746 | |
| @@ -767,8 +769,12 @@ fail: · 22 unmodified lines | ||
| 767 | 769 | XE_UC_FIRMWARE_MISSING : |
| 768 | 770 | XE_UC_FIRMWARE_ERROR); |
| 769 | 771 | |
| 770 | − xe_gt_notice(gt, "%s firmware %s: fetch failed with error %pe\n", | |
| 771 | − xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, ERR_PTR(err)); | |
| 772 | + if (err == -ENOENT) | |
| 773 | + xe_gt_info(gt, "%s firmware %s not found\n", | |
| 774 | + xe_uc_fw_type_repr(uc_fw->type), uc_fw->path); | |
| 775 | + else | |
| 776 | + xe_gt_notice(gt, "%s firmware %s: fetch failed with error %pe\n", | |
| 777 | + xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, ERR_PTR(err)); | |
| 772 | 778 | xe_gt_info(gt, "%s firmware(s) can be downloaded from %s\n", |
| 773 | 779 | xe_uc_fw_type_repr(uc_fw->type), XE_UC_FIRMWARE_URL); |
| 774 | 780 | |
| @@ -2,7 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright © 2024 Intel Corporation |
| 4 | 4 | */ |
| 5 | −#include "xe_bo.h" | |
| 6 | 5 | #include <drm/drm_exec.h> |
| 7 | 6 | #include <drm/drm_gem.h> |
| 8 | 7 | #include <drm/drm_gpuvm.h> |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | ||
| 33 | 33 | #include "xe_preempt_fence.h" |
| 34 | 34 | #include "xe_pt.h" |
| 35 | 35 | #include "xe_pxp.h" |
| 36 | −#include "xe_res_cursor.h" | |
| 37 | 36 | #include "xe_sriov_vf.h" |
| 38 | 37 | #include "xe_svm.h" |
| 39 | 38 | #include "xe_sync.h" |
| @@ -2209,7 +2208,7 @@ static void print_op(struct xe_device *xe, struct drm_gpuva_op *op) · 2169 unmodified lines | ||
| 2209 | 2208 | (ULL)xe_vma_start(vma), (ULL)xe_vma_size(vma)); |
| 2210 | 2209 | break; |
| 2211 | 2210 | default: |
| 2212 | − drm_warn(&xe->drm, "NOT POSSIBLE"); | |
| 2211 | + drm_warn(&xe->drm, "NOT POSSIBLE\n"); | |
| 2213 | 2212 | } |
| 2214 | 2213 | } |
| 2215 | 2214 | #else |
| @@ -2312,7 +2311,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, · 96 unmodified lines | ||
| 2312 | 2311 | xe_bo_unlock(bo); |
| 2313 | 2312 | break; |
| 2314 | 2313 | default: |
| 2315 | − drm_warn(&vm->xe->drm, "NOT POSSIBLE"); | |
| 2314 | + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); | |
| 2316 | 2315 | ops = ERR_PTR(-EINVAL); |
| 2317 | 2316 | } |
| 2318 | 2317 | if (IS_ERR(ops)) |
| @@ -2584,7 +2583,7 @@ static int xe_vma_op_commit(struct xe_vm *vm, struct xe_vma_op *op) · 265 unmodified lines | ||
| 2584 | 2583 | op->flags |= XE_VMA_OP_COMMITTED; |
| 2585 | 2584 | break; |
| 2586 | 2585 | default: |
| 2587 | − drm_warn(&vm->xe->drm, "NOT POSSIBLE"); | |
| 2586 | + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); | |
| 2588 | 2587 | } |
| 2589 | 2588 | |
| 2590 | 2589 | return err; |
| @@ -2783,7 +2782,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, · 192 unmodified lines | ||
| 2783 | 2782 | |
| 2784 | 2783 | break; |
| 2785 | 2784 | default: |
| 2786 | − drm_warn(&vm->xe->drm, "NOT POSSIBLE"); | |
| 2785 | + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); | |
| 2787 | 2786 | } |
| 2788 | 2787 | |
| 2789 | 2788 | err = xe_vma_op_commit(vm, op); |
| @@ -2845,7 +2844,7 @@ static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op, · 55 unmodified lines | ||
| 2845 | 2844 | /* Nothing to do */ |
| 2846 | 2845 | break; |
| 2847 | 2846 | default: |
| 2848 | − drm_warn(&vm->xe->drm, "NOT POSSIBLE"); | |
| 2847 | + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); | |
| 2849 | 2848 | } |
| 2850 | 2849 | } |
| 2851 | 2850 | |
| @@ -3029,7 +3028,7 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, · 177 unmodified lines | ||
| 3029 | 3028 | break; |
| 3030 | 3029 | } |
| 3031 | 3030 | default: |
| 3032 | − drm_warn(&vm->xe->drm, "NOT POSSIBLE"); | |
| 3031 | + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); | |
| 3033 | 3032 | } |
| 3034 | 3033 | |
| 3035 | 3034 | return err; |
| @@ -3268,7 +3267,7 @@ static void op_add_ufence(struct xe_vm *vm, struct xe_vma_op *op, · 232 unmodified lines | ||
| 3268 | 3267 | vma_add_ufence(gpuva_to_vma(op->base.prefetch.va), ufence); |
| 3269 | 3268 | break; |
| 3270 | 3269 | default: |
| 3271 | − drm_warn(&vm->xe->drm, "NOT POSSIBLE"); | |
| 3270 | + drm_warn(&vm->xe->drm, "NOT POSSIBLE\n"); | |
| 3272 | 3271 | } |
| 3273 | 3272 | } |
| 3274 | 3273 | |
| @@ -3405,6 +3404,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, · 130 unmodified lines | ||
| 3405 | 3404 | DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR; |
| 3406 | 3405 | u16 pat_index = (*bind_ops)[i].pat_index; |
| 3407 | 3406 | u16 coh_mode; |
| 3407 | + bool comp_en; | |
| 3408 | 3408 | |
| 3409 | 3409 | if (XE_IOCTL_DBG(xe, is_cpu_addr_mirror && |
| 3410 | 3410 | (!xe_vm_in_fault_mode(vm) || |
| @@ -3421,6 +3421,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, · 10 unmodified lines | ||
| 3421 | 3421 | pat_index = array_index_nospec(pat_index, xe->pat.n_entries); |
| 3422 | 3422 | (*bind_ops)[i].pat_index = pat_index; |
| 3423 | 3423 | coh_mode = xe_pat_index_get_coh_mode(xe, pat_index); |
| 3424 | + comp_en = xe_pat_index_get_comp_en(xe, pat_index); | |
| 3424 | 3425 | if (XE_IOCTL_DBG(xe, !coh_mode)) { /* hw reserved */ |
| 3425 | 3426 | err = -EINVAL; |
| 3426 | 3427 | goto free_bind_ops; |
| @@ -3451,6 +3452,8 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, · 24 unmodified lines | ||
| 3451 | 3452 | op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || |
| 3452 | 3453 | XE_IOCTL_DBG(xe, coh_mode == XE_COH_NONE && |
| 3453 | 3454 | op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || |
| 3455 | + XE_IOCTL_DBG(xe, comp_en && | |
| 3456 | + op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || | |
| 3454 | 3457 | XE_IOCTL_DBG(xe, op == DRM_XE_VM_BIND_OP_MAP_USERPTR && |
| 3455 | 3458 | !IS_ENABLED(CONFIG_DRM_GPUSVM)) || |
| 3456 | 3459 | XE_IOCTL_DBG(xe, obj && |
| @@ -3529,6 +3532,7 @@ static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, · 72 unmodified lines | ||
| 3529 | 3532 | u16 pat_index, u32 op, u32 bind_flags) |
| 3530 | 3533 | { |
| 3531 | 3534 | u16 coh_mode; |
| 3535 | + bool comp_en; | |
| 3532 | 3536 | |
| 3533 | 3537 | if (XE_IOCTL_DBG(xe, (bo->flags & XE_BO_FLAG_NO_COMPRESSION) && |
| 3534 | 3538 | xe_pat_index_get_comp_en(xe, pat_index))) |
| @@ -3574,6 +3578,14 @@ static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, · 39 unmodified lines | ||
| 3574 | 3578 | return -EINVAL; |
| 3575 | 3579 | } |
| 3576 | 3580 | |
| 3581 | + /* | |
| 3582 | + * Ensures that imported buffer objects (dma-bufs) are not mapped | |
| 3583 | + * with a PAT index that enables compression. | |
| 3584 | + */ | |
| 3585 | + comp_en = xe_pat_index_get_comp_en(xe, pat_index); | |
| 3586 | + if (XE_IOCTL_DBG(xe, bo->ttm.base.import_attach && comp_en)) | |
| 3587 | + return -EINVAL; | |
| 3588 | + | |
| 3577 | 3589 | /* If a BO is protected it can only be mapped if the key is still valid */ |
| 3578 | 3590 | if ((bind_flags & DRM_XE_VM_BIND_FLAG_CHECK_PXP) && xe_bo_is_protected(bo) && |
| 3579 | 3591 | op != DRM_XE_VM_BIND_OP_UNMAP && op != DRM_XE_VM_BIND_OP_UNMAP_ALL) |
| @@ -382,7 +382,7 @@ static inline void xe_vm_set_validation_exec(struct xe_vm *vm, struct drm_exec * · 381 unmodified lines | ||
| 382 | 382 | } |
| 383 | 383 | |
| 384 | 384 | /** |
| 385 | − * xe_vm_set_validation_exec() - Accessor to read the drm_exec object | |
| 385 | + * xe_vm_validation_exec() - Accessor to read the drm_exec object | |
| 386 | 386 | * @vm: The vm we want to register a drm_exec object with. |
| 387 | 387 | * |
| 388 | 388 | * Return: The drm_exec object used to lock the vm's resv. The value |
| @@ -13,12 +13,10 @@ · 12 unmodified lines | ||
| 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" | |
| 17 | 16 | #include "xe_device.h" |
| 18 | 17 | #include "xe_force_wake.h" |
| 19 | 18 | #include "xe_gt_mcr.h" |
| 20 | 19 | #include "xe_mmio.h" |
| 21 | −#include "xe_module.h" | |
| 22 | 20 | #include "xe_sriov.h" |
| 23 | 21 | #include "xe_tile_sriov_vf.h" |
| 24 | 22 | #include "xe_ttm_vram_mgr.h" |
| @@ -155,7 +153,7 @@ static int tile_vram_size(struct xe_tile *tile, u64 *vram_size, · 130 unmodified lines | ||
| 155 | 153 | *tile_offset = 0; |
| 156 | 154 | } else { |
| 157 | 155 | reg = xe_mmio_read32(&tile->mmio, SG_TILE_ADDR_RANGE(tile->id)); |
| 158 | − *tile_size = (u64)REG_FIELD_GET(GENMASK(14, 8), reg) * SZ_1G; | |
| 156 | + *tile_size = (u64)REG_FIELD_GET(GENMASK(17, 8), reg) * SZ_1G; | |
| 159 | 157 | *tile_offset = (u64)REG_FIELD_GET(GENMASK(7, 1), reg) * SZ_1G; |
| 160 | 158 | } |
| 161 | 159 | |
| @@ -5,7 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <linux/sysfs.h> |
| 6 | 6 | #include <drm/drm_managed.h> |
| 7 | 7 | |
| 8 | −#include "xe_gt_types.h" | |
| 9 | 8 | #include "xe_pcode.h" |
| 10 | 9 | #include "xe_pcode_api.h" |
| 11 | 10 | #include "xe_tile.h" |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include "xe_device.h" |
| 14 | 14 | #include "xe_device_types.h" |
| 15 | −#include "xe_drv.h" | |
| 16 | 15 | #include "xe_mmio.h" |
| 17 | 16 | #include "xe_platform_types.h" |
| 18 | 17 | #include "xe_pm.h" |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "regs/xe_regs.h" |
| 20 | 20 | #include "xe_device_types.h" |
| 21 | 21 | #include "xe_force_wake.h" |
| 22 | −#include "xe_gt.h" | |
| 22 | +#include "xe_gt_types.h" | |
| 23 | 23 | #include "xe_hw_engine_types.h" |
| 24 | 24 | #include "xe_mmio.h" |
| 25 | 25 | #include "xe_platform_types.h" |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <uapi/drm/xe_drm.h> |
| 12 | 12 | |
| 13 | 13 | #include "xe_device.h" |
| 14 | −#include "xe_gt.h" | |
| 15 | 14 | #include "xe_macros.h" |
| 16 | 15 | #include "xe_exec_queue.h" |
| 17 | 16 | |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include "regs/xe_guc_regs.h" |
| 11 | 11 | #include "xe_device.h" |
| 12 | 12 | #include "xe_force_wake.h" |
| 13 | −#include "xe_gt.h" | |
| 13 | +#include "xe_gt_types.h" | |
| 14 | 14 | #include "xe_mmio.h" |
| 15 | 15 | #include "xe_uc_fw.h" |
| 16 | 16 | |
| @@ -1280,9 +1280,6 @@ struct drm_xe_vm_bind { · 1279 unmodified lines | ||
| 1280 | 1280 | * then a new multi-queue group is created with this queue as the primary queue |
| 1281 | 1281 | * (Q0). Otherwise, the queue gets added to the multi-queue group whose primary |
| 1282 | 1282 | * queue's exec_queue_id is specified in the lower 32 bits of the 'value' field. |
| 1283 | − * If the extension's 'value' field has %DRM_XE_MULTI_GROUP_KEEP_ACTIVE flag | |
| 1284 | − * set, then the multi-queue group is kept active after the primary queue is | |
| 1285 | − * destroyed. | |
| 1286 | 1283 | * All the other non-relevant bits of extension's 'value' field while adding the |
| 1287 | 1284 | * primary or the secondary queues of the group must be set to 0. |
| 1288 | 1285 | * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY - Set the queue |
| @@ -1331,7 +1328,6 @@ struct drm_xe_exec_queue_create { · 42 unmodified lines | ||
| 1331 | 1328 | #define DRM_XE_EXEC_QUEUE_SET_HANG_REPLAY_STATE 3 |
| 1332 | 1329 | #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_GROUP 4 |
| 1333 | 1330 | #define DRM_XE_MULTI_GROUP_CREATE (1ull << 63) |
| 1334 | −#define DRM_XE_MULTI_GROUP_KEEP_ACTIVE (1ull << 62) | |
| 1335 | 1331 | #define DRM_XE_EXEC_QUEUE_SET_PROPERTY_MULTI_QUEUE_PRIORITY 5 |
| 1336 | 1332 | /** @extensions: Pointer to the first extension struct, if any */ |
| 1337 | 1333 | __u64 extensions; |