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