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