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 */ 15 static 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 31 static 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 56 static 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 81 static 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 */ 97 static 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 packet queues */ 113 nitrox_config_pkt_input_rings(ndev); 114 nitrox_config_pkt_solicit_ports(ndev); 115 116 /* set device to ready state */ 117 atomic_set(&ndev->state, __NDEV_READY); 118 119 /* register crypto algorithms */ 120 return nitrox_crypto_register(); 121 } 122 123 static void nitrox_sriov_cleanup(struct nitrox_device *ndev) 124 { 125 /* unregister interrupts for PF in SR-IOV */ 126 nitrox_sriov_unregister_interrupts(ndev); 127 nitrox_mbox_cleanup(ndev); 128 } 129 130 static int nitrox_sriov_init(struct nitrox_device *ndev) 131 { 132 int ret; 133 134 /* register interrupts for PF in SR-IOV */ 135 ret = nitrox_sriov_register_interupts(ndev); 136 if (ret) 137 return ret; 138 139 ret = nitrox_mbox_init(ndev); 140 if (ret) 141 goto sriov_init_fail; 142 143 return 0; 144 145 sriov_init_fail: 146 nitrox_sriov_cleanup(ndev); 147 return ret; 148 } 149 150 static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs) 151 { 152 struct nitrox_device *ndev = pci_get_drvdata(pdev); 153 int err; 154 155 if (!num_vfs_valid(num_vfs)) { 156 dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs); 157 return -EINVAL; 158 } 159 160 if (pci_num_vf(pdev) == num_vfs) 161 return num_vfs; 162 163 err = pci_enable_sriov(pdev, num_vfs); 164 if (err) { 165 dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err); 166 return err; 167 } 168 dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs); 169 170 ndev->mode = num_vfs_to_mode(num_vfs); 171 ndev->iov.num_vfs = num_vfs; 172 ndev->iov.max_vf_queues = vf_mode_to_nr_queues(ndev->mode); 173 /* set bit in flags */ 174 set_bit(__NDEV_SRIOV_BIT, &ndev->flags); 175 176 /* cleanup PF resources */ 177 nitrox_pf_cleanup(ndev); 178 179 /* PF SR-IOV mode initialization */ 180 err = nitrox_sriov_init(ndev); 181 if (err) 182 goto iov_fail; 183 184 config_nps_core_vfcfg_mode(ndev, ndev->mode); 185 return num_vfs; 186 187 iov_fail: 188 pci_disable_sriov(pdev); 189 /* clear bit in flags */ 190 clear_bit(__NDEV_SRIOV_BIT, &ndev->flags); 191 ndev->iov.num_vfs = 0; 192 ndev->mode = __NDEV_MODE_PF; 193 /* reset back to working mode in PF */ 194 nitrox_pf_reinit(ndev); 195 return err; 196 } 197 198 static int nitrox_sriov_disable(struct pci_dev *pdev) 199 { 200 struct nitrox_device *ndev = pci_get_drvdata(pdev); 201 202 if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags)) 203 return 0; 204 205 if (pci_vfs_assigned(pdev)) { 206 dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n"); 207 return -EPERM; 208 } 209 pci_disable_sriov(pdev); 210 /* clear bit in flags */ 211 clear_bit(__NDEV_SRIOV_BIT, &ndev->flags); 212 213 ndev->iov.num_vfs = 0; 214 ndev->iov.max_vf_queues = 0; 215 ndev->mode = __NDEV_MODE_PF; 216 217 /* cleanup PF SR-IOV resources */ 218 nitrox_sriov_cleanup(ndev); 219 220 config_nps_core_vfcfg_mode(ndev, ndev->mode); 221 222 return nitrox_pf_reinit(ndev); 223 } 224 225 int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs) 226 { 227 if (!num_vfs) 228 return nitrox_sriov_disable(pdev); 229 230 return nitrox_sriov_enable(pdev, num_vfs); 231 } 232