brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 5a1d65e Raw
153 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */5 6#include <drm/drm_managed.h>7 8#include "regs/xe_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 convert19 *20 * Returns: SR-IOV mode as a user friendly string.21 */22const 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 36static 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 on46 *47 * This function should be called only once and as soon as possible during48 * driver probe to detect whether we are running a SR-IOV Physical Function49 * (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 */54void xe_sriov_probe_early(struct xe_device *xe)55{56	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);57	enum xe_sriov_mode mode = XE_SRIOV_MODE_NONE;58	bool has_sriov = xe->info.has_sriov;59 60	if (has_sriov) {61		if (test_is_vf(xe))62			mode = XE_SRIOV_MODE_VF;63		else if (xe_sriov_pf_readiness(xe))64			mode = XE_SRIOV_MODE_PF;65	} else if (pci_sriov_get_totalvfs(pdev)) {66		/*67		 * Even if we have not enabled SR-IOV support using the68		 * platform specific has_sriov flag, the hardware may still69		 * report SR-IOV capability and the PCI layer may wrongly70		 * advertise driver support to enable VFs. Explicitly reset71		 * the number of supported VFs to zero to avoid confusion.72		 */73		drm_info(&xe->drm, "Support for SR-IOV is not available\n");74		pci_sriov_set_totalvfs(pdev, 0);75	}76 77	xe_assert(xe, !xe->sriov.__mode);78	xe->sriov.__mode = mode;79	xe_assert(xe, xe->sriov.__mode);80 81	if (has_sriov)82		drm_info(&xe->drm, "Running in %s mode\n",83			 xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));84}85 86static void fini_sriov(struct drm_device *drm, void *arg)87{88	struct xe_device *xe = arg;89 90	destroy_workqueue(xe->sriov.wq);91	xe->sriov.wq = NULL;92}93 94/**95 * xe_sriov_init - Initialize SR-IOV specific data.96 * @xe: the &xe_device to initialize97 *98 * In this function we create dedicated workqueue that will be used99 * by the SR-IOV specific workers.100 *101 * Return: 0 on success or a negative error code on failure.102 */103int xe_sriov_init(struct xe_device *xe)104{105	if (!IS_SRIOV(xe))106		return 0;107 108	if (IS_SRIOV_PF(xe)) {109		int err = xe_sriov_pf_init_early(xe);110 111		if (err)112			return err;113	}114 115	xe_assert(xe, !xe->sriov.wq);116	xe->sriov.wq = alloc_workqueue("xe-sriov-wq", 0, 0);117	if (!xe->sriov.wq)118		return -ENOMEM;119 120	return drmm_add_action_or_reset(&xe->drm, fini_sriov, xe);121}122 123/**124 * xe_sriov_print_info - Print basic SR-IOV information.125 * @xe: the &xe_device to print info from126 * @p: the &drm_printer127 *128 * Print SR-IOV related information into provided DRM printer.129 */130void xe_sriov_print_info(struct xe_device *xe, struct drm_printer *p)131{132	drm_printf(p, "supported: %s\n", str_yes_no(xe_device_has_sriov(xe)));133	drm_printf(p, "enabled: %s\n", str_yes_no(IS_SRIOV(xe)));134	drm_printf(p, "mode: %s\n", xe_sriov_mode_to_string(xe_device_sriov_mode(xe)));135}136 137/**138 * xe_sriov_function_name() - Get SR-IOV Function name.139 * @n: the Function number (identifier) to get name of140 * @buf: the buffer to format to141 * @size: size of the buffer (shall be at least 5 bytes)142 *143 * Return: formatted function name ("PF" or "VF%u").144 */145const char *xe_sriov_function_name(unsigned int n, char *buf, size_t size)146{147	if (n)148		snprintf(buf, size, "VF%u", n);149	else150		strscpy(buf, "PF", size);151	return buf;152}153