1
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
13
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
84 atomic_set(&ndev->state, __NDEV_NOT_READY);
85
86 nitrox_crypto_unregister();
87
88
89 nitrox_unregister_interrupts(ndev);
90 nitrox_common_sw_cleanup(ndev);
91}
92
93
94
95
96
97static int nitrox_pf_reinit(struct nitrox_device *ndev)
98{
99 int err;
100
101
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
113 nitrox_config_pkt_input_rings(ndev);
114 nitrox_config_pkt_solicit_ports(ndev);
115
116
117 atomic_set(&ndev->state, __NDEV_READY);
118
119
120 return nitrox_crypto_register();
121}
122
123static void nitrox_sriov_cleanup(struct nitrox_device *ndev)
124{
125
126 nitrox_sriov_unregister_interrupts(ndev);
127 nitrox_mbox_cleanup(ndev);
128}
129
130static int nitrox_sriov_init(struct nitrox_device *ndev)
131{
132 int ret;
133
134
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
145sriov_init_fail:
146 nitrox_sriov_cleanup(ndev);
147 return ret;
148}
149
150static 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
174 set_bit(__NDEV_SRIOV_BIT, &ndev->flags);
175
176
177 nitrox_pf_cleanup(ndev);
178
179
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
187iov_fail:
188 pci_disable_sriov(pdev);
189
190 clear_bit(__NDEV_SRIOV_BIT, &ndev->flags);
191 ndev->iov.num_vfs = 0;
192 ndev->mode = __NDEV_MODE_PF;
193
194 nitrox_pf_reinit(ndev);
195 return err;
196}
197
198static 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
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
218 nitrox_sriov_cleanup(ndev);
219
220 config_nps_core_vfcfg_mode(ndev, ndev->mode);
221
222 return nitrox_pf_reinit(ndev);
223}
224
225int 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