xref: /linux/drivers/gpu/drm/xe/xe_sriov.c (revision 78c3925c048c752334873f56c3a3d1c9d53e0416)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <drm/drm_managed.h>
7 
8 #include "xe_assert.h"
9 #include "xe_sriov.h"
10 
11 /**
12  * xe_sriov_mode_to_string - Convert enum value to string.
13  * @mode: the &xe_sriov_mode to convert
14  *
15  * Returns: SR-IOV mode as a user friendly string.
16  */
17 const char *xe_sriov_mode_to_string(enum xe_sriov_mode mode)
18 {
19 	switch (mode) {
20 	case XE_SRIOV_MODE_NONE:
21 		return "none";
22 	case XE_SRIOV_MODE_PF:
23 		return "SR-IOV PF";
24 	case XE_SRIOV_MODE_VF:
25 		return "SR-IOV VF";
26 	default:
27 		return "<invalid>";
28 	}
29 }
30 
31 /**
32  * xe_sriov_probe_early - Probe a SR-IOV mode.
33  * @xe: the &xe_device to probe mode on
34  * @has_sriov: flag indicating hardware support for SR-IOV
35  *
36  * This function should be called only once and as soon as possible during
37  * driver probe to detect whether we are running a SR-IOV Physical Function
38  * (PF) or a Virtual Function (VF) device.
39  *
40  * SR-IOV PF mode detection is based on PCI @dev_is_pf() function.
41  * SR-IOV VF mode detection is based on dedicated MMIO register read.
42  */
43 void xe_sriov_probe_early(struct xe_device *xe, bool has_sriov)
44 {
45 	enum xe_sriov_mode mode = XE_SRIOV_MODE_NONE;
46 
47 	/* TODO: replace with proper mode detection */
48 	xe_assert(xe, !has_sriov);
49 
50 	xe_assert(xe, !xe->sriov.__mode);
51 	xe->sriov.__mode = mode;
52 	xe_assert(xe, xe->sriov.__mode);
53 
54 	if (has_sriov)
55 		drm_info(&xe->drm, "Running in %s mode\n",
56 			 xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));
57 }
58 
59 static void fini_sriov(struct drm_device *drm, void *arg)
60 {
61 	struct xe_device *xe = arg;
62 
63 	destroy_workqueue(xe->sriov.wq);
64 	xe->sriov.wq = NULL;
65 }
66 
67 /**
68  * xe_sriov_init - Initialize SR-IOV specific data.
69  * @xe: the &xe_device to initialize
70  *
71  * In this function we create dedicated workqueue that will be used
72  * by the SR-IOV specific workers.
73  *
74  * Return: 0 on success or a negative error code on failure.
75  */
76 int xe_sriov_init(struct xe_device *xe)
77 {
78 	if (!IS_SRIOV(xe))
79 		return 0;
80 
81 	xe_assert(xe, !xe->sriov.wq);
82 	xe->sriov.wq = alloc_workqueue("xe-sriov-wq", 0, 0);
83 	if (!xe->sriov.wq)
84 		return -ENOMEM;
85 
86 	return drmm_add_action_or_reset(&xe->drm, fini_sriov, xe);
87 }
88