brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · aaceee7 Raw
171 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023-2024 Intel Corporation4 */5 6#include "xe_assert.h"7#include "xe_device.h"8#include "xe_gt_sriov_pf_config.h"9#include "xe_gt_sriov_pf_control.h"10#include "xe_pci_sriov.h"11#include "xe_pm.h"12#include "xe_sriov.h"13#include "xe_sriov_pf_helpers.h"14#include "xe_sriov_printk.h"15 16static int pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs)17{18	unsigned int n;19 20	for (n = 1; n <= num_vfs; n++)21		if (!xe_gt_sriov_pf_config_is_empty(gt, n))22			return false;23 24	return true;25}26 27static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)28{29	struct xe_gt *gt;30	unsigned int id;31	int result = 0, err;32 33	for_each_gt(gt, xe, id) {34		if (!pf_needs_provisioning(gt, num_vfs))35			continue;36		err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);37		result = result ?: err;38	}39 40	return result;41}42 43static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)44{45	struct xe_gt *gt;46	unsigned int id;47	unsigned int n;48 49	for_each_gt(gt, xe, id)50		for (n = 1; n <= num_vfs; n++)51			xe_gt_sriov_pf_config_release(gt, n, true);52}53 54static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs)55{56	struct xe_gt *gt;57	unsigned int id;58	unsigned int n;59 60	for_each_gt(gt, xe, id)61		for (n = 1; n <= num_vfs; n++)62			xe_gt_sriov_pf_control_trigger_flr(gt, n);63}64 65static int pf_enable_vfs(struct xe_device *xe, int num_vfs)66{67	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);68	int total_vfs = xe_sriov_pf_get_totalvfs(xe);69	int err;70 71	xe_assert(xe, IS_SRIOV_PF(xe));72	xe_assert(xe, num_vfs > 0);73	xe_assert(xe, num_vfs <= total_vfs);74	xe_sriov_dbg(xe, "enabling %u VF%s\n", num_vfs, str_plural(num_vfs));75 76	/*77	 * We must hold additional reference to the runtime PM to keep PF in D078	 * during VFs lifetime, as our VFs do not implement the PM capability.79	 *80	 * With PF being in D0 state, all VFs will also behave as in D0 state.81	 * This will also keep GuC alive with all VFs' configurations.82	 *83	 * We will release this additional PM reference in pf_disable_vfs().84	 */85	xe_pm_runtime_get_noresume(xe);86 87	err = pf_provision_vfs(xe, num_vfs);88	if (err < 0)89		goto failed;90 91	err = pci_enable_sriov(pdev, num_vfs);92	if (err < 0)93		goto failed;94 95	xe_sriov_info(xe, "Enabled %u of %u VF%s\n",96		      num_vfs, total_vfs, str_plural(total_vfs));97	return num_vfs;98 99failed:100	pf_unprovision_vfs(xe, num_vfs);101	xe_pm_runtime_put(xe);102 103	xe_sriov_notice(xe, "Failed to enable %u VF%s (%pe)\n",104			num_vfs, str_plural(num_vfs), ERR_PTR(err));105	return err;106}107 108static int pf_disable_vfs(struct xe_device *xe)109{110	struct device *dev = xe->drm.dev;111	struct pci_dev *pdev = to_pci_dev(dev);112	u16 num_vfs = pci_num_vf(pdev);113 114	xe_assert(xe, IS_SRIOV_PF(xe));115	xe_sriov_dbg(xe, "disabling %u VF%s\n", num_vfs, str_plural(num_vfs));116 117	if (!num_vfs)118		return 0;119 120	pci_disable_sriov(pdev);121 122	pf_reset_vfs(xe, num_vfs);123 124	pf_unprovision_vfs(xe, num_vfs);125 126	/* not needed anymore - see pf_enable_vfs() */127	xe_pm_runtime_put(xe);128 129	xe_sriov_info(xe, "Disabled %u VF%s\n", num_vfs, str_plural(num_vfs));130	return 0;131}132 133/**134 * xe_pci_sriov_configure - Configure SR-IOV (enable/disable VFs).135 * @pdev: the &pci_dev136 * @num_vfs: number of VFs to enable or zero to disable all VFs137 *138 * This is the Xe implementation of struct pci_driver.sriov_configure callback.139 *140 * This callback will be called by the PCI subsystem to enable or disable SR-IOV141 * Virtual Functions (VFs) as requested by the used via the PCI sysfs interface.142 *143 * Return: number of configured VFs or a negative error code on failure.144 */145int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)146{147	struct xe_device *xe = pdev_to_xe_device(pdev);148	int ret;149 150	if (!IS_SRIOV_PF(xe))151		return -ENODEV;152 153	if (num_vfs < 0)154		return -EINVAL;155 156	if (num_vfs > xe_sriov_pf_get_totalvfs(xe))157		return -ERANGE;158 159	if (num_vfs && pci_num_vf(pdev))160		return -EBUSY;161 162	xe_pm_runtime_get(xe);163	if (num_vfs > 0)164		ret = pf_enable_vfs(xe, num_vfs);165	else166		ret = pf_disable_vfs(xe);167	xe_pm_runtime_put(xe);168 169	return ret;170}171