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 */
17const 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 */
43void 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
59static 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 */
76int 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