brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 43287f8 Raw
235 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/pci.h>3#include <linux/delay.h>4 5#include "nitrox_dev.h"6#include "nitrox_hal.h"7#include "nitrox_common.h"8#include "nitrox_isr.h"9#include "nitrox_mbx.h"10 11/**12 * num_vfs_valid - validate VF count13 * @num_vfs: number of VF(s)14 */15static inline bool num_vfs_valid(int num_vfs)16{17	bool valid = false;18 19	switch (num_vfs) {20	case 16:21	case 32:22	case 64:23	case 128:24		valid = true;25		break;26	}27 28	return valid;29}30 31static inline enum vf_mode num_vfs_to_mode(int num_vfs)32{33	enum vf_mode mode = 0;34 35	switch (num_vfs) {36	case 0:37		mode = __NDEV_MODE_PF;38		break;39	case 16:40		mode = __NDEV_MODE_VF16;41		break;42	case 32:43		mode = __NDEV_MODE_VF32;44		break;45	case 64:46		mode = __NDEV_MODE_VF64;47		break;48	case 128:49		mode = __NDEV_MODE_VF128;50		break;51	}52 53	return mode;54}55 56static inline int vf_mode_to_nr_queues(enum vf_mode mode)57{58	int nr_queues = 0;59 60	switch (mode) {61	case __NDEV_MODE_PF:62		nr_queues = MAX_PF_QUEUES;63		break;64	case __NDEV_MODE_VF16:65		nr_queues = 8;66		break;67	case __NDEV_MODE_VF32:68		nr_queues = 4;69		break;70	case __NDEV_MODE_VF64:71		nr_queues = 2;72		break;73	case __NDEV_MODE_VF128:74		nr_queues = 1;75		break;76	}77 78	return nr_queues;79}80 81static void nitrox_pf_cleanup(struct nitrox_device *ndev)82{83	 /* PF has no queues in SR-IOV mode */84	atomic_set(&ndev->state, __NDEV_NOT_READY);85	/* unregister crypto algorithms */86	nitrox_crypto_unregister();87 88	/* cleanup PF resources */89	nitrox_unregister_interrupts(ndev);90	nitrox_common_sw_cleanup(ndev);91}92 93/**94 * nitrox_pf_reinit - re-initialize PF resources once SR-IOV is disabled95 * @ndev: NITROX device96 */97static int nitrox_pf_reinit(struct nitrox_device *ndev)98{99	int err;100 101	/* allocate resources for PF */102	err = nitrox_common_sw_init(ndev);103	if (err)104		return err;105 106	err = nitrox_register_interrupts(ndev);107	if (err) {108		nitrox_common_sw_cleanup(ndev);109		return err;110	}111 112	/* configure the AQM queues */113	nitrox_config_aqm_rings(ndev);114 115	/* configure the packet queues */116	nitrox_config_pkt_input_rings(ndev);117	nitrox_config_pkt_solicit_ports(ndev);118 119	/* set device to ready state */120	atomic_set(&ndev->state, __NDEV_READY);121 122	/* register crypto algorithms */123	return nitrox_crypto_register();124}125 126static void nitrox_sriov_cleanup(struct nitrox_device *ndev)127{128	/* unregister interrupts for PF in SR-IOV */129	nitrox_sriov_unregister_interrupts(ndev);130	nitrox_mbox_cleanup(ndev);131}132 133static int nitrox_sriov_init(struct nitrox_device *ndev)134{135	int ret;136 137	/* register interrupts for PF in SR-IOV */138	ret = nitrox_sriov_register_interupts(ndev);139	if (ret)140		return ret;141 142	ret = nitrox_mbox_init(ndev);143	if (ret)144		goto sriov_init_fail;145 146	return 0;147 148sriov_init_fail:149	nitrox_sriov_cleanup(ndev);150	return ret;151}152 153static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs)154{155	struct nitrox_device *ndev = pci_get_drvdata(pdev);156	int err;157 158	if (!num_vfs_valid(num_vfs)) {159		dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs);160		return -EINVAL;161	}162 163	if (pci_num_vf(pdev) == num_vfs)164		return num_vfs;165 166	err = pci_enable_sriov(pdev, num_vfs);167	if (err) {168		dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err);169		return err;170	}171	dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs);172 173	ndev->mode = num_vfs_to_mode(num_vfs);174	ndev->iov.num_vfs = num_vfs;175	ndev->iov.max_vf_queues = vf_mode_to_nr_queues(ndev->mode);176	/* set bit in flags */177	set_bit(__NDEV_SRIOV_BIT, &ndev->flags);178 179	/* cleanup PF resources */180	nitrox_pf_cleanup(ndev);181 182	/* PF SR-IOV mode initialization */183	err = nitrox_sriov_init(ndev);184	if (err)185		goto iov_fail;186 187	config_nps_core_vfcfg_mode(ndev, ndev->mode);188	return num_vfs;189 190iov_fail:191	pci_disable_sriov(pdev);192	/* clear bit in flags */193	clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);194	ndev->iov.num_vfs = 0;195	ndev->mode = __NDEV_MODE_PF;196	/* reset back to working mode in PF */197	nitrox_pf_reinit(ndev);198	return err;199}200 201static int nitrox_sriov_disable(struct pci_dev *pdev)202{203	struct nitrox_device *ndev = pci_get_drvdata(pdev);204 205	if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags))206		return 0;207 208	if (pci_vfs_assigned(pdev)) {209		dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n");210		return -EPERM;211	}212	pci_disable_sriov(pdev);213	/* clear bit in flags */214	clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);215 216	ndev->iov.num_vfs = 0;217	ndev->iov.max_vf_queues = 0;218	ndev->mode = __NDEV_MODE_PF;219 220	/* cleanup PF SR-IOV resources */221	nitrox_sriov_cleanup(ndev);222 223	config_nps_core_vfcfg_mode(ndev, ndev->mode);224 225	return nitrox_pf_reinit(ndev);226}227 228int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs)229{230	if (!num_vfs)231		return nitrox_sriov_disable(pdev);232 233	return nitrox_sriov_enable(pdev, num_vfs);234}235