1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2023 Intel Corporation
4 */
5
6 #include <linux/fault-inject.h>
7
8 #include <drm/drm_managed.h>
9
10 #include "regs/xe_regs.h"
11
12 #include "xe_assert.h"
13 #include "xe_device.h"
14 #include "xe_mmio.h"
15 #include "xe_sriov.h"
16 #include "xe_sriov_pf.h"
17 #include "xe_sriov_vf.h"
18
19 /**
20 * xe_sriov_mode_to_string - Convert enum value to string.
21 * @mode: the &xe_sriov_mode to convert
22 *
23 * Returns: SR-IOV mode as a user friendly string.
24 */
xe_sriov_mode_to_string(enum xe_sriov_mode mode)25 const char *xe_sriov_mode_to_string(enum xe_sriov_mode mode)
26 {
27 switch (mode) {
28 case XE_SRIOV_MODE_NONE:
29 return "none";
30 case XE_SRIOV_MODE_PF:
31 return "SR-IOV PF";
32 case XE_SRIOV_MODE_VF:
33 return "SR-IOV VF";
34 default:
35 return "<invalid>";
36 }
37 }
38
test_is_vf(struct xe_device * xe)39 static bool test_is_vf(struct xe_device *xe)
40 {
41 u32 value = xe_mmio_read32(xe_root_tile_mmio(xe), VF_CAP_REG);
42
43 return value & VF_CAP;
44 }
45
46 /**
47 * xe_sriov_probe_early - Probe a SR-IOV mode.
48 * @xe: the &xe_device to probe mode on
49 *
50 * This function should be called only once and as soon as possible during
51 * driver probe to detect whether we are running a SR-IOV Physical Function
52 * (PF) or a Virtual Function (VF) device.
53 *
54 * SR-IOV PF mode detection is based on PCI @dev_is_pf() function.
55 * SR-IOV VF mode detection is based on dedicated MMIO register read.
56 */
xe_sriov_probe_early(struct xe_device * xe)57 void xe_sriov_probe_early(struct xe_device *xe)
58 {
59 struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
60 enum xe_sriov_mode mode = XE_SRIOV_MODE_NONE;
61 bool has_sriov = xe->info.has_sriov;
62
63 if (has_sriov) {
64 if (test_is_vf(xe))
65 mode = XE_SRIOV_MODE_VF;
66 else if (xe_sriov_pf_readiness(xe))
67 mode = XE_SRIOV_MODE_PF;
68 } else if (pci_sriov_get_totalvfs(pdev)) {
69 /*
70 * Even if we have not enabled SR-IOV support using the
71 * platform specific has_sriov flag, the hardware may still
72 * report SR-IOV capability and the PCI layer may wrongly
73 * advertise driver support to enable VFs. Explicitly reset
74 * the number of supported VFs to zero to avoid confusion.
75 */
76 drm_info(&xe->drm, "Support for SR-IOV is not available\n");
77 pci_sriov_set_totalvfs(pdev, 0);
78 }
79
80 xe_assert(xe, !xe->sriov.__mode);
81 xe->sriov.__mode = mode;
82 xe_assert(xe, xe->sriov.__mode);
83
84 if (has_sriov)
85 drm_info(&xe->drm, "Running in %s mode\n",
86 xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
87 }
88
fini_sriov(struct drm_device * drm,void * arg)89 static void fini_sriov(struct drm_device *drm, void *arg)
90 {
91 struct xe_device *xe = arg;
92
93 destroy_workqueue(xe->sriov.wq);
94 xe->sriov.wq = NULL;
95 }
96
97 /**
98 * xe_sriov_init - Initialize SR-IOV specific data.
99 * @xe: the &xe_device to initialize
100 *
101 * In this function we create dedicated workqueue that will be used
102 * by the SR-IOV specific workers.
103 *
104 * Return: 0 on success or a negative error code on failure.
105 */
xe_sriov_init(struct xe_device * xe)106 int xe_sriov_init(struct xe_device *xe)
107 {
108 if (!IS_SRIOV(xe))
109 return 0;
110
111 if (IS_SRIOV_PF(xe)) {
112 int err = xe_sriov_pf_init_early(xe);
113
114 if (err)
115 return err;
116 }
117
118 if (IS_SRIOV_VF(xe))
119 xe_sriov_vf_init_early(xe);
120
121 xe_assert(xe, !xe->sriov.wq);
122 xe->sriov.wq = alloc_workqueue("xe-sriov-wq", 0, 0);
123 if (!xe->sriov.wq)
124 return -ENOMEM;
125
126 return drmm_add_action_or_reset(&xe->drm, fini_sriov, xe);
127 }
128 ALLOW_ERROR_INJECTION(xe_sriov_init, ERRNO); /* See xe_pci_probe() */
129
130 /**
131 * xe_sriov_print_info - Print basic SR-IOV information.
132 * @xe: the &xe_device to print info from
133 * @p: the &drm_printer
134 *
135 * Print SR-IOV related information into provided DRM printer.
136 */
xe_sriov_print_info(struct xe_device * xe,struct drm_printer * p)137 void xe_sriov_print_info(struct xe_device *xe, struct drm_printer *p)
138 {
139 drm_printf(p, "supported: %s\n", str_yes_no(xe_device_has_sriov(xe)));
140 drm_printf(p, "enabled: %s\n", str_yes_no(IS_SRIOV(xe)));
141 drm_printf(p, "mode: %s\n", xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
142 }
143
144 /**
145 * xe_sriov_function_name() - Get SR-IOV Function name.
146 * @n: the Function number (identifier) to get name of
147 * @buf: the buffer to format to
148 * @size: size of the buffer (shall be at least 5 bytes)
149 *
150 * Return: formatted function name ("PF" or "VF%u").
151 */
xe_sriov_function_name(unsigned int n,char * buf,size_t size)152 const char *xe_sriov_function_name(unsigned int n, char *buf, size_t size)
153 {
154 if (n)
155 snprintf(buf, size, "VF%u", n);
156 else
157 strscpy(buf, "PF", size);
158 return buf;
159 }
160