Lines Matching +full:capture +full:- +full:only

1 // SPDX-License-Identifier: MIT
3 * Copyright © 2021-2024 Intel Corporation
45 * Book-keeping structure used to track read and write pointers
46 * as we extract error capture data from the GuC-log-buffer's
47 * error-capture region as a stream of dwords.
57 * struct __guc_capture_parsed_output - extracted error capture node
59 * A single unit of extracted error-capture output data grouped together
60 * at an engine-instance level. We keep these nodes in a linked list.
65 * A single set of 3 capture lists: a global-list
66 * an engine-class-list and an engine-instance list.
91 * Define all device tables of GuC error capture register lists
93 * For engine-registers, GuC only needs the register offsets
94 * from the engine-mmio-base
157 /* Render / Compute Per-Engine-Instance */
162 /* Render / Compute Engine-Class */
168 /* Render / Compute Engine-Class for xehpg */
173 /* Media Decode/Encode Per-Engine-Instance */
178 /* Video Enhancement Engine-Class */
183 /* Video Enhancement Per-Engine-Instance */
188 /* Blitter Per-Engine-Instance */
193 /* XE_LP - GSC Per-Engine-Instance */
259 "GSC-Other",
273 * (slices or dual-sub-slices) and thus depends on HW fuses discovered
327 struct xe_guc *guc = &gt->uc.guc; in xe_guc_capture_get_reg_desc_list()
329 reglists = guc->capture->extlists; in xe_guc_capture_get_reg_desc_list()
360 ext->reg = XE_REG(extlist->reg.__reg.addr); in __fill_ext_reg()
361 ext->flags = FIELD_PREP(GUC_REGSET_STEERING_NEEDED, 1); in __fill_ext_reg()
362 ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id); in __fill_ext_reg()
363 ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id); in __fill_ext_reg()
364 ext->regname = extlist->name; in __fill_ext_reg()
375 return -ENOMEM; in __alloc_ext_regs()
377 newlist->list = list; in __alloc_ext_regs()
378 newlist->num_regs = num_regs; in __alloc_ext_regs()
379 newlist->owner = rootlist->owner; in __alloc_ext_regs()
380 newlist->engine = rootlist->engine; in __alloc_ext_regs()
381 newlist->type = rootlist->type; in __alloc_ext_regs()
401 const struct __guc_mmio_reg_descr_group *lists = guc->capture->reglists; in guc_capture_alloc_steered_lists()
406 struct drm_device *drm = &gt_to_xe(gt)->drm; in guc_capture_alloc_steered_lists()
413 * Currently, only rcs/ccs has steering register, if in the future, in guc_capture_alloc_steered_lists()
418 if (xe_engine_class_to_guc_capture_class(hwe->class) == in guc_capture_alloc_steered_lists()
428 /* steered registers currently only exist for the render-class */ in guc_capture_alloc_steered_lists()
436 if (!list || guc->capture->extlists) in guc_capture_alloc_steered_lists()
439 total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) * in guc_capture_alloc_steered_lists()
455 /* For steering registers, the list is generated at run-time */ in guc_capture_alloc_steered_lists()
472 xe_gt_dbg(guc_to_gt(guc), "capture found %d ext-regs.\n", total); in guc_capture_alloc_steered_lists()
473 guc->capture->extlists = extlists; in guc_capture_alloc_steered_lists()
482 const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; in guc_capture_list_init()
483 struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; in guc_capture_list_init()
488 return -ENODEV; in guc_capture_list_init()
492 return -ENODATA; in guc_capture_list_init()
494 list_num = match->num_regs; in guc_capture_list_init()
496 ptr[ptr_idx].offset = match->list[list_idx].reg.addr; in guc_capture_list_init()
498 ptr[ptr_idx].flags = match->list[list_idx].flags; in guc_capture_list_init()
499 ptr[ptr_idx].mask = match->list[list_idx].mask; in guc_capture_list_init()
505 ptr_idx < num_entries && list_idx < match->num_regs; in guc_capture_list_init()
507 ptr[ptr_idx].offset = match->list[list_idx].reg.addr; in guc_capture_list_init()
509 ptr[ptr_idx].flags = match->list[list_idx].flags; in guc_capture_list_init()
510 ptr[ptr_idx].mask = match->list[list_idx].mask; in guc_capture_list_init()
514 xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out-of %d.\n", in guc_capture_list_init()
527 match = guc_capture_get_one_list(guc->capture->reglists, owner, type, capture_class); in guc_cap_list_num_regs()
529 num_regs = match->num_regs; in guc_cap_list_num_regs()
531 match = guc_capture_get_one_list(guc->capture->extlists, owner, type, capture_class); in guc_cap_list_num_regs()
533 num_regs += match->num_regs; in guc_cap_list_num_regs()
537 * not yet got the hw-config, which is before max_mmio_per_node in guc_cap_list_num_regs()
538 * is initialized, then provide a worst-case number for in guc_cap_list_num_regs()
539 * extlists based on max dss fuse bits, but only ever for in guc_cap_list_num_regs()
545 !guc->capture->max_mmio_per_node) in guc_cap_list_num_regs()
557 struct xe_guc_state_capture *gc = guc->capture; in guc_capture_getlistsize()
565 cache = &gc->ads_cache[owner][type][capture_class]; in guc_capture_getlistsize()
566 if (!gc->reglists) { in guc_capture_getlistsize()
567 xe_gt_warn(gt, "No capture reglist for this device\n"); in guc_capture_getlistsize()
568 return -ENODEV; in guc_capture_getlistsize()
571 if (cache->is_valid) { in guc_capture_getlistsize()
572 *size = cache->size; in guc_capture_getlistsize()
573 return cache->status; in guc_capture_getlistsize()
577 !guc_capture_get_one_list(gc->reglists, owner, type, capture_class)) { in guc_capture_getlistsize()
579 xe_gt_warn(gt, "Missing capture reglist: global!\n"); in guc_capture_getlistsize()
581 xe_gt_warn(gt, "Missing capture reglist: %s(%u):%s(%u)!\n", in guc_capture_getlistsize()
584 return -ENODEV; in guc_capture_getlistsize()
590 return -ENODATA; in guc_capture_getlistsize()
600 * xe_guc_capture_getlistsize - Get list size for owner/type/class combination
603 * @type: GuC capture register type
604 * @capture_class: GuC capture engine class id
620 * xe_guc_capture_getlist - Get register capture list for owner/type/class
624 * @type: GuC capture register type
625 * @capture_class: GuC capture engine class id
626 * @outptr: Point to cached register capture list
628 * This function will get the register capture list for the owner/type/class
637 struct xe_guc_state_capture *gc = guc->capture; in xe_guc_capture_getlist()
638 struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][capture_class]; in xe_guc_capture_getlist()
644 if (!gc->reglists) in xe_guc_capture_getlist()
645 return -ENODEV; in xe_guc_capture_getlist()
647 if (cache->is_valid) { in xe_guc_capture_getlist()
648 *outptr = cache->ptr; in xe_guc_capture_getlist()
649 return cache->status; in xe_guc_capture_getlist()
654 cache->is_valid = true; in xe_guc_capture_getlist()
655 cache->ptr = NULL; in xe_guc_capture_getlist()
656 cache->size = 0; in xe_guc_capture_getlist()
657 cache->status = ret; in xe_guc_capture_getlist()
663 return -ENOMEM; in xe_guc_capture_getlist()
665 /* populate capture list header */ in xe_guc_capture_getlist()
669 listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); in xe_guc_capture_getlist()
677 cache->is_valid = true; in xe_guc_capture_getlist()
678 cache->ptr = caplist; in xe_guc_capture_getlist()
679 cache->size = size; in xe_guc_capture_getlist()
680 cache->status = 0; in xe_guc_capture_getlist()
688 * xe_guc_capture_getnullheader - Get a null list for register capture
690 * @outptr: Point to cached register capture list
693 * This function will alloc for a null list for register capture.
700 struct xe_guc_state_capture *gc = guc->capture; in xe_guc_capture_getnullheader()
704 if (gc->ads_null_cache) { in xe_guc_capture_getnullheader()
705 *outptr = gc->ads_null_cache; in xe_guc_capture_getnullheader()
712 return -ENOMEM; in xe_guc_capture_getnullheader()
714 gc->ads_null_cache = null_header; in xe_guc_capture_getnullheader()
722 * xe_guc_capture_ads_input_worst_size - Calculate the worst size for GuC register capture
725 * Calculate the worst size for GuC register capture by including all possible engines classes.
737 * first of a two-phase GuC (and ADS-population) initialization in xe_guc_capture_ads_input_worst_size()
738 * sequence, that is, during the pre-hwconfig phase before we have in xe_guc_capture_ads_input_worst_size()
773 if (!guc->capture) in guc_capture_output_size_est()
774 return -ENODEV; in guc_capture_output_size_est()
777 * If every single engine-instance suffered a failure in quick succession but in guc_capture_output_size_est()
778 * were all unrelated, then a burst of multiple error-capture events would dump in guc_capture_output_size_est()
780 * would even dump the global-registers repeatedly. in guc_capture_output_size_est()
790 capture_class = xe_engine_class_to_guc_capture_class(hwe->class); in guc_capture_output_size_est()
809 * Add on a 3x multiplier to allow for multiple back-to-back captures occurring
818 u32 buffer_size = xe_guc_log_section_size_capture(&guc->log); in check_guc_capture_size()
821 * NOTE: capture_size is much smaller than the capture region in check_guc_capture_size()
827 * G2H event capture-notification, search for: in check_guc_capture_size()
832 "Failed to calculate error state capture buffer minimum size: %d!\n", in check_guc_capture_size()
835 xe_gt_dbg(guc_to_gt(guc), "Error state capture buffer maybe small: %d < %d\n", in check_guc_capture_size()
839 "Error state capture buffer lacks spare size: %d < %d (min = %d)\n", in check_guc_capture_size()
847 list_add(&node->link, list); in guc_capture_add_node_to_list()
855 guc_capture_add_node_to_list(node, &gc->outlist); in guc_capture_add_node_to_outlist()
862 guc_capture_add_node_to_list(node, &gc->cachelist); in guc_capture_add_node_to_cachelist()
870 n->locked = 0; in guc_capture_free_outlist_node()
871 list_del(&n->link); in guc_capture_free_outlist_node()
882 int guc_id = node->guc_id; in guc_capture_remove_stale_matches_from_list()
884 list_for_each_entry_safe(n, ntmp, &gc->outlist, link) { in guc_capture_remove_stale_matches_from_list()
885 if (n != node && !n->locked && n->guc_id == guc_id) in guc_capture_remove_stale_matches_from_list()
897 tmp[i] = node->reginfo[i].regs; in guc_capture_init_node()
899 guc->capture->max_mmio_per_node); in guc_capture_init_node()
903 node->reginfo[i].regs = tmp[i]; in guc_capture_init_node()
905 INIT_LIST_HEAD(&node->link); in guc_capture_init_node()
909 * DOC: Init, G2H-event and reporting flows for GuC-error-capture
912 * --------------------
913 * --> alloc A: GuC input capture regs lists (registered to GuC via ADS).
916 * where n = 1 for global-reg-list +
917 * num_engine_classes for class-reg-list +
918 * num_engine_classes for instance-reg-list
919 * (since all instances of the same engine-class type
920 * have an identical engine-instance register-list).
923 * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param))
924 * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small)
925 * Note2: 'x 3' to hold multiple capture groups
927 * GUC Runtime notify capture:
928 * --------------------------
929 * --> G2H STATE_CAPTURE_NOTIFICATION
930 * L--> xe_guc_capture_process
931 * L--> Loop through B (head..tail) and for each engine instance's
932 * err-state-captured register-list we find, we alloc 'C':
933 * --> alloc C: A capture-output-node structure that includes misc capture info along
934 * with 3 register list dumps (global, engine-class and engine-instance)
935 * This node is created from a pre-allocated list of blank nodes in
936 * guc->capture->cachelist and populated with the error-capture
937 * data from GuC and then it's added into guc->capture->outlist linked
941 * GUC --> notify context reset:
942 * -----------------------------
943 * --> guc_exec_queue_timedout_job
944 * L--> xe_devcoredump
945 * L--> devcoredump_snapshot
946 * --> xe_hw_engine_snapshot_capture
947 * --> xe_engine_manual_capture(For manual capture)
950 * --------------------
951 * --> xe_devcoredump_read->
952 * L--> xxx_snapshot_print
953 * L--> xe_engine_snapshot_print
955 * guc->capture->outlist
961 if (buf->wr >= buf->rd) in guc_capture_buf_cnt()
962 return (buf->wr - buf->rd); in guc_capture_buf_cnt()
963 return (buf->size - buf->rd) + buf->wr; in guc_capture_buf_cnt()
968 if (buf->rd > buf->wr) in guc_capture_buf_cnt_to_end()
969 return (buf->size - buf->rd); in guc_capture_buf_cnt_to_end()
970 return (buf->wr - buf->rd); in guc_capture_buf_cnt_to_end()
974 * GuC's error-capture output is a ring buffer populated in a byte-stream fashion:
976 * The GuC Log buffer region for error-capture is managed like a ring buffer.
977 * The GuC firmware dumps error capture logs into this ring in a byte-stream flow.
978 * Additionally, as per the current and foreseeable future, all packed error-
979 * capture output structures are dword aligned.
982 * than one dword but the tail end of the err-capture buffer-region has lesser space left,
987 * function would typically do a straight-up memcpy from the ring contents and will only
988 * call this helper if their structure-extraction is straddling across the end of the
989 * ring. GuC firmware does not add any padding. The reason for the no-padding is to ease
1005 return -1; in guc_capture_log_remove_bytes()
1007 while (bytes_needed > 0 && tries--) { in guc_capture_log_remove_bytes()
1015 if (!buf->rd) in guc_capture_log_remove_bytes()
1017 buf->rd = 0; in guc_capture_log_remove_bytes()
1021 /* Only copy to u32 aligned data */ in guc_capture_log_remove_bytes()
1022 copy_size = avail < bytes_needed ? avail - misaligned : bytes_needed; in guc_capture_log_remove_bytes()
1023 xe_map_memcpy_from(guc_to_xe(guc), out + fill_size, &guc->log.bo->vmap, in guc_capture_log_remove_bytes()
1024 buf->data_offset + buf->rd, copy_size); in guc_capture_log_remove_bytes()
1025 buf->rd += copy_size; in guc_capture_log_remove_bytes()
1027 bytes_needed -= copy_size; in guc_capture_log_remove_bytes()
1044 return -1; in guc_capture_log_get_group_hdr()
1055 return -1; in guc_capture_log_get_data_hdr()
1066 return -1; in guc_capture_log_get_register()
1075 if (!list_empty(&guc->capture->cachelist)) { in guc_capture_get_prealloc_node()
1079 list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) { in guc_capture_get_prealloc_node()
1090 list_for_each_entry_safe_reverse(n, ntmp, &guc->capture->outlist, link) { in guc_capture_get_prealloc_node()
1091 if (!n->locked) in guc_capture_get_prealloc_node()
1096 list_del(&found->link); in guc_capture_get_prealloc_node()
1116 new->is_partial = original->is_partial; in guc_capture_clone_node()
1118 /* copy reg-lists that we want to clone */ in guc_capture_clone_node()
1121 XE_WARN_ON(original->reginfo[i].num_regs > in guc_capture_clone_node()
1122 guc->capture->max_mmio_per_node); in guc_capture_clone_node()
1124 memcpy(new->reginfo[i].regs, original->reginfo[i].regs, in guc_capture_clone_node()
1125 original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); in guc_capture_clone_node()
1127 new->reginfo[i].num_regs = original->reginfo[i].num_regs; in guc_capture_clone_node()
1128 new->reginfo[i].vfid = original->reginfo[i].vfid; in guc_capture_clone_node()
1131 new->eng_class = original->eng_class; in guc_capture_clone_node()
1133 new->eng_inst = original->eng_inst; in guc_capture_clone_node()
1134 new->guc_id = original->guc_id; in guc_capture_clone_node()
1135 new->lrca = original->lrca; in guc_capture_clone_node()
1158 return -ENODATA; in guc_capture_extract_reglists()
1161 xe_gt_warn(gt, "Got mis-aligned register capture entries\n"); in guc_capture_extract_reglists()
1162 ret = -EIO; in guc_capture_extract_reglists()
1166 /* first get the capture group header */ in guc_capture_extract_reglists()
1168 ret = -EIO; in guc_capture_extract_reglists()
1176 * | Capture Group | in guc_capture_extract_reglists()
1178 * | | Capture Group Header: | | in guc_capture_extract_reglists()
1179 * | | - num_captures = 5 | | in guc_capture_extract_reglists()
1186 * | | | - reg1, reg2, ... rega | | | in guc_capture_extract_reglists()
1194 * | | | - reg1, reg2, ... regb | | | in guc_capture_extract_reglists()
1202 * | | | - reg1, reg2, ... regc | | | in guc_capture_extract_reglists()
1210 * | | | - reg1, reg2, ... regd | | | in guc_capture_extract_reglists()
1218 * | | | - reg1, reg2, ... rege | | | in guc_capture_extract_reglists()
1226 while (numlists--) { in guc_capture_extract_reglists()
1228 ret = -EIO; in guc_capture_extract_reglists()
1234 /* unknown capture type - skip over to next capture set */ in guc_capture_extract_reglists()
1237 while (numregs--) { in guc_capture_extract_reglists()
1239 ret = -EIO; in guc_capture_extract_reglists()
1246 * Based on the current capture type and what we have so far, in guc_capture_extract_reglists()
1248 * linked list for match-up when xe_devcoredump calls later in guc_capture_extract_reglists()
1251 * but only retain the global or class registers (such as the in guc_capture_extract_reglists()
1255 guc_capture_add_node_to_outlist(guc->capture, node); in guc_capture_extract_reglists()
1258 node->reginfo[GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS].num_regs) { in guc_capture_extract_reglists()
1260 guc_capture_add_node_to_outlist(guc->capture, node); in guc_capture_extract_reglists()
1264 node->reginfo[GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE].num_regs) { in guc_capture_extract_reglists()
1266 guc_capture_add_node_to_outlist(guc->capture, node); in guc_capture_extract_reglists()
1276 ret = -ENOMEM; in guc_capture_extract_reglists()
1280 xe_gt_dbg(gt, "Register capture missing global dump: %08x!\n", in guc_capture_extract_reglists()
1283 node->is_partial = is_partial; in guc_capture_extract_reglists()
1284 node->reginfo[datatype].vfid = FIELD_GET(GUC_STATE_CAPTURE_HEADER_VFID, hdr.owner); in guc_capture_extract_reglists()
1285 node->source = XE_ENGINE_CAPTURE_SOURCE_GUC; in guc_capture_extract_reglists()
1286 node->type = datatype; in guc_capture_extract_reglists()
1290 node->eng_class = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_CLASS, in guc_capture_extract_reglists()
1292 node->eng_inst = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_INSTANCE, in guc_capture_extract_reglists()
1294 node->lrca = hdr.lrca; in guc_capture_extract_reglists()
1295 node->guc_id = hdr.guc_id; in guc_capture_extract_reglists()
1298 node->eng_class = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_CLASS, in guc_capture_extract_reglists()
1307 if (numregs > guc->capture->max_mmio_per_node) { in guc_capture_extract_reglists()
1308 xe_gt_dbg(gt, "Register capture list extraction clipped by prealloc!\n"); in guc_capture_extract_reglists()
1309 numregs = guc->capture->max_mmio_per_node; in guc_capture_extract_reglists()
1311 node->reginfo[datatype].num_regs = numregs; in guc_capture_extract_reglists()
1312 regs = node->reginfo[datatype].regs; in guc_capture_extract_reglists()
1314 while (numregs--) { in guc_capture_extract_reglists()
1316 ret = -EIO; in guc_capture_extract_reglists()
1324 /* If we have data, add to linked list for match-up when xe_devcoredump calls */ in guc_capture_extract_reglists()
1326 if (node->reginfo[i].regs) { in guc_capture_extract_reglists()
1327 guc_capture_add_node_to_outlist(guc->capture, node); in guc_capture_extract_reglists()
1333 guc_capture_add_node_to_cachelist(guc->capture, node); in guc_capture_extract_reglists()
1345 return xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action)); in __guc_capture_flushlog_complete()
1360 src_data_offset = xe_guc_get_log_buffer_offset(&guc->log, GUC_LOG_BUFFER_CAPTURE); in __guc_capture_process_output()
1367 xe_map_memcpy_from(guc_to_xe(guc), &log_buf_state_local, &guc->log.bo->vmap, in __guc_capture_process_output()
1370 buffer_size = xe_guc_get_log_buffer_size(&guc->log, GUC_LOG_BUFFER_CAPTURE); in __guc_capture_process_output()
1377 guc->log.stats[GUC_LOG_BUFFER_CAPTURE].flush += tmp; in __guc_capture_process_output()
1378 new_overflow = xe_guc_check_log_buf_overflow(&guc->log, GUC_LOG_BUFFER_CAPTURE, in __guc_capture_process_output()
1389 "Register capture buffer in invalid state: read = 0x%X, size = 0x%X!\n", in __guc_capture_process_output()
1404 if (ret && ret != -ENODATA) in __guc_capture_process_output()
1405 xe_gt_dbg(guc_to_gt(guc), "Capture extraction failed:%d\n", ret); in __guc_capture_process_output()
1409 /* Update the state of log buffer err-cap state */ in __guc_capture_process_output()
1410 xe_map_wr(guc_to_xe(guc), &guc->log.bo->vmap, in __guc_capture_process_output()
1420 xe_map_wr(guc_to_xe(guc), &guc->log.bo->vmap, in __guc_capture_process_output()
1427 * xe_guc_capture_process - Process GuC register captured data
1438 if (guc->capture) in xe_guc_capture_process()
1454 new->reginfo[i].regs = drmm_kzalloc(drm, guc->capture->max_mmio_per_node * in guc_capture_alloc_one_node()
1456 if (!new->reginfo[i].regs) { in guc_capture_alloc_one_node()
1458 drmm_kfree(drm, new->reginfo[--i].regs); in guc_capture_alloc_one_node()
1477 xe_gt_warn(guc_to_gt(guc), "Register capture pre-alloc-cache failure\n"); in __guc_capture_create_prealloc_nodes()
1481 guc_capture_add_node_to_cachelist(guc->capture, node); in __guc_capture_create_prealloc_nodes()
1499 match = guc_capture_get_one_list(guc->capture->reglists, i, j, k); in guc_get_max_reglist_count()
1501 tmp = match->num_regs; in guc_get_max_reglist_count()
1503 match = guc_capture_get_one_list(guc->capture->extlists, i, j, k); in guc_get_max_reglist_count()
1505 tmp += match->num_regs; in guc_get_max_reglist_count()
1521 /* skip if we've already done the pre-alloc */ in guc_capture_create_prealloc_nodes()
1522 if (guc->capture->max_mmio_per_node) in guc_capture_create_prealloc_nodes()
1525 guc->capture->max_mmio_per_node = guc_get_max_reglist_count(guc); in guc_capture_create_prealloc_nodes()
1535 if (!list || !list->list || list->num_regs == 0) in read_reg_to_node()
1541 for (i = 0; i < list->num_regs; i++) { in read_reg_to_node()
1542 struct __guc_mmio_reg_descr desc = list->list[i]; in read_reg_to_node()
1545 if (list->type == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) { in read_reg_to_node()
1548 if (list->type == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS && in read_reg_to_node()
1554 value = xe_gt_mcr_unicast_read(hwe->gt, XE_REG_MCR(desc.reg.addr), in read_reg_to_node()
1557 value = xe_mmio_read32(&hwe->gt->mmio, desc.reg); in read_reg_to_node()
1569 * xe_engine_manual_capture - Take a manual engine snapshot from engine.
1580 struct xe_gt *gt = hwe->gt; in xe_engine_manual_capture()
1582 struct xe_guc *guc = &gt->uc.guc; in xe_engine_manual_capture()
1583 struct xe_devcoredump *devcoredump = &xe->devcoredump; in xe_engine_manual_capture()
1598 capture_class = xe_engine_class_to_guc_capture_class(hwe->class); in xe_engine_manual_capture()
1600 struct gcap_reg_list_info *reginfo = &new->reginfo[type]; in xe_engine_manual_capture()
1602 * regsinfo->regs is allocated based on guc->capture->max_mmio_per_node in xe_engine_manual_capture()
1611 xe_gt_dbg(gt, "Empty GuC capture register descriptor for %s", in xe_engine_manual_capture()
1612 hwe->name); in xe_engine_manual_capture()
1616 read_reg_to_node(hwe, list, reginfo->regs); in xe_engine_manual_capture()
1617 reginfo->num_regs = list->num_regs; in xe_engine_manual_capture()
1619 /* Capture steering registers for rcs/ccs */ in xe_engine_manual_capture()
1624 read_reg_to_node(hwe, list, &reginfo->regs[reginfo->num_regs]); in xe_engine_manual_capture()
1625 reginfo->num_regs += list->num_regs; in xe_engine_manual_capture()
1630 if (devcoredump && devcoredump->captured) { in xe_engine_manual_capture()
1631 struct xe_guc_submit_exec_queue_snapshot *ge = devcoredump->snapshot.ge; in xe_engine_manual_capture()
1634 guc_id = ge->guc.id; in xe_engine_manual_capture()
1635 if (ge->lrc[0]) in xe_engine_manual_capture()
1636 lrca = ge->lrc[0]->context_desc; in xe_engine_manual_capture()
1640 new->eng_class = xe_engine_class_to_guc_class(hwe->class); in xe_engine_manual_capture()
1641 new->eng_inst = hwe->instance; in xe_engine_manual_capture()
1642 new->guc_id = guc_id; in xe_engine_manual_capture()
1643 new->lrca = lrca; in xe_engine_manual_capture()
1644 new->is_partial = 0; in xe_engine_manual_capture()
1645 new->locked = 1; in xe_engine_manual_capture()
1646 new->source = XE_ENGINE_CAPTURE_SOURCE_MANUAL; in xe_engine_manual_capture()
1648 guc_capture_add_node_to_outlist(guc->capture, new); in xe_engine_manual_capture()
1649 devcoredump->snapshot.matched_node = new; in xe_engine_manual_capture()
1657 if (reginfo && reginfo->num_regs > 0) { in guc_capture_find_reg()
1658 struct guc_mmio_reg *regs = reginfo->regs; in guc_capture_find_reg()
1661 for (i = 0; i < reginfo->num_regs; i++) in guc_capture_find_reg()
1673 struct xe_gt *gt = snapshot->hwe->gt; in snapshot_print_by_list_order()
1675 struct xe_guc *guc = &gt->uc.guc; in snapshot_print_by_list_order()
1676 struct xe_devcoredump *devcoredump = &xe->devcoredump; in snapshot_print_by_list_order()
1677 struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot; in snapshot_print_by_list_order()
1682 if (!list || !list->list || list->num_regs == 0) in snapshot_print_by_list_order()
1684 XE_WARN_ON(!devcore_snapshot->matched_node); in snapshot_print_by_list_order()
1686 is_ext = list == guc->capture->extlists; in snapshot_print_by_list_order()
1687 reginfo = &devcore_snapshot->matched_node->reginfo[type]; in snapshot_print_by_list_order()
1693 * table-of-lists in snapshot_print_by_list_order()
1695 for (i = 0; i < list->num_regs; i++) { in snapshot_print_by_list_order()
1696 const struct __guc_mmio_reg_descr *reg_desc = &list->list[i]; in snapshot_print_by_list_order()
1700 reg = guc_capture_find_reg(reginfo, reg_desc->reg.addr, reg_desc->flags); in snapshot_print_by_list_order()
1704 value = reg->value; in snapshot_print_by_list_order()
1705 switch (reg_desc->data_type) { in snapshot_print_by_list_order()
1739 drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw); in snapshot_print_by_list_order()
1755 group = FIELD_GET(GUC_REGSET_STEERING_GROUP, reg_desc->flags); in snapshot_print_by_list_order()
1756 instance = FIELD_GET(GUC_REGSET_STEERING_INSTANCE, reg_desc->flags); in snapshot_print_by_list_order()
1759 drm_printf(p, "\t%s[%u]: 0x%08x\n", reg_desc->regname, dss, value); in snapshot_print_by_list_order()
1761 drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value); in snapshot_print_by_list_order()
1771 * } // <- Register list end in snapshot_print_by_list_order()
1777 * xe_engine_snapshot_print - Print out a given Xe HW Engine snapshot.
1786 "full-capture", in xe_engine_snapshot_print()
1787 "partial-capture" in xe_engine_snapshot_print()
1801 gt = snapshot->hwe->gt; in xe_engine_snapshot_print()
1803 devcoredump = &xe->devcoredump; in xe_engine_snapshot_print()
1804 devcore_snapshot = &devcoredump->snapshot; in xe_engine_snapshot_print()
1806 if (!devcore_snapshot->matched_node) in xe_engine_snapshot_print()
1809 xe_gt_assert(gt, snapshot->hwe); in xe_engine_snapshot_print()
1811 capture_class = xe_engine_class_to_guc_capture_class(snapshot->hwe->class); in xe_engine_snapshot_print()
1814 snapshot->name ? snapshot->name : "", in xe_engine_snapshot_print()
1815 snapshot->logical_instance); in xe_engine_snapshot_print()
1817 devcore_snapshot->matched_node->source == XE_ENGINE_CAPTURE_SOURCE_GUC ? in xe_engine_snapshot_print()
1819 drm_printf(p, "\tCoverage: %s\n", grptype[devcore_snapshot->matched_node->is_partial]); in xe_engine_snapshot_print()
1821 snapshot->forcewake.domain, snapshot->forcewake.ref); in xe_engine_snapshot_print()
1823 str_yes_no(snapshot->kernel_reserved)); in xe_engine_snapshot_print()
1843 * xe_guc_capture_get_matching_and_lock - Matching GuC capture for the queue.
1846 * Search within the capture outlist for the queue, could be used for check if
1847 * GuC capture is ready for the queue.
1850 * Returns: found guc-capture node ptr else NULL
1861 if (!q || !q->gt) in xe_guc_capture_get_matching_and_lock()
1864 xe = gt_to_xe(q->gt); in xe_guc_capture_get_matching_and_lock()
1865 if (xe->wedged.mode >= 2 || !xe_device_uc_enabled(xe) || IS_SRIOV_VF(xe)) in xe_guc_capture_get_matching_and_lock()
1868 ss = &xe->devcoredump.snapshot; in xe_guc_capture_get_matching_and_lock()
1869 if (ss->matched_node && ss->matched_node->source == XE_ENGINE_CAPTURE_SOURCE_GUC) in xe_guc_capture_get_matching_and_lock()
1870 return ss->matched_node; in xe_guc_capture_get_matching_and_lock()
1873 for_each_hw_engine(hwe, q->gt, id) { in xe_guc_capture_get_matching_and_lock()
1874 if (hwe != q->hwe) in xe_guc_capture_get_matching_and_lock()
1876 guc_class = xe_engine_class_to_guc_class(hwe->class); in xe_guc_capture_get_matching_and_lock()
1882 struct xe_guc *guc = &q->gt->uc.guc; in xe_guc_capture_get_matching_and_lock()
1883 u16 guc_id = q->guc->id; in xe_guc_capture_get_matching_and_lock()
1884 u32 lrca = xe_lrc_ggtt_addr(q->lrc[0]); in xe_guc_capture_get_matching_and_lock()
1887 * Look for a matching GuC reported error capture node from in xe_guc_capture_get_matching_and_lock()
1888 * the internal output link-list based on engine, guc id and in xe_guc_capture_get_matching_and_lock()
1891 list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) { in xe_guc_capture_get_matching_and_lock()
1892 if (n->eng_class == guc_class && n->eng_inst == hwe->instance && in xe_guc_capture_get_matching_and_lock()
1893 n->guc_id == guc_id && n->lrca == lrca && in xe_guc_capture_get_matching_and_lock()
1894 n->source == XE_ENGINE_CAPTURE_SOURCE_GUC) { in xe_guc_capture_get_matching_and_lock()
1895 n->locked = 1; in xe_guc_capture_get_matching_and_lock()
1904 * xe_engine_snapshot_capture_for_queue - Take snapshot of associated engine
1914 struct xe_device *xe = gt_to_xe(q->gt); in xe_engine_snapshot_capture_for_queue()
1915 struct xe_devcoredump *coredump = &xe->devcoredump; in xe_engine_snapshot_capture_for_queue()
1918 u32 adj_logical_mask = q->logical_mask; in xe_engine_snapshot_capture_for_queue()
1923 for_each_hw_engine(hwe, q->gt, id) { in xe_engine_snapshot_capture_for_queue()
1924 if (hwe->class != q->hwe->class || in xe_engine_snapshot_capture_for_queue()
1925 !(BIT(hwe->logical_instance) & adj_logical_mask)) { in xe_engine_snapshot_capture_for_queue()
1926 coredump->snapshot.hwe[id] = NULL; in xe_engine_snapshot_capture_for_queue()
1930 if (!coredump->snapshot.hwe[id]) { in xe_engine_snapshot_capture_for_queue()
1931 coredump->snapshot.hwe[id] = in xe_engine_snapshot_capture_for_queue()
1938 struct xe_guc *guc = &q->gt->uc.guc; in xe_engine_snapshot_capture_for_queue()
1942 * GuC-err-capture node for this engine after in xe_engine_snapshot_capture_for_queue()
1947 guc_capture_free_outlist_node(guc->capture, in xe_engine_snapshot_capture_for_queue()
1948 coredump->snapshot.matched_node); in xe_engine_snapshot_capture_for_queue()
1949 coredump->snapshot.matched_node = new; in xe_engine_snapshot_capture_for_queue()
1958 * xe_guc_capture_put_matched_nodes - Cleanup matched nodes
1967 struct xe_devcoredump *devcoredump = &xe->devcoredump; in xe_guc_capture_put_matched_nodes()
1968 struct __guc_capture_parsed_output *n = devcoredump->snapshot.matched_node; in xe_guc_capture_put_matched_nodes()
1971 guc_capture_remove_stale_matches_from_list(guc->capture, n); in xe_guc_capture_put_matched_nodes()
1972 guc_capture_free_outlist_node(guc->capture, n); in xe_guc_capture_put_matched_nodes()
1973 devcoredump->snapshot.matched_node = NULL; in xe_guc_capture_put_matched_nodes()
1978 * xe_guc_capture_steered_list_init - Init steering register list
1981 * Init steering register list for GuC register capture, create pre-alloc node
1989 * the end of the pre-populated render list. in xe_guc_capture_steered_list_init()
1997 * xe_guc_capture_init - Init for GuC register capture
2000 * Init for GuC register capture, alloc memory for capture data structure.
2003 * -ENOMEM if out of memory
2007 guc->capture = drmm_kzalloc(guc_to_drm(guc), sizeof(*guc->capture), GFP_KERNEL); in xe_guc_capture_init()
2008 if (!guc->capture) in xe_guc_capture_init()
2009 return -ENOMEM; in xe_guc_capture_init()
2011 guc->capture->reglists = guc_capture_get_device_reglist(guc_to_xe(guc)); in xe_guc_capture_init()
2013 INIT_LIST_HEAD(&guc->capture->outlist); in xe_guc_capture_init()
2014 INIT_LIST_HEAD(&guc->capture->cachelist); in xe_guc_capture_init()