Commit 146e4384 authored by Michal Wajdeczko's avatar Michal Wajdeczko
Browse files

drm/xe: Add proper detection of the SR-IOV PF mode



SR-IOV PF mode detection is based on PCI capability as reported by
the PCI dev_is_pf() function and additionally on 'max_vfs' module
parameter which could be also used to disable PF capability even
if SR-IOV PF capability is reported by the hardware.

Signed-off-by: default avatarMichal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240404154431.583-3-michal.wajdeczko@intel.com
parent e806fac0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -159,7 +159,8 @@ xe-$(CONFIG_PCI_IOV) += \
	xe_gt_sriov_pf_control.o \
	xe_lmtt.o \
	xe_lmtt_2l.o \
	xe_lmtt_ml.o
	xe_lmtt_ml.o \
	xe_sriov_pf.o

# include helpers for tests even when XE is built-in
ifdef CONFIG_DRM_XE_KUNIT_TEST
+4 −0
Original line number Diff line number Diff line
@@ -321,6 +321,10 @@ struct xe_device {
	struct {
		/** @sriov.__mode: SR-IOV mode (Don't access directly!) */
		enum xe_sriov_mode __mode;

		/** @sriov.pf: PF specific data */
		struct xe_device_pf pf;

		/** @sriov.wq: workqueue used by the virtualization workers */
		struct workqueue_struct *wq;
	} sriov;
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include "xe_device.h"
#include "xe_mmio.h"
#include "xe_sriov.h"
#include "xe_sriov_pf.h"

/**
 * xe_sriov_mode_to_string - Convert enum value to string.
@@ -58,6 +59,8 @@ void xe_sriov_probe_early(struct xe_device *xe)
	if (has_sriov) {
		if (test_is_vf(xe))
			mode = XE_SRIOV_MODE_VF;
		else if (xe_sriov_pf_readiness(xe))
			mode = XE_SRIOV_MODE_PF;
	}

	xe_assert(xe, !xe->sriov.__mode);
+89 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: MIT
/*
 * Copyright © 2023-2024 Intel Corporation
 */

#include "xe_assert.h"
#include "xe_device.h"
#include "xe_module.h"
#include "xe_sriov.h"
#include "xe_sriov_pf.h"
#include "xe_sriov_printk.h"

static unsigned int wanted_max_vfs(struct xe_device *xe)
{
	return xe_modparam.max_vfs;
}

static int pf_reduce_totalvfs(struct xe_device *xe, int limit)
{
	struct device *dev = xe->drm.dev;
	struct pci_dev *pdev = to_pci_dev(dev);
	int err;

	err = pci_sriov_set_totalvfs(pdev, limit);
	if (err)
		xe_sriov_notice(xe, "Failed to set number of VFs to %d (%pe)\n",
				limit, ERR_PTR(err));
	return err;
}

static bool pf_continue_as_native(struct xe_device *xe, const char *why)
{
	xe_sriov_dbg(xe, "%s, continuing as native\n", why);
	pf_reduce_totalvfs(xe, 0);
	return false;
}

/**
 * xe_sriov_pf_readiness - Check if PF functionality can be enabled.
 * @xe: the &xe_device to check
 *
 * This function is called as part of the SR-IOV probe to validate if all
 * PF prerequisites are satisfied and we can continue with enabling PF mode.
 *
 * Return: true if the PF mode can be turned on.
 */
bool xe_sriov_pf_readiness(struct xe_device *xe)
{
	struct device *dev = xe->drm.dev;
	struct pci_dev *pdev = to_pci_dev(dev);
	int totalvfs = pci_sriov_get_totalvfs(pdev);
	int newlimit = min_t(u16, wanted_max_vfs(xe), totalvfs);

	xe_assert(xe, totalvfs <= U16_MAX);

	if (!dev_is_pf(dev))
		return false;

	if (!xe_device_uc_enabled(xe))
		return pf_continue_as_native(xe, "Guc submission disabled");

	if (!newlimit)
		return pf_continue_as_native(xe, "all VFs disabled");

	pf_reduce_totalvfs(xe, newlimit);

	xe->sriov.pf.device_total_vfs = totalvfs;
	xe->sriov.pf.driver_max_vfs = newlimit;

	return true;
}

/**
 * xe_sriov_pf_print_vfs_summary - Print SR-IOV PF information.
 * @xe: the &xe_device to print info from
 * @p: the &drm_printer
 *
 * Print SR-IOV PF related information into provided DRM printer.
 */
void xe_sriov_pf_print_vfs_summary(struct xe_device *xe, struct drm_printer *p)
{
	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);

	xe_assert(xe, IS_SRIOV_PF(xe));

	drm_printf(p, "total: %u\n", xe->sriov.pf.device_total_vfs);
	drm_printf(p, "supported: %u\n", xe->sriov.pf.driver_max_vfs);
	drm_printf(p, "enabled: %u\n", pci_num_vf(pdev));
}
+24 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2023-2024 Intel Corporation
 */

#ifndef _XE_SRIOV_PF_H_
#define _XE_SRIOV_PF_H_

#include <linux/types.h>

struct drm_printer;
struct xe_device;

#ifdef CONFIG_PCI_IOV
bool xe_sriov_pf_readiness(struct xe_device *xe);
void xe_sriov_pf_print_vfs_summary(struct xe_device *xe, struct drm_printer *p);
#else
static inline bool xe_sriov_pf_readiness(struct xe_device *xe)
{
	return false;
}
#endif

#endif
Loading