@@ -935,20 +935,21 @@ guc_capture_init_node(struct xe_guc *guc, struct __guc_capture_parsed_output *no
935
935
* guc->capture->cachelist and populated with the error-capture
936
936
* data from GuC and then it's added into guc->capture->outlist linked
937
937
* list. This list is used for matchup and printout by xe_devcoredump_read
938
- * and xe_hw_engine_snapshot_print , (when user invokes the devcoredump sysfs).
938
+ * and xe_engine_snapshot_print , (when user invokes the devcoredump sysfs).
939
939
*
940
940
* GUC --> notify context reset:
941
941
* -----------------------------
942
942
* --> guc_exec_queue_timedout_job
943
943
* L--> xe_devcoredump
944
944
* L--> devcoredump_snapshot
945
945
* --> xe_hw_engine_snapshot_capture
946
+ * --> xe_engine_manual_capture(For manual capture)
946
947
*
947
948
* User Sysfs / Debugfs
948
949
* --------------------
949
950
* --> xe_devcoredump_read->
950
951
* L--> xxx_snapshot_print
951
- * L--> xe_hw_engine_snapshot_print
952
+ * L--> xe_engine_snapshot_print
952
953
* Print register lists values saved at
953
954
* guc->capture->outlist
954
955
*
@@ -1524,6 +1525,129 @@ guc_capture_create_prealloc_nodes(struct xe_guc *guc)
1524
1525
__guc_capture_create_prealloc_nodes (guc );
1525
1526
}
1526
1527
1528
+ static void
1529
+ read_reg_to_node (struct xe_hw_engine * hwe , const struct __guc_mmio_reg_descr_group * list ,
1530
+ struct guc_mmio_reg * regs )
1531
+ {
1532
+ int i ;
1533
+
1534
+ if (!list || list -> num_regs == 0 )
1535
+ return ;
1536
+
1537
+ if (!regs )
1538
+ return ;
1539
+
1540
+ for (i = 0 ; i < list -> num_regs ; i ++ ) {
1541
+ struct __guc_mmio_reg_descr desc = list -> list [i ];
1542
+ u32 value ;
1543
+
1544
+ if (!list -> list )
1545
+ return ;
1546
+
1547
+ if (list -> type == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE ) {
1548
+ value = xe_hw_engine_mmio_read32 (hwe , desc .reg );
1549
+ } else {
1550
+ if (list -> type == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS &&
1551
+ FIELD_GET (GUC_REGSET_STEERING_NEEDED , desc .flags )) {
1552
+ int group , instance ;
1553
+
1554
+ group = FIELD_GET (GUC_REGSET_STEERING_GROUP , desc .flags );
1555
+ instance = FIELD_GET (GUC_REGSET_STEERING_INSTANCE , desc .flags );
1556
+ value = xe_gt_mcr_unicast_read (hwe -> gt , XE_REG_MCR (desc .reg .addr ),
1557
+ group , instance );
1558
+ } else {
1559
+ value = xe_mmio_read32 (& hwe -> gt -> mmio , desc .reg );
1560
+ }
1561
+ }
1562
+
1563
+ regs [i ].value = value ;
1564
+ regs [i ].offset = desc .reg .addr ;
1565
+ regs [i ].flags = desc .flags ;
1566
+ regs [i ].mask = desc .mask ;
1567
+ }
1568
+ }
1569
+
1570
+ /**
1571
+ * xe_engine_manual_capture - Take a manual engine snapshot from engine.
1572
+ * @hwe: Xe HW Engine.
1573
+ * @snapshot: The engine snapshot
1574
+ *
1575
+ * Take engine snapshot from engine read.
1576
+ *
1577
+ * Returns: None
1578
+ */
1579
+ void
1580
+ xe_engine_manual_capture (struct xe_hw_engine * hwe , struct xe_hw_engine_snapshot * snapshot )
1581
+ {
1582
+ struct xe_gt * gt = hwe -> gt ;
1583
+ struct xe_device * xe = gt_to_xe (gt );
1584
+ struct xe_guc * guc = & gt -> uc .guc ;
1585
+ struct xe_devcoredump * devcoredump = & xe -> devcoredump ;
1586
+ enum guc_capture_list_class_type capture_class ;
1587
+ const struct __guc_mmio_reg_descr_group * list ;
1588
+ struct __guc_capture_parsed_output * new ;
1589
+ enum guc_state_capture_type type ;
1590
+ u16 guc_id = 0 ;
1591
+ u32 lrca = 0 ;
1592
+
1593
+ new = guc_capture_get_prealloc_node (guc );
1594
+ if (!new )
1595
+ return ;
1596
+
1597
+ capture_class = xe_engine_class_to_guc_capture_class (hwe -> class );
1598
+ for (type = GUC_STATE_CAPTURE_TYPE_GLOBAL ; type < GUC_STATE_CAPTURE_TYPE_MAX ; type ++ ) {
1599
+ struct gcap_reg_list_info * reginfo = & new -> reginfo [type ];
1600
+ /*
1601
+ * regsinfo->regs is allocated based on guc->capture->max_mmio_per_node
1602
+ * which is based on the descriptor list driving the population so
1603
+ * should not overflow
1604
+ */
1605
+
1606
+ /* Get register list for the type/class */
1607
+ list = xe_guc_capture_get_reg_desc_list (gt , GUC_CAPTURE_LIST_INDEX_PF , type ,
1608
+ capture_class , false);
1609
+ if (!list ) {
1610
+ xe_gt_dbg (gt , "Empty GuC capture register descriptor for %s" ,
1611
+ hwe -> name );
1612
+ continue ;
1613
+ }
1614
+
1615
+ read_reg_to_node (hwe , list , reginfo -> regs );
1616
+ reginfo -> num_regs = list -> num_regs ;
1617
+
1618
+ /* Capture steering registers for rcs/ccs */
1619
+ if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE ) {
1620
+ list = xe_guc_capture_get_reg_desc_list (gt , GUC_CAPTURE_LIST_INDEX_PF ,
1621
+ type , capture_class , true);
1622
+ if (list ) {
1623
+ read_reg_to_node (hwe , list , & reginfo -> regs [reginfo -> num_regs ]);
1624
+ reginfo -> num_regs += list -> num_regs ;
1625
+ }
1626
+ }
1627
+ }
1628
+
1629
+ if (devcoredump && devcoredump -> captured ) {
1630
+ struct xe_guc_submit_exec_queue_snapshot * ge = devcoredump -> snapshot .ge ;
1631
+
1632
+ if (ge ) {
1633
+ guc_id = ge -> guc .id ;
1634
+ if (ge -> lrc [0 ])
1635
+ lrca = ge -> lrc [0 ]-> context_desc ;
1636
+ }
1637
+ }
1638
+
1639
+ new -> eng_class = xe_engine_class_to_guc_class (hwe -> class );
1640
+ new -> eng_inst = hwe -> instance ;
1641
+ new -> guc_id = guc_id ;
1642
+ new -> lrca = lrca ;
1643
+ new -> is_partial = 0 ;
1644
+ new -> locked = 1 ;
1645
+ new -> source = XE_ENGINE_CAPTURE_SOURCE_MANUAL ;
1646
+
1647
+ guc_capture_add_node_to_outlist (guc -> capture , new );
1648
+ devcoredump -> snapshot .matched_node = new ;
1649
+ }
1650
+
1527
1651
static struct guc_mmio_reg *
1528
1652
guc_capture_find_reg (struct gcap_reg_list_info * reginfo , u32 addr , u32 flags )
1529
1653
{
@@ -1609,7 +1733,7 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
1609
1733
*
1610
1734
* This function prints out a given Xe HW Engine snapshot object.
1611
1735
*/
1612
- void xe_engine_guc_capture_print (struct xe_hw_engine_snapshot * snapshot , struct drm_printer * p )
1736
+ void xe_engine_snapshot_print (struct xe_hw_engine_snapshot * snapshot , struct drm_printer * p )
1613
1737
{
1614
1738
const char * grptype [GUC_STATE_CAPTURE_GROUP_TYPE_MAX ] = {
1615
1739
"full-capture" ,
@@ -1648,6 +1772,8 @@ void xe_engine_guc_capture_print(struct xe_hw_engine_snapshot *snapshot, struct
1648
1772
drm_printf (p , "\tCoverage: %s\n" , grptype [devcore_snapshot -> matched_node -> is_partial ]);
1649
1773
drm_printf (p , "\tForcewake: domain 0x%x, ref %d\n" ,
1650
1774
snapshot -> forcewake .domain , snapshot -> forcewake .ref );
1775
+ drm_printf (p , "\tReserved: %s\n" ,
1776
+ str_yes_no (snapshot -> kernel_reserved ));
1651
1777
1652
1778
for (type = GUC_STATE_CAPTURE_TYPE_GLOBAL ; type < GUC_STATE_CAPTURE_TYPE_MAX ; type ++ ) {
1653
1779
list = xe_guc_capture_get_reg_desc_list (gt , GUC_CAPTURE_LIST_INDEX_PF , type ,
@@ -1757,8 +1883,27 @@ xe_engine_snapshot_capture_for_job(struct xe_sched_job *job)
1757
1883
continue ;
1758
1884
}
1759
1885
1760
- if (!coredump -> snapshot .hwe [id ])
1886
+ if (!coredump -> snapshot .hwe [id ]) {
1761
1887
coredump -> snapshot .hwe [id ] = xe_hw_engine_snapshot_capture (hwe , job );
1888
+ } else {
1889
+ struct __guc_capture_parsed_output * new ;
1890
+
1891
+ new = xe_guc_capture_get_matching_and_lock (job );
1892
+ if (new ) {
1893
+ struct xe_guc * guc = & q -> gt -> uc .guc ;
1894
+
1895
+ /*
1896
+ * If we are in here, it means we found a fresh
1897
+ * GuC-err-capture node for this engine after
1898
+ * previously failing to find a match in the
1899
+ * early part of guc_exec_queue_timedout_job.
1900
+ * Thus we must free the manually captured node
1901
+ */
1902
+ guc_capture_free_outlist_node (guc -> capture ,
1903
+ coredump -> snapshot .matched_node );
1904
+ coredump -> snapshot .matched_node = new ;
1905
+ }
1906
+ }
1762
1907
1763
1908
break ;
1764
1909
}
0 commit comments