1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include <linux/debugfs.h> 7 #include <drm/drm_debugfs.h> 8 9 #include "xe_device.h" 10 #include "xe_device_types.h" 11 #include "xe_gt_sriov_pf_config.h" 12 #include "xe_gt_sriov_pf_debugfs.h" 13 #include "xe_pm.h" 14 #include "xe_tile_debugfs.h" 15 #include "xe_tile_sriov_pf_debugfs.h" 16 #include "xe_sriov.h" 17 #include "xe_sriov_pf.h" 18 19 /* 20 * /sys/kernel/debug/dri/BDF/ 21 * ├── sriov # d_inode->i_private = (xe_device*) 22 * │ ├── pf # d_inode->i_private = (xe_device*) 23 * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 24 * │ │ ├── tile1 25 * │ │ : : 26 * │ ├── vf1 # d_inode->i_private = VFID(1) 27 * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 28 * │ │ ├── tile1 29 * │ │ : : 30 * │ ├── vfN # d_inode->i_private = VFID(N) 31 * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 32 * │ │ ├── tile1 33 * : : : : 34 */ 35 36 static void *extract_priv(struct dentry *d) 37 { 38 return d->d_inode->i_private; 39 } 40 41 __maybe_unused 42 static struct xe_tile *extract_tile(struct dentry *d) 43 { 44 return extract_priv(d); 45 } 46 47 static struct xe_device *extract_xe(struct dentry *d) 48 { 49 return extract_priv(d->d_parent->d_parent); 50 } 51 52 __maybe_unused 53 static unsigned int extract_vfid(struct dentry *d) 54 { 55 void *pp = extract_priv(d->d_parent); 56 57 return pp == extract_xe(d) ? PFID : (uintptr_t)pp; 58 } 59 60 /* 61 * /sys/kernel/debug/dri/BDF/ 62 * ├── sriov 63 * : ├── pf 64 * : ├── tile0 65 * : ├── ggtt_available 66 * ├── ggtt_provisioned 67 */ 68 69 static int pf_config_print_available_ggtt(struct xe_tile *tile, struct drm_printer *p) 70 { 71 return xe_gt_sriov_pf_config_print_available_ggtt(tile->primary_gt, p); 72 } 73 74 static int pf_config_print_ggtt(struct xe_tile *tile, struct drm_printer *p) 75 { 76 return xe_gt_sriov_pf_config_print_ggtt(tile->primary_gt, p); 77 } 78 79 static const struct drm_info_list pf_ggtt_info[] = { 80 { 81 "ggtt_available", 82 .show = xe_tile_debugfs_simple_show, 83 .data = pf_config_print_available_ggtt, 84 }, 85 { 86 "ggtt_provisioned", 87 .show = xe_tile_debugfs_simple_show, 88 .data = pf_config_print_ggtt, 89 }, 90 }; 91 92 /* 93 * /sys/kernel/debug/dri/BDF/ 94 * ├── sriov 95 * : ├── pf 96 * : ├── tile0 97 * : ├── vram_provisioned 98 */ 99 100 static int pf_config_print_vram(struct xe_tile *tile, struct drm_printer *p) 101 { 102 return xe_gt_sriov_pf_config_print_lmem(tile->primary_gt, p); 103 } 104 105 static const struct drm_info_list pf_vram_info[] = { 106 { 107 "vram_provisioned", 108 .show = xe_tile_debugfs_simple_show, 109 .data = pf_config_print_vram, 110 }, 111 }; 112 113 /* 114 * /sys/kernel/debug/dri/BDF/ 115 * ├── sriov 116 * │ ├── pf 117 * │ │ ├── tile0 118 * │ │ │ ├── ggtt_spare 119 * │ │ │ ├── vram_spare 120 * │ │ ├── tile1 121 * │ │ : : 122 * │ ├── vf1 123 * │ : ├── tile0 124 * │ │ ├── ggtt_quota 125 * │ │ ├── vram_quota 126 * │ ├── tile1 127 * │ : : 128 */ 129 130 #define DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(NAME, CONFIG, TYPE, FORMAT) \ 131 \ 132 static int NAME##_set(void *data, u64 val) \ 133 { \ 134 struct xe_tile *tile = extract_tile(data); \ 135 unsigned int vfid = extract_vfid(data); \ 136 struct xe_gt *gt = tile->primary_gt; \ 137 struct xe_device *xe = tile->xe; \ 138 int err; \ 139 \ 140 if (val > (TYPE)~0ull) \ 141 return -EOVERFLOW; \ 142 \ 143 xe_pm_runtime_get(xe); \ 144 err = xe_sriov_pf_wait_ready(xe) ?: \ 145 xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \ 146 xe_pm_runtime_put(xe); \ 147 \ 148 return err; \ 149 } \ 150 \ 151 static int NAME##_get(void *data, u64 *val) \ 152 { \ 153 struct xe_tile *tile = extract_tile(data); \ 154 unsigned int vfid = extract_vfid(data); \ 155 struct xe_gt *gt = tile->primary_gt; \ 156 \ 157 *val = xe_gt_sriov_pf_config_get_##CONFIG(gt, vfid); \ 158 return 0; \ 159 } \ 160 \ 161 DEFINE_DEBUGFS_ATTRIBUTE(NAME##_fops, NAME##_get, NAME##_set, FORMAT) 162 163 DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, ggtt, u64, "%llu\n"); 164 DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(vram, lmem, u64, "%llu\n"); 165 166 static void pf_add_config_attrs(struct xe_tile *tile, struct dentry *dent, unsigned int vfid) 167 { 168 xe_tile_assert(tile, tile == extract_tile(dent)); 169 xe_tile_assert(tile, vfid == extract_vfid(dent)); 170 171 debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare", 172 0644, dent, dent, &ggtt_fops); 173 if (xe_device_has_lmtt(tile->xe)) 174 debugfs_create_file_unsafe(vfid ? "vram_quota" : "vram_spare", 175 0644, dent, dent, &vram_fops); 176 } 177 178 static void pf_populate_tile(struct xe_tile *tile, struct dentry *dent, unsigned int vfid) 179 { 180 struct xe_device *xe = tile->xe; 181 struct drm_minor *minor = xe->drm.primary; 182 struct xe_gt *gt; 183 unsigned int id; 184 185 pf_add_config_attrs(tile, dent, vfid); 186 187 if (!vfid) { 188 drm_debugfs_create_files(pf_ggtt_info, 189 ARRAY_SIZE(pf_ggtt_info), 190 dent, minor); 191 if (xe_device_has_lmtt(xe)) 192 drm_debugfs_create_files(pf_vram_info, 193 ARRAY_SIZE(pf_vram_info), 194 dent, minor); 195 } 196 197 for_each_gt_on_tile(gt, tile, id) 198 xe_gt_sriov_pf_debugfs_populate(gt, dent, vfid); 199 } 200 201 /** 202 * xe_tile_sriov_pf_debugfs_populate() - Populate SR-IOV debugfs tree with tile files. 203 * @tile: the &xe_tile to register 204 * @parent: the parent &dentry that represents the SR-IOV @vfid function 205 * @vfid: the VF identifier 206 * 207 * Add to the @parent directory new debugfs directory that will represent a @tile and 208 * populate it with files that are related to the SR-IOV @vfid function. 209 * 210 * This function can only be called on PF. 211 */ 212 void xe_tile_sriov_pf_debugfs_populate(struct xe_tile *tile, struct dentry *parent, 213 unsigned int vfid) 214 { 215 struct xe_device *xe = tile->xe; 216 struct dentry *dent; 217 char name[10]; /* should be enough up to "tile%u\0" for 2^16 - 1 */ 218 219 xe_tile_assert(tile, IS_SRIOV_PF(xe)); 220 xe_tile_assert(tile, extract_priv(parent->d_parent) == xe); 221 xe_tile_assert(tile, extract_priv(parent) == tile->xe || 222 (uintptr_t)extract_priv(parent) == vfid); 223 224 /* 225 * /sys/kernel/debug/dri/BDF/ 226 * ├── sriov 227 * │ ├── pf # parent, d_inode->i_private = (xe_device*) 228 * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 229 * │ │ ├── tile1 230 * │ │ : : 231 * │ ├── vf1 # parent, d_inode->i_private = VFID(1) 232 * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 233 * │ │ ├── tile1 234 * : : : : 235 */ 236 snprintf(name, sizeof(name), "tile%u", tile->id); 237 dent = debugfs_create_dir(name, parent); 238 if (IS_ERR(dent)) 239 return; 240 dent->d_inode->i_private = tile; 241 242 xe_tile_assert(tile, extract_tile(dent) == tile); 243 xe_tile_assert(tile, extract_vfid(dent) == vfid); 244 xe_tile_assert(tile, extract_xe(dent) == xe); 245 246 pf_populate_tile(tile, dent, vfid); 247 } 248