xref: /linux/drivers/gpu/drm/xe/xe_sriov.c (revision daa121128a2d2ac6006159e2c47676e4fcd21eab)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <drm/drm_managed.h>
7 
8 #include "regs/xe_sriov_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  */
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 
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  */
54 void xe_sriov_probe_early(struct xe_device *xe)
55 {
56 	enum xe_sriov_mode mode = XE_SRIOV_MODE_NONE;
57 	bool has_sriov = xe->info.has_sriov;
58 
59 	if (has_sriov) {
60 		if (test_is_vf(xe))
61 			mode = XE_SRIOV_MODE_VF;
62 		else if (xe_sriov_pf_readiness(xe))
63 			mode = XE_SRIOV_MODE_PF;
64 	}
65 
66 	xe_assert(xe, !xe->sriov.__mode);
67 	xe->sriov.__mode = mode;
68 	xe_assert(xe, xe->sriov.__mode);
69 
70 	if (has_sriov)
71 		drm_info(&xe->drm, "Running in %s mode\n",
72 			 xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
73 }
74 
75 static void fini_sriov(struct drm_device *drm, void *arg)
76 {
77 	struct xe_device *xe = arg;
78 
79 	destroy_workqueue(xe->sriov.wq);
80 	xe->sriov.wq = NULL;
81 }
82 
83 /**
84  * xe_sriov_init - Initialize SR-IOV specific data.
85  * @xe: the &xe_device to initialize
86  *
87  * In this function we create dedicated workqueue that will be used
88  * by the SR-IOV specific workers.
89  *
90  * Return: 0 on success or a negative error code on failure.
91  */
92 int xe_sriov_init(struct xe_device *xe)
93 {
94 	if (!IS_SRIOV(xe))
95 		return 0;
96 
97 	if (IS_SRIOV_PF(xe)) {
98 		int err = xe_sriov_pf_init_early(xe);
99 
100 		if (err)
101 			return err;
102 	}
103 
104 	xe_assert(xe, !xe->sriov.wq);
105 	xe->sriov.wq = alloc_workqueue("xe-sriov-wq", 0, 0);
106 	if (!xe->sriov.wq)
107 		return -ENOMEM;
108 
109 	return drmm_add_action_or_reset(&xe->drm, fini_sriov, xe);
110 }
111 
112 /**
113  * xe_sriov_print_info - Print basic SR-IOV information.
114  * @xe: the &xe_device to print info from
115  * @p: the &drm_printer
116  *
117  * Print SR-IOV related information into provided DRM printer.
118  */
119 void xe_sriov_print_info(struct xe_device *xe, struct drm_printer *p)
120 {
121 	drm_printf(p, "supported: %s\n", str_yes_no(xe_device_has_sriov(xe)));
122 	drm_printf(p, "enabled: %s\n", str_yes_no(IS_SRIOV(xe)));
123 	drm_printf(p, "mode: %s\n", xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
124 }
125 
126 /**
127  * xe_sriov_function_name() - Get SR-IOV Function name.
128  * @n: the Function number (identifier) to get name of
129  * @buf: the buffer to format to
130  * @size: size of the buffer (shall be at least 5 bytes)
131  *
132  * Return: formatted function name ("PF" or "VF%u").
133  */
134 const char *xe_sriov_function_name(unsigned int n, char *buf, size_t size)
135 {
136 	if (n)
137 		snprintf(buf, size, "VF%u", n);
138 	else
139 		strscpy(buf, "PF", size);
140 	return buf;
141 }
142