xref: /linux/drivers/gpu/drm/xe/xe_sriov_pf.c (revision e6c2b0f23221ed43c4cc6f636e9ab7862954d562)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023-2024 Intel Corporation
4  */
5 
6 #include <linux/debugfs.h>
7 #include <drm/drm_debugfs.h>
8 #include <drm/drm_managed.h>
9 
10 #include "xe_assert.h"
11 #include "xe_device.h"
12 #include "xe_module.h"
13 #include "xe_sriov.h"
14 #include "xe_sriov_pf.h"
15 #include "xe_sriov_pf_helpers.h"
16 #include "xe_sriov_pf_service.h"
17 #include "xe_sriov_printk.h"
18 
19 static unsigned int wanted_max_vfs(struct xe_device *xe)
20 {
21 	return xe_modparam.max_vfs;
22 }
23 
24 static int pf_reduce_totalvfs(struct xe_device *xe, int limit)
25 {
26 	struct device *dev = xe->drm.dev;
27 	struct pci_dev *pdev = to_pci_dev(dev);
28 	int err;
29 
30 	err = pci_sriov_set_totalvfs(pdev, limit);
31 	if (err)
32 		xe_sriov_notice(xe, "Failed to set number of VFs to %d (%pe)\n",
33 				limit, ERR_PTR(err));
34 	return err;
35 }
36 
37 static bool pf_continue_as_native(struct xe_device *xe, const char *why)
38 {
39 	xe_sriov_dbg(xe, "%s, continuing as native\n", why);
40 	pf_reduce_totalvfs(xe, 0);
41 	return false;
42 }
43 
44 /**
45  * xe_sriov_pf_readiness - Check if PF functionality can be enabled.
46  * @xe: the &xe_device to check
47  *
48  * This function is called as part of the SR-IOV probe to validate if all
49  * PF prerequisites are satisfied and we can continue with enabling PF mode.
50  *
51  * Return: true if the PF mode can be turned on.
52  */
53 bool xe_sriov_pf_readiness(struct xe_device *xe)
54 {
55 	struct device *dev = xe->drm.dev;
56 	struct pci_dev *pdev = to_pci_dev(dev);
57 	int totalvfs = pci_sriov_get_totalvfs(pdev);
58 	int newlimit = min_t(u16, wanted_max_vfs(xe), totalvfs);
59 
60 	xe_assert(xe, totalvfs <= U16_MAX);
61 
62 	if (!dev_is_pf(dev))
63 		return false;
64 
65 	if (!xe_device_uc_enabled(xe))
66 		return pf_continue_as_native(xe, "Guc submission disabled");
67 
68 	if (!newlimit)
69 		return pf_continue_as_native(xe, "all VFs disabled");
70 
71 	pf_reduce_totalvfs(xe, newlimit);
72 
73 	xe->sriov.pf.device_total_vfs = totalvfs;
74 	xe->sriov.pf.driver_max_vfs = newlimit;
75 
76 	return true;
77 }
78 
79 /**
80  * xe_sriov_pf_init_early - Initialize SR-IOV PF specific data.
81  * @xe: the &xe_device to initialize
82  *
83  * Return: 0 on success or a negative error code on failure.
84  */
85 int xe_sriov_pf_init_early(struct xe_device *xe)
86 {
87 	int err;
88 
89 	xe_assert(xe, IS_SRIOV_PF(xe));
90 
91 	xe->sriov.pf.vfs = drmm_kcalloc(&xe->drm, 1 + xe_sriov_pf_get_totalvfs(xe),
92 					sizeof(*xe->sriov.pf.vfs), GFP_KERNEL);
93 	if (!xe->sriov.pf.vfs)
94 		return -ENOMEM;
95 
96 	err = drmm_mutex_init(&xe->drm, &xe->sriov.pf.master_lock);
97 	if (err)
98 		return err;
99 
100 	xe_sriov_pf_service_init(xe);
101 
102 	return 0;
103 }
104 
105 /**
106  * xe_sriov_pf_print_vfs_summary - Print SR-IOV PF information.
107  * @xe: the &xe_device to print info from
108  * @p: the &drm_printer
109  *
110  * Print SR-IOV PF related information into provided DRM printer.
111  */
112 void xe_sriov_pf_print_vfs_summary(struct xe_device *xe, struct drm_printer *p)
113 {
114 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
115 
116 	xe_assert(xe, IS_SRIOV_PF(xe));
117 
118 	drm_printf(p, "total: %u\n", xe->sriov.pf.device_total_vfs);
119 	drm_printf(p, "supported: %u\n", xe->sriov.pf.driver_max_vfs);
120 	drm_printf(p, "enabled: %u\n", pci_num_vf(pdev));
121 }
122 
123 static int simple_show(struct seq_file *m, void *data)
124 {
125 	struct drm_printer p = drm_seq_file_printer(m);
126 	struct drm_info_node *node = m->private;
127 	struct dentry *parent = node->dent->d_parent;
128 	struct xe_device *xe = parent->d_inode->i_private;
129 	void (*print)(struct xe_device *, struct drm_printer *) = node->info_ent->data;
130 
131 	print(xe, &p);
132 	return 0;
133 }
134 
135 static const struct drm_info_list debugfs_list[] = {
136 	{ .name = "vfs", .show = simple_show, .data = xe_sriov_pf_print_vfs_summary },
137 	{ .name = "versions", .show = simple_show, .data = xe_sriov_pf_service_print_versions },
138 };
139 
140 /**
141  * xe_sriov_pf_debugfs_register - Register PF debugfs attributes.
142  * @xe: the &xe_device
143  * @root: the root &dentry
144  *
145  * Prepare debugfs attributes exposed by the PF.
146  */
147 void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root)
148 {
149 	struct drm_minor *minor = xe->drm.primary;
150 	struct dentry *parent;
151 
152 	/*
153 	 *      /sys/kernel/debug/dri/0/
154 	 *      ├── pf
155 	 *      │   ├── ...
156 	 */
157 	parent = debugfs_create_dir("pf", root);
158 	if (IS_ERR(parent))
159 		return;
160 	parent->d_inode->i_private = xe;
161 
162 	drm_debugfs_create_files(debugfs_list, ARRAY_SIZE(debugfs_list), parent, minor);
163 }
164