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