Linux Audio

Check our new training course

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