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

drm/xe/pf: Add sysfs device symlinks to enabled VFs

For convenience, for every enabled VF add 'device' symlink from
our SR-IOV admin VF folder to enabled sysfs PCI VF device entry.
Remove all those links when disabling PCI VFs.

For completeness, add static 'device' symlink for the PF itself.

/sys/bus/pci/drivers/xe/BDF/sriov_admin/
├── pf
│   └── device -> ../../../BDF # PF BDF
├── vf1
│   └── device -> ../../../BDF' # VF1 BDF
├── vf2
│   └── device -> ../../../BDF" # VF2 BDF

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://patch.msgid.link/20251030222348.186658-16-michal.wajdeczko@intel.com

+101
+5
drivers/gpu/drm/xe/xe_pci_sriov.c
··· 20 20 #include "xe_sriov_pf_control.h" 21 21 #include "xe_sriov_pf_helpers.h" 22 22 #include "xe_sriov_pf_provision.h" 23 + #include "xe_sriov_pf_sysfs.h" 23 24 #include "xe_sriov_printk.h" 24 25 25 26 static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) ··· 139 138 xe_sriov_info(xe, "Enabled %u of %u VF%s\n", 140 139 num_vfs, total_vfs, str_plural(total_vfs)); 141 140 141 + xe_sriov_pf_sysfs_link_vfs(xe, num_vfs); 142 + 142 143 pf_engine_activity_stats(xe, num_vfs, true); 143 144 144 145 return num_vfs; ··· 167 164 return 0; 168 165 169 166 pf_engine_activity_stats(xe, num_vfs, false); 167 + 168 + xe_sriov_pf_sysfs_unlink_vfs(xe, num_vfs); 170 169 171 170 pci_disable_sriov(pdev); 172 171
+93
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
··· 9 9 #include <drm/drm_managed.h> 10 10 11 11 #include "xe_assert.h" 12 + #include "xe_pci_sriov.h" 12 13 #include "xe_pm.h" 13 14 #include "xe_sriov.h" 14 15 #include "xe_sriov_pf.h" ··· 46 45 * │ └── sched_priority 47 46 * ├── pf/ 48 47 * │ ├── ... 48 + * │ ├── device -> ../../../BDF 49 49 * │ └── profile 50 50 * │ ├── exec_quantum_ms 51 51 * │ ├── preempt_timeout_us 52 52 * │ └── sched_priority 53 53 * ├── vf1/ 54 54 * │ ├── ... 55 + * │ ├── device -> ../../../BDF.1 55 56 * │ └── profile 56 57 * │ ├── exec_quantum_ms 57 58 * │ ├── preempt_timeout_us ··· 417 414 return err; 418 415 } 419 416 417 + static void pf_sysfs_note(struct xe_device *xe, int err, const char *what) 418 + { 419 + xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 420 + } 421 + 420 422 static void action_put_kobject(void *arg) 421 423 { 422 424 struct kobject *kobj = arg; ··· 488 480 return 0; 489 481 } 490 482 483 + static void action_rm_device_link(void *arg) 484 + { 485 + struct kobject *kobj = arg; 486 + 487 + sysfs_remove_link(kobj, "device"); 488 + } 489 + 490 + static int pf_link_pf_device(struct xe_device *xe) 491 + { 492 + struct kobject *kobj = xe->sriov.pf.vfs[PFID].kobj; 493 + int err; 494 + 495 + err = sysfs_create_link(kobj, &xe->drm.dev->kobj, "device"); 496 + if (err) 497 + return pf_sysfs_error(xe, err, "PF device link"); 498 + 499 + err = devm_add_action_or_reset(xe->drm.dev, action_rm_device_link, kobj); 500 + if (err) 501 + return pf_sysfs_error(xe, err, "PF unlink action"); 502 + 503 + return 0; 504 + } 505 + 491 506 /** 492 507 * xe_sriov_pf_sysfs_init() - Setup PF's SR-IOV sysfs tree. 493 508 * @xe: the PF &xe_device to setup sysfs ··· 532 501 if (err) 533 502 return err; 534 503 504 + err = pf_link_pf_device(xe); 505 + if (err) 506 + return err; 507 + 535 508 return 0; 509 + } 510 + 511 + /** 512 + * xe_sriov_pf_sysfs_link_vfs() - Add VF's links in SR-IOV sysfs tree. 513 + * @xe: the &xe_device where to update sysfs 514 + * @num_vfs: number of enabled VFs to link 515 + * 516 + * This function is specific for the PF driver. 517 + * 518 + * This function will add symbolic links between VFs represented in the SR-IOV 519 + * sysfs tree maintained by the PF and enabled VF PCI devices. 520 + * 521 + * The @xe_sriov_pf_sysfs_unlink_vfs() shall be used to remove those links. 522 + */ 523 + void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs) 524 + { 525 + unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 526 + struct pci_dev *pf_pdev = to_pci_dev(xe->drm.dev); 527 + struct pci_dev *vf_pdev = NULL; 528 + unsigned int n; 529 + int err; 530 + 531 + xe_assert(xe, IS_SRIOV_PF(xe)); 532 + xe_assert(xe, num_vfs <= totalvfs); 533 + 534 + for (n = 1; n <= num_vfs; n++) { 535 + vf_pdev = xe_pci_sriov_get_vf_pdev(pf_pdev, VFID(n)); 536 + if (!vf_pdev) 537 + return pf_sysfs_note(xe, -ENOENT, "VF link"); 538 + 539 + err = sysfs_create_link(xe->sriov.pf.vfs[VFID(n)].kobj, 540 + &vf_pdev->dev.kobj, "device"); 541 + 542 + /* must balance xe_pci_sriov_get_vf_pdev() */ 543 + pci_dev_put(vf_pdev); 544 + 545 + if (err) 546 + return pf_sysfs_note(xe, err, "VF link"); 547 + } 548 + } 549 + 550 + /** 551 + * xe_sriov_pf_sysfs_unlink_vfs() - Remove VF's links from SR-IOV sysfs tree. 552 + * @xe: the &xe_device where to update sysfs 553 + * @num_vfs: number of VFs to unlink 554 + * 555 + * This function shall be called only on the PF. 556 + * This function will remove "device" links added by @xe_sriov_sysfs_link_vfs(). 557 + */ 558 + void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs) 559 + { 560 + unsigned int n; 561 + 562 + xe_assert(xe, IS_SRIOV_PF(xe)); 563 + xe_assert(xe, num_vfs <= xe_sriov_pf_get_totalvfs(xe)); 564 + 565 + for (n = 1; n <= num_vfs; n++) 566 + sysfs_remove_link(xe->sriov.pf.vfs[VFID(n)].kobj, "device"); 536 567 }
+3
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.h
··· 10 10 11 11 int xe_sriov_pf_sysfs_init(struct xe_device *xe); 12 12 13 + void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs); 14 + void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs); 15 + 13 16 #endif