1*9c8c7a7eSZhanjun Dong // SPDX-License-Identifier: MIT 2*9c8c7a7eSZhanjun Dong /* 3*9c8c7a7eSZhanjun Dong * Copyright © 2021-2024 Intel Corporation 4*9c8c7a7eSZhanjun Dong */ 5*9c8c7a7eSZhanjun Dong 6*9c8c7a7eSZhanjun Dong #include <linux/types.h> 7*9c8c7a7eSZhanjun Dong 8*9c8c7a7eSZhanjun Dong #include <drm/drm_managed.h> 9*9c8c7a7eSZhanjun Dong #include <drm/drm_print.h> 10*9c8c7a7eSZhanjun Dong 11*9c8c7a7eSZhanjun Dong #include "abi/guc_actions_abi.h" 12*9c8c7a7eSZhanjun Dong #include "abi/guc_capture_abi.h" 13*9c8c7a7eSZhanjun Dong #include "regs/xe_engine_regs.h" 14*9c8c7a7eSZhanjun Dong #include "regs/xe_gt_regs.h" 15*9c8c7a7eSZhanjun Dong #include "regs/xe_guc_regs.h" 16*9c8c7a7eSZhanjun Dong #include "regs/xe_regs.h" 17*9c8c7a7eSZhanjun Dong 18*9c8c7a7eSZhanjun Dong #include "xe_bo.h" 19*9c8c7a7eSZhanjun Dong #include "xe_device.h" 20*9c8c7a7eSZhanjun Dong #include "xe_exec_queue_types.h" 21*9c8c7a7eSZhanjun Dong #include "xe_gt.h" 22*9c8c7a7eSZhanjun Dong #include "xe_gt_mcr.h" 23*9c8c7a7eSZhanjun Dong #include "xe_gt_printk.h" 24*9c8c7a7eSZhanjun Dong #include "xe_guc.h" 25*9c8c7a7eSZhanjun Dong #include "xe_guc_capture.h" 26*9c8c7a7eSZhanjun Dong #include "xe_guc_capture_types.h" 27*9c8c7a7eSZhanjun Dong #include "xe_guc_ct.h" 28*9c8c7a7eSZhanjun Dong #include "xe_guc_log.h" 29*9c8c7a7eSZhanjun Dong #include "xe_guc_submit.h" 30*9c8c7a7eSZhanjun Dong #include "xe_hw_engine_types.h" 31*9c8c7a7eSZhanjun Dong #include "xe_macros.h" 32*9c8c7a7eSZhanjun Dong #include "xe_map.h" 33*9c8c7a7eSZhanjun Dong 34*9c8c7a7eSZhanjun Dong /* 35*9c8c7a7eSZhanjun Dong * Define all device tables of GuC error capture register lists 36*9c8c7a7eSZhanjun Dong * NOTE: 37*9c8c7a7eSZhanjun Dong * For engine-registers, GuC only needs the register offsets 38*9c8c7a7eSZhanjun Dong * from the engine-mmio-base 39*9c8c7a7eSZhanjun Dong * 40*9c8c7a7eSZhanjun Dong * 64 bit registers need 2 entries for low 32 bit register and high 32 bit 41*9c8c7a7eSZhanjun Dong * register, for example: 42*9c8c7a7eSZhanjun Dong * Register data_type flags mask Register name 43*9c8c7a7eSZhanjun Dong * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, 44*9c8c7a7eSZhanjun Dong * { XXX_REG_HI(0), REG_64BIT_HI_DW,, 0, 0, "XXX_REG"}, 45*9c8c7a7eSZhanjun Dong * 1. data_type: Indicate is hi/low 32 bit for a 64 bit register 46*9c8c7a7eSZhanjun Dong * A 64 bit register define requires 2 consecutive entries, 47*9c8c7a7eSZhanjun Dong * with low dword first and hi dword the second. 48*9c8c7a7eSZhanjun Dong * 2. Register name: null for incompleted define 49*9c8c7a7eSZhanjun Dong */ 50*9c8c7a7eSZhanjun Dong #define COMMON_XELP_BASE_GLOBAL \ 51*9c8c7a7eSZhanjun Dong { FORCEWAKE_GT, REG_32BIT, 0, 0, "FORCEWAKE_GT"} 52*9c8c7a7eSZhanjun Dong 53*9c8c7a7eSZhanjun Dong #define COMMON_BASE_ENGINE_INSTANCE \ 54*9c8c7a7eSZhanjun Dong { RING_HWSTAM(0), REG_32BIT, 0, 0, "HWSTAM"}, \ 55*9c8c7a7eSZhanjun Dong { RING_HWS_PGA(0), REG_32BIT, 0, 0, "RING_HWS_PGA"}, \ 56*9c8c7a7eSZhanjun Dong { RING_HEAD(0), REG_32BIT, 0, 0, "RING_HEAD"}, \ 57*9c8c7a7eSZhanjun Dong { RING_TAIL(0), REG_32BIT, 0, 0, "RING_TAIL"}, \ 58*9c8c7a7eSZhanjun Dong { RING_CTL(0), REG_32BIT, 0, 0, "RING_CTL"}, \ 59*9c8c7a7eSZhanjun Dong { RING_MI_MODE(0), REG_32BIT, 0, 0, "RING_MI_MODE"}, \ 60*9c8c7a7eSZhanjun Dong { RING_MODE(0), REG_32BIT, 0, 0, "RING_MODE"}, \ 61*9c8c7a7eSZhanjun Dong { RING_ESR(0), REG_32BIT, 0, 0, "RING_ESR"}, \ 62*9c8c7a7eSZhanjun Dong { RING_EMR(0), REG_32BIT, 0, 0, "RING_EMR"}, \ 63*9c8c7a7eSZhanjun Dong { RING_EIR(0), REG_32BIT, 0, 0, "RING_EIR"}, \ 64*9c8c7a7eSZhanjun Dong { RING_IMR(0), REG_32BIT, 0, 0, "RING_IMR"}, \ 65*9c8c7a7eSZhanjun Dong { RING_IPEHR(0), REG_32BIT, 0, 0, "IPEHR"}, \ 66*9c8c7a7eSZhanjun Dong { RING_INSTDONE(0), REG_32BIT, 0, 0, "RING_INSTDONE"}, \ 67*9c8c7a7eSZhanjun Dong { INDIRECT_RING_STATE(0), REG_32BIT, 0, 0, "INDIRECT_RING_STATE"}, \ 68*9c8c7a7eSZhanjun Dong { RING_ACTHD(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 69*9c8c7a7eSZhanjun Dong { RING_ACTHD_UDW(0), REG_64BIT_HI_DW, 0, 0, "ACTHD"}, \ 70*9c8c7a7eSZhanjun Dong { RING_BBADDR(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 71*9c8c7a7eSZhanjun Dong { RING_BBADDR_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_BBADDR"}, \ 72*9c8c7a7eSZhanjun Dong { RING_START(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 73*9c8c7a7eSZhanjun Dong { RING_START_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_START"}, \ 74*9c8c7a7eSZhanjun Dong { RING_DMA_FADD(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 75*9c8c7a7eSZhanjun Dong { RING_DMA_FADD_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_DMA_FADD"}, \ 76*9c8c7a7eSZhanjun Dong { RING_EXECLIST_STATUS_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 77*9c8c7a7eSZhanjun Dong { RING_EXECLIST_STATUS_HI(0), REG_64BIT_HI_DW, 0, 0, "RING_EXECLIST_STATUS"}, \ 78*9c8c7a7eSZhanjun Dong { RING_EXECLIST_SQ_CONTENTS_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 79*9c8c7a7eSZhanjun Dong { RING_EXECLIST_SQ_CONTENTS_HI(0), REG_64BIT_HI_DW, 0, 0, "RING_EXECLIST_SQ_CONTENTS"} 80*9c8c7a7eSZhanjun Dong 81*9c8c7a7eSZhanjun Dong #define COMMON_XELP_RC_CLASS \ 82*9c8c7a7eSZhanjun Dong { RCU_MODE, REG_32BIT, 0, 0, "RCU_MODE"} 83*9c8c7a7eSZhanjun Dong 84*9c8c7a7eSZhanjun Dong #define COMMON_XELP_RC_CLASS_INSTDONE \ 85*9c8c7a7eSZhanjun Dong { SC_INSTDONE, REG_32BIT, 0, 0, "SC_INSTDONE"}, \ 86*9c8c7a7eSZhanjun Dong { SC_INSTDONE_EXTRA, REG_32BIT, 0, 0, "SC_INSTDONE_EXTRA"}, \ 87*9c8c7a7eSZhanjun Dong { SC_INSTDONE_EXTRA2, REG_32BIT, 0, 0, "SC_INSTDONE_EXTRA2"} 88*9c8c7a7eSZhanjun Dong 89*9c8c7a7eSZhanjun Dong #define XELP_VEC_CLASS_REGS \ 90*9c8c7a7eSZhanjun Dong { SFC_DONE(0), 0, 0, 0, "SFC_DONE[0]"}, \ 91*9c8c7a7eSZhanjun Dong { SFC_DONE(1), 0, 0, 0, "SFC_DONE[1]"}, \ 92*9c8c7a7eSZhanjun Dong { SFC_DONE(2), 0, 0, 0, "SFC_DONE[2]"}, \ 93*9c8c7a7eSZhanjun Dong { SFC_DONE(3), 0, 0, 0, "SFC_DONE[3]"} 94*9c8c7a7eSZhanjun Dong 95*9c8c7a7eSZhanjun Dong /* XE_LP Global */ 96*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { 97*9c8c7a7eSZhanjun Dong COMMON_XELP_BASE_GLOBAL, 98*9c8c7a7eSZhanjun Dong }; 99*9c8c7a7eSZhanjun Dong 100*9c8c7a7eSZhanjun Dong /* Render / Compute Per-Engine-Instance */ 101*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_rc_inst_regs[] = { 102*9c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 103*9c8c7a7eSZhanjun Dong }; 104*9c8c7a7eSZhanjun Dong 105*9c8c7a7eSZhanjun Dong /* Render / Compute Engine-Class */ 106*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_rc_class_regs[] = { 107*9c8c7a7eSZhanjun Dong COMMON_XELP_RC_CLASS, 108*9c8c7a7eSZhanjun Dong COMMON_XELP_RC_CLASS_INSTDONE, 109*9c8c7a7eSZhanjun Dong }; 110*9c8c7a7eSZhanjun Dong 111*9c8c7a7eSZhanjun Dong /* Render / Compute Engine-Class for xehpg */ 112*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_hpg_rc_class_regs[] = { 113*9c8c7a7eSZhanjun Dong COMMON_XELP_RC_CLASS, 114*9c8c7a7eSZhanjun Dong }; 115*9c8c7a7eSZhanjun Dong 116*9c8c7a7eSZhanjun Dong /* Media Decode/Encode Per-Engine-Instance */ 117*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_vd_inst_regs[] = { 118*9c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 119*9c8c7a7eSZhanjun Dong }; 120*9c8c7a7eSZhanjun Dong 121*9c8c7a7eSZhanjun Dong /* Video Enhancement Engine-Class */ 122*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_vec_class_regs[] = { 123*9c8c7a7eSZhanjun Dong XELP_VEC_CLASS_REGS, 124*9c8c7a7eSZhanjun Dong }; 125*9c8c7a7eSZhanjun Dong 126*9c8c7a7eSZhanjun Dong /* Video Enhancement Per-Engine-Instance */ 127*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_vec_inst_regs[] = { 128*9c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 129*9c8c7a7eSZhanjun Dong }; 130*9c8c7a7eSZhanjun Dong 131*9c8c7a7eSZhanjun Dong /* Blitter Per-Engine-Instance */ 132*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_blt_inst_regs[] = { 133*9c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 134*9c8c7a7eSZhanjun Dong }; 135*9c8c7a7eSZhanjun Dong 136*9c8c7a7eSZhanjun Dong /* XE_LP - GSC Per-Engine-Instance */ 137*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { 138*9c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 139*9c8c7a7eSZhanjun Dong }; 140*9c8c7a7eSZhanjun Dong 141*9c8c7a7eSZhanjun Dong /* 142*9c8c7a7eSZhanjun Dong * Empty list to prevent warnings about unknown class/instance types 143*9c8c7a7eSZhanjun Dong * as not all class/instance types have entries on all platforms. 144*9c8c7a7eSZhanjun Dong */ 145*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr empty_regs_list[] = { 146*9c8c7a7eSZhanjun Dong }; 147*9c8c7a7eSZhanjun Dong 148*9c8c7a7eSZhanjun Dong #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) 149*9c8c7a7eSZhanjun Dong #define TO_GCAP_DEF_TYPE(x) (GUC_STATE_CAPTURE_TYPE_##x) 150*9c8c7a7eSZhanjun Dong #define MAKE_REGLIST(regslist, regsowner, regstype, class) \ 151*9c8c7a7eSZhanjun Dong { \ 152*9c8c7a7eSZhanjun Dong regslist, \ 153*9c8c7a7eSZhanjun Dong ARRAY_SIZE(regslist), \ 154*9c8c7a7eSZhanjun Dong TO_GCAP_DEF_OWNER(regsowner), \ 155*9c8c7a7eSZhanjun Dong TO_GCAP_DEF_TYPE(regstype), \ 156*9c8c7a7eSZhanjun Dong class \ 157*9c8c7a7eSZhanjun Dong } 158*9c8c7a7eSZhanjun Dong 159*9c8c7a7eSZhanjun Dong /* List of lists for legacy graphic product version < 1255 */ 160*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group xe_lp_lists[] = { 161*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 162*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 163*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 164*9c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 165*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 166*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 167*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 168*9c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 169*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 170*9c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 171*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 172*9c8c7a7eSZhanjun Dong {} 173*9c8c7a7eSZhanjun Dong }; 174*9c8c7a7eSZhanjun Dong 175*9c8c7a7eSZhanjun Dong /* List of lists for graphic product version >= 1255 */ 176*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group xe_hpg_lists[] = { 177*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 178*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_hpg_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 179*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 180*9c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 181*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 182*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 183*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 184*9c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 185*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 186*9c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 187*9c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 188*9c8c7a7eSZhanjun Dong {} 189*9c8c7a7eSZhanjun Dong }; 190*9c8c7a7eSZhanjun Dong 191*9c8c7a7eSZhanjun Dong static const char * const capture_list_type_names[] = { 192*9c8c7a7eSZhanjun Dong "Global", 193*9c8c7a7eSZhanjun Dong "Class", 194*9c8c7a7eSZhanjun Dong "Instance", 195*9c8c7a7eSZhanjun Dong }; 196*9c8c7a7eSZhanjun Dong 197*9c8c7a7eSZhanjun Dong static const char * const capture_engine_class_names[] = { 198*9c8c7a7eSZhanjun Dong "Render/Compute", 199*9c8c7a7eSZhanjun Dong "Video", 200*9c8c7a7eSZhanjun Dong "VideoEnhance", 201*9c8c7a7eSZhanjun Dong "Blitter", 202*9c8c7a7eSZhanjun Dong "GSC-Other", 203*9c8c7a7eSZhanjun Dong }; 204*9c8c7a7eSZhanjun Dong 205*9c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache { 206*9c8c7a7eSZhanjun Dong bool is_valid; 207*9c8c7a7eSZhanjun Dong void *ptr; 208*9c8c7a7eSZhanjun Dong size_t size; 209*9c8c7a7eSZhanjun Dong int status; 210*9c8c7a7eSZhanjun Dong }; 211*9c8c7a7eSZhanjun Dong 212*9c8c7a7eSZhanjun Dong struct xe_guc_state_capture { 213*9c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *reglists; 214*9c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX] 215*9c8c7a7eSZhanjun Dong [GUC_STATE_CAPTURE_TYPE_MAX] 216*9c8c7a7eSZhanjun Dong [GUC_CAPTURE_LIST_CLASS_MAX]; 217*9c8c7a7eSZhanjun Dong void *ads_null_cache; 218*9c8c7a7eSZhanjun Dong }; 219*9c8c7a7eSZhanjun Dong 220*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group * 221*9c8c7a7eSZhanjun Dong guc_capture_get_device_reglist(struct xe_device *xe) 222*9c8c7a7eSZhanjun Dong { 223*9c8c7a7eSZhanjun Dong if (GRAPHICS_VERx100(xe) >= 1255) 224*9c8c7a7eSZhanjun Dong return xe_hpg_lists; 225*9c8c7a7eSZhanjun Dong else 226*9c8c7a7eSZhanjun Dong return xe_lp_lists; 227*9c8c7a7eSZhanjun Dong } 228*9c8c7a7eSZhanjun Dong 229*9c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group * 230*9c8c7a7eSZhanjun Dong guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, 231*9c8c7a7eSZhanjun Dong u32 owner, u32 type, enum guc_capture_list_class_type capture_class) 232*9c8c7a7eSZhanjun Dong { 233*9c8c7a7eSZhanjun Dong int i; 234*9c8c7a7eSZhanjun Dong 235*9c8c7a7eSZhanjun Dong if (!reglists) 236*9c8c7a7eSZhanjun Dong return NULL; 237*9c8c7a7eSZhanjun Dong 238*9c8c7a7eSZhanjun Dong for (i = 0; reglists[i].list; ++i) { 239*9c8c7a7eSZhanjun Dong if (reglists[i].owner == owner && reglists[i].type == type && 240*9c8c7a7eSZhanjun Dong (reglists[i].engine == capture_class || 241*9c8c7a7eSZhanjun Dong reglists[i].type == GUC_STATE_CAPTURE_TYPE_GLOBAL)) 242*9c8c7a7eSZhanjun Dong return ®lists[i]; 243*9c8c7a7eSZhanjun Dong } 244*9c8c7a7eSZhanjun Dong 245*9c8c7a7eSZhanjun Dong return NULL; 246*9c8c7a7eSZhanjun Dong } 247*9c8c7a7eSZhanjun Dong 248*9c8c7a7eSZhanjun Dong static int 249*9c8c7a7eSZhanjun Dong guc_capture_list_init(struct xe_guc *guc, u32 owner, u32 type, 250*9c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, struct guc_mmio_reg *ptr, 251*9c8c7a7eSZhanjun Dong u16 num_entries) 252*9c8c7a7eSZhanjun Dong { 253*9c8c7a7eSZhanjun Dong u32 i = 0; 254*9c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; 255*9c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *match; 256*9c8c7a7eSZhanjun Dong 257*9c8c7a7eSZhanjun Dong if (!reglists) 258*9c8c7a7eSZhanjun Dong return -ENODEV; 259*9c8c7a7eSZhanjun Dong 260*9c8c7a7eSZhanjun Dong match = guc_capture_get_one_list(reglists, owner, type, capture_class); 261*9c8c7a7eSZhanjun Dong if (!match) 262*9c8c7a7eSZhanjun Dong return -ENODATA; 263*9c8c7a7eSZhanjun Dong 264*9c8c7a7eSZhanjun Dong for (i = 0; i < num_entries && i < match->num_regs; ++i) { 265*9c8c7a7eSZhanjun Dong ptr[i].offset = match->list[i].reg.addr; 266*9c8c7a7eSZhanjun Dong ptr[i].value = 0xDEADF00D; 267*9c8c7a7eSZhanjun Dong ptr[i].flags = match->list[i].flags; 268*9c8c7a7eSZhanjun Dong ptr[i].mask = match->list[i].mask; 269*9c8c7a7eSZhanjun Dong } 270*9c8c7a7eSZhanjun Dong 271*9c8c7a7eSZhanjun Dong if (i < num_entries) 272*9c8c7a7eSZhanjun Dong xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out %d.\n", i, 273*9c8c7a7eSZhanjun Dong num_entries); 274*9c8c7a7eSZhanjun Dong 275*9c8c7a7eSZhanjun Dong return 0; 276*9c8c7a7eSZhanjun Dong } 277*9c8c7a7eSZhanjun Dong 278*9c8c7a7eSZhanjun Dong static int 279*9c8c7a7eSZhanjun Dong guc_cap_list_num_regs(struct xe_guc *guc, u32 owner, u32 type, 280*9c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class) 281*9c8c7a7eSZhanjun Dong { 282*9c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *match; 283*9c8c7a7eSZhanjun Dong 284*9c8c7a7eSZhanjun Dong match = guc_capture_get_one_list(guc->capture->reglists, owner, type, capture_class); 285*9c8c7a7eSZhanjun Dong if (!match) 286*9c8c7a7eSZhanjun Dong return 0; 287*9c8c7a7eSZhanjun Dong 288*9c8c7a7eSZhanjun Dong return match->num_regs; 289*9c8c7a7eSZhanjun Dong } 290*9c8c7a7eSZhanjun Dong 291*9c8c7a7eSZhanjun Dong static int 292*9c8c7a7eSZhanjun Dong guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type, 293*9c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, 294*9c8c7a7eSZhanjun Dong size_t *size, bool is_purpose_est) 295*9c8c7a7eSZhanjun Dong { 296*9c8c7a7eSZhanjun Dong struct xe_guc_state_capture *gc = guc->capture; 297*9c8c7a7eSZhanjun Dong struct xe_gt *gt = guc_to_gt(guc); 298*9c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache *cache; 299*9c8c7a7eSZhanjun Dong int num_regs; 300*9c8c7a7eSZhanjun Dong 301*9c8c7a7eSZhanjun Dong xe_gt_assert(gt, type < GUC_STATE_CAPTURE_TYPE_MAX); 302*9c8c7a7eSZhanjun Dong xe_gt_assert(gt, capture_class < GUC_CAPTURE_LIST_CLASS_MAX); 303*9c8c7a7eSZhanjun Dong 304*9c8c7a7eSZhanjun Dong cache = &gc->ads_cache[owner][type][capture_class]; 305*9c8c7a7eSZhanjun Dong if (!gc->reglists) { 306*9c8c7a7eSZhanjun Dong xe_gt_warn(gt, "No capture reglist for this device\n"); 307*9c8c7a7eSZhanjun Dong return -ENODEV; 308*9c8c7a7eSZhanjun Dong } 309*9c8c7a7eSZhanjun Dong 310*9c8c7a7eSZhanjun Dong if (cache->is_valid) { 311*9c8c7a7eSZhanjun Dong *size = cache->size; 312*9c8c7a7eSZhanjun Dong return cache->status; 313*9c8c7a7eSZhanjun Dong } 314*9c8c7a7eSZhanjun Dong 315*9c8c7a7eSZhanjun Dong if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF && 316*9c8c7a7eSZhanjun Dong !guc_capture_get_one_list(gc->reglists, owner, type, capture_class)) { 317*9c8c7a7eSZhanjun Dong if (type == GUC_STATE_CAPTURE_TYPE_GLOBAL) 318*9c8c7a7eSZhanjun Dong xe_gt_warn(gt, "Missing capture reglist: global!\n"); 319*9c8c7a7eSZhanjun Dong else 320*9c8c7a7eSZhanjun Dong xe_gt_warn(gt, "Missing capture reglist: %s(%u):%s(%u)!\n", 321*9c8c7a7eSZhanjun Dong capture_list_type_names[type], type, 322*9c8c7a7eSZhanjun Dong capture_engine_class_names[capture_class], capture_class); 323*9c8c7a7eSZhanjun Dong return -ENODEV; 324*9c8c7a7eSZhanjun Dong } 325*9c8c7a7eSZhanjun Dong 326*9c8c7a7eSZhanjun Dong num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class); 327*9c8c7a7eSZhanjun Dong /* intentional empty lists can exist depending on hw config */ 328*9c8c7a7eSZhanjun Dong if (!num_regs) 329*9c8c7a7eSZhanjun Dong return -ENODATA; 330*9c8c7a7eSZhanjun Dong 331*9c8c7a7eSZhanjun Dong if (size) 332*9c8c7a7eSZhanjun Dong *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + 333*9c8c7a7eSZhanjun Dong (num_regs * sizeof(struct guc_mmio_reg))); 334*9c8c7a7eSZhanjun Dong 335*9c8c7a7eSZhanjun Dong return 0; 336*9c8c7a7eSZhanjun Dong } 337*9c8c7a7eSZhanjun Dong 338*9c8c7a7eSZhanjun Dong /** 339*9c8c7a7eSZhanjun Dong * xe_guc_capture_getlistsize - Get list size for owner/type/class combination 340*9c8c7a7eSZhanjun Dong * @guc: The GuC object 341*9c8c7a7eSZhanjun Dong * @owner: PF/VF owner 342*9c8c7a7eSZhanjun Dong * @type: GuC capture register type 343*9c8c7a7eSZhanjun Dong * @capture_class: GuC capture engine class id 344*9c8c7a7eSZhanjun Dong * @size: Point to the size 345*9c8c7a7eSZhanjun Dong * 346*9c8c7a7eSZhanjun Dong * This function will get the list for the owner/type/class combination, and 347*9c8c7a7eSZhanjun Dong * return the page aligned list size. 348*9c8c7a7eSZhanjun Dong * 349*9c8c7a7eSZhanjun Dong * Returns: 0 on success or a negative error code on failure. 350*9c8c7a7eSZhanjun Dong */ 351*9c8c7a7eSZhanjun Dong int 352*9c8c7a7eSZhanjun Dong xe_guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type, 353*9c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, size_t *size) 354*9c8c7a7eSZhanjun Dong { 355*9c8c7a7eSZhanjun Dong return guc_capture_getlistsize(guc, owner, type, capture_class, size, false); 356*9c8c7a7eSZhanjun Dong } 357*9c8c7a7eSZhanjun Dong 358*9c8c7a7eSZhanjun Dong /** 359*9c8c7a7eSZhanjun Dong * xe_guc_capture_getlist - Get register capture list for owner/type/class 360*9c8c7a7eSZhanjun Dong * combination 361*9c8c7a7eSZhanjun Dong * @guc: The GuC object 362*9c8c7a7eSZhanjun Dong * @owner: PF/VF owner 363*9c8c7a7eSZhanjun Dong * @type: GuC capture register type 364*9c8c7a7eSZhanjun Dong * @capture_class: GuC capture engine class id 365*9c8c7a7eSZhanjun Dong * @outptr: Point to cached register capture list 366*9c8c7a7eSZhanjun Dong * 367*9c8c7a7eSZhanjun Dong * This function will get the register capture list for the owner/type/class 368*9c8c7a7eSZhanjun Dong * combination. 369*9c8c7a7eSZhanjun Dong * 370*9c8c7a7eSZhanjun Dong * Returns: 0 on success or a negative error code on failure. 371*9c8c7a7eSZhanjun Dong */ 372*9c8c7a7eSZhanjun Dong int 373*9c8c7a7eSZhanjun Dong xe_guc_capture_getlist(struct xe_guc *guc, u32 owner, u32 type, 374*9c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, void **outptr) 375*9c8c7a7eSZhanjun Dong { 376*9c8c7a7eSZhanjun Dong struct xe_guc_state_capture *gc = guc->capture; 377*9c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][capture_class]; 378*9c8c7a7eSZhanjun Dong struct guc_debug_capture_list *listnode; 379*9c8c7a7eSZhanjun Dong int ret, num_regs; 380*9c8c7a7eSZhanjun Dong u8 *caplist, *tmp; 381*9c8c7a7eSZhanjun Dong size_t size = 0; 382*9c8c7a7eSZhanjun Dong 383*9c8c7a7eSZhanjun Dong if (!gc->reglists) 384*9c8c7a7eSZhanjun Dong return -ENODEV; 385*9c8c7a7eSZhanjun Dong 386*9c8c7a7eSZhanjun Dong if (cache->is_valid) { 387*9c8c7a7eSZhanjun Dong *outptr = cache->ptr; 388*9c8c7a7eSZhanjun Dong return cache->status; 389*9c8c7a7eSZhanjun Dong } 390*9c8c7a7eSZhanjun Dong 391*9c8c7a7eSZhanjun Dong ret = xe_guc_capture_getlistsize(guc, owner, type, capture_class, &size); 392*9c8c7a7eSZhanjun Dong if (ret) { 393*9c8c7a7eSZhanjun Dong cache->is_valid = true; 394*9c8c7a7eSZhanjun Dong cache->ptr = NULL; 395*9c8c7a7eSZhanjun Dong cache->size = 0; 396*9c8c7a7eSZhanjun Dong cache->status = ret; 397*9c8c7a7eSZhanjun Dong return ret; 398*9c8c7a7eSZhanjun Dong } 399*9c8c7a7eSZhanjun Dong 400*9c8c7a7eSZhanjun Dong caplist = drmm_kzalloc(guc_to_drm(guc), size, GFP_KERNEL); 401*9c8c7a7eSZhanjun Dong if (!caplist) 402*9c8c7a7eSZhanjun Dong return -ENOMEM; 403*9c8c7a7eSZhanjun Dong 404*9c8c7a7eSZhanjun Dong /* populate capture list header */ 405*9c8c7a7eSZhanjun Dong tmp = caplist; 406*9c8c7a7eSZhanjun Dong num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class); 407*9c8c7a7eSZhanjun Dong listnode = (struct guc_debug_capture_list *)tmp; 408*9c8c7a7eSZhanjun Dong listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); 409*9c8c7a7eSZhanjun Dong 410*9c8c7a7eSZhanjun Dong /* populate list of register descriptor */ 411*9c8c7a7eSZhanjun Dong tmp += sizeof(struct guc_debug_capture_list); 412*9c8c7a7eSZhanjun Dong guc_capture_list_init(guc, owner, type, capture_class, 413*9c8c7a7eSZhanjun Dong (struct guc_mmio_reg *)tmp, num_regs); 414*9c8c7a7eSZhanjun Dong 415*9c8c7a7eSZhanjun Dong /* cache this list */ 416*9c8c7a7eSZhanjun Dong cache->is_valid = true; 417*9c8c7a7eSZhanjun Dong cache->ptr = caplist; 418*9c8c7a7eSZhanjun Dong cache->size = size; 419*9c8c7a7eSZhanjun Dong cache->status = 0; 420*9c8c7a7eSZhanjun Dong 421*9c8c7a7eSZhanjun Dong *outptr = caplist; 422*9c8c7a7eSZhanjun Dong 423*9c8c7a7eSZhanjun Dong return 0; 424*9c8c7a7eSZhanjun Dong } 425*9c8c7a7eSZhanjun Dong 426*9c8c7a7eSZhanjun Dong /** 427*9c8c7a7eSZhanjun Dong * xe_guc_capture_getnullheader - Get a null list for register capture 428*9c8c7a7eSZhanjun Dong * @guc: The GuC object 429*9c8c7a7eSZhanjun Dong * @outptr: Point to cached register capture list 430*9c8c7a7eSZhanjun Dong * @size: Point to the size 431*9c8c7a7eSZhanjun Dong * 432*9c8c7a7eSZhanjun Dong * This function will alloc for a null list for register capture. 433*9c8c7a7eSZhanjun Dong * 434*9c8c7a7eSZhanjun Dong * Returns: 0 on success or a negative error code on failure. 435*9c8c7a7eSZhanjun Dong */ 436*9c8c7a7eSZhanjun Dong int 437*9c8c7a7eSZhanjun Dong xe_guc_capture_getnullheader(struct xe_guc *guc, void **outptr, size_t *size) 438*9c8c7a7eSZhanjun Dong { 439*9c8c7a7eSZhanjun Dong struct xe_guc_state_capture *gc = guc->capture; 440*9c8c7a7eSZhanjun Dong int tmp = sizeof(u32) * 4; 441*9c8c7a7eSZhanjun Dong void *null_header; 442*9c8c7a7eSZhanjun Dong 443*9c8c7a7eSZhanjun Dong if (gc->ads_null_cache) { 444*9c8c7a7eSZhanjun Dong *outptr = gc->ads_null_cache; 445*9c8c7a7eSZhanjun Dong *size = tmp; 446*9c8c7a7eSZhanjun Dong return 0; 447*9c8c7a7eSZhanjun Dong } 448*9c8c7a7eSZhanjun Dong 449*9c8c7a7eSZhanjun Dong null_header = drmm_kzalloc(guc_to_drm(guc), tmp, GFP_KERNEL); 450*9c8c7a7eSZhanjun Dong if (!null_header) 451*9c8c7a7eSZhanjun Dong return -ENOMEM; 452*9c8c7a7eSZhanjun Dong 453*9c8c7a7eSZhanjun Dong gc->ads_null_cache = null_header; 454*9c8c7a7eSZhanjun Dong *outptr = null_header; 455*9c8c7a7eSZhanjun Dong *size = tmp; 456*9c8c7a7eSZhanjun Dong 457*9c8c7a7eSZhanjun Dong return 0; 458*9c8c7a7eSZhanjun Dong } 459*9c8c7a7eSZhanjun Dong 460*9c8c7a7eSZhanjun Dong /** 461*9c8c7a7eSZhanjun Dong * xe_guc_capture_ads_input_worst_size - Calculate the worst size for GuC register capture 462*9c8c7a7eSZhanjun Dong * @guc: point to xe_guc structure 463*9c8c7a7eSZhanjun Dong * 464*9c8c7a7eSZhanjun Dong * Calculate the worst size for GuC register capture by including all possible engines classes. 465*9c8c7a7eSZhanjun Dong * 466*9c8c7a7eSZhanjun Dong * Returns: Calculated size 467*9c8c7a7eSZhanjun Dong */ 468*9c8c7a7eSZhanjun Dong size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc) 469*9c8c7a7eSZhanjun Dong { 470*9c8c7a7eSZhanjun Dong size_t total_size, class_size, instance_size, global_size; 471*9c8c7a7eSZhanjun Dong int i, j; 472*9c8c7a7eSZhanjun Dong 473*9c8c7a7eSZhanjun Dong /* 474*9c8c7a7eSZhanjun Dong * This function calculates the worst case register lists size by 475*9c8c7a7eSZhanjun Dong * including all possible engines classes. It is called during the 476*9c8c7a7eSZhanjun Dong * first of a two-phase GuC (and ADS-population) initialization 477*9c8c7a7eSZhanjun Dong * sequence, that is, during the pre-hwconfig phase before we have 478*9c8c7a7eSZhanjun Dong * the exact engine fusing info. 479*9c8c7a7eSZhanjun Dong */ 480*9c8c7a7eSZhanjun Dong total_size = PAGE_SIZE; /* Pad a page in front for empty lists */ 481*9c8c7a7eSZhanjun Dong for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { 482*9c8c7a7eSZhanjun Dong for (j = 0; j < GUC_CAPTURE_LIST_CLASS_MAX; j++) { 483*9c8c7a7eSZhanjun Dong if (xe_guc_capture_getlistsize(guc, i, 484*9c8c7a7eSZhanjun Dong GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 485*9c8c7a7eSZhanjun Dong j, &class_size) < 0) 486*9c8c7a7eSZhanjun Dong class_size = 0; 487*9c8c7a7eSZhanjun Dong if (xe_guc_capture_getlistsize(guc, i, 488*9c8c7a7eSZhanjun Dong GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE, 489*9c8c7a7eSZhanjun Dong j, &instance_size) < 0) 490*9c8c7a7eSZhanjun Dong instance_size = 0; 491*9c8c7a7eSZhanjun Dong total_size += class_size + instance_size; 492*9c8c7a7eSZhanjun Dong } 493*9c8c7a7eSZhanjun Dong if (xe_guc_capture_getlistsize(guc, i, 494*9c8c7a7eSZhanjun Dong GUC_STATE_CAPTURE_TYPE_GLOBAL, 495*9c8c7a7eSZhanjun Dong 0, &global_size) < 0) 496*9c8c7a7eSZhanjun Dong global_size = 0; 497*9c8c7a7eSZhanjun Dong total_size += global_size; 498*9c8c7a7eSZhanjun Dong } 499*9c8c7a7eSZhanjun Dong 500*9c8c7a7eSZhanjun Dong return PAGE_ALIGN(total_size); 501*9c8c7a7eSZhanjun Dong } 502*9c8c7a7eSZhanjun Dong 503*9c8c7a7eSZhanjun Dong /** 504*9c8c7a7eSZhanjun Dong * xe_guc_capture_init - Init for GuC register capture 505*9c8c7a7eSZhanjun Dong * @guc: The GuC object 506*9c8c7a7eSZhanjun Dong * 507*9c8c7a7eSZhanjun Dong * Init for GuC register capture, alloc memory for capture data structure. 508*9c8c7a7eSZhanjun Dong * 509*9c8c7a7eSZhanjun Dong * Returns: 0 if success. 510*9c8c7a7eSZhanjun Dong -ENOMEM if out of memory 511*9c8c7a7eSZhanjun Dong */ 512*9c8c7a7eSZhanjun Dong int xe_guc_capture_init(struct xe_guc *guc) 513*9c8c7a7eSZhanjun Dong { 514*9c8c7a7eSZhanjun Dong guc->capture = drmm_kzalloc(guc_to_drm(guc), sizeof(*guc->capture), GFP_KERNEL); 515*9c8c7a7eSZhanjun Dong if (!guc->capture) 516*9c8c7a7eSZhanjun Dong return -ENOMEM; 517*9c8c7a7eSZhanjun Dong 518*9c8c7a7eSZhanjun Dong guc->capture->reglists = guc_capture_get_device_reglist(guc_to_xe(guc)); 519*9c8c7a7eSZhanjun Dong return 0; 520*9c8c7a7eSZhanjun Dong } 521