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 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 
126 static 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 
133 static 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 
148 sriov_init_fail:
149 	nitrox_sriov_cleanup(ndev);
150 	return ret;
151 }
152 
153 static 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 
190 iov_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 
201 static 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 
228 int 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