19c8c7a7eSZhanjun Dong // SPDX-License-Identifier: MIT 29c8c7a7eSZhanjun Dong /* 39c8c7a7eSZhanjun Dong * Copyright © 2021-2024 Intel Corporation 49c8c7a7eSZhanjun Dong */ 59c8c7a7eSZhanjun Dong 69c8c7a7eSZhanjun Dong #include <linux/types.h> 79c8c7a7eSZhanjun Dong 89c8c7a7eSZhanjun Dong #include <drm/drm_managed.h> 99c8c7a7eSZhanjun Dong #include <drm/drm_print.h> 109c8c7a7eSZhanjun Dong 119c8c7a7eSZhanjun Dong #include "abi/guc_actions_abi.h" 129c8c7a7eSZhanjun Dong #include "abi/guc_capture_abi.h" 139c8c7a7eSZhanjun Dong #include "regs/xe_engine_regs.h" 149c8c7a7eSZhanjun Dong #include "regs/xe_gt_regs.h" 159c8c7a7eSZhanjun Dong #include "regs/xe_guc_regs.h" 169c8c7a7eSZhanjun Dong #include "regs/xe_regs.h" 179c8c7a7eSZhanjun Dong 189c8c7a7eSZhanjun Dong #include "xe_bo.h" 199c8c7a7eSZhanjun Dong #include "xe_device.h" 209c8c7a7eSZhanjun Dong #include "xe_exec_queue_types.h" 219c8c7a7eSZhanjun Dong #include "xe_gt.h" 229c8c7a7eSZhanjun Dong #include "xe_gt_mcr.h" 239c8c7a7eSZhanjun Dong #include "xe_gt_printk.h" 249c8c7a7eSZhanjun Dong #include "xe_guc.h" 259c8c7a7eSZhanjun Dong #include "xe_guc_capture.h" 269c8c7a7eSZhanjun Dong #include "xe_guc_capture_types.h" 279c8c7a7eSZhanjun Dong #include "xe_guc_ct.h" 289c8c7a7eSZhanjun Dong #include "xe_guc_log.h" 299c8c7a7eSZhanjun Dong #include "xe_guc_submit.h" 309c8c7a7eSZhanjun Dong #include "xe_hw_engine_types.h" 319c8c7a7eSZhanjun Dong #include "xe_macros.h" 329c8c7a7eSZhanjun Dong #include "xe_map.h" 339c8c7a7eSZhanjun Dong 349c8c7a7eSZhanjun Dong /* 359c8c7a7eSZhanjun Dong * Define all device tables of GuC error capture register lists 369c8c7a7eSZhanjun Dong * NOTE: 379c8c7a7eSZhanjun Dong * For engine-registers, GuC only needs the register offsets 389c8c7a7eSZhanjun Dong * from the engine-mmio-base 399c8c7a7eSZhanjun Dong * 409c8c7a7eSZhanjun Dong * 64 bit registers need 2 entries for low 32 bit register and high 32 bit 419c8c7a7eSZhanjun Dong * register, for example: 429c8c7a7eSZhanjun Dong * Register data_type flags mask Register name 439c8c7a7eSZhanjun Dong * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, 449c8c7a7eSZhanjun Dong * { XXX_REG_HI(0), REG_64BIT_HI_DW,, 0, 0, "XXX_REG"}, 459c8c7a7eSZhanjun Dong * 1. data_type: Indicate is hi/low 32 bit for a 64 bit register 469c8c7a7eSZhanjun Dong * A 64 bit register define requires 2 consecutive entries, 479c8c7a7eSZhanjun Dong * with low dword first and hi dword the second. 489c8c7a7eSZhanjun Dong * 2. Register name: null for incompleted define 499c8c7a7eSZhanjun Dong */ 509c8c7a7eSZhanjun Dong #define COMMON_XELP_BASE_GLOBAL \ 519c8c7a7eSZhanjun Dong { FORCEWAKE_GT, REG_32BIT, 0, 0, "FORCEWAKE_GT"} 529c8c7a7eSZhanjun Dong 539c8c7a7eSZhanjun Dong #define COMMON_BASE_ENGINE_INSTANCE \ 549c8c7a7eSZhanjun Dong { RING_HWSTAM(0), REG_32BIT, 0, 0, "HWSTAM"}, \ 559c8c7a7eSZhanjun Dong { RING_HWS_PGA(0), REG_32BIT, 0, 0, "RING_HWS_PGA"}, \ 569c8c7a7eSZhanjun Dong { RING_HEAD(0), REG_32BIT, 0, 0, "RING_HEAD"}, \ 579c8c7a7eSZhanjun Dong { RING_TAIL(0), REG_32BIT, 0, 0, "RING_TAIL"}, \ 589c8c7a7eSZhanjun Dong { RING_CTL(0), REG_32BIT, 0, 0, "RING_CTL"}, \ 599c8c7a7eSZhanjun Dong { RING_MI_MODE(0), REG_32BIT, 0, 0, "RING_MI_MODE"}, \ 609c8c7a7eSZhanjun Dong { RING_MODE(0), REG_32BIT, 0, 0, "RING_MODE"}, \ 619c8c7a7eSZhanjun Dong { RING_ESR(0), REG_32BIT, 0, 0, "RING_ESR"}, \ 629c8c7a7eSZhanjun Dong { RING_EMR(0), REG_32BIT, 0, 0, "RING_EMR"}, \ 639c8c7a7eSZhanjun Dong { RING_EIR(0), REG_32BIT, 0, 0, "RING_EIR"}, \ 649c8c7a7eSZhanjun Dong { RING_IMR(0), REG_32BIT, 0, 0, "RING_IMR"}, \ 659c8c7a7eSZhanjun Dong { RING_IPEHR(0), REG_32BIT, 0, 0, "IPEHR"}, \ 669c8c7a7eSZhanjun Dong { RING_INSTDONE(0), REG_32BIT, 0, 0, "RING_INSTDONE"}, \ 679c8c7a7eSZhanjun Dong { INDIRECT_RING_STATE(0), REG_32BIT, 0, 0, "INDIRECT_RING_STATE"}, \ 689c8c7a7eSZhanjun Dong { RING_ACTHD(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 699c8c7a7eSZhanjun Dong { RING_ACTHD_UDW(0), REG_64BIT_HI_DW, 0, 0, "ACTHD"}, \ 709c8c7a7eSZhanjun Dong { RING_BBADDR(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 719c8c7a7eSZhanjun Dong { RING_BBADDR_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_BBADDR"}, \ 729c8c7a7eSZhanjun Dong { RING_START(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 739c8c7a7eSZhanjun Dong { RING_START_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_START"}, \ 749c8c7a7eSZhanjun Dong { RING_DMA_FADD(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 759c8c7a7eSZhanjun Dong { RING_DMA_FADD_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_DMA_FADD"}, \ 769c8c7a7eSZhanjun Dong { RING_EXECLIST_STATUS_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 779c8c7a7eSZhanjun Dong { RING_EXECLIST_STATUS_HI(0), REG_64BIT_HI_DW, 0, 0, "RING_EXECLIST_STATUS"}, \ 789c8c7a7eSZhanjun Dong { RING_EXECLIST_SQ_CONTENTS_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 799c8c7a7eSZhanjun Dong { RING_EXECLIST_SQ_CONTENTS_HI(0), REG_64BIT_HI_DW, 0, 0, "RING_EXECLIST_SQ_CONTENTS"} 809c8c7a7eSZhanjun Dong 819c8c7a7eSZhanjun Dong #define COMMON_XELP_RC_CLASS \ 829c8c7a7eSZhanjun Dong { RCU_MODE, REG_32BIT, 0, 0, "RCU_MODE"} 839c8c7a7eSZhanjun Dong 849c8c7a7eSZhanjun Dong #define COMMON_XELP_RC_CLASS_INSTDONE \ 859c8c7a7eSZhanjun Dong { SC_INSTDONE, REG_32BIT, 0, 0, "SC_INSTDONE"}, \ 869c8c7a7eSZhanjun Dong { SC_INSTDONE_EXTRA, REG_32BIT, 0, 0, "SC_INSTDONE_EXTRA"}, \ 879c8c7a7eSZhanjun Dong { SC_INSTDONE_EXTRA2, REG_32BIT, 0, 0, "SC_INSTDONE_EXTRA2"} 889c8c7a7eSZhanjun Dong 899c8c7a7eSZhanjun Dong #define XELP_VEC_CLASS_REGS \ 909c8c7a7eSZhanjun Dong { SFC_DONE(0), 0, 0, 0, "SFC_DONE[0]"}, \ 919c8c7a7eSZhanjun Dong { SFC_DONE(1), 0, 0, 0, "SFC_DONE[1]"}, \ 929c8c7a7eSZhanjun Dong { SFC_DONE(2), 0, 0, 0, "SFC_DONE[2]"}, \ 939c8c7a7eSZhanjun Dong { SFC_DONE(3), 0, 0, 0, "SFC_DONE[3]"} 949c8c7a7eSZhanjun Dong 959c8c7a7eSZhanjun Dong /* XE_LP Global */ 969c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { 979c8c7a7eSZhanjun Dong COMMON_XELP_BASE_GLOBAL, 989c8c7a7eSZhanjun Dong }; 999c8c7a7eSZhanjun Dong 1009c8c7a7eSZhanjun Dong /* Render / Compute Per-Engine-Instance */ 1019c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_rc_inst_regs[] = { 1029c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 1039c8c7a7eSZhanjun Dong }; 1049c8c7a7eSZhanjun Dong 1059c8c7a7eSZhanjun Dong /* Render / Compute Engine-Class */ 1069c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_rc_class_regs[] = { 1079c8c7a7eSZhanjun Dong COMMON_XELP_RC_CLASS, 1089c8c7a7eSZhanjun Dong COMMON_XELP_RC_CLASS_INSTDONE, 1099c8c7a7eSZhanjun Dong }; 1109c8c7a7eSZhanjun Dong 1119c8c7a7eSZhanjun Dong /* Render / Compute Engine-Class for xehpg */ 1129c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_hpg_rc_class_regs[] = { 1139c8c7a7eSZhanjun Dong COMMON_XELP_RC_CLASS, 1149c8c7a7eSZhanjun Dong }; 1159c8c7a7eSZhanjun Dong 1169c8c7a7eSZhanjun Dong /* Media Decode/Encode Per-Engine-Instance */ 1179c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_vd_inst_regs[] = { 1189c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 1199c8c7a7eSZhanjun Dong }; 1209c8c7a7eSZhanjun Dong 1219c8c7a7eSZhanjun Dong /* Video Enhancement Engine-Class */ 1229c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_vec_class_regs[] = { 1239c8c7a7eSZhanjun Dong XELP_VEC_CLASS_REGS, 1249c8c7a7eSZhanjun Dong }; 1259c8c7a7eSZhanjun Dong 1269c8c7a7eSZhanjun Dong /* Video Enhancement Per-Engine-Instance */ 1279c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_vec_inst_regs[] = { 1289c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 1299c8c7a7eSZhanjun Dong }; 1309c8c7a7eSZhanjun Dong 1319c8c7a7eSZhanjun Dong /* Blitter Per-Engine-Instance */ 1329c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_blt_inst_regs[] = { 1339c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 1349c8c7a7eSZhanjun Dong }; 1359c8c7a7eSZhanjun Dong 1369c8c7a7eSZhanjun Dong /* XE_LP - GSC Per-Engine-Instance */ 1379c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { 1389c8c7a7eSZhanjun Dong COMMON_BASE_ENGINE_INSTANCE, 1399c8c7a7eSZhanjun Dong }; 1409c8c7a7eSZhanjun Dong 1419c8c7a7eSZhanjun Dong /* 1429c8c7a7eSZhanjun Dong * Empty list to prevent warnings about unknown class/instance types 1439c8c7a7eSZhanjun Dong * as not all class/instance types have entries on all platforms. 1449c8c7a7eSZhanjun Dong */ 1459c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr empty_regs_list[] = { 1469c8c7a7eSZhanjun Dong }; 1479c8c7a7eSZhanjun Dong 1489c8c7a7eSZhanjun Dong #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) 1499c8c7a7eSZhanjun Dong #define TO_GCAP_DEF_TYPE(x) (GUC_STATE_CAPTURE_TYPE_##x) 1509c8c7a7eSZhanjun Dong #define MAKE_REGLIST(regslist, regsowner, regstype, class) \ 1519c8c7a7eSZhanjun Dong { \ 1529c8c7a7eSZhanjun Dong regslist, \ 1539c8c7a7eSZhanjun Dong ARRAY_SIZE(regslist), \ 1549c8c7a7eSZhanjun Dong TO_GCAP_DEF_OWNER(regsowner), \ 1559c8c7a7eSZhanjun Dong TO_GCAP_DEF_TYPE(regstype), \ 1569c8c7a7eSZhanjun Dong class \ 1579c8c7a7eSZhanjun Dong } 1589c8c7a7eSZhanjun Dong 1599c8c7a7eSZhanjun Dong /* List of lists for legacy graphic product version < 1255 */ 1609c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group xe_lp_lists[] = { 1619c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 1629c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 1639c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 1649c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 1659c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 1669c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 1679c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 1689c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 1699c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 1709c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 1719c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 1729c8c7a7eSZhanjun Dong {} 1739c8c7a7eSZhanjun Dong }; 1749c8c7a7eSZhanjun Dong 1759c8c7a7eSZhanjun Dong /* List of lists for graphic product version >= 1255 */ 1769c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group xe_hpg_lists[] = { 1779c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 1789c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_hpg_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 1799c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 1809c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 1819c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 1829c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 1839c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 1849c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 1859c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 1869c8c7a7eSZhanjun Dong MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 1879c8c7a7eSZhanjun Dong MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 1889c8c7a7eSZhanjun Dong {} 1899c8c7a7eSZhanjun Dong }; 1909c8c7a7eSZhanjun Dong 1919c8c7a7eSZhanjun Dong static const char * const capture_list_type_names[] = { 1929c8c7a7eSZhanjun Dong "Global", 1939c8c7a7eSZhanjun Dong "Class", 1949c8c7a7eSZhanjun Dong "Instance", 1959c8c7a7eSZhanjun Dong }; 1969c8c7a7eSZhanjun Dong 1979c8c7a7eSZhanjun Dong static const char * const capture_engine_class_names[] = { 1989c8c7a7eSZhanjun Dong "Render/Compute", 1999c8c7a7eSZhanjun Dong "Video", 2009c8c7a7eSZhanjun Dong "VideoEnhance", 2019c8c7a7eSZhanjun Dong "Blitter", 2029c8c7a7eSZhanjun Dong "GSC-Other", 2039c8c7a7eSZhanjun Dong }; 2049c8c7a7eSZhanjun Dong 2059c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache { 2069c8c7a7eSZhanjun Dong bool is_valid; 2079c8c7a7eSZhanjun Dong void *ptr; 2089c8c7a7eSZhanjun Dong size_t size; 2099c8c7a7eSZhanjun Dong int status; 2109c8c7a7eSZhanjun Dong }; 2119c8c7a7eSZhanjun Dong 2129c8c7a7eSZhanjun Dong struct xe_guc_state_capture { 2139c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *reglists; 214*b170d696SZhanjun Dong /** 215*b170d696SZhanjun Dong * NOTE: steered registers have multiple instances depending on the HW configuration 216*b170d696SZhanjun Dong * (slices or dual-sub-slices) and thus depends on HW fuses discovered 217*b170d696SZhanjun Dong */ 218*b170d696SZhanjun Dong struct __guc_mmio_reg_descr_group *extlists; 2199c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX] 2209c8c7a7eSZhanjun Dong [GUC_STATE_CAPTURE_TYPE_MAX] 2219c8c7a7eSZhanjun Dong [GUC_CAPTURE_LIST_CLASS_MAX]; 2229c8c7a7eSZhanjun Dong void *ads_null_cache; 2239c8c7a7eSZhanjun Dong }; 2249c8c7a7eSZhanjun Dong 2259c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group * 2269c8c7a7eSZhanjun Dong guc_capture_get_device_reglist(struct xe_device *xe) 2279c8c7a7eSZhanjun Dong { 2289c8c7a7eSZhanjun Dong if (GRAPHICS_VERx100(xe) >= 1255) 2299c8c7a7eSZhanjun Dong return xe_hpg_lists; 2309c8c7a7eSZhanjun Dong else 2319c8c7a7eSZhanjun Dong return xe_lp_lists; 2329c8c7a7eSZhanjun Dong } 2339c8c7a7eSZhanjun Dong 2349c8c7a7eSZhanjun Dong static const struct __guc_mmio_reg_descr_group * 2359c8c7a7eSZhanjun Dong guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, 2369c8c7a7eSZhanjun Dong u32 owner, u32 type, enum guc_capture_list_class_type capture_class) 2379c8c7a7eSZhanjun Dong { 2389c8c7a7eSZhanjun Dong int i; 2399c8c7a7eSZhanjun Dong 2409c8c7a7eSZhanjun Dong if (!reglists) 2419c8c7a7eSZhanjun Dong return NULL; 2429c8c7a7eSZhanjun Dong 2439c8c7a7eSZhanjun Dong for (i = 0; reglists[i].list; ++i) { 2449c8c7a7eSZhanjun Dong if (reglists[i].owner == owner && reglists[i].type == type && 2459c8c7a7eSZhanjun Dong (reglists[i].engine == capture_class || 2469c8c7a7eSZhanjun Dong reglists[i].type == GUC_STATE_CAPTURE_TYPE_GLOBAL)) 2479c8c7a7eSZhanjun Dong return ®lists[i]; 2489c8c7a7eSZhanjun Dong } 2499c8c7a7eSZhanjun Dong 2509c8c7a7eSZhanjun Dong return NULL; 2519c8c7a7eSZhanjun Dong } 2529c8c7a7eSZhanjun Dong 253*b170d696SZhanjun Dong struct __ext_steer_reg { 254*b170d696SZhanjun Dong const char *name; 255*b170d696SZhanjun Dong struct xe_reg_mcr reg; 256*b170d696SZhanjun Dong }; 257*b170d696SZhanjun Dong 258*b170d696SZhanjun Dong static const struct __ext_steer_reg xe_extregs[] = { 259*b170d696SZhanjun Dong {"SAMPLER_INSTDONE", SAMPLER_INSTDONE}, 260*b170d696SZhanjun Dong {"ROW_INSTDONE", ROW_INSTDONE} 261*b170d696SZhanjun Dong }; 262*b170d696SZhanjun Dong 263*b170d696SZhanjun Dong static const struct __ext_steer_reg xehpg_extregs[] = { 264*b170d696SZhanjun Dong {"SC_INSTDONE", XEHPG_SC_INSTDONE}, 265*b170d696SZhanjun Dong {"SC_INSTDONE_EXTRA", XEHPG_SC_INSTDONE_EXTRA}, 266*b170d696SZhanjun Dong {"SC_INSTDONE_EXTRA2", XEHPG_SC_INSTDONE_EXTRA2}, 267*b170d696SZhanjun Dong {"INSTDONE_GEOM_SVGUNIT", XEHPG_INSTDONE_GEOM_SVGUNIT} 268*b170d696SZhanjun Dong }; 269*b170d696SZhanjun Dong 270*b170d696SZhanjun Dong static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext, 271*b170d696SZhanjun Dong const struct __ext_steer_reg *extlist, 272*b170d696SZhanjun Dong int slice_id, int subslice_id) 273*b170d696SZhanjun Dong { 274*b170d696SZhanjun Dong if (!ext || !extlist) 275*b170d696SZhanjun Dong return; 276*b170d696SZhanjun Dong 277*b170d696SZhanjun Dong ext->reg = XE_REG(extlist->reg.__reg.addr); 278*b170d696SZhanjun Dong ext->flags = FIELD_PREP(GUC_REGSET_STEERING_NEEDED, 1); 279*b170d696SZhanjun Dong ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id); 280*b170d696SZhanjun Dong ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id); 281*b170d696SZhanjun Dong ext->regname = extlist->name; 282*b170d696SZhanjun Dong } 283*b170d696SZhanjun Dong 284*b170d696SZhanjun Dong static int 285*b170d696SZhanjun Dong __alloc_ext_regs(struct drm_device *drm, struct __guc_mmio_reg_descr_group *newlist, 286*b170d696SZhanjun Dong const struct __guc_mmio_reg_descr_group *rootlist, int num_regs) 287*b170d696SZhanjun Dong { 288*b170d696SZhanjun Dong struct __guc_mmio_reg_descr *list; 289*b170d696SZhanjun Dong 290*b170d696SZhanjun Dong list = drmm_kzalloc(drm, num_regs * sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL); 291*b170d696SZhanjun Dong if (!list) 292*b170d696SZhanjun Dong return -ENOMEM; 293*b170d696SZhanjun Dong 294*b170d696SZhanjun Dong newlist->list = list; 295*b170d696SZhanjun Dong newlist->num_regs = num_regs; 296*b170d696SZhanjun Dong newlist->owner = rootlist->owner; 297*b170d696SZhanjun Dong newlist->engine = rootlist->engine; 298*b170d696SZhanjun Dong newlist->type = rootlist->type; 299*b170d696SZhanjun Dong 300*b170d696SZhanjun Dong return 0; 301*b170d696SZhanjun Dong } 302*b170d696SZhanjun Dong 303*b170d696SZhanjun Dong static int guc_capture_get_steer_reg_num(struct xe_device *xe) 304*b170d696SZhanjun Dong { 305*b170d696SZhanjun Dong int num = ARRAY_SIZE(xe_extregs); 306*b170d696SZhanjun Dong 307*b170d696SZhanjun Dong if (GRAPHICS_VERx100(xe) >= 1255) 308*b170d696SZhanjun Dong num += ARRAY_SIZE(xehpg_extregs); 309*b170d696SZhanjun Dong 310*b170d696SZhanjun Dong return num; 311*b170d696SZhanjun Dong } 312*b170d696SZhanjun Dong 313*b170d696SZhanjun Dong static void guc_capture_alloc_steered_lists(struct xe_guc *guc) 314*b170d696SZhanjun Dong { 315*b170d696SZhanjun Dong struct xe_gt *gt = guc_to_gt(guc); 316*b170d696SZhanjun Dong u16 slice, subslice; 317*b170d696SZhanjun Dong int iter, i, total = 0; 318*b170d696SZhanjun Dong const struct __guc_mmio_reg_descr_group *lists = guc->capture->reglists; 319*b170d696SZhanjun Dong const struct __guc_mmio_reg_descr_group *list; 320*b170d696SZhanjun Dong struct __guc_mmio_reg_descr_group *extlists; 321*b170d696SZhanjun Dong struct __guc_mmio_reg_descr *extarray; 322*b170d696SZhanjun Dong bool has_xehpg_extregs = GRAPHICS_VERx100(gt_to_xe(gt)) >= 1255; 323*b170d696SZhanjun Dong struct drm_device *drm = >_to_xe(gt)->drm; 324*b170d696SZhanjun Dong bool has_rcs_ccs = false; 325*b170d696SZhanjun Dong struct xe_hw_engine *hwe; 326*b170d696SZhanjun Dong enum xe_hw_engine_id id; 327*b170d696SZhanjun Dong 328*b170d696SZhanjun Dong /* 329*b170d696SZhanjun Dong * If GT has no rcs/ccs, no need to alloc steered list. 330*b170d696SZhanjun Dong * Currently, only rcs/ccs has steering register, if in the future, 331*b170d696SZhanjun Dong * other engine types has steering register, this condition check need 332*b170d696SZhanjun Dong * to be extended 333*b170d696SZhanjun Dong */ 334*b170d696SZhanjun Dong for_each_hw_engine(hwe, gt, id) { 335*b170d696SZhanjun Dong if (xe_engine_class_to_guc_capture_class(hwe->class) == 336*b170d696SZhanjun Dong GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) { 337*b170d696SZhanjun Dong has_rcs_ccs = true; 338*b170d696SZhanjun Dong break; 339*b170d696SZhanjun Dong } 340*b170d696SZhanjun Dong } 341*b170d696SZhanjun Dong 342*b170d696SZhanjun Dong if (!has_rcs_ccs) 343*b170d696SZhanjun Dong return; 344*b170d696SZhanjun Dong 345*b170d696SZhanjun Dong /* steered registers currently only exist for the render-class */ 346*b170d696SZhanjun Dong list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, 347*b170d696SZhanjun Dong GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 348*b170d696SZhanjun Dong GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE); 349*b170d696SZhanjun Dong /* 350*b170d696SZhanjun Dong * Skip if this platform has no engine class registers or if extlists 351*b170d696SZhanjun Dong * was previously allocated 352*b170d696SZhanjun Dong */ 353*b170d696SZhanjun Dong if (!list || guc->capture->extlists) 354*b170d696SZhanjun Dong return; 355*b170d696SZhanjun Dong 356*b170d696SZhanjun Dong total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) * 357*b170d696SZhanjun Dong guc_capture_get_steer_reg_num(guc_to_xe(guc)); 358*b170d696SZhanjun Dong 359*b170d696SZhanjun Dong if (!total) 360*b170d696SZhanjun Dong return; 361*b170d696SZhanjun Dong 362*b170d696SZhanjun Dong /* allocate an extra for an end marker */ 363*b170d696SZhanjun Dong extlists = drmm_kzalloc(drm, 2 * sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); 364*b170d696SZhanjun Dong if (!extlists) 365*b170d696SZhanjun Dong return; 366*b170d696SZhanjun Dong 367*b170d696SZhanjun Dong if (__alloc_ext_regs(drm, &extlists[0], list, total)) { 368*b170d696SZhanjun Dong drmm_kfree(drm, extlists); 369*b170d696SZhanjun Dong return; 370*b170d696SZhanjun Dong } 371*b170d696SZhanjun Dong 372*b170d696SZhanjun Dong /* For steering registers, the list is generated at run-time */ 373*b170d696SZhanjun Dong extarray = (struct __guc_mmio_reg_descr *)extlists[0].list; 374*b170d696SZhanjun Dong for_each_dss_steering(iter, gt, slice, subslice) { 375*b170d696SZhanjun Dong for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) { 376*b170d696SZhanjun Dong __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); 377*b170d696SZhanjun Dong ++extarray; 378*b170d696SZhanjun Dong } 379*b170d696SZhanjun Dong 380*b170d696SZhanjun Dong if (has_xehpg_extregs) 381*b170d696SZhanjun Dong for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) { 382*b170d696SZhanjun Dong __fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice); 383*b170d696SZhanjun Dong ++extarray; 384*b170d696SZhanjun Dong } 385*b170d696SZhanjun Dong } 386*b170d696SZhanjun Dong 387*b170d696SZhanjun Dong extlists[0].num_regs = total; 388*b170d696SZhanjun Dong 389*b170d696SZhanjun Dong xe_gt_dbg(guc_to_gt(guc), "capture found %d ext-regs.\n", total); 390*b170d696SZhanjun Dong guc->capture->extlists = extlists; 391*b170d696SZhanjun Dong } 392*b170d696SZhanjun Dong 3939c8c7a7eSZhanjun Dong static int 3949c8c7a7eSZhanjun Dong guc_capture_list_init(struct xe_guc *guc, u32 owner, u32 type, 3959c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, struct guc_mmio_reg *ptr, 3969c8c7a7eSZhanjun Dong u16 num_entries) 3979c8c7a7eSZhanjun Dong { 398*b170d696SZhanjun Dong u32 ptr_idx = 0, list_idx = 0; 3999c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; 400*b170d696SZhanjun Dong struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; 4019c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *match; 402*b170d696SZhanjun Dong u32 list_num; 4039c8c7a7eSZhanjun Dong 4049c8c7a7eSZhanjun Dong if (!reglists) 4059c8c7a7eSZhanjun Dong return -ENODEV; 4069c8c7a7eSZhanjun Dong 4079c8c7a7eSZhanjun Dong match = guc_capture_get_one_list(reglists, owner, type, capture_class); 4089c8c7a7eSZhanjun Dong if (!match) 4099c8c7a7eSZhanjun Dong return -ENODATA; 4109c8c7a7eSZhanjun Dong 411*b170d696SZhanjun Dong list_num = match->num_regs; 412*b170d696SZhanjun Dong for (list_idx = 0; ptr_idx < num_entries && list_idx < list_num; ++list_idx, ++ptr_idx) { 413*b170d696SZhanjun Dong ptr[ptr_idx].offset = match->list[list_idx].reg.addr; 414*b170d696SZhanjun Dong ptr[ptr_idx].value = 0xDEADF00D; 415*b170d696SZhanjun Dong ptr[ptr_idx].flags = match->list[list_idx].flags; 416*b170d696SZhanjun Dong ptr[ptr_idx].mask = match->list[list_idx].mask; 4179c8c7a7eSZhanjun Dong } 4189c8c7a7eSZhanjun Dong 419*b170d696SZhanjun Dong match = guc_capture_get_one_list(extlists, owner, type, capture_class); 420*b170d696SZhanjun Dong if (match) 421*b170d696SZhanjun Dong for (ptr_idx = list_num, list_idx = 0; 422*b170d696SZhanjun Dong ptr_idx < num_entries && list_idx < match->num_regs; 423*b170d696SZhanjun Dong ++ptr_idx, ++list_idx) { 424*b170d696SZhanjun Dong ptr[ptr_idx].offset = match->list[list_idx].reg.addr; 425*b170d696SZhanjun Dong ptr[ptr_idx].value = 0xDEADF00D; 426*b170d696SZhanjun Dong ptr[ptr_idx].flags = match->list[list_idx].flags; 427*b170d696SZhanjun Dong ptr[ptr_idx].mask = match->list[list_idx].mask; 428*b170d696SZhanjun Dong } 429*b170d696SZhanjun Dong 430*b170d696SZhanjun Dong if (ptr_idx < num_entries) 431*b170d696SZhanjun Dong xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out-of %d.\n", 432*b170d696SZhanjun Dong ptr_idx, num_entries); 4339c8c7a7eSZhanjun Dong 4349c8c7a7eSZhanjun Dong return 0; 4359c8c7a7eSZhanjun Dong } 4369c8c7a7eSZhanjun Dong 4379c8c7a7eSZhanjun Dong static int 4389c8c7a7eSZhanjun Dong guc_cap_list_num_regs(struct xe_guc *guc, u32 owner, u32 type, 4399c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class) 4409c8c7a7eSZhanjun Dong { 4419c8c7a7eSZhanjun Dong const struct __guc_mmio_reg_descr_group *match; 442*b170d696SZhanjun Dong int num_regs = 0; 4439c8c7a7eSZhanjun Dong 4449c8c7a7eSZhanjun Dong match = guc_capture_get_one_list(guc->capture->reglists, owner, type, capture_class); 445*b170d696SZhanjun Dong if (match) 446*b170d696SZhanjun Dong num_regs = match->num_regs; 4479c8c7a7eSZhanjun Dong 448*b170d696SZhanjun Dong match = guc_capture_get_one_list(guc->capture->extlists, owner, type, capture_class); 449*b170d696SZhanjun Dong if (match) 450*b170d696SZhanjun Dong num_regs += match->num_regs; 451*b170d696SZhanjun Dong else 452*b170d696SZhanjun Dong /* Estimate steering register size for rcs/ccs */ 453*b170d696SZhanjun Dong if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) 454*b170d696SZhanjun Dong num_regs += guc_capture_get_steer_reg_num(guc_to_xe(guc)) * 455*b170d696SZhanjun Dong XE_MAX_DSS_FUSE_BITS; 456*b170d696SZhanjun Dong 457*b170d696SZhanjun Dong return num_regs; 4589c8c7a7eSZhanjun Dong } 4599c8c7a7eSZhanjun Dong 4609c8c7a7eSZhanjun Dong static int 4619c8c7a7eSZhanjun Dong guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type, 4629c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, 4639c8c7a7eSZhanjun Dong size_t *size, bool is_purpose_est) 4649c8c7a7eSZhanjun Dong { 4659c8c7a7eSZhanjun Dong struct xe_guc_state_capture *gc = guc->capture; 4669c8c7a7eSZhanjun Dong struct xe_gt *gt = guc_to_gt(guc); 4679c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache *cache; 4689c8c7a7eSZhanjun Dong int num_regs; 4699c8c7a7eSZhanjun Dong 4709c8c7a7eSZhanjun Dong xe_gt_assert(gt, type < GUC_STATE_CAPTURE_TYPE_MAX); 4719c8c7a7eSZhanjun Dong xe_gt_assert(gt, capture_class < GUC_CAPTURE_LIST_CLASS_MAX); 4729c8c7a7eSZhanjun Dong 4739c8c7a7eSZhanjun Dong cache = &gc->ads_cache[owner][type][capture_class]; 4749c8c7a7eSZhanjun Dong if (!gc->reglists) { 4759c8c7a7eSZhanjun Dong xe_gt_warn(gt, "No capture reglist for this device\n"); 4769c8c7a7eSZhanjun Dong return -ENODEV; 4779c8c7a7eSZhanjun Dong } 4789c8c7a7eSZhanjun Dong 4799c8c7a7eSZhanjun Dong if (cache->is_valid) { 4809c8c7a7eSZhanjun Dong *size = cache->size; 4819c8c7a7eSZhanjun Dong return cache->status; 4829c8c7a7eSZhanjun Dong } 4839c8c7a7eSZhanjun Dong 4849c8c7a7eSZhanjun Dong if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF && 4859c8c7a7eSZhanjun Dong !guc_capture_get_one_list(gc->reglists, owner, type, capture_class)) { 4869c8c7a7eSZhanjun Dong if (type == GUC_STATE_CAPTURE_TYPE_GLOBAL) 4879c8c7a7eSZhanjun Dong xe_gt_warn(gt, "Missing capture reglist: global!\n"); 4889c8c7a7eSZhanjun Dong else 4899c8c7a7eSZhanjun Dong xe_gt_warn(gt, "Missing capture reglist: %s(%u):%s(%u)!\n", 4909c8c7a7eSZhanjun Dong capture_list_type_names[type], type, 4919c8c7a7eSZhanjun Dong capture_engine_class_names[capture_class], capture_class); 4929c8c7a7eSZhanjun Dong return -ENODEV; 4939c8c7a7eSZhanjun Dong } 4949c8c7a7eSZhanjun Dong 4959c8c7a7eSZhanjun Dong num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class); 4969c8c7a7eSZhanjun Dong /* intentional empty lists can exist depending on hw config */ 4979c8c7a7eSZhanjun Dong if (!num_regs) 4989c8c7a7eSZhanjun Dong return -ENODATA; 4999c8c7a7eSZhanjun Dong 5009c8c7a7eSZhanjun Dong if (size) 5019c8c7a7eSZhanjun Dong *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + 5029c8c7a7eSZhanjun Dong (num_regs * sizeof(struct guc_mmio_reg))); 5039c8c7a7eSZhanjun Dong 5049c8c7a7eSZhanjun Dong return 0; 5059c8c7a7eSZhanjun Dong } 5069c8c7a7eSZhanjun Dong 5079c8c7a7eSZhanjun Dong /** 5089c8c7a7eSZhanjun Dong * xe_guc_capture_getlistsize - Get list size for owner/type/class combination 5099c8c7a7eSZhanjun Dong * @guc: The GuC object 5109c8c7a7eSZhanjun Dong * @owner: PF/VF owner 5119c8c7a7eSZhanjun Dong * @type: GuC capture register type 5129c8c7a7eSZhanjun Dong * @capture_class: GuC capture engine class id 5139c8c7a7eSZhanjun Dong * @size: Point to the size 5149c8c7a7eSZhanjun Dong * 5159c8c7a7eSZhanjun Dong * This function will get the list for the owner/type/class combination, and 5169c8c7a7eSZhanjun Dong * return the page aligned list size. 5179c8c7a7eSZhanjun Dong * 5189c8c7a7eSZhanjun Dong * Returns: 0 on success or a negative error code on failure. 5199c8c7a7eSZhanjun Dong */ 5209c8c7a7eSZhanjun Dong int 5219c8c7a7eSZhanjun Dong xe_guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type, 5229c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, size_t *size) 5239c8c7a7eSZhanjun Dong { 5249c8c7a7eSZhanjun Dong return guc_capture_getlistsize(guc, owner, type, capture_class, size, false); 5259c8c7a7eSZhanjun Dong } 5269c8c7a7eSZhanjun Dong 5279c8c7a7eSZhanjun Dong /** 5289c8c7a7eSZhanjun Dong * xe_guc_capture_getlist - Get register capture list for owner/type/class 5299c8c7a7eSZhanjun Dong * combination 5309c8c7a7eSZhanjun Dong * @guc: The GuC object 5319c8c7a7eSZhanjun Dong * @owner: PF/VF owner 5329c8c7a7eSZhanjun Dong * @type: GuC capture register type 5339c8c7a7eSZhanjun Dong * @capture_class: GuC capture engine class id 5349c8c7a7eSZhanjun Dong * @outptr: Point to cached register capture list 5359c8c7a7eSZhanjun Dong * 5369c8c7a7eSZhanjun Dong * This function will get the register capture list for the owner/type/class 5379c8c7a7eSZhanjun Dong * combination. 5389c8c7a7eSZhanjun Dong * 5399c8c7a7eSZhanjun Dong * Returns: 0 on success or a negative error code on failure. 5409c8c7a7eSZhanjun Dong */ 5419c8c7a7eSZhanjun Dong int 5429c8c7a7eSZhanjun Dong xe_guc_capture_getlist(struct xe_guc *guc, u32 owner, u32 type, 5439c8c7a7eSZhanjun Dong enum guc_capture_list_class_type capture_class, void **outptr) 5449c8c7a7eSZhanjun Dong { 5459c8c7a7eSZhanjun Dong struct xe_guc_state_capture *gc = guc->capture; 5469c8c7a7eSZhanjun Dong struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][capture_class]; 5479c8c7a7eSZhanjun Dong struct guc_debug_capture_list *listnode; 5489c8c7a7eSZhanjun Dong int ret, num_regs; 5499c8c7a7eSZhanjun Dong u8 *caplist, *tmp; 5509c8c7a7eSZhanjun Dong size_t size = 0; 5519c8c7a7eSZhanjun Dong 5529c8c7a7eSZhanjun Dong if (!gc->reglists) 5539c8c7a7eSZhanjun Dong return -ENODEV; 5549c8c7a7eSZhanjun Dong 5559c8c7a7eSZhanjun Dong if (cache->is_valid) { 5569c8c7a7eSZhanjun Dong *outptr = cache->ptr; 5579c8c7a7eSZhanjun Dong return cache->status; 5589c8c7a7eSZhanjun Dong } 5599c8c7a7eSZhanjun Dong 5609c8c7a7eSZhanjun Dong ret = xe_guc_capture_getlistsize(guc, owner, type, capture_class, &size); 5619c8c7a7eSZhanjun Dong if (ret) { 5629c8c7a7eSZhanjun Dong cache->is_valid = true; 5639c8c7a7eSZhanjun Dong cache->ptr = NULL; 5649c8c7a7eSZhanjun Dong cache->size = 0; 5659c8c7a7eSZhanjun Dong cache->status = ret; 5669c8c7a7eSZhanjun Dong return ret; 5679c8c7a7eSZhanjun Dong } 5689c8c7a7eSZhanjun Dong 5699c8c7a7eSZhanjun Dong caplist = drmm_kzalloc(guc_to_drm(guc), size, GFP_KERNEL); 5709c8c7a7eSZhanjun Dong if (!caplist) 5719c8c7a7eSZhanjun Dong return -ENOMEM; 5729c8c7a7eSZhanjun Dong 5739c8c7a7eSZhanjun Dong /* populate capture list header */ 5749c8c7a7eSZhanjun Dong tmp = caplist; 5759c8c7a7eSZhanjun Dong num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class); 5769c8c7a7eSZhanjun Dong listnode = (struct guc_debug_capture_list *)tmp; 5779c8c7a7eSZhanjun Dong listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); 5789c8c7a7eSZhanjun Dong 5799c8c7a7eSZhanjun Dong /* populate list of register descriptor */ 5809c8c7a7eSZhanjun Dong tmp += sizeof(struct guc_debug_capture_list); 5819c8c7a7eSZhanjun Dong guc_capture_list_init(guc, owner, type, capture_class, 5829c8c7a7eSZhanjun Dong (struct guc_mmio_reg *)tmp, num_regs); 5839c8c7a7eSZhanjun Dong 5849c8c7a7eSZhanjun Dong /* cache this list */ 5859c8c7a7eSZhanjun Dong cache->is_valid = true; 5869c8c7a7eSZhanjun Dong cache->ptr = caplist; 5879c8c7a7eSZhanjun Dong cache->size = size; 5889c8c7a7eSZhanjun Dong cache->status = 0; 5899c8c7a7eSZhanjun Dong 5909c8c7a7eSZhanjun Dong *outptr = caplist; 5919c8c7a7eSZhanjun Dong 5929c8c7a7eSZhanjun Dong return 0; 5939c8c7a7eSZhanjun Dong } 5949c8c7a7eSZhanjun Dong 5959c8c7a7eSZhanjun Dong /** 5969c8c7a7eSZhanjun Dong * xe_guc_capture_getnullheader - Get a null list for register capture 5979c8c7a7eSZhanjun Dong * @guc: The GuC object 5989c8c7a7eSZhanjun Dong * @outptr: Point to cached register capture list 5999c8c7a7eSZhanjun Dong * @size: Point to the size 6009c8c7a7eSZhanjun Dong * 6019c8c7a7eSZhanjun Dong * This function will alloc for a null list for register capture. 6029c8c7a7eSZhanjun Dong * 6039c8c7a7eSZhanjun Dong * Returns: 0 on success or a negative error code on failure. 6049c8c7a7eSZhanjun Dong */ 6059c8c7a7eSZhanjun Dong int 6069c8c7a7eSZhanjun Dong xe_guc_capture_getnullheader(struct xe_guc *guc, void **outptr, size_t *size) 6079c8c7a7eSZhanjun Dong { 6089c8c7a7eSZhanjun Dong struct xe_guc_state_capture *gc = guc->capture; 6099c8c7a7eSZhanjun Dong int tmp = sizeof(u32) * 4; 6109c8c7a7eSZhanjun Dong void *null_header; 6119c8c7a7eSZhanjun Dong 6129c8c7a7eSZhanjun Dong if (gc->ads_null_cache) { 6139c8c7a7eSZhanjun Dong *outptr = gc->ads_null_cache; 6149c8c7a7eSZhanjun Dong *size = tmp; 6159c8c7a7eSZhanjun Dong return 0; 6169c8c7a7eSZhanjun Dong } 6179c8c7a7eSZhanjun Dong 6189c8c7a7eSZhanjun Dong null_header = drmm_kzalloc(guc_to_drm(guc), tmp, GFP_KERNEL); 6199c8c7a7eSZhanjun Dong if (!null_header) 6209c8c7a7eSZhanjun Dong return -ENOMEM; 6219c8c7a7eSZhanjun Dong 6229c8c7a7eSZhanjun Dong gc->ads_null_cache = null_header; 6239c8c7a7eSZhanjun Dong *outptr = null_header; 6249c8c7a7eSZhanjun Dong *size = tmp; 6259c8c7a7eSZhanjun Dong 6269c8c7a7eSZhanjun Dong return 0; 6279c8c7a7eSZhanjun Dong } 6289c8c7a7eSZhanjun Dong 6299c8c7a7eSZhanjun Dong /** 6309c8c7a7eSZhanjun Dong * xe_guc_capture_ads_input_worst_size - Calculate the worst size for GuC register capture 6319c8c7a7eSZhanjun Dong * @guc: point to xe_guc structure 6329c8c7a7eSZhanjun Dong * 6339c8c7a7eSZhanjun Dong * Calculate the worst size for GuC register capture by including all possible engines classes. 6349c8c7a7eSZhanjun Dong * 6359c8c7a7eSZhanjun Dong * Returns: Calculated size 6369c8c7a7eSZhanjun Dong */ 6379c8c7a7eSZhanjun Dong size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc) 6389c8c7a7eSZhanjun Dong { 6399c8c7a7eSZhanjun Dong size_t total_size, class_size, instance_size, global_size; 6409c8c7a7eSZhanjun Dong int i, j; 6419c8c7a7eSZhanjun Dong 6429c8c7a7eSZhanjun Dong /* 6439c8c7a7eSZhanjun Dong * This function calculates the worst case register lists size by 6449c8c7a7eSZhanjun Dong * including all possible engines classes. It is called during the 6459c8c7a7eSZhanjun Dong * first of a two-phase GuC (and ADS-population) initialization 6469c8c7a7eSZhanjun Dong * sequence, that is, during the pre-hwconfig phase before we have 6479c8c7a7eSZhanjun Dong * the exact engine fusing info. 6489c8c7a7eSZhanjun Dong */ 6499c8c7a7eSZhanjun Dong total_size = PAGE_SIZE; /* Pad a page in front for empty lists */ 6509c8c7a7eSZhanjun Dong for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { 6519c8c7a7eSZhanjun Dong for (j = 0; j < GUC_CAPTURE_LIST_CLASS_MAX; j++) { 6529c8c7a7eSZhanjun Dong if (xe_guc_capture_getlistsize(guc, i, 6539c8c7a7eSZhanjun Dong GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 6549c8c7a7eSZhanjun Dong j, &class_size) < 0) 6559c8c7a7eSZhanjun Dong class_size = 0; 6569c8c7a7eSZhanjun Dong if (xe_guc_capture_getlistsize(guc, i, 6579c8c7a7eSZhanjun Dong GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE, 6589c8c7a7eSZhanjun Dong j, &instance_size) < 0) 6599c8c7a7eSZhanjun Dong instance_size = 0; 6609c8c7a7eSZhanjun Dong total_size += class_size + instance_size; 6619c8c7a7eSZhanjun Dong } 6629c8c7a7eSZhanjun Dong if (xe_guc_capture_getlistsize(guc, i, 6639c8c7a7eSZhanjun Dong GUC_STATE_CAPTURE_TYPE_GLOBAL, 6649c8c7a7eSZhanjun Dong 0, &global_size) < 0) 6659c8c7a7eSZhanjun Dong global_size = 0; 6669c8c7a7eSZhanjun Dong total_size += global_size; 6679c8c7a7eSZhanjun Dong } 6689c8c7a7eSZhanjun Dong 6699c8c7a7eSZhanjun Dong return PAGE_ALIGN(total_size); 6709c8c7a7eSZhanjun Dong } 6719c8c7a7eSZhanjun Dong 672*b170d696SZhanjun Dong /* 673*b170d696SZhanjun Dong * xe_guc_capture_steered_list_init - Init steering register list 674*b170d696SZhanjun Dong * @guc: The GuC object 675*b170d696SZhanjun Dong * 676*b170d696SZhanjun Dong * Init steering register list for GuC register capture 677*b170d696SZhanjun Dong */ 678*b170d696SZhanjun Dong void xe_guc_capture_steered_list_init(struct xe_guc *guc) 679*b170d696SZhanjun Dong { 680*b170d696SZhanjun Dong /* 681*b170d696SZhanjun Dong * For certain engine classes, there are slice and subslice 682*b170d696SZhanjun Dong * level registers requiring steering. We allocate and populate 683*b170d696SZhanjun Dong * these based on hw config and add it as an extension list at 684*b170d696SZhanjun Dong * the end of the pre-populated render list. 685*b170d696SZhanjun Dong */ 686*b170d696SZhanjun Dong guc_capture_alloc_steered_lists(guc); 687*b170d696SZhanjun Dong } 688*b170d696SZhanjun Dong 6899c8c7a7eSZhanjun Dong /** 6909c8c7a7eSZhanjun Dong * xe_guc_capture_init - Init for GuC register capture 6919c8c7a7eSZhanjun Dong * @guc: The GuC object 6929c8c7a7eSZhanjun Dong * 6939c8c7a7eSZhanjun Dong * Init for GuC register capture, alloc memory for capture data structure. 6949c8c7a7eSZhanjun Dong * 6959c8c7a7eSZhanjun Dong * Returns: 0 if success. 696*b170d696SZhanjun Dong * -ENOMEM if out of memory 6979c8c7a7eSZhanjun Dong */ 6989c8c7a7eSZhanjun Dong int xe_guc_capture_init(struct xe_guc *guc) 6999c8c7a7eSZhanjun Dong { 7009c8c7a7eSZhanjun Dong guc->capture = drmm_kzalloc(guc_to_drm(guc), sizeof(*guc->capture), GFP_KERNEL); 7019c8c7a7eSZhanjun Dong if (!guc->capture) 7029c8c7a7eSZhanjun Dong return -ENOMEM; 7039c8c7a7eSZhanjun Dong 7049c8c7a7eSZhanjun Dong guc->capture->reglists = guc_capture_get_device_reglist(guc_to_xe(guc)); 7059c8c7a7eSZhanjun Dong return 0; 7069c8c7a7eSZhanjun Dong } 707