Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/pf: Expose SR-IOV VFs configuration over debugfs

We already have functions to configure VF resources and to print
actual provisioning details. Expose this functionality in debugfs
to allow experiment with different settings or inspect details in
case of unexpected issues with the provisioning.

As debugfs attributes are per-VF, we use parent d_inode->i_private
to store VFID, similarly how we did for per-GT attributes.

Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240423131244.2045-2-michal.wajdeczko@intel.com

+227
+1
drivers/gpu/drm/xe/Makefile
··· 163 163 xe_gt_sriov_pf.o \ 164 164 xe_gt_sriov_pf_config.o \ 165 165 xe_gt_sriov_pf_control.o \ 166 + xe_gt_sriov_pf_debugfs.o \ 166 167 xe_gt_sriov_pf_policy.o \ 167 168 xe_gt_sriov_pf_service.o \ 168 169 xe_lmtt.o \
+5
drivers/gpu/drm/xe/xe_gt_debugfs.c
··· 13 13 #include "xe_ggtt.h" 14 14 #include "xe_gt.h" 15 15 #include "xe_gt_mcr.h" 16 + #include "xe_gt_sriov_pf_debugfs.h" 16 17 #include "xe_gt_topology.h" 17 18 #include "xe_hw_engine.h" 18 19 #include "xe_lrc.h" ··· 22 21 #include "xe_pm.h" 23 22 #include "xe_reg_sr.h" 24 23 #include "xe_reg_whitelist.h" 24 + #include "xe_sriov.h" 25 25 #include "xe_uc_debugfs.h" 26 26 #include "xe_wa.h" 27 27 ··· 290 288 root, minor); 291 289 292 290 xe_uc_debugfs_register(&gt->uc, root); 291 + 292 + if (IS_SRIOV_PF(xe)) 293 + xe_gt_sriov_pf_debugfs_register(gt, root); 293 294 }
+203
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2023-2024 Intel Corporation 4 + */ 5 + 6 + #include <linux/debugfs.h> 7 + 8 + #include <drm/drm_print.h> 9 + #include <drm/drm_debugfs.h> 10 + 11 + #include "xe_bo.h" 12 + #include "xe_debugfs.h" 13 + #include "xe_device.h" 14 + #include "xe_gt.h" 15 + #include "xe_gt_debugfs.h" 16 + #include "xe_gt_sriov_pf_config.h" 17 + #include "xe_gt_sriov_pf_debugfs.h" 18 + #include "xe_gt_sriov_pf_helpers.h" 19 + #include "xe_pm.h" 20 + 21 + /* 22 + * /sys/kernel/debug/dri/0/ 23 + * ├── gt0 # d_inode->i_private = gt 24 + * │   ├── pf # d_inode->i_private = gt 25 + * │   ├── vf1 # d_inode->i_private = VFID(1) 26 + * :   : 27 + * │   ├── vfN # d_inode->i_private = VFID(N) 28 + */ 29 + 30 + static void *extract_priv(struct dentry *d) 31 + { 32 + return d->d_inode->i_private; 33 + } 34 + 35 + static struct xe_gt *extract_gt(struct dentry *d) 36 + { 37 + return extract_priv(d->d_parent); 38 + } 39 + 40 + static unsigned int extract_vfid(struct dentry *d) 41 + { 42 + return extract_priv(d) == extract_gt(d) ? PFID : (uintptr_t)extract_priv(d); 43 + } 44 + 45 + /* 46 + * /sys/kernel/debug/dri/0/ 47 + * ├── gt0 48 + * │   ├── pf 49 + * │   │   ├── ggtt_available 50 + * │   │   ├── ggtt_provisioned 51 + * │   │   ├── contexts_provisioned 52 + * │   │   ├── doorbells_provisioned 53 + */ 54 + 55 + static const struct drm_info_list pf_info[] = { 56 + { 57 + "ggtt_available", 58 + .show = xe_gt_debugfs_simple_show, 59 + .data = xe_gt_sriov_pf_config_print_available_ggtt, 60 + }, 61 + { 62 + "ggtt_provisioned", 63 + .show = xe_gt_debugfs_simple_show, 64 + .data = xe_gt_sriov_pf_config_print_ggtt, 65 + }, 66 + { 67 + "contexts_provisioned", 68 + .show = xe_gt_debugfs_simple_show, 69 + .data = xe_gt_sriov_pf_config_print_ctxs, 70 + }, 71 + { 72 + "doorbells_provisioned", 73 + .show = xe_gt_debugfs_simple_show, 74 + .data = xe_gt_sriov_pf_config_print_dbs, 75 + }, 76 + }; 77 + 78 + /* 79 + * /sys/kernel/debug/dri/0/ 80 + * ├── gt0 81 + * │   ├── pf 82 + * │   │   ├── ggtt_spare 83 + * │   │   ├── lmem_spare 84 + * │   │   ├── doorbells_spare 85 + * │   │   ├── contexts_spare 86 + * │   │   ├── exec_quantum_ms 87 + * │   │   ├── preempt_timeout_us 88 + * │   ├── vf1 89 + * │   │   ├── ggtt_quota 90 + * │   │   ├── lmem_quota 91 + * │   │   ├── doorbells_quota 92 + * │   │   ├── contexts_quota 93 + * │   │   ├── exec_quantum_ms 94 + * │   │   ├── preempt_timeout_us 95 + */ 96 + 97 + #define DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(CONFIG, TYPE, FORMAT) \ 98 + \ 99 + static int CONFIG##_set(void *data, u64 val) \ 100 + { \ 101 + struct xe_gt *gt = extract_gt(data); \ 102 + unsigned int vfid = extract_vfid(data); \ 103 + struct xe_device *xe = gt_to_xe(gt); \ 104 + int err; \ 105 + \ 106 + if (val > (TYPE)~0ull) \ 107 + return -EOVERFLOW; \ 108 + \ 109 + xe_pm_runtime_get(xe); \ 110 + err = xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \ 111 + xe_pm_runtime_put(xe); \ 112 + \ 113 + return err; \ 114 + } \ 115 + \ 116 + static int CONFIG##_get(void *data, u64 *val) \ 117 + { \ 118 + struct xe_gt *gt = extract_gt(data); \ 119 + unsigned int vfid = extract_vfid(data); \ 120 + \ 121 + *val = xe_gt_sriov_pf_config_get_##CONFIG(gt, vfid); \ 122 + return 0; \ 123 + } \ 124 + \ 125 + DEFINE_DEBUGFS_ATTRIBUTE(CONFIG##_fops, CONFIG##_get, CONFIG##_set, FORMAT) 126 + 127 + DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, u64, "%llu\n"); 128 + DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(lmem, u64, "%llu\n"); 129 + DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(ctxs, u32, "%llu\n"); 130 + DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(dbs, u32, "%llu\n"); 131 + DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(exec_quantum, u32, "%llu\n"); 132 + DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(preempt_timeout, u32, "%llu\n"); 133 + 134 + static void pf_add_config_attrs(struct xe_gt *gt, struct dentry *parent, unsigned int vfid) 135 + { 136 + xe_gt_assert(gt, gt == extract_gt(parent)); 137 + xe_gt_assert(gt, vfid == extract_vfid(parent)); 138 + 139 + if (!xe_gt_is_media_type(gt)) { 140 + debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare", 141 + 0644, parent, parent, &ggtt_fops); 142 + if (IS_DGFX(gt_to_xe(gt))) 143 + debugfs_create_file_unsafe(vfid ? "lmem_quota" : "lmem_spare", 144 + 0644, parent, parent, &lmem_fops); 145 + } 146 + debugfs_create_file_unsafe(vfid ? "doorbells_quota" : "doorbells_spare", 147 + 0644, parent, parent, &dbs_fops); 148 + debugfs_create_file_unsafe(vfid ? "contexts_quota" : "contexts_spare", 149 + 0644, parent, parent, &ctxs_fops); 150 + debugfs_create_file_unsafe("exec_quantum_ms", 0644, parent, parent, 151 + &exec_quantum_fops); 152 + debugfs_create_file_unsafe("preempt_timeout_us", 0644, parent, parent, 153 + &preempt_timeout_fops); 154 + } 155 + 156 + /** 157 + * xe_gt_sriov_pf_debugfs_register - Register SR-IOV PF specific entries in GT debugfs. 158 + * @gt: the &xe_gt to register 159 + * @root: the &dentry that represents the GT directory 160 + * 161 + * Register SR-IOV PF entries that are GT related and must be shown under GT debugfs. 162 + */ 163 + void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) 164 + { 165 + struct xe_device *xe = gt_to_xe(gt); 166 + struct drm_minor *minor = xe->drm.primary; 167 + int n, totalvfs = xe_sriov_pf_get_totalvfs(xe); 168 + struct dentry *pfdentry; 169 + struct dentry *vfdentry; 170 + char buf[14]; /* should be enough up to "vf%u\0" for 2^32 - 1 */ 171 + 172 + xe_gt_assert(gt, IS_SRIOV_PF(xe)); 173 + xe_gt_assert(gt, root->d_inode->i_private == gt); 174 + 175 + /* 176 + * /sys/kernel/debug/dri/0/ 177 + * ├── gt0 178 + * │   ├── pf 179 + */ 180 + pfdentry = debugfs_create_dir("pf", root); 181 + if (IS_ERR(pfdentry)) 182 + return; 183 + pfdentry->d_inode->i_private = gt; 184 + 185 + drm_debugfs_create_files(pf_info, ARRAY_SIZE(pf_info), pfdentry, minor); 186 + pf_add_config_attrs(gt, pfdentry, PFID); 187 + 188 + for (n = 1; n <= totalvfs; n++) { 189 + /* 190 + * /sys/kernel/debug/dri/0/ 191 + * ├── gt0 192 + * │   ├── vf1 193 + * │   ├── vf2 194 + */ 195 + snprintf(buf, sizeof(buf), "vf%u", n); 196 + vfdentry = debugfs_create_dir(buf, root); 197 + if (IS_ERR(vfdentry)) 198 + break; 199 + vfdentry->d_inode->i_private = (void *)(uintptr_t)n; 200 + 201 + pf_add_config_attrs(gt, vfdentry, VFID(n)); 202 + } 203 + }
+18
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2023-2024 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_GT_SRIOV_PF_DEBUGFS_H_ 7 + #define _XE_GT_SRIOV_PF_DEBUGFS_H_ 8 + 9 + struct xe_gt; 10 + struct dentry; 11 + 12 + #ifdef CONFIG_PCI_IOV 13 + void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root); 14 + #else 15 + static inline void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) { } 16 + #endif 17 + 18 + #endif