nitrox_sriov.c (4640B)
1// SPDX-License-Identifier: GPL-2.0 2#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 count 13 * @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 disabled 95 * @ndev: NITROX device 96 */ 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}