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