// SPDX-License-Identifier: MIT /* * Copyright © 2022 Intel Corporation */ #include "xe_guc_debugfs.h" #include #include #include "xe_device.h" #include "xe_gt.h" #include "xe_guc.h" #include "xe_guc_ct.h" #include "xe_guc_log.h" #include "xe_guc_pc.h" #include "xe_macros.h" #include "xe_pm.h" /* * guc_debugfs_show - A show callback for struct drm_info_list * @m: the &seq_file * @data: data used by the drm debugfs helpers * * This callback can be used in struct drm_info_list to describe debugfs * files that are &xe_guc specific in similar way how we handle &xe_gt * specific files using &xe_gt_debugfs_simple_show. * * It is assumed that those debugfs files will be created on directory entry * which grandparent struct dentry d_inode->i_private points to &xe_gt. * * /sys/kernel/debug/dri/0/ * ├── gt0 # dent->d_parent->d_parent (d_inode->i_private == gt) * │   ├── uc # dent->d_parent * │   │   ├── guc_info # dent * │   │   ├── guc_... * * This function assumes that &m->private will be set to the &struct * drm_info_node corresponding to the instance of the info on a given &struct * drm_minor (see struct drm_info_list.show for details). * * This function also assumes that struct drm_info_list.data will point to the * function code that will actually print a file content:: * * int (*print)(struct xe_guc *, struct drm_printer *) * * Example:: * * int foo(struct xe_guc *guc, struct drm_printer *p) * { * drm_printf(p, "enabled %d\n", guc->submission_state.enabled); * return 0; * } * * static const struct drm_info_list bar[] = { * { name = "foo", .show = guc_debugfs_show, .data = foo }, * }; * * parent = debugfs_create_dir("uc", gtdir); * drm_debugfs_create_files(bar, ARRAY_SIZE(bar), parent, minor); * * Return: 0 on success or a negative error code on failure. */ static int guc_debugfs_show(struct seq_file *m, void *data) { struct drm_printer p = drm_seq_file_printer(m); struct drm_info_node *node = m->private; struct dentry *parent = node->dent->d_parent; struct dentry *grandparent = parent->d_parent; struct xe_gt *gt = grandparent->d_inode->i_private; struct xe_device *xe = gt_to_xe(gt); int (*print)(struct xe_guc *, struct drm_printer *) = node->info_ent->data; int ret; xe_pm_runtime_get(xe); ret = print(>->uc.guc, &p); xe_pm_runtime_put(xe); return ret; } static int guc_log(struct xe_guc *guc, struct drm_printer *p) { xe_guc_log_print(&guc->log, p); return 0; } static int guc_log_dmesg(struct xe_guc *guc, struct drm_printer *p) { xe_guc_log_print_dmesg(&guc->log); return 0; } static int guc_ctb(struct xe_guc *guc, struct drm_printer *p) { xe_guc_ct_print(&guc->ct, p, true); return 0; } static int guc_pc(struct xe_guc *guc, struct drm_printer *p) { xe_guc_pc_print(&guc->pc, p); return 0; } /* * only for GuC debugfs files which can be safely used on the VF as well: * - without access to the GuC privileged registers * - without access to the PF specific GuC objects */ static const struct drm_info_list vf_safe_debugfs_list[] = { { "guc_info", .show = guc_debugfs_show, .data = xe_guc_print_info }, { "guc_ctb", .show = guc_debugfs_show, .data = guc_ctb }, }; /* everything else should be added here */ static const struct drm_info_list pf_only_debugfs_list[] = { { "guc_log", .show = guc_debugfs_show, .data = guc_log }, { "guc_log_dmesg", .show = guc_debugfs_show, .data = guc_log_dmesg }, { "guc_pc", .show = guc_debugfs_show, .data = guc_pc }, }; void xe_guc_debugfs_register(struct xe_guc *guc, struct dentry *parent) { struct drm_minor *minor = guc_to_xe(guc)->drm.primary; drm_debugfs_create_files(vf_safe_debugfs_list, ARRAY_SIZE(vf_safe_debugfs_list), parent, minor); if (!IS_SRIOV_VF(guc_to_xe(guc))) drm_debugfs_create_files(pf_only_debugfs_list, ARRAY_SIZE(pf_only_debugfs_list), parent, minor); }