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

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19-rc2 647 lines 17 kB view raw
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6#include <linux/kobject.h> 7#include <linux/sysfs.h> 8 9#include <drm/drm_managed.h> 10 11#include "xe_assert.h" 12#include "xe_pci_sriov.h" 13#include "xe_pm.h" 14#include "xe_sriov.h" 15#include "xe_sriov_pf.h" 16#include "xe_sriov_pf_control.h" 17#include "xe_sriov_pf_helpers.h" 18#include "xe_sriov_pf_provision.h" 19#include "xe_sriov_pf_sysfs.h" 20#include "xe_sriov_printk.h" 21 22static int emit_choice(char *buf, int choice, const char * const *array, size_t size) 23{ 24 int pos = 0; 25 int n; 26 27 for (n = 0; n < size; n++) { 28 pos += sysfs_emit_at(buf, pos, "%s%s%s%s", 29 n ? " " : "", 30 n == choice ? "[" : "", 31 array[n], 32 n == choice ? "]" : ""); 33 } 34 pos += sysfs_emit_at(buf, pos, "\n"); 35 36 return pos; 37} 38 39/* 40 * /sys/bus/pci/drivers/xe/BDF/ 41 * : 42 * ├── sriov_admin/ 43 * ├── ... 44 * ├── .bulk_profile 45 * │ ├── exec_quantum_ms 46 * │ ├── preempt_timeout_us 47 * │ └── sched_priority 48 * ├── pf/ 49 * │ ├── ... 50 * │ ├── device -> ../../../BDF 51 * │ └── profile 52 * │ ├── exec_quantum_ms 53 * │ ├── preempt_timeout_us 54 * │ └── sched_priority 55 * ├── vf1/ 56 * │ ├── ... 57 * │ ├── device -> ../../../BDF.1 58 * │ ├── stop 59 * │ └── profile 60 * │ ├── exec_quantum_ms 61 * │ ├── preempt_timeout_us 62 * │ └── sched_priority 63 * ├── vf2/ 64 * : 65 * └── vfN/ 66 */ 67 68struct xe_sriov_kobj { 69 struct kobject base; 70 struct xe_device *xe; 71 unsigned int vfid; 72}; 73#define to_xe_sriov_kobj(p) container_of_const((p), struct xe_sriov_kobj, base) 74 75struct xe_sriov_dev_attr { 76 struct attribute attr; 77 ssize_t (*show)(struct xe_device *xe, char *buf); 78 ssize_t (*store)(struct xe_device *xe, const char *buf, size_t count); 79}; 80#define to_xe_sriov_dev_attr(p) container_of_const((p), struct xe_sriov_dev_attr, attr) 81 82#define XE_SRIOV_DEV_ATTR(NAME) \ 83struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 84 __ATTR(NAME, 0644, xe_sriov_dev_attr_##NAME##_show, xe_sriov_dev_attr_##NAME##_store) 85 86#define XE_SRIOV_DEV_ATTR_RO(NAME) \ 87struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 88 __ATTR(NAME, 0444, xe_sriov_dev_attr_##NAME##_show, NULL) 89 90#define XE_SRIOV_DEV_ATTR_WO(NAME) \ 91struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 92 __ATTR(NAME, 0200, NULL, xe_sriov_dev_attr_##NAME##_store) 93 94struct xe_sriov_vf_attr { 95 struct attribute attr; 96 ssize_t (*show)(struct xe_device *xe, unsigned int vfid, char *buf); 97 ssize_t (*store)(struct xe_device *xe, unsigned int vfid, const char *buf, size_t count); 98}; 99#define to_xe_sriov_vf_attr(p) container_of_const((p), struct xe_sriov_vf_attr, attr) 100 101#define XE_SRIOV_VF_ATTR(NAME) \ 102struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 103 __ATTR(NAME, 0644, xe_sriov_vf_attr_##NAME##_show, xe_sriov_vf_attr_##NAME##_store) 104 105#define XE_SRIOV_VF_ATTR_RO(NAME) \ 106struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 107 __ATTR(NAME, 0444, xe_sriov_vf_attr_##NAME##_show, NULL) 108 109#define XE_SRIOV_VF_ATTR_WO(NAME) \ 110struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 111 __ATTR(NAME, 0200, NULL, xe_sriov_vf_attr_##NAME##_store) 112 113/* device level attributes go here */ 114 115#define DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(NAME, ITEM, TYPE) \ 116 \ 117static ssize_t xe_sriov_dev_attr_##NAME##_store(struct xe_device *xe, \ 118 const char *buf, size_t count) \ 119{ \ 120 TYPE value; \ 121 int err; \ 122 \ 123 err = kstrto##TYPE(buf, 0, &value); \ 124 if (err) \ 125 return err; \ 126 \ 127 err = xe_sriov_pf_provision_bulk_apply_##ITEM(xe, value); \ 128 return err ?: count; \ 129} \ 130 \ 131static XE_SRIOV_DEV_ATTR_WO(NAME) 132 133DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(exec_quantum_ms, eq, u32); 134DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(preempt_timeout_us, pt, u32); 135 136static const char * const sched_priority_names[] = { 137 [GUC_SCHED_PRIORITY_LOW] = "low", 138 [GUC_SCHED_PRIORITY_NORMAL] = "normal", 139 [GUC_SCHED_PRIORITY_HIGH] = "high", 140}; 141 142static bool sched_priority_change_allowed(unsigned int vfid) 143{ 144 /* As of today GuC FW allows to selectively change only the PF priority. */ 145 return vfid == PFID; 146} 147 148static bool sched_priority_high_allowed(unsigned int vfid) 149{ 150 /* As of today GuC FW allows to select 'high' priority only for the PF. */ 151 return vfid == PFID; 152} 153 154static bool sched_priority_bulk_high_allowed(struct xe_device *xe) 155{ 156 /* all VFs are equal - it's sufficient to check VF1 only */ 157 return sched_priority_high_allowed(VFID(1)); 158} 159 160static ssize_t xe_sriov_dev_attr_sched_priority_store(struct xe_device *xe, 161 const char *buf, size_t count) 162{ 163 size_t num_priorities = ARRAY_SIZE(sched_priority_names); 164 int match; 165 int err; 166 167 if (!sched_priority_bulk_high_allowed(xe)) 168 num_priorities--; 169 170 match = __sysfs_match_string(sched_priority_names, num_priorities, buf); 171 if (match < 0) 172 return -EINVAL; 173 174 err = xe_sriov_pf_provision_bulk_apply_priority(xe, match); 175 return err ?: count; 176} 177 178static XE_SRIOV_DEV_ATTR_WO(sched_priority); 179 180static struct attribute *bulk_profile_dev_attrs[] = { 181 &xe_sriov_dev_attr_exec_quantum_ms.attr, 182 &xe_sriov_dev_attr_preempt_timeout_us.attr, 183 &xe_sriov_dev_attr_sched_priority.attr, 184 NULL 185}; 186 187static const struct attribute_group bulk_profile_dev_attr_group = { 188 .name = ".bulk_profile", 189 .attrs = bulk_profile_dev_attrs, 190}; 191 192static const struct attribute_group *xe_sriov_dev_attr_groups[] = { 193 &bulk_profile_dev_attr_group, 194 NULL 195}; 196 197/* and VF-level attributes go here */ 198 199#define DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(NAME, ITEM, TYPE, FORMAT) \ 200static ssize_t xe_sriov_vf_attr_##NAME##_show(struct xe_device *xe, unsigned int vfid, \ 201 char *buf) \ 202{ \ 203 TYPE value = 0; \ 204 int err; \ 205 \ 206 err = xe_sriov_pf_provision_query_vf_##ITEM(xe, vfid, &value); \ 207 if (err) \ 208 return err; \ 209 \ 210 return sysfs_emit(buf, FORMAT, value); \ 211} \ 212 \ 213static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 214 const char *buf, size_t count) \ 215{ \ 216 TYPE value; \ 217 int err; \ 218 \ 219 err = kstrto##TYPE(buf, 0, &value); \ 220 if (err) \ 221 return err; \ 222 \ 223 err = xe_sriov_pf_provision_apply_vf_##ITEM(xe, vfid, value); \ 224 return err ?: count; \ 225} \ 226 \ 227static XE_SRIOV_VF_ATTR(NAME) 228 229DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(exec_quantum_ms, eq, u32, "%u\n"); 230DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(preempt_timeout_us, pt, u32, "%u\n"); 231 232static ssize_t xe_sriov_vf_attr_sched_priority_show(struct xe_device *xe, unsigned int vfid, 233 char *buf) 234{ 235 size_t num_priorities = ARRAY_SIZE(sched_priority_names); 236 u32 priority; 237 int err; 238 239 err = xe_sriov_pf_provision_query_vf_priority(xe, vfid, &priority); 240 if (err) 241 return err; 242 243 if (!sched_priority_high_allowed(vfid)) 244 num_priorities--; 245 246 xe_assert(xe, priority < num_priorities); 247 return emit_choice(buf, priority, sched_priority_names, num_priorities); 248} 249 250static ssize_t xe_sriov_vf_attr_sched_priority_store(struct xe_device *xe, unsigned int vfid, 251 const char *buf, size_t count) 252{ 253 size_t num_priorities = ARRAY_SIZE(sched_priority_names); 254 int match; 255 int err; 256 257 if (!sched_priority_change_allowed(vfid)) 258 return -EOPNOTSUPP; 259 260 if (!sched_priority_high_allowed(vfid)) 261 num_priorities--; 262 263 match = __sysfs_match_string(sched_priority_names, num_priorities, buf); 264 if (match < 0) 265 return -EINVAL; 266 267 err = xe_sriov_pf_provision_apply_vf_priority(xe, vfid, match); 268 return err ?: count; 269} 270 271static XE_SRIOV_VF_ATTR(sched_priority); 272 273static struct attribute *profile_vf_attrs[] = { 274 &xe_sriov_vf_attr_exec_quantum_ms.attr, 275 &xe_sriov_vf_attr_preempt_timeout_us.attr, 276 &xe_sriov_vf_attr_sched_priority.attr, 277 NULL 278}; 279 280static umode_t profile_vf_attr_is_visible(struct kobject *kobj, 281 struct attribute *attr, int index) 282{ 283 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 284 285 if (attr == &xe_sriov_vf_attr_sched_priority.attr && 286 !sched_priority_change_allowed(vkobj->vfid)) 287 return attr->mode & 0444; 288 289 return attr->mode; 290} 291 292static const struct attribute_group profile_vf_attr_group = { 293 .name = "profile", 294 .attrs = profile_vf_attrs, 295 .is_visible = profile_vf_attr_is_visible, 296}; 297 298#define DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(NAME) \ 299 \ 300static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 301 const char *buf, size_t count) \ 302{ \ 303 bool yes; \ 304 int err; \ 305 \ 306 if (!vfid) \ 307 return -EPERM; \ 308 \ 309 err = kstrtobool(buf, &yes); \ 310 if (err) \ 311 return err; \ 312 if (!yes) \ 313 return count; \ 314 \ 315 err = xe_sriov_pf_control_##NAME##_vf(xe, vfid); \ 316 return err ?: count; \ 317} \ 318 \ 319static XE_SRIOV_VF_ATTR_WO(NAME) 320 321DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(stop); 322 323static struct attribute *control_vf_attrs[] = { 324 &xe_sriov_vf_attr_stop.attr, 325 NULL 326}; 327 328static umode_t control_vf_attr_is_visible(struct kobject *kobj, 329 struct attribute *attr, int index) 330{ 331 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 332 333 if (vkobj->vfid == PFID) 334 return 0; 335 336 return attr->mode; 337} 338 339static const struct attribute_group control_vf_attr_group = { 340 .attrs = control_vf_attrs, 341 .is_visible = control_vf_attr_is_visible, 342}; 343 344static const struct attribute_group *xe_sriov_vf_attr_groups[] = { 345 &profile_vf_attr_group, 346 &control_vf_attr_group, 347 NULL 348}; 349 350/* no user serviceable parts below */ 351 352static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid) 353{ 354 struct xe_sriov_kobj *vkobj; 355 356 xe_sriov_pf_assert_vfid(xe, vfid); 357 358 vkobj = kzalloc(sizeof(*vkobj), GFP_KERNEL); 359 if (!vkobj) 360 return NULL; 361 362 vkobj->xe = xe; 363 vkobj->vfid = vfid; 364 return &vkobj->base; 365} 366 367static void release_xe_sriov_kobj(struct kobject *kobj) 368{ 369 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 370 371 kfree(vkobj); 372} 373 374static ssize_t xe_sriov_dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 375{ 376 struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); 377 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 378 struct xe_device *xe = vkobj->xe; 379 380 if (!vattr->show) 381 return -EPERM; 382 383 return vattr->show(xe, buf); 384} 385 386static ssize_t xe_sriov_dev_attr_store(struct kobject *kobj, struct attribute *attr, 387 const char *buf, size_t count) 388{ 389 struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); 390 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 391 struct xe_device *xe = vkobj->xe; 392 ssize_t ret; 393 394 if (!vattr->store) 395 return -EPERM; 396 397 xe_pm_runtime_get(xe); 398 ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count); 399 xe_pm_runtime_put(xe); 400 401 return ret; 402} 403 404static ssize_t xe_sriov_vf_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 405{ 406 struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr); 407 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 408 struct xe_device *xe = vkobj->xe; 409 unsigned int vfid = vkobj->vfid; 410 411 xe_sriov_pf_assert_vfid(xe, vfid); 412 413 if (!vattr->show) 414 return -EPERM; 415 416 return vattr->show(xe, vfid, buf); 417} 418 419static ssize_t xe_sriov_vf_attr_store(struct kobject *kobj, struct attribute *attr, 420 const char *buf, size_t count) 421{ 422 struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr); 423 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 424 struct xe_device *xe = vkobj->xe; 425 unsigned int vfid = vkobj->vfid; 426 ssize_t ret; 427 428 xe_sriov_pf_assert_vfid(xe, vfid); 429 430 if (!vattr->store) 431 return -EPERM; 432 433 xe_pm_runtime_get(xe); 434 ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count); 435 xe_pm_runtime_get(xe); 436 437 return ret; 438} 439 440static const struct sysfs_ops xe_sriov_dev_sysfs_ops = { 441 .show = xe_sriov_dev_attr_show, 442 .store = xe_sriov_dev_attr_store, 443}; 444 445static const struct sysfs_ops xe_sriov_vf_sysfs_ops = { 446 .show = xe_sriov_vf_attr_show, 447 .store = xe_sriov_vf_attr_store, 448}; 449 450static const struct kobj_type xe_sriov_dev_ktype = { 451 .release = release_xe_sriov_kobj, 452 .sysfs_ops = &xe_sriov_dev_sysfs_ops, 453 .default_groups = xe_sriov_dev_attr_groups, 454}; 455 456static const struct kobj_type xe_sriov_vf_ktype = { 457 .release = release_xe_sriov_kobj, 458 .sysfs_ops = &xe_sriov_vf_sysfs_ops, 459 .default_groups = xe_sriov_vf_attr_groups, 460}; 461 462static int pf_sysfs_error(struct xe_device *xe, int err, const char *what) 463{ 464 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) 465 xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 466 return err; 467} 468 469static void pf_sysfs_note(struct xe_device *xe, int err, const char *what) 470{ 471 xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 472} 473 474static void action_put_kobject(void *arg) 475{ 476 struct kobject *kobj = arg; 477 478 kobject_put(kobj); 479} 480 481static int pf_setup_root(struct xe_device *xe) 482{ 483 struct kobject *parent = &xe->drm.dev->kobj; 484 struct kobject *root; 485 int err; 486 487 root = create_xe_sriov_kobj(xe, PFID); 488 if (!root) 489 return pf_sysfs_error(xe, -ENOMEM, "root obj"); 490 491 err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root); 492 if (err) 493 return pf_sysfs_error(xe, err, "root action"); 494 495 err = kobject_init_and_add(root, &xe_sriov_dev_ktype, parent, "sriov_admin"); 496 if (err) 497 return pf_sysfs_error(xe, err, "root init"); 498 499 xe_assert(xe, IS_SRIOV_PF(xe)); 500 xe_assert(xe, !xe->sriov.pf.sysfs.root); 501 xe->sriov.pf.sysfs.root = root; 502 return 0; 503} 504 505static int pf_setup_tree(struct xe_device *xe) 506{ 507 unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 508 struct kobject *root, *kobj; 509 unsigned int n; 510 int err; 511 512 xe_assert(xe, IS_SRIOV_PF(xe)); 513 root = xe->sriov.pf.sysfs.root; 514 515 for (n = 0; n <= totalvfs; n++) { 516 kobj = create_xe_sriov_kobj(xe, VFID(n)); 517 if (!kobj) 518 return pf_sysfs_error(xe, -ENOMEM, "tree obj"); 519 520 err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root); 521 if (err) 522 return pf_sysfs_error(xe, err, "tree action"); 523 524 if (n) 525 err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype, 526 root, "vf%u", n); 527 else 528 err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype, 529 root, "pf"); 530 if (err) 531 return pf_sysfs_error(xe, err, "tree init"); 532 533 xe_assert(xe, !xe->sriov.pf.vfs[n].kobj); 534 xe->sriov.pf.vfs[n].kobj = kobj; 535 } 536 537 return 0; 538} 539 540static void action_rm_device_link(void *arg) 541{ 542 struct kobject *kobj = arg; 543 544 sysfs_remove_link(kobj, "device"); 545} 546 547static int pf_link_pf_device(struct xe_device *xe) 548{ 549 struct kobject *kobj = xe->sriov.pf.vfs[PFID].kobj; 550 int err; 551 552 err = sysfs_create_link(kobj, &xe->drm.dev->kobj, "device"); 553 if (err) 554 return pf_sysfs_error(xe, err, "PF device link"); 555 556 err = devm_add_action_or_reset(xe->drm.dev, action_rm_device_link, kobj); 557 if (err) 558 return pf_sysfs_error(xe, err, "PF unlink action"); 559 560 return 0; 561} 562 563/** 564 * xe_sriov_pf_sysfs_init() - Setup PF's SR-IOV sysfs tree. 565 * @xe: the PF &xe_device to setup sysfs 566 * 567 * This function will create additional nodes that will represent PF and VFs 568 * devices, each populated with SR-IOV Xe specific attributes. 569 * 570 * Return: 0 on success or a negative error code on failure. 571 */ 572int xe_sriov_pf_sysfs_init(struct xe_device *xe) 573{ 574 int err; 575 576 err = pf_setup_root(xe); 577 if (err) 578 return err; 579 580 err = pf_setup_tree(xe); 581 if (err) 582 return err; 583 584 err = pf_link_pf_device(xe); 585 if (err) 586 return err; 587 588 return 0; 589} 590 591/** 592 * xe_sriov_pf_sysfs_link_vfs() - Add VF's links in SR-IOV sysfs tree. 593 * @xe: the &xe_device where to update sysfs 594 * @num_vfs: number of enabled VFs to link 595 * 596 * This function is specific for the PF driver. 597 * 598 * This function will add symbolic links between VFs represented in the SR-IOV 599 * sysfs tree maintained by the PF and enabled VF PCI devices. 600 * 601 * The @xe_sriov_pf_sysfs_unlink_vfs() shall be used to remove those links. 602 */ 603void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs) 604{ 605 unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 606 struct pci_dev *pf_pdev = to_pci_dev(xe->drm.dev); 607 struct pci_dev *vf_pdev = NULL; 608 unsigned int n; 609 int err; 610 611 xe_assert(xe, IS_SRIOV_PF(xe)); 612 xe_assert(xe, num_vfs <= totalvfs); 613 614 for (n = 1; n <= num_vfs; n++) { 615 vf_pdev = xe_pci_sriov_get_vf_pdev(pf_pdev, VFID(n)); 616 if (!vf_pdev) 617 return pf_sysfs_note(xe, -ENOENT, "VF link"); 618 619 err = sysfs_create_link(xe->sriov.pf.vfs[VFID(n)].kobj, 620 &vf_pdev->dev.kobj, "device"); 621 622 /* must balance xe_pci_sriov_get_vf_pdev() */ 623 pci_dev_put(vf_pdev); 624 625 if (err) 626 return pf_sysfs_note(xe, err, "VF link"); 627 } 628} 629 630/** 631 * xe_sriov_pf_sysfs_unlink_vfs() - Remove VF's links from SR-IOV sysfs tree. 632 * @xe: the &xe_device where to update sysfs 633 * @num_vfs: number of VFs to unlink 634 * 635 * This function shall be called only on the PF. 636 * This function will remove "device" links added by @xe_sriov_sysfs_link_vfs(). 637 */ 638void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs) 639{ 640 unsigned int n; 641 642 xe_assert(xe, IS_SRIOV_PF(xe)); 643 xe_assert(xe, num_vfs <= xe_sriov_pf_get_totalvfs(xe)); 644 645 for (n = 1; n <= num_vfs; n++) 646 sysfs_remove_link(xe->sriov.pf.vfs[VFID(n)].kobj, "device"); 647}