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

drm/xe/pf: Move SR-IOV GT debugfs files to new tree

Instead of expanding GT debugfs directories with large number of
SR-IOV files, as those are replicated per each SR-IOV function,
move them to our new debugfs tree, organized by the function.

But to avoid breaking IGT tests that use current layout, provide
symlinks which could be removed once transition period is over,
or we can we can leave them for convenience.

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/20250928140029.198847-5-michal.wajdeczko@intel.com

+234 -135
+220 -135
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c
··· 25 25 #include "xe_sriov_pf.h" 26 26 27 27 /* 28 - * /sys/kernel/debug/dri/0/ 29 - * ├── gt0 # d_inode->i_private = gt 30 - * │   ├── pf # d_inode->i_private = gt 31 - * │   ├── vf1 # d_inode->i_private = VFID(1) 32 - * :   : 33 - * │   ├── vfN # d_inode->i_private = VFID(N) 28 + * /sys/kernel/debug/dri/BDF/ 29 + * ├── sriov # d_inode->i_private = (xe_device*) 30 + * │ ├── pf # d_inode->i_private = (xe_device*) 31 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 32 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 33 + * │ │ │ ├── gt1 # d_inode->i_private = (xe_gt*) 34 + * │ │ ├── tile1 35 + * │ │ │ : 36 + * │ ├── vf1 # d_inode->i_private = VFID(1) 37 + * │ │ ├── tile0 # d_inode->i_private = (xe_tile*) 38 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 39 + * │ │ │ ├── gt1 # d_inode->i_private = (xe_gt*) 40 + * │ │ ├── tile1 41 + * │ │ │ : 42 + * : : 43 + * │ ├── vfN # d_inode->i_private = VFID(N) 34 44 */ 35 45 36 46 static void *extract_priv(struct dentry *d) ··· 50 40 51 41 static struct xe_gt *extract_gt(struct dentry *d) 52 42 { 53 - return extract_priv(d->d_parent); 43 + return extract_priv(d); 44 + } 45 + 46 + static struct xe_device *extract_xe(struct dentry *d) 47 + { 48 + return extract_priv(d->d_parent->d_parent->d_parent); 54 49 } 55 50 56 51 static unsigned int extract_vfid(struct dentry *d) 57 52 { 58 - return extract_priv(d) == extract_gt(d) ? PFID : (uintptr_t)extract_priv(d); 53 + void *priv = extract_priv(d->d_parent->d_parent); 54 + 55 + return priv == extract_xe(d) ? PFID : (uintptr_t)priv; 59 56 } 60 57 61 58 /* 62 - * /sys/kernel/debug/dri/0/ 63 - * ├── gt0 64 - * │   ├── pf 65 - * │   │   ├── contexts_provisioned 66 - * │   │   ├── doorbells_provisioned 67 - * │   │   ├── runtime_registers 68 - * │   │   ├── negotiated_versions 69 - * │   │   ├── adverse_events 70 - * ├── gt1 71 - * │   ├── pf 72 - * │   │   ├── ... 59 + * /sys/kernel/debug/dri/BDF/ 60 + * ├── sriov 61 + * : ├── pf 62 + * : ├── tile0 63 + * : ├── gt0 64 + * : ├── contexts_provisioned 65 + * ├── doorbells_provisioned 66 + * ├── runtime_registers 67 + * ├── adverse_events 73 68 */ 74 69 75 70 static const struct drm_info_list pf_info[] = { ··· 101 86 }; 102 87 103 88 /* 104 - * /sys/kernel/debug/dri/0/ 105 - * ├── gt0 106 - * │   ├── pf 107 - * │   │   ├── ggtt_available 108 - * │   │   ├── ggtt_provisioned 89 + * /sys/kernel/debug/dri/BDF/ 90 + * ├── sriov 91 + * : ├── pf 92 + * : ├── tile0 93 + * : ├── gt0 94 + * : ├── ggtt_available 95 + * ├── ggtt_provisioned 109 96 */ 110 97 111 98 static const struct drm_info_list pf_ggtt_info[] = { ··· 124 107 }; 125 108 126 109 /* 127 - * /sys/kernel/debug/dri/0/ 128 - * ├── gt0 129 - * │   ├── pf 130 - * │   │   ├── lmem_provisioned 110 + * /sys/kernel/debug/dri/BDF/ 111 + * ├── sriov 112 + * : ├── pf 113 + * : ├── tile0 114 + * : ├── gt0 115 + * : ├── lmem_provisioned 131 116 */ 132 117 133 118 static const struct drm_info_list pf_lmem_info[] = { ··· 141 122 }; 142 123 143 124 /* 144 - * /sys/kernel/debug/dri/0/ 145 - * ├── gt0 146 - * │   ├── pf 147 - * │   │   ├── reset_engine 148 - * │   │   ├── sample_period 149 - * │   │   ├── sched_if_idle 125 + * /sys/kernel/debug/dri/BDF/ 126 + * ├── sriov 127 + * : ├── pf 128 + * : ├── tile0 129 + * : ├── gt0 130 + * : ├── reset_engine 131 + * ├── sample_period 132 + * ├── sched_if_idle 150 133 */ 151 134 152 135 #define DEFINE_SRIOV_GT_POLICY_DEBUGFS_ATTRIBUTE(POLICY, TYPE, FORMAT) \ ··· 194 173 } 195 174 196 175 /* 197 - * /sys/kernel/debug/dri/0/ 198 - * ├── gt0 199 - * │   ├── pf 200 - * │   │   ├── ggtt_spare 201 - * │   │   ├── lmem_spare 202 - * │   │   ├── doorbells_spare 203 - * │   │   ├── contexts_spare 204 - * │   │   ├── exec_quantum_ms 205 - * │   │   ├── preempt_timeout_us 206 - * │   │   ├── sched_priority 207 - * │   ├── vf1 208 - * │   │   ├── ggtt_quota 209 - * │   │   ├── lmem_quota 210 - * │   │   ├── doorbells_quota 211 - * │   │   ├── contexts_quota 212 - * │   │   ├── exec_quantum_ms 213 - * │   │   ├── preempt_timeout_us 214 - * │   │   ├── sched_priority 176 + * /sys/kernel/debug/dri/BDF/ 177 + * ├── sriov 178 + * : ├── pf 179 + * │ ├── tile0 180 + * │ : ├── gt0 181 + * │ : ├── ggtt_spare 182 + * │ ├── lmem_spare 183 + * │ ├── doorbells_spare 184 + * │ ├── contexts_spare 185 + * │ ├── exec_quantum_ms 186 + * │ ├── preempt_timeout_us 187 + * │ ├── sched_priority 188 + * ├── vf1 189 + * : ├── tile0 190 + * : ├── gt0 191 + * : ├── ggtt_quota 192 + * ├── lmem_quota 193 + * ├── doorbells_quota 194 + * ├── contexts_quota 195 + * ├── exec_quantum_ms 196 + * ├── preempt_timeout_us 197 + * ├── sched_priority 215 198 */ 216 199 217 200 #define DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(CONFIG, TYPE, FORMAT) \ ··· 258 233 DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(sched_priority, u32, "%llu\n"); 259 234 260 235 /* 261 - * /sys/kernel/debug/dri/0/ 262 - * ├── gt0 263 - * │   ├── pf 264 - * │   │   ├── threshold_cat_error_count 265 - * │   │   ├── threshold_doorbell_time_us 266 - * │   │   ├── threshold_engine_reset_count 267 - * │   │   ├── threshold_guc_time_us 268 - * │   │   ├── threshold_irq_time_us 269 - * │   │   ├── threshold_page_fault_count 270 - * │   ├── vf1 271 - * │   │   ├── threshold_cat_error_count 272 - * │   │   ├── threshold_doorbell_time_us 273 - * │   │   ├── threshold_engine_reset_count 274 - * │   │   ├── threshold_guc_time_us 275 - * │   │   ├── threshold_irq_time_us 276 - * │   │   ├── threshold_page_fault_count 236 + * /sys/kernel/debug/dri/BDF/ 237 + * ├── sriov 238 + * : ├── pf 239 + * │ ├── tile0 240 + * │ : ├── gt0 241 + * │ : ├── threshold_cat_error_count 242 + * │ ├── threshold_doorbell_time_us 243 + * │ ├── threshold_engine_reset_count 244 + * │ ├── threshold_guc_time_us 245 + * │ ├── threshold_irq_time_us 246 + * │ ├── threshold_page_fault_count 247 + * ├── vf1 248 + * : ├── tile0 249 + * : ├── gt0 250 + * : ├── threshold_cat_error_count 251 + * ├── threshold_doorbell_time_us 252 + * ├── threshold_engine_reset_count 253 + * ├── threshold_guc_time_us 254 + * ├── threshold_irq_time_us 255 + * ├── threshold_page_fault_count 277 256 */ 278 257 279 258 static int set_threshold(void *data, u64 val, enum xe_guc_klv_threshold_index index) ··· 358 329 } 359 330 360 331 /* 361 - * /sys/kernel/debug/dri/0/ 362 - * ├── gt0 363 - * │   ├── vf1 364 - * │   │   ├── control { stop, pause, resume } 332 + * /sys/kernel/debug/dri/BDF/ 333 + * ├── sriov 334 + * : ├── vf1 335 + * : ├── tile0 336 + * : ├── gt0 337 + * : ├── control { stop, pause, resume } 365 338 */ 366 339 367 340 static const struct { ··· 440 409 }; 441 410 442 411 /* 443 - * /sys/kernel/debug/dri/0/ 444 - * ├── gt0 445 - * │   ├── vf1 446 - * │   │   ├── guc_state 412 + * /sys/kernel/debug/dri/BDF/ 413 + * ├── sriov 414 + * : ├── vf1 415 + * : ├── tile0 416 + * : ├── gt0 417 + * : ├── guc_state 447 418 */ 419 + 448 420 static ssize_t guc_state_read(struct file *file, char __user *buf, 449 421 size_t count, loff_t *pos) 450 422 { ··· 481 447 }; 482 448 483 449 /* 484 - * /sys/kernel/debug/dri/0/ 485 - * ├── gt0 486 - * │   ├── vf1 487 - * │   │   ├── config_blob 450 + * /sys/kernel/debug/dri/BDF/ 451 + * ├── sriov 452 + * : ├── vf1 453 + * : ├── tile0 454 + * : ├── gt0 455 + * : ├── config_blob 488 456 */ 457 + 489 458 static ssize_t config_blob_read(struct file *file, char __user *buf, 490 459 size_t count, loff_t *pos) 491 460 { ··· 558 521 .llseek = default_llseek, 559 522 }; 560 523 561 - /** 562 - * xe_gt_sriov_pf_debugfs_register - Register SR-IOV PF specific entries in GT debugfs. 563 - * @gt: the &xe_gt to register 564 - * @root: the &dentry that represents the GT directory 565 - * 566 - * Register SR-IOV PF entries that are GT related and must be shown under GT debugfs. 567 - */ 568 - void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) 524 + static void pf_populate_gt(struct xe_gt *gt, struct dentry *dent, unsigned int vfid) 569 525 { 570 526 struct xe_device *xe = gt_to_xe(gt); 571 527 struct drm_minor *minor = xe->drm.primary; 572 - int n, totalvfs = xe_sriov_pf_get_totalvfs(xe); 573 - struct dentry *pfdentry; 574 - struct dentry *vfdentry; 575 - char buf[14]; /* should be enough up to "vf%u\0" for 2^32 - 1 */ 576 528 577 - xe_gt_assert(gt, IS_SRIOV_PF(xe)); 578 - xe_gt_assert(gt, root->d_inode->i_private == gt); 529 + if (vfid) { 530 + pf_add_config_attrs(gt, dent, vfid); 579 531 580 - /* 581 - * /sys/kernel/debug/dri/0/ 582 - * ├── gt0 583 - * │   ├── pf 584 - */ 585 - pfdentry = debugfs_create_dir("pf", root); 586 - if (IS_ERR(pfdentry)) 587 - return; 588 - pfdentry->d_inode->i_private = gt; 589 - 590 - drm_debugfs_create_files(pf_info, ARRAY_SIZE(pf_info), pfdentry, minor); 591 - if (xe_gt_is_main_type(gt)) { 592 - drm_debugfs_create_files(pf_ggtt_info, 593 - ARRAY_SIZE(pf_ggtt_info), 594 - pfdentry, minor); 595 - if (xe_device_has_lmtt(gt_to_xe(gt))) 596 - drm_debugfs_create_files(pf_lmem_info, 597 - ARRAY_SIZE(pf_lmem_info), 598 - pfdentry, minor); 599 - } 600 - 601 - pf_add_policy_attrs(gt, pfdentry); 602 - pf_add_config_attrs(gt, pfdentry, PFID); 603 - 604 - for (n = 1; n <= totalvfs; n++) { 605 - /* 606 - * /sys/kernel/debug/dri/0/ 607 - * ├── gt0 608 - * │   ├── vf1 609 - * │   ├── vf2 610 - */ 611 - snprintf(buf, sizeof(buf), "vf%u", n); 612 - vfdentry = debugfs_create_dir(buf, root); 613 - if (IS_ERR(vfdentry)) 614 - break; 615 - vfdentry->d_inode->i_private = (void *)(uintptr_t)n; 616 - 617 - pf_add_config_attrs(gt, vfdentry, VFID(n)); 618 - debugfs_create_file("control", 0600, vfdentry, NULL, &control_ops); 532 + debugfs_create_file("control", 0600, dent, NULL, &control_ops); 619 533 620 534 /* for testing/debugging purposes only! */ 621 535 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) { 622 536 debugfs_create_file("guc_state", 623 537 IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ? 0600 : 0400, 624 - vfdentry, NULL, &guc_state_ops); 538 + dent, NULL, &guc_state_ops); 625 539 debugfs_create_file("config_blob", 626 540 IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ? 0600 : 0400, 627 - vfdentry, NULL, &config_blob_ops); 541 + dent, NULL, &config_blob_ops); 542 + } 543 + 544 + } else { 545 + pf_add_config_attrs(gt, dent, PFID); 546 + pf_add_policy_attrs(gt, dent); 547 + 548 + drm_debugfs_create_files(pf_info, ARRAY_SIZE(pf_info), dent, minor); 549 + 550 + if (xe_gt_is_main_type(gt)) { 551 + drm_debugfs_create_files(pf_ggtt_info, 552 + ARRAY_SIZE(pf_ggtt_info), 553 + dent, minor); 554 + if (xe_device_has_lmtt(xe)) 555 + drm_debugfs_create_files(pf_lmem_info, 556 + ARRAY_SIZE(pf_lmem_info), 557 + dent, minor); 628 558 } 629 559 } 560 + } 561 + 562 + /** 563 + * xe_gt_sriov_pf_debugfs_populate() - Create SR-IOV GT-level debugfs directories and files. 564 + * @gt: the &xe_gt to register 565 + * @parent: the parent &dentry that represents a &xe_tile 566 + * @vfid: the VF identifier 567 + * 568 + * Add to the @parent directory new debugfs directory that will represent a @gt and 569 + * populate it with GT files that are related to the SR-IOV @vfid function. 570 + * 571 + * This function can only be called on PF. 572 + */ 573 + void xe_gt_sriov_pf_debugfs_populate(struct xe_gt *gt, struct dentry *parent, unsigned int vfid) 574 + { 575 + struct dentry *dent; 576 + char name[8]; /* should be enough up to "gt%u\0" for 2^8 - 1 */ 577 + 578 + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 579 + xe_gt_assert(gt, extract_priv(parent) == gt->tile); 580 + xe_gt_assert(gt, extract_priv(parent->d_parent) == gt_to_xe(gt) || 581 + (uintptr_t)extract_priv(parent->d_parent) == vfid); 582 + 583 + /* 584 + * /sys/kernel/debug/dri/BDF/ 585 + * ├── sriov 586 + * │ ├── pf 587 + * │ │ ├── tile0 # parent 588 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 589 + * │ │ │ ├── gt1 590 + * │ │ : : 591 + * │ ├── vf1 592 + * │ │ ├── tile0 # parent 593 + * │ │ │ ├── gt0 # d_inode->i_private = (xe_gt*) 594 + * │ │ │ ├── gt1 595 + * │ : : : 596 + */ 597 + snprintf(name, sizeof(name), "gt%u", gt->info.id); 598 + dent = debugfs_create_dir(name, parent); 599 + if (IS_ERR(dent)) 600 + return; 601 + dent->d_inode->i_private = gt; 602 + 603 + xe_gt_assert(gt, extract_gt(dent) == gt); 604 + xe_gt_assert(gt, extract_vfid(dent) == vfid); 605 + 606 + pf_populate_gt(gt, dent, vfid); 607 + } 608 + 609 + static void pf_add_links(struct xe_gt *gt, struct dentry *dent) 610 + { 611 + unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); 612 + unsigned int vfid; 613 + char name[16]; /* should be more than enough for "vf%u\0" and VFID(UINT_MAX) */ 614 + char symlink[64]; /* should be more enough for "../../sriov/vf%u/tile%u/gt%u\0" */ 615 + 616 + for (vfid = 0; vfid <= totalvfs; vfid++) { 617 + if (vfid) 618 + snprintf(name, sizeof(name), "vf%u", vfid); 619 + else 620 + snprintf(name, sizeof(name), "pf"); 621 + snprintf(symlink, sizeof(symlink), "../../sriov/%s/tile%u/gt%u", 622 + name, gt->tile->id, gt->info.id); 623 + debugfs_create_symlink(name, dent, symlink); 624 + } 625 + } 626 + 627 + /** 628 + * xe_gt_sriov_pf_debugfs_register - Register SR-IOV PF specific entries in GT debugfs. 629 + * @gt: the &xe_gt to register 630 + * @dent: the &dentry that represents the GT directory 631 + * 632 + * Instead of actual files, create symlinks for PF and each VF to their GT specific 633 + * attributes that should be already exposed in the dedicated debugfs SR-IOV tree. 634 + */ 635 + void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *dent) 636 + { 637 + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 638 + xe_gt_assert(gt, dent->d_inode->i_private == gt); 639 + 640 + pf_add_links(gt, dent); 630 641 }
+1
drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.h
··· 11 11 12 12 #ifdef CONFIG_PCI_IOV 13 13 void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root); 14 + void xe_gt_sriov_pf_debugfs_populate(struct xe_gt *gt, struct dentry *parent, unsigned int vfid); 14 15 #else 15 16 static inline void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) { } 16 17 #endif
+13
drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c
··· 6 6 #include <linux/debugfs.h> 7 7 #include <drm/drm_debugfs.h> 8 8 9 + #include "xe_device.h" 9 10 #include "xe_device_types.h" 11 + #include "xe_gt_sriov_pf_debugfs.h" 10 12 #include "xe_tile_sriov_pf_debugfs.h" 11 13 #include "xe_sriov.h" 12 14 ··· 51 49 void *pp = extract_priv(d->d_parent); 52 50 53 51 return pp == extract_xe(d) ? PFID : (uintptr_t)pp; 52 + } 53 + 54 + static void pf_populate_tile(struct xe_tile *tile, struct dentry *dent, unsigned int vfid) 55 + { 56 + struct xe_gt *gt; 57 + unsigned int id; 58 + 59 + for_each_gt_on_tile(gt, tile, id) 60 + xe_gt_sriov_pf_debugfs_populate(gt, dent, vfid); 54 61 } 55 62 56 63 /** ··· 106 95 xe_tile_assert(tile, extract_tile(dent) == tile); 107 96 xe_tile_assert(tile, extract_vfid(dent) == vfid); 108 97 xe_tile_assert(tile, extract_xe(dent) == xe); 98 + 99 + pf_populate_tile(tile, dent, vfid); 109 100 }