xref: /linux/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
15c170a4dSMichal Wajdeczko // SPDX-License-Identifier: MIT
25c170a4dSMichal Wajdeczko /*
35c170a4dSMichal Wajdeczko  * Copyright © 2025 Intel Corporation
45c170a4dSMichal Wajdeczko  */
55c170a4dSMichal Wajdeczko 
65c170a4dSMichal Wajdeczko #include <linux/kobject.h>
75c170a4dSMichal Wajdeczko #include <linux/sysfs.h>
85c170a4dSMichal Wajdeczko 
95c170a4dSMichal Wajdeczko #include <drm/drm_managed.h>
105c170a4dSMichal Wajdeczko 
115c170a4dSMichal Wajdeczko #include "xe_assert.h"
1217899358SMichal Wajdeczko #include "xe_pci_sriov.h"
13f9091794SMichal Wajdeczko #include "xe_pm.h"
145c170a4dSMichal Wajdeczko #include "xe_sriov.h"
15f9091794SMichal Wajdeczko #include "xe_sriov_pf.h"
16*79e419c9SMichal Wajdeczko #include "xe_sriov_pf_control.h"
175c170a4dSMichal Wajdeczko #include "xe_sriov_pf_helpers.h"
183f984d70SMichal Wajdeczko #include "xe_sriov_pf_provision.h"
195c170a4dSMichal Wajdeczko #include "xe_sriov_pf_sysfs.h"
205c170a4dSMichal Wajdeczko #include "xe_sriov_printk.h"
215c170a4dSMichal Wajdeczko 
22b5b297b9SMichal Wajdeczko static int emit_choice(char *buf, int choice, const char * const *array, size_t size)
23b5b297b9SMichal Wajdeczko {
24b5b297b9SMichal Wajdeczko 	int pos = 0;
25b5b297b9SMichal Wajdeczko 	int n;
26b5b297b9SMichal Wajdeczko 
27b5b297b9SMichal Wajdeczko 	for (n = 0; n < size; n++) {
28b5b297b9SMichal Wajdeczko 		pos += sysfs_emit_at(buf, pos, "%s%s%s%s",
29b5b297b9SMichal Wajdeczko 				    n ? " " : "",
30b5b297b9SMichal Wajdeczko 				    n == choice ? "[" : "",
31b5b297b9SMichal Wajdeczko 				    array[n],
32b5b297b9SMichal Wajdeczko 				    n == choice ? "]" : "");
33b5b297b9SMichal Wajdeczko 	}
34b5b297b9SMichal Wajdeczko 	pos += sysfs_emit_at(buf, pos, "\n");
35b5b297b9SMichal Wajdeczko 
36b5b297b9SMichal Wajdeczko 	return pos;
37b5b297b9SMichal Wajdeczko }
38b5b297b9SMichal Wajdeczko 
395c170a4dSMichal Wajdeczko /*
405c170a4dSMichal Wajdeczko  * /sys/bus/pci/drivers/xe/BDF/
415c170a4dSMichal Wajdeczko  * :
425c170a4dSMichal Wajdeczko  * ├── sriov_admin/
435c170a4dSMichal Wajdeczko  *     ├── ...
4471f5933cSMichal Wajdeczko  *     ├── .bulk_profile
4571f5933cSMichal Wajdeczko  *     │   ├── exec_quantum_ms
469f64d21dSMichal Wajdeczko  *     │   ├── preempt_timeout_us
479f64d21dSMichal Wajdeczko  *     │   └── sched_priority
485c170a4dSMichal Wajdeczko  *     ├── pf/
495c170a4dSMichal Wajdeczko  *     │   ├── ...
5017899358SMichal Wajdeczko  *     │   ├── device -> ../../../BDF
513f984d70SMichal Wajdeczko  *     │   └── profile
523f984d70SMichal Wajdeczko  *     │       ├── exec_quantum_ms
53b5b297b9SMichal Wajdeczko  *     │       ├── preempt_timeout_us
54b5b297b9SMichal Wajdeczko  *     │       └── sched_priority
555c170a4dSMichal Wajdeczko  *     ├── vf1/
565c170a4dSMichal Wajdeczko  *     │   ├── ...
5717899358SMichal Wajdeczko  *     │   ├── device -> ../../../BDF.1
58*79e419c9SMichal Wajdeczko  *     │   ├── stop
593f984d70SMichal Wajdeczko  *     │   └── profile
603f984d70SMichal Wajdeczko  *     │       ├── exec_quantum_ms
61b5b297b9SMichal Wajdeczko  *     │       ├── preempt_timeout_us
62b5b297b9SMichal Wajdeczko  *     │       └── sched_priority
635c170a4dSMichal Wajdeczko  *     ├── vf2/
645c170a4dSMichal Wajdeczko  *     :
655c170a4dSMichal Wajdeczko  *     └── vfN/
665c170a4dSMichal Wajdeczko  */
675c170a4dSMichal Wajdeczko 
685c170a4dSMichal Wajdeczko struct xe_sriov_kobj {
695c170a4dSMichal Wajdeczko 	struct kobject base;
705c170a4dSMichal Wajdeczko 	struct xe_device *xe;
715c170a4dSMichal Wajdeczko 	unsigned int vfid;
725c170a4dSMichal Wajdeczko };
735c170a4dSMichal Wajdeczko #define to_xe_sriov_kobj(p) container_of_const((p), struct xe_sriov_kobj, base)
745c170a4dSMichal Wajdeczko 
755c170a4dSMichal Wajdeczko struct xe_sriov_dev_attr {
765c170a4dSMichal Wajdeczko 	struct attribute attr;
775c170a4dSMichal Wajdeczko 	ssize_t (*show)(struct xe_device *xe, char *buf);
785c170a4dSMichal Wajdeczko 	ssize_t (*store)(struct xe_device *xe, const char *buf, size_t count);
795c170a4dSMichal Wajdeczko };
805c170a4dSMichal Wajdeczko #define to_xe_sriov_dev_attr(p) container_of_const((p), struct xe_sriov_dev_attr, attr)
815c170a4dSMichal Wajdeczko 
825c170a4dSMichal Wajdeczko #define XE_SRIOV_DEV_ATTR(NAME) \
835c170a4dSMichal Wajdeczko struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \
845c170a4dSMichal Wajdeczko 	__ATTR(NAME, 0644, xe_sriov_dev_attr_##NAME##_show, xe_sriov_dev_attr_##NAME##_store)
855c170a4dSMichal Wajdeczko 
865c170a4dSMichal Wajdeczko #define XE_SRIOV_DEV_ATTR_RO(NAME) \
875c170a4dSMichal Wajdeczko struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \
885c170a4dSMichal Wajdeczko 	__ATTR(NAME, 0444, xe_sriov_dev_attr_##NAME##_show, NULL)
895c170a4dSMichal Wajdeczko 
905c170a4dSMichal Wajdeczko #define XE_SRIOV_DEV_ATTR_WO(NAME) \
915c170a4dSMichal Wajdeczko struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \
925c170a4dSMichal Wajdeczko 	__ATTR(NAME, 0200, NULL, xe_sriov_dev_attr_##NAME##_store)
935c170a4dSMichal Wajdeczko 
945c170a4dSMichal Wajdeczko struct xe_sriov_vf_attr {
955c170a4dSMichal Wajdeczko 	struct attribute attr;
965c170a4dSMichal Wajdeczko 	ssize_t (*show)(struct xe_device *xe, unsigned int vfid, char *buf);
975c170a4dSMichal Wajdeczko 	ssize_t (*store)(struct xe_device *xe, unsigned int vfid, const char *buf, size_t count);
985c170a4dSMichal Wajdeczko };
995c170a4dSMichal Wajdeczko #define to_xe_sriov_vf_attr(p) container_of_const((p), struct xe_sriov_vf_attr, attr)
1005c170a4dSMichal Wajdeczko 
1015c170a4dSMichal Wajdeczko #define XE_SRIOV_VF_ATTR(NAME) \
1025c170a4dSMichal Wajdeczko struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \
1035c170a4dSMichal Wajdeczko 	__ATTR(NAME, 0644, xe_sriov_vf_attr_##NAME##_show, xe_sriov_vf_attr_##NAME##_store)
1045c170a4dSMichal Wajdeczko 
1055c170a4dSMichal Wajdeczko #define XE_SRIOV_VF_ATTR_RO(NAME) \
1065c170a4dSMichal Wajdeczko struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \
1075c170a4dSMichal Wajdeczko 	__ATTR(NAME, 0444, xe_sriov_vf_attr_##NAME##_show, NULL)
1085c170a4dSMichal Wajdeczko 
1095c170a4dSMichal Wajdeczko #define XE_SRIOV_VF_ATTR_WO(NAME) \
1105c170a4dSMichal Wajdeczko struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \
1115c170a4dSMichal Wajdeczko 	__ATTR(NAME, 0200, NULL, xe_sriov_vf_attr_##NAME##_store)
1125c170a4dSMichal Wajdeczko 
1135c170a4dSMichal Wajdeczko /* device level attributes go here */
1145c170a4dSMichal Wajdeczko 
11571f5933cSMichal Wajdeczko #define DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(NAME, ITEM, TYPE)		\
11671f5933cSMichal Wajdeczko 											\
11771f5933cSMichal Wajdeczko static ssize_t xe_sriov_dev_attr_##NAME##_store(struct xe_device *xe,			\
11871f5933cSMichal Wajdeczko 						const char *buf, size_t count)		\
11971f5933cSMichal Wajdeczko {											\
12071f5933cSMichal Wajdeczko 	TYPE value;									\
12171f5933cSMichal Wajdeczko 	int err;									\
12271f5933cSMichal Wajdeczko 											\
12371f5933cSMichal Wajdeczko 	err = kstrto##TYPE(buf, 0, &value);						\
12471f5933cSMichal Wajdeczko 	if (err)									\
12571f5933cSMichal Wajdeczko 		return err;								\
12671f5933cSMichal Wajdeczko 											\
12771f5933cSMichal Wajdeczko 	err = xe_sriov_pf_provision_bulk_apply_##ITEM(xe, value);			\
12871f5933cSMichal Wajdeczko 	return err ?: count;								\
12971f5933cSMichal Wajdeczko }											\
13071f5933cSMichal Wajdeczko 											\
13171f5933cSMichal Wajdeczko static XE_SRIOV_DEV_ATTR_WO(NAME)
13271f5933cSMichal Wajdeczko 
13371f5933cSMichal Wajdeczko DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(exec_quantum_ms, eq, u32);
13471f5933cSMichal Wajdeczko DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(preempt_timeout_us, pt, u32);
13571f5933cSMichal Wajdeczko 
1369f64d21dSMichal Wajdeczko static const char * const sched_priority_names[] = {
1379f64d21dSMichal Wajdeczko 	[GUC_SCHED_PRIORITY_LOW] = "low",
1389f64d21dSMichal Wajdeczko 	[GUC_SCHED_PRIORITY_NORMAL] = "normal",
1399f64d21dSMichal Wajdeczko 	[GUC_SCHED_PRIORITY_HIGH] = "high",
1409f64d21dSMichal Wajdeczko };
1419f64d21dSMichal Wajdeczko 
142b5b297b9SMichal Wajdeczko static bool sched_priority_change_allowed(unsigned int vfid)
143b5b297b9SMichal Wajdeczko {
144b5b297b9SMichal Wajdeczko 	/* As of today GuC FW allows to selectively change only the PF priority. */
145b5b297b9SMichal Wajdeczko 	return vfid == PFID;
146b5b297b9SMichal Wajdeczko }
147b5b297b9SMichal Wajdeczko 
1489f64d21dSMichal Wajdeczko static bool sched_priority_high_allowed(unsigned int vfid)
1499f64d21dSMichal Wajdeczko {
1509f64d21dSMichal Wajdeczko 	/* As of today GuC FW allows to select 'high' priority only for the PF. */
1519f64d21dSMichal Wajdeczko 	return vfid == PFID;
1529f64d21dSMichal Wajdeczko }
1539f64d21dSMichal Wajdeczko 
1549f64d21dSMichal Wajdeczko static bool sched_priority_bulk_high_allowed(struct xe_device *xe)
1559f64d21dSMichal Wajdeczko {
1569f64d21dSMichal Wajdeczko 	/* all VFs are equal - it's sufficient to check VF1 only */
1579f64d21dSMichal Wajdeczko 	return sched_priority_high_allowed(VFID(1));
1589f64d21dSMichal Wajdeczko }
1599f64d21dSMichal Wajdeczko 
1609f64d21dSMichal Wajdeczko static ssize_t xe_sriov_dev_attr_sched_priority_store(struct xe_device *xe,
1619f64d21dSMichal Wajdeczko 						      const char *buf, size_t count)
1629f64d21dSMichal Wajdeczko {
1639f64d21dSMichal Wajdeczko 	size_t num_priorities = ARRAY_SIZE(sched_priority_names);
1649f64d21dSMichal Wajdeczko 	int match;
1659f64d21dSMichal Wajdeczko 	int err;
1669f64d21dSMichal Wajdeczko 
1679f64d21dSMichal Wajdeczko 	if (!sched_priority_bulk_high_allowed(xe))
1689f64d21dSMichal Wajdeczko 		num_priorities--;
1699f64d21dSMichal Wajdeczko 
1709f64d21dSMichal Wajdeczko 	match = __sysfs_match_string(sched_priority_names, num_priorities, buf);
1719f64d21dSMichal Wajdeczko 	if (match < 0)
1729f64d21dSMichal Wajdeczko 		return -EINVAL;
1739f64d21dSMichal Wajdeczko 
1749f64d21dSMichal Wajdeczko 	err = xe_sriov_pf_provision_bulk_apply_priority(xe, match);
1759f64d21dSMichal Wajdeczko 	return err ?: count;
1769f64d21dSMichal Wajdeczko }
1779f64d21dSMichal Wajdeczko 
1789f64d21dSMichal Wajdeczko static XE_SRIOV_DEV_ATTR_WO(sched_priority);
1799f64d21dSMichal Wajdeczko 
18071f5933cSMichal Wajdeczko static struct attribute *bulk_profile_dev_attrs[] = {
18171f5933cSMichal Wajdeczko 	&xe_sriov_dev_attr_exec_quantum_ms.attr,
18271f5933cSMichal Wajdeczko 	&xe_sriov_dev_attr_preempt_timeout_us.attr,
1839f64d21dSMichal Wajdeczko 	&xe_sriov_dev_attr_sched_priority.attr,
18471f5933cSMichal Wajdeczko 	NULL
18571f5933cSMichal Wajdeczko };
18671f5933cSMichal Wajdeczko 
18771f5933cSMichal Wajdeczko static const struct attribute_group bulk_profile_dev_attr_group = {
18871f5933cSMichal Wajdeczko 	.name = ".bulk_profile",
18971f5933cSMichal Wajdeczko 	.attrs = bulk_profile_dev_attrs,
19071f5933cSMichal Wajdeczko };
19171f5933cSMichal Wajdeczko 
1925c170a4dSMichal Wajdeczko static const struct attribute_group *xe_sriov_dev_attr_groups[] = {
19371f5933cSMichal Wajdeczko 	&bulk_profile_dev_attr_group,
1945c170a4dSMichal Wajdeczko 	NULL
1955c170a4dSMichal Wajdeczko };
1965c170a4dSMichal Wajdeczko 
1975c170a4dSMichal Wajdeczko /* and VF-level attributes go here */
1985c170a4dSMichal Wajdeczko 
1993f984d70SMichal Wajdeczko #define DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(NAME, ITEM, TYPE, FORMAT)		\
2003f984d70SMichal Wajdeczko static ssize_t xe_sriov_vf_attr_##NAME##_show(struct xe_device *xe, unsigned int vfid,	\
2013f984d70SMichal Wajdeczko 					      char *buf)				\
2023f984d70SMichal Wajdeczko {											\
2033f984d70SMichal Wajdeczko 	TYPE value = 0;									\
2043f984d70SMichal Wajdeczko 	int err;									\
2053f984d70SMichal Wajdeczko 											\
2063f984d70SMichal Wajdeczko 	err = xe_sriov_pf_provision_query_vf_##ITEM(xe, vfid, &value);			\
2073f984d70SMichal Wajdeczko 	if (err)									\
2083f984d70SMichal Wajdeczko 		return err;								\
2093f984d70SMichal Wajdeczko 											\
2103f984d70SMichal Wajdeczko 	return sysfs_emit(buf, FORMAT, value);						\
2113f984d70SMichal Wajdeczko }											\
2123f984d70SMichal Wajdeczko 											\
2133f984d70SMichal Wajdeczko static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid,	\
2143f984d70SMichal Wajdeczko 					       const char *buf, size_t count)		\
2153f984d70SMichal Wajdeczko {											\
2163f984d70SMichal Wajdeczko 	TYPE value;									\
2173f984d70SMichal Wajdeczko 	int err;									\
2183f984d70SMichal Wajdeczko 											\
2193f984d70SMichal Wajdeczko 	err = kstrto##TYPE(buf, 0, &value);						\
2203f984d70SMichal Wajdeczko 	if (err)									\
2213f984d70SMichal Wajdeczko 		return err;								\
2223f984d70SMichal Wajdeczko 											\
2233f984d70SMichal Wajdeczko 	err = xe_sriov_pf_provision_apply_vf_##ITEM(xe, vfid, value);			\
2243f984d70SMichal Wajdeczko 	return err ?: count;								\
2253f984d70SMichal Wajdeczko }											\
2263f984d70SMichal Wajdeczko 											\
2273f984d70SMichal Wajdeczko static XE_SRIOV_VF_ATTR(NAME)
2283f984d70SMichal Wajdeczko 
2293f984d70SMichal Wajdeczko DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(exec_quantum_ms, eq, u32, "%u\n");
2303f984d70SMichal Wajdeczko DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(preempt_timeout_us, pt, u32, "%u\n");
2313f984d70SMichal Wajdeczko 
232b5b297b9SMichal Wajdeczko static ssize_t xe_sriov_vf_attr_sched_priority_show(struct xe_device *xe, unsigned int vfid,
233b5b297b9SMichal Wajdeczko 						    char *buf)
234b5b297b9SMichal Wajdeczko {
235b5b297b9SMichal Wajdeczko 	size_t num_priorities = ARRAY_SIZE(sched_priority_names);
236b5b297b9SMichal Wajdeczko 	u32 priority;
237b5b297b9SMichal Wajdeczko 	int err;
238b5b297b9SMichal Wajdeczko 
239b5b297b9SMichal Wajdeczko 	err = xe_sriov_pf_provision_query_vf_priority(xe, vfid, &priority);
240b5b297b9SMichal Wajdeczko 	if (err)
241b5b297b9SMichal Wajdeczko 		return err;
242b5b297b9SMichal Wajdeczko 
243b5b297b9SMichal Wajdeczko 	if (!sched_priority_high_allowed(vfid))
244b5b297b9SMichal Wajdeczko 		num_priorities--;
245b5b297b9SMichal Wajdeczko 
246b5b297b9SMichal Wajdeczko 	xe_assert(xe, priority < num_priorities);
247b5b297b9SMichal Wajdeczko 	return emit_choice(buf, priority, sched_priority_names, num_priorities);
248b5b297b9SMichal Wajdeczko }
249b5b297b9SMichal Wajdeczko 
250b5b297b9SMichal Wajdeczko static ssize_t xe_sriov_vf_attr_sched_priority_store(struct xe_device *xe, unsigned int vfid,
251b5b297b9SMichal Wajdeczko 						     const char *buf, size_t count)
252b5b297b9SMichal Wajdeczko {
253b5b297b9SMichal Wajdeczko 	size_t num_priorities = ARRAY_SIZE(sched_priority_names);
254b5b297b9SMichal Wajdeczko 	int match;
255b5b297b9SMichal Wajdeczko 	int err;
256b5b297b9SMichal Wajdeczko 
257b5b297b9SMichal Wajdeczko 	if (!sched_priority_change_allowed(vfid))
258b5b297b9SMichal Wajdeczko 		return -EOPNOTSUPP;
259b5b297b9SMichal Wajdeczko 
260b5b297b9SMichal Wajdeczko 	if (!sched_priority_high_allowed(vfid))
261b5b297b9SMichal Wajdeczko 		num_priorities--;
262b5b297b9SMichal Wajdeczko 
263b5b297b9SMichal Wajdeczko 	match = __sysfs_match_string(sched_priority_names, num_priorities, buf);
264b5b297b9SMichal Wajdeczko 	if (match < 0)
265b5b297b9SMichal Wajdeczko 		return -EINVAL;
266b5b297b9SMichal Wajdeczko 
267b5b297b9SMichal Wajdeczko 	err = xe_sriov_pf_provision_apply_vf_priority(xe, vfid, match);
268b5b297b9SMichal Wajdeczko 	return err ?: count;
269b5b297b9SMichal Wajdeczko }
270b5b297b9SMichal Wajdeczko 
271b5b297b9SMichal Wajdeczko static XE_SRIOV_VF_ATTR(sched_priority);
272b5b297b9SMichal Wajdeczko 
2733f984d70SMichal Wajdeczko static struct attribute *profile_vf_attrs[] = {
2743f984d70SMichal Wajdeczko 	&xe_sriov_vf_attr_exec_quantum_ms.attr,
2753f984d70SMichal Wajdeczko 	&xe_sriov_vf_attr_preempt_timeout_us.attr,
276b5b297b9SMichal Wajdeczko 	&xe_sriov_vf_attr_sched_priority.attr,
2773f984d70SMichal Wajdeczko 	NULL
2783f984d70SMichal Wajdeczko };
2793f984d70SMichal Wajdeczko 
280b5b297b9SMichal Wajdeczko static umode_t profile_vf_attr_is_visible(struct kobject *kobj,
281b5b297b9SMichal Wajdeczko 					  struct attribute *attr, int index)
282b5b297b9SMichal Wajdeczko {
283b5b297b9SMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
284b5b297b9SMichal Wajdeczko 
285b5b297b9SMichal Wajdeczko 	if (attr == &xe_sriov_vf_attr_sched_priority.attr &&
286b5b297b9SMichal Wajdeczko 	    !sched_priority_change_allowed(vkobj->vfid))
287b5b297b9SMichal Wajdeczko 		return attr->mode & 0444;
288b5b297b9SMichal Wajdeczko 
289b5b297b9SMichal Wajdeczko 	return attr->mode;
290b5b297b9SMichal Wajdeczko }
291b5b297b9SMichal Wajdeczko 
2923f984d70SMichal Wajdeczko static const struct attribute_group profile_vf_attr_group = {
2933f984d70SMichal Wajdeczko 	.name = "profile",
2943f984d70SMichal Wajdeczko 	.attrs = profile_vf_attrs,
295b5b297b9SMichal Wajdeczko 	.is_visible = profile_vf_attr_is_visible,
2963f984d70SMichal Wajdeczko };
2973f984d70SMichal Wajdeczko 
298*79e419c9SMichal Wajdeczko #define DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(NAME)					\
299*79e419c9SMichal Wajdeczko 											\
300*79e419c9SMichal Wajdeczko static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid,	\
301*79e419c9SMichal Wajdeczko 					       const char *buf, size_t count)		\
302*79e419c9SMichal Wajdeczko {											\
303*79e419c9SMichal Wajdeczko 	bool yes;									\
304*79e419c9SMichal Wajdeczko 	int err;									\
305*79e419c9SMichal Wajdeczko 											\
306*79e419c9SMichal Wajdeczko 	if (!vfid)									\
307*79e419c9SMichal Wajdeczko 		return -EPERM;								\
308*79e419c9SMichal Wajdeczko 											\
309*79e419c9SMichal Wajdeczko 	err = kstrtobool(buf, &yes);							\
310*79e419c9SMichal Wajdeczko 	if (err)									\
311*79e419c9SMichal Wajdeczko 		return err;								\
312*79e419c9SMichal Wajdeczko 	if (!yes)									\
313*79e419c9SMichal Wajdeczko 		return count;								\
314*79e419c9SMichal Wajdeczko 											\
315*79e419c9SMichal Wajdeczko 	err = xe_sriov_pf_control_##NAME##_vf(xe, vfid);				\
316*79e419c9SMichal Wajdeczko 	return err ?: count;								\
317*79e419c9SMichal Wajdeczko }											\
318*79e419c9SMichal Wajdeczko 											\
319*79e419c9SMichal Wajdeczko static XE_SRIOV_VF_ATTR_WO(NAME)
320*79e419c9SMichal Wajdeczko 
321*79e419c9SMichal Wajdeczko DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(stop);
322*79e419c9SMichal Wajdeczko 
323*79e419c9SMichal Wajdeczko static struct attribute *control_vf_attrs[] = {
324*79e419c9SMichal Wajdeczko 	&xe_sriov_vf_attr_stop.attr,
325*79e419c9SMichal Wajdeczko 	NULL
326*79e419c9SMichal Wajdeczko };
327*79e419c9SMichal Wajdeczko 
328*79e419c9SMichal Wajdeczko static umode_t control_vf_attr_is_visible(struct kobject *kobj,
329*79e419c9SMichal Wajdeczko 					  struct attribute *attr, int index)
330*79e419c9SMichal Wajdeczko {
331*79e419c9SMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
332*79e419c9SMichal Wajdeczko 
333*79e419c9SMichal Wajdeczko 	if (vkobj->vfid == PFID)
334*79e419c9SMichal Wajdeczko 		return 0;
335*79e419c9SMichal Wajdeczko 
336*79e419c9SMichal Wajdeczko 	return attr->mode;
337*79e419c9SMichal Wajdeczko }
338*79e419c9SMichal Wajdeczko 
339*79e419c9SMichal Wajdeczko static const struct attribute_group control_vf_attr_group = {
340*79e419c9SMichal Wajdeczko 	.attrs = control_vf_attrs,
341*79e419c9SMichal Wajdeczko 	.is_visible = control_vf_attr_is_visible,
342*79e419c9SMichal Wajdeczko };
343*79e419c9SMichal Wajdeczko 
3445c170a4dSMichal Wajdeczko static const struct attribute_group *xe_sriov_vf_attr_groups[] = {
3453f984d70SMichal Wajdeczko 	&profile_vf_attr_group,
346*79e419c9SMichal Wajdeczko 	&control_vf_attr_group,
3475c170a4dSMichal Wajdeczko 	NULL
3485c170a4dSMichal Wajdeczko };
3495c170a4dSMichal Wajdeczko 
3505c170a4dSMichal Wajdeczko /* no user serviceable parts below */
3515c170a4dSMichal Wajdeczko 
3525c170a4dSMichal Wajdeczko static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid)
3535c170a4dSMichal Wajdeczko {
3545c170a4dSMichal Wajdeczko 	struct xe_sriov_kobj *vkobj;
3555c170a4dSMichal Wajdeczko 
3565c170a4dSMichal Wajdeczko 	xe_sriov_pf_assert_vfid(xe, vfid);
3575c170a4dSMichal Wajdeczko 
3585c170a4dSMichal Wajdeczko 	vkobj = kzalloc(sizeof(*vkobj), GFP_KERNEL);
3595c170a4dSMichal Wajdeczko 	if (!vkobj)
3605c170a4dSMichal Wajdeczko 		return NULL;
3615c170a4dSMichal Wajdeczko 
3625c170a4dSMichal Wajdeczko 	vkobj->xe = xe;
3635c170a4dSMichal Wajdeczko 	vkobj->vfid = vfid;
3645c170a4dSMichal Wajdeczko 	return &vkobj->base;
3655c170a4dSMichal Wajdeczko }
3665c170a4dSMichal Wajdeczko 
3675c170a4dSMichal Wajdeczko static void release_xe_sriov_kobj(struct kobject *kobj)
3685c170a4dSMichal Wajdeczko {
3695c170a4dSMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
3705c170a4dSMichal Wajdeczko 
3715c170a4dSMichal Wajdeczko 	kfree(vkobj);
3725c170a4dSMichal Wajdeczko }
3735c170a4dSMichal Wajdeczko 
3745c170a4dSMichal Wajdeczko static ssize_t xe_sriov_dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
3755c170a4dSMichal Wajdeczko {
3765c170a4dSMichal Wajdeczko 	struct xe_sriov_dev_attr *vattr  = to_xe_sriov_dev_attr(attr);
3775c170a4dSMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
3785c170a4dSMichal Wajdeczko 	struct xe_device *xe = vkobj->xe;
3795c170a4dSMichal Wajdeczko 
3805c170a4dSMichal Wajdeczko 	if (!vattr->show)
3815c170a4dSMichal Wajdeczko 		return -EPERM;
3825c170a4dSMichal Wajdeczko 
3835c170a4dSMichal Wajdeczko 	return vattr->show(xe, buf);
3845c170a4dSMichal Wajdeczko }
3855c170a4dSMichal Wajdeczko 
3865c170a4dSMichal Wajdeczko static ssize_t xe_sriov_dev_attr_store(struct kobject *kobj, struct attribute *attr,
3875c170a4dSMichal Wajdeczko 				       const char *buf, size_t count)
3885c170a4dSMichal Wajdeczko {
3895c170a4dSMichal Wajdeczko 	struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr);
3905c170a4dSMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
3915c170a4dSMichal Wajdeczko 	struct xe_device *xe = vkobj->xe;
392f9091794SMichal Wajdeczko 	ssize_t ret;
3935c170a4dSMichal Wajdeczko 
3945c170a4dSMichal Wajdeczko 	if (!vattr->store)
3955c170a4dSMichal Wajdeczko 		return -EPERM;
3965c170a4dSMichal Wajdeczko 
397f9091794SMichal Wajdeczko 	xe_pm_runtime_get(xe);
398f9091794SMichal Wajdeczko 	ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count);
399f9091794SMichal Wajdeczko 	xe_pm_runtime_put(xe);
400f9091794SMichal Wajdeczko 
401f9091794SMichal Wajdeczko 	return ret;
4025c170a4dSMichal Wajdeczko }
4035c170a4dSMichal Wajdeczko 
4045c170a4dSMichal Wajdeczko static ssize_t xe_sriov_vf_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
4055c170a4dSMichal Wajdeczko {
4065c170a4dSMichal Wajdeczko 	struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr);
4075c170a4dSMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
4085c170a4dSMichal Wajdeczko 	struct xe_device *xe = vkobj->xe;
4095c170a4dSMichal Wajdeczko 	unsigned int vfid = vkobj->vfid;
4105c170a4dSMichal Wajdeczko 
4115c170a4dSMichal Wajdeczko 	xe_sriov_pf_assert_vfid(xe, vfid);
4125c170a4dSMichal Wajdeczko 
4135c170a4dSMichal Wajdeczko 	if (!vattr->show)
4145c170a4dSMichal Wajdeczko 		return -EPERM;
4155c170a4dSMichal Wajdeczko 
4165c170a4dSMichal Wajdeczko 	return vattr->show(xe, vfid, buf);
4175c170a4dSMichal Wajdeczko }
4185c170a4dSMichal Wajdeczko 
4195c170a4dSMichal Wajdeczko static ssize_t xe_sriov_vf_attr_store(struct kobject *kobj, struct attribute *attr,
4205c170a4dSMichal Wajdeczko 				      const char *buf, size_t count)
4215c170a4dSMichal Wajdeczko {
4225c170a4dSMichal Wajdeczko 	struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr);
4235c170a4dSMichal Wajdeczko 	struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj);
4245c170a4dSMichal Wajdeczko 	struct xe_device *xe = vkobj->xe;
4255c170a4dSMichal Wajdeczko 	unsigned int vfid = vkobj->vfid;
426f9091794SMichal Wajdeczko 	ssize_t ret;
4275c170a4dSMichal Wajdeczko 
4285c170a4dSMichal Wajdeczko 	xe_sriov_pf_assert_vfid(xe, vfid);
4295c170a4dSMichal Wajdeczko 
4305c170a4dSMichal Wajdeczko 	if (!vattr->store)
4315c170a4dSMichal Wajdeczko 		return -EPERM;
4325c170a4dSMichal Wajdeczko 
433f9091794SMichal Wajdeczko 	xe_pm_runtime_get(xe);
434f9091794SMichal Wajdeczko 	ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count);
435f9091794SMichal Wajdeczko 	xe_pm_runtime_get(xe);
436f9091794SMichal Wajdeczko 
437f9091794SMichal Wajdeczko 	return ret;
4385c170a4dSMichal Wajdeczko }
4395c170a4dSMichal Wajdeczko 
4405c170a4dSMichal Wajdeczko static const struct sysfs_ops xe_sriov_dev_sysfs_ops = {
4415c170a4dSMichal Wajdeczko 	.show = xe_sriov_dev_attr_show,
4425c170a4dSMichal Wajdeczko 	.store = xe_sriov_dev_attr_store,
4435c170a4dSMichal Wajdeczko };
4445c170a4dSMichal Wajdeczko 
4455c170a4dSMichal Wajdeczko static const struct sysfs_ops xe_sriov_vf_sysfs_ops = {
4465c170a4dSMichal Wajdeczko 	.show = xe_sriov_vf_attr_show,
4475c170a4dSMichal Wajdeczko 	.store = xe_sriov_vf_attr_store,
4485c170a4dSMichal Wajdeczko };
4495c170a4dSMichal Wajdeczko 
4505c170a4dSMichal Wajdeczko static const struct kobj_type xe_sriov_dev_ktype = {
4515c170a4dSMichal Wajdeczko 	.release = release_xe_sriov_kobj,
4525c170a4dSMichal Wajdeczko 	.sysfs_ops = &xe_sriov_dev_sysfs_ops,
4535c170a4dSMichal Wajdeczko 	.default_groups = xe_sriov_dev_attr_groups,
4545c170a4dSMichal Wajdeczko };
4555c170a4dSMichal Wajdeczko 
4565c170a4dSMichal Wajdeczko static const struct kobj_type xe_sriov_vf_ktype = {
4575c170a4dSMichal Wajdeczko 	.release = release_xe_sriov_kobj,
4585c170a4dSMichal Wajdeczko 	.sysfs_ops = &xe_sriov_vf_sysfs_ops,
4595c170a4dSMichal Wajdeczko 	.default_groups = xe_sriov_vf_attr_groups,
4605c170a4dSMichal Wajdeczko };
4615c170a4dSMichal Wajdeczko 
4625c170a4dSMichal Wajdeczko static int pf_sysfs_error(struct xe_device *xe, int err, const char *what)
4635c170a4dSMichal Wajdeczko {
4645c170a4dSMichal Wajdeczko 	if (IS_ENABLED(CONFIG_DRM_XE_DEBUG))
4655c170a4dSMichal Wajdeczko 		xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err));
4665c170a4dSMichal Wajdeczko 	return err;
4675c170a4dSMichal Wajdeczko }
4685c170a4dSMichal Wajdeczko 
46917899358SMichal Wajdeczko static void pf_sysfs_note(struct xe_device *xe, int err, const char *what)
47017899358SMichal Wajdeczko {
47117899358SMichal Wajdeczko 	xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err));
47217899358SMichal Wajdeczko }
47317899358SMichal Wajdeczko 
4745c170a4dSMichal Wajdeczko static void action_put_kobject(void *arg)
4755c170a4dSMichal Wajdeczko {
4765c170a4dSMichal Wajdeczko 	struct kobject *kobj = arg;
4775c170a4dSMichal Wajdeczko 
4785c170a4dSMichal Wajdeczko 	kobject_put(kobj);
4795c170a4dSMichal Wajdeczko }
4805c170a4dSMichal Wajdeczko 
4815c170a4dSMichal Wajdeczko static int pf_setup_root(struct xe_device *xe)
4825c170a4dSMichal Wajdeczko {
4835c170a4dSMichal Wajdeczko 	struct kobject *parent = &xe->drm.dev->kobj;
4845c170a4dSMichal Wajdeczko 	struct kobject *root;
4855c170a4dSMichal Wajdeczko 	int err;
4865c170a4dSMichal Wajdeczko 
4875c170a4dSMichal Wajdeczko 	root = create_xe_sriov_kobj(xe, PFID);
4885c170a4dSMichal Wajdeczko 	if (!root)
4895c170a4dSMichal Wajdeczko 		return pf_sysfs_error(xe, -ENOMEM, "root obj");
4905c170a4dSMichal Wajdeczko 
4915c170a4dSMichal Wajdeczko 	err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root);
4925c170a4dSMichal Wajdeczko 	if (err)
4935c170a4dSMichal Wajdeczko 		return pf_sysfs_error(xe, err, "root action");
4945c170a4dSMichal Wajdeczko 
4955c170a4dSMichal Wajdeczko 	err = kobject_init_and_add(root, &xe_sriov_dev_ktype, parent, "sriov_admin");
4965c170a4dSMichal Wajdeczko 	if (err)
4975c170a4dSMichal Wajdeczko 		return pf_sysfs_error(xe, err, "root init");
4985c170a4dSMichal Wajdeczko 
4995c170a4dSMichal Wajdeczko 	xe_assert(xe, IS_SRIOV_PF(xe));
5005c170a4dSMichal Wajdeczko 	xe_assert(xe, !xe->sriov.pf.sysfs.root);
5015c170a4dSMichal Wajdeczko 	xe->sriov.pf.sysfs.root = root;
5025c170a4dSMichal Wajdeczko 	return 0;
5035c170a4dSMichal Wajdeczko }
5045c170a4dSMichal Wajdeczko 
5055c170a4dSMichal Wajdeczko static int pf_setup_tree(struct xe_device *xe)
5065c170a4dSMichal Wajdeczko {
5075c170a4dSMichal Wajdeczko 	unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe);
5085c170a4dSMichal Wajdeczko 	struct kobject *root, *kobj;
5095c170a4dSMichal Wajdeczko 	unsigned int n;
5105c170a4dSMichal Wajdeczko 	int err;
5115c170a4dSMichal Wajdeczko 
5125c170a4dSMichal Wajdeczko 	xe_assert(xe, IS_SRIOV_PF(xe));
5135c170a4dSMichal Wajdeczko 	root = xe->sriov.pf.sysfs.root;
5145c170a4dSMichal Wajdeczko 
5155c170a4dSMichal Wajdeczko 	for (n = 0; n <= totalvfs; n++) {
5165c170a4dSMichal Wajdeczko 		kobj = create_xe_sriov_kobj(xe, VFID(n));
5175c170a4dSMichal Wajdeczko 		if (!kobj)
5185c170a4dSMichal Wajdeczko 			return pf_sysfs_error(xe, -ENOMEM, "tree obj");
5195c170a4dSMichal Wajdeczko 
5205c170a4dSMichal Wajdeczko 		err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root);
5215c170a4dSMichal Wajdeczko 		if (err)
5225c170a4dSMichal Wajdeczko 			return pf_sysfs_error(xe, err, "tree action");
5235c170a4dSMichal Wajdeczko 
5245c170a4dSMichal Wajdeczko 		if (n)
5255c170a4dSMichal Wajdeczko 			err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype,
5265c170a4dSMichal Wajdeczko 						   root, "vf%u", n);
5275c170a4dSMichal Wajdeczko 		else
5285c170a4dSMichal Wajdeczko 			err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype,
5295c170a4dSMichal Wajdeczko 						   root, "pf");
5305c170a4dSMichal Wajdeczko 		if (err)
5315c170a4dSMichal Wajdeczko 			return pf_sysfs_error(xe, err, "tree init");
5325c170a4dSMichal Wajdeczko 
5335c170a4dSMichal Wajdeczko 		xe_assert(xe, !xe->sriov.pf.vfs[n].kobj);
5345c170a4dSMichal Wajdeczko 		xe->sriov.pf.vfs[n].kobj = kobj;
5355c170a4dSMichal Wajdeczko 	}
5365c170a4dSMichal Wajdeczko 
5375c170a4dSMichal Wajdeczko 	return 0;
5385c170a4dSMichal Wajdeczko }
5395c170a4dSMichal Wajdeczko 
54017899358SMichal Wajdeczko static void action_rm_device_link(void *arg)
54117899358SMichal Wajdeczko {
54217899358SMichal Wajdeczko 	struct kobject *kobj = arg;
54317899358SMichal Wajdeczko 
54417899358SMichal Wajdeczko 	sysfs_remove_link(kobj, "device");
54517899358SMichal Wajdeczko }
54617899358SMichal Wajdeczko 
54717899358SMichal Wajdeczko static int pf_link_pf_device(struct xe_device *xe)
54817899358SMichal Wajdeczko {
54917899358SMichal Wajdeczko 	struct kobject *kobj = xe->sriov.pf.vfs[PFID].kobj;
55017899358SMichal Wajdeczko 	int err;
55117899358SMichal Wajdeczko 
55217899358SMichal Wajdeczko 	err = sysfs_create_link(kobj, &xe->drm.dev->kobj, "device");
55317899358SMichal Wajdeczko 	if (err)
55417899358SMichal Wajdeczko 		return pf_sysfs_error(xe, err, "PF device link");
55517899358SMichal Wajdeczko 
55617899358SMichal Wajdeczko 	err = devm_add_action_or_reset(xe->drm.dev, action_rm_device_link, kobj);
55717899358SMichal Wajdeczko 	if (err)
55817899358SMichal Wajdeczko 		return pf_sysfs_error(xe, err, "PF unlink action");
55917899358SMichal Wajdeczko 
56017899358SMichal Wajdeczko 	return 0;
56117899358SMichal Wajdeczko }
56217899358SMichal Wajdeczko 
5635c170a4dSMichal Wajdeczko /**
5645c170a4dSMichal Wajdeczko  * xe_sriov_pf_sysfs_init() - Setup PF's SR-IOV sysfs tree.
5655c170a4dSMichal Wajdeczko  * @xe: the PF &xe_device to setup sysfs
5665c170a4dSMichal Wajdeczko  *
5675c170a4dSMichal Wajdeczko  * This function will create additional nodes that will represent PF and VFs
5685c170a4dSMichal Wajdeczko  * devices, each populated with SR-IOV Xe specific attributes.
5695c170a4dSMichal Wajdeczko  *
5705c170a4dSMichal Wajdeczko  * Return: 0 on success or a negative error code on failure.
5715c170a4dSMichal Wajdeczko  */
5725c170a4dSMichal Wajdeczko int xe_sriov_pf_sysfs_init(struct xe_device *xe)
5735c170a4dSMichal Wajdeczko {
5745c170a4dSMichal Wajdeczko 	int err;
5755c170a4dSMichal Wajdeczko 
5765c170a4dSMichal Wajdeczko 	err = pf_setup_root(xe);
5775c170a4dSMichal Wajdeczko 	if (err)
5785c170a4dSMichal Wajdeczko 		return err;
5795c170a4dSMichal Wajdeczko 
5805c170a4dSMichal Wajdeczko 	err = pf_setup_tree(xe);
5815c170a4dSMichal Wajdeczko 	if (err)
5825c170a4dSMichal Wajdeczko 		return err;
5835c170a4dSMichal Wajdeczko 
58417899358SMichal Wajdeczko 	err = pf_link_pf_device(xe);
58517899358SMichal Wajdeczko 	if (err)
58617899358SMichal Wajdeczko 		return err;
58717899358SMichal Wajdeczko 
5885c170a4dSMichal Wajdeczko 	return 0;
5895c170a4dSMichal Wajdeczko }
59017899358SMichal Wajdeczko 
59117899358SMichal Wajdeczko /**
59217899358SMichal Wajdeczko  * xe_sriov_pf_sysfs_link_vfs() - Add VF's links in SR-IOV sysfs tree.
59317899358SMichal Wajdeczko  * @xe: the &xe_device where to update sysfs
59417899358SMichal Wajdeczko  * @num_vfs: number of enabled VFs to link
59517899358SMichal Wajdeczko  *
59617899358SMichal Wajdeczko  * This function is specific for the PF driver.
59717899358SMichal Wajdeczko  *
59817899358SMichal Wajdeczko  * This function will add symbolic links between VFs represented in the SR-IOV
59917899358SMichal Wajdeczko  * sysfs tree maintained by the PF and enabled VF PCI devices.
60017899358SMichal Wajdeczko  *
60117899358SMichal Wajdeczko  * The @xe_sriov_pf_sysfs_unlink_vfs() shall be used to remove those links.
60217899358SMichal Wajdeczko  */
60317899358SMichal Wajdeczko void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs)
60417899358SMichal Wajdeczko {
60517899358SMichal Wajdeczko 	unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe);
60617899358SMichal Wajdeczko 	struct pci_dev *pf_pdev = to_pci_dev(xe->drm.dev);
60717899358SMichal Wajdeczko 	struct pci_dev *vf_pdev = NULL;
60817899358SMichal Wajdeczko 	unsigned int n;
60917899358SMichal Wajdeczko 	int err;
61017899358SMichal Wajdeczko 
61117899358SMichal Wajdeczko 	xe_assert(xe, IS_SRIOV_PF(xe));
61217899358SMichal Wajdeczko 	xe_assert(xe, num_vfs <= totalvfs);
61317899358SMichal Wajdeczko 
61417899358SMichal Wajdeczko 	for (n = 1; n <= num_vfs; n++) {
61517899358SMichal Wajdeczko 		vf_pdev = xe_pci_sriov_get_vf_pdev(pf_pdev, VFID(n));
61617899358SMichal Wajdeczko 		if (!vf_pdev)
61717899358SMichal Wajdeczko 			return pf_sysfs_note(xe, -ENOENT, "VF link");
61817899358SMichal Wajdeczko 
61917899358SMichal Wajdeczko 		err = sysfs_create_link(xe->sriov.pf.vfs[VFID(n)].kobj,
62017899358SMichal Wajdeczko 					&vf_pdev->dev.kobj, "device");
62117899358SMichal Wajdeczko 
62217899358SMichal Wajdeczko 		/* must balance xe_pci_sriov_get_vf_pdev() */
62317899358SMichal Wajdeczko 		pci_dev_put(vf_pdev);
62417899358SMichal Wajdeczko 
62517899358SMichal Wajdeczko 		if (err)
62617899358SMichal Wajdeczko 			return pf_sysfs_note(xe, err, "VF link");
62717899358SMichal Wajdeczko 	}
62817899358SMichal Wajdeczko }
62917899358SMichal Wajdeczko 
63017899358SMichal Wajdeczko /**
63117899358SMichal Wajdeczko  * xe_sriov_pf_sysfs_unlink_vfs() - Remove VF's links from SR-IOV sysfs tree.
63217899358SMichal Wajdeczko  * @xe: the &xe_device where to update sysfs
63317899358SMichal Wajdeczko  * @num_vfs: number of VFs to unlink
63417899358SMichal Wajdeczko  *
63517899358SMichal Wajdeczko  * This function shall be called only on the PF.
63617899358SMichal Wajdeczko  * This function will remove "device" links added by @xe_sriov_sysfs_link_vfs().
63717899358SMichal Wajdeczko  */
63817899358SMichal Wajdeczko void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs)
63917899358SMichal Wajdeczko {
64017899358SMichal Wajdeczko 	unsigned int n;
64117899358SMichal Wajdeczko 
64217899358SMichal Wajdeczko 	xe_assert(xe, IS_SRIOV_PF(xe));
64317899358SMichal Wajdeczko 	xe_assert(xe, num_vfs <= xe_sriov_pf_get_totalvfs(xe));
64417899358SMichal Wajdeczko 
64517899358SMichal Wajdeczko 	for (n = 1; n <= num_vfs; n++)
64617899358SMichal Wajdeczko 		sysfs_remove_link(xe->sriov.pf.vfs[VFID(n)].kobj, "device");
64717899358SMichal Wajdeczko }
648