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 10 static inline bool num_vfs_valid(int num_vfs) 11 { 12 bool valid = false; 13 14 switch (num_vfs) { 15 case 16: 16 case 32: 17 case 64: 18 case 128: 19 valid = true; 20 break; 21 } 22 23 return valid; 24 } 25 26 static inline enum vf_mode num_vfs_to_mode(int num_vfs) 27 { 28 enum vf_mode mode = 0; 29 30 switch (num_vfs) { 31 case 0: 32 mode = __NDEV_MODE_PF; 33 break; 34 case 16: 35 mode = __NDEV_MODE_VF16; 36 break; 37 case 32: 38 mode = __NDEV_MODE_VF32; 39 break; 40 case 64: 41 mode = __NDEV_MODE_VF64; 42 break; 43 case 128: 44 mode = __NDEV_MODE_VF128; 45 break; 46 } 47 48 return mode; 49 } 50 51 static void pf_sriov_cleanup(struct nitrox_device *ndev) 52 { 53 /* PF has no queues in SR-IOV mode */ 54 atomic_set(&ndev->state, __NDEV_NOT_READY); 55 /* unregister crypto algorithms */ 56 nitrox_crypto_unregister(); 57 58 /* cleanup PF resources */ 59 nitrox_unregister_interrupts(ndev); 60 nitrox_common_sw_cleanup(ndev); 61 } 62 63 static int pf_sriov_init(struct nitrox_device *ndev) 64 { 65 int err; 66 67 /* allocate resources for PF */ 68 err = nitrox_common_sw_init(ndev); 69 if (err) 70 return err; 71 72 err = nitrox_register_interrupts(ndev); 73 if (err) { 74 nitrox_common_sw_cleanup(ndev); 75 return err; 76 } 77 78 /* configure the packet queues */ 79 nitrox_config_pkt_input_rings(ndev); 80 nitrox_config_pkt_solicit_ports(ndev); 81 82 /* set device to ready state */ 83 atomic_set(&ndev->state, __NDEV_READY); 84 85 /* register crypto algorithms */ 86 return nitrox_crypto_register(); 87 } 88 89 static int nitrox_sriov_enable(struct pci_dev *pdev, int num_vfs) 90 { 91 struct nitrox_device *ndev = pci_get_drvdata(pdev); 92 int err; 93 94 if (!num_vfs_valid(num_vfs)) { 95 dev_err(DEV(ndev), "Invalid num_vfs %d\n", num_vfs); 96 return -EINVAL; 97 } 98 99 if (pci_num_vf(pdev) == num_vfs) 100 return num_vfs; 101 102 err = pci_enable_sriov(pdev, num_vfs); 103 if (err) { 104 dev_err(DEV(ndev), "failed to enable PCI sriov %d\n", err); 105 return err; 106 } 107 dev_info(DEV(ndev), "Enabled VF(s) %d\n", num_vfs); 108 109 ndev->num_vfs = num_vfs; 110 ndev->mode = num_vfs_to_mode(num_vfs); 111 /* set bit in flags */ 112 set_bit(__NDEV_SRIOV_BIT, &ndev->flags); 113 114 /* cleanup PF resources */ 115 pf_sriov_cleanup(ndev); 116 117 config_nps_core_vfcfg_mode(ndev, ndev->mode); 118 119 return num_vfs; 120 } 121 122 static int nitrox_sriov_disable(struct pci_dev *pdev) 123 { 124 struct nitrox_device *ndev = pci_get_drvdata(pdev); 125 126 if (!test_bit(__NDEV_SRIOV_BIT, &ndev->flags)) 127 return 0; 128 129 if (pci_vfs_assigned(pdev)) { 130 dev_warn(DEV(ndev), "VFs are attached to VM. Can't disable SR-IOV\n"); 131 return -EPERM; 132 } 133 pci_disable_sriov(pdev); 134 /* clear bit in flags */ 135 clear_bit(__NDEV_SRIOV_BIT, &ndev->flags); 136 137 ndev->num_vfs = 0; 138 ndev->mode = __NDEV_MODE_PF; 139 140 config_nps_core_vfcfg_mode(ndev, ndev->mode); 141 142 return pf_sriov_init(ndev); 143 } 144 145 int nitrox_sriov_configure(struct pci_dev *pdev, int num_vfs) 146 { 147 if (!num_vfs) 148 return nitrox_sriov_disable(pdev); 149 150 return nitrox_sriov_enable(pdev, num_vfs); 151 } 152