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