blob: 6c9b6e45509a18706ef9488e097f83f9f4a41ecf [file] [log] [blame]
Shradha Shah834e23d2015-05-06 00:55:58 +01001/****************************************************************************
2 * Driver for Solarflare network controllers and boards
3 * Copyright 2015 Solarflare Communications Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation, incorporated herein by reference.
8 */
9#include <linux/pci.h>
10#include <linux/module.h>
11#include "net_driver.h"
12#include "ef10_sriov.h"
13#include "efx.h"
14#include "nic.h"
15#include "mcdi_pcol.h"
16
Shradha Shah3c5eb872015-05-06 00:58:31 +010017static int efx_ef10_evb_port_assign(struct efx_nic *efx, unsigned int port_id,
18 unsigned int vf_fn)
Shradha Shah834e23d2015-05-06 00:55:58 +010019{
Shradha Shah3c5eb872015-05-06 00:58:31 +010020 MCDI_DECLARE_BUF(inbuf, MC_CMD_EVB_PORT_ASSIGN_IN_LEN);
21 struct efx_ef10_nic_data *nic_data = efx->nic_data;
Shradha Shah834e23d2015-05-06 00:55:58 +010022
Shradha Shah3c5eb872015-05-06 00:58:31 +010023 MCDI_SET_DWORD(inbuf, EVB_PORT_ASSIGN_IN_PORT_ID, port_id);
24 MCDI_POPULATE_DWORD_2(inbuf, EVB_PORT_ASSIGN_IN_FUNCTION,
25 EVB_PORT_ASSIGN_IN_PF, nic_data->pf_index,
26 EVB_PORT_ASSIGN_IN_VF, vf_fn);
27
28 return efx_mcdi_rpc(efx, MC_CMD_EVB_PORT_ASSIGN, inbuf, sizeof(inbuf),
29 NULL, 0, NULL);
Shradha Shah834e23d2015-05-06 00:55:58 +010030}
31
Shradha Shah3c5eb872015-05-06 00:58:31 +010032static int efx_ef10_vport_add_mac(struct efx_nic *efx,
33 unsigned int port_id, u8 *mac)
Shradha Shah834e23d2015-05-06 00:55:58 +010034{
Shradha Shah3c5eb872015-05-06 00:58:31 +010035 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
Shradha Shah834e23d2015-05-06 00:55:58 +010036
Shradha Shah3c5eb872015-05-06 00:58:31 +010037 MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
38 ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
39
40 return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
41 sizeof(inbuf), NULL, 0, NULL);
Shradha Shah834e23d2015-05-06 00:55:58 +010042}
43
Shradha Shah3c5eb872015-05-06 00:58:31 +010044static int efx_ef10_vport_del_mac(struct efx_nic *efx,
45 unsigned int port_id, u8 *mac)
Shradha Shah834e23d2015-05-06 00:55:58 +010046{
Shradha Shah3c5eb872015-05-06 00:58:31 +010047 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +010048
Shradha Shah3c5eb872015-05-06 00:58:31 +010049 MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
50 ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
Shradha Shah02246a72015-05-06 00:58:14 +010051
Shradha Shah3c5eb872015-05-06 00:58:31 +010052 return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
53 sizeof(inbuf), NULL, 0, NULL);
Shradha Shah02246a72015-05-06 00:58:14 +010054}
55
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +010056static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
57 unsigned int vswitch_type)
58{
59 MCDI_DECLARE_BUF(inbuf, MC_CMD_VSWITCH_ALLOC_IN_LEN);
Shradha Shah2d432f22015-05-20 11:11:54 +010060 int rc;
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +010061
62 MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
63 MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_TYPE, vswitch_type);
Shradha Shah2d432f22015-05-20 11:11:54 +010064 MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, 2);
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +010065 MCDI_POPULATE_DWORD_1(inbuf, VSWITCH_ALLOC_IN_FLAGS,
66 VSWITCH_ALLOC_IN_FLAG_AUTO_PORT, 0);
67
Shradha Shah2d432f22015-05-20 11:11:54 +010068 /* Quietly try to allocate 2 VLAN tags */
69 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VSWITCH_ALLOC, inbuf, sizeof(inbuf),
70 NULL, 0, NULL);
71
72 /* If 2 VLAN tags is too many, revert to trying with 1 VLAN tags */
73 if (rc == -EPROTO) {
74 MCDI_SET_DWORD(inbuf, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, 1);
75 rc = efx_mcdi_rpc(efx, MC_CMD_VSWITCH_ALLOC, inbuf,
76 sizeof(inbuf), NULL, 0, NULL);
77 } else if (rc) {
78 efx_mcdi_display_error(efx, MC_CMD_VSWITCH_ALLOC,
79 MC_CMD_VSWITCH_ALLOC_IN_LEN,
80 NULL, 0, rc);
81 }
82 return rc;
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +010083}
84
85static int efx_ef10_vswitch_free(struct efx_nic *efx, unsigned int port_id)
86{
87 MCDI_DECLARE_BUF(inbuf, MC_CMD_VSWITCH_FREE_IN_LEN);
88
89 MCDI_SET_DWORD(inbuf, VSWITCH_FREE_IN_UPSTREAM_PORT_ID, port_id);
90
91 return efx_mcdi_rpc(efx, MC_CMD_VSWITCH_FREE, inbuf, sizeof(inbuf),
92 NULL, 0, NULL);
93}
94
95static int efx_ef10_vport_alloc(struct efx_nic *efx,
96 unsigned int port_id_in,
97 unsigned int vport_type,
Shradha Shah2d432f22015-05-20 11:11:54 +010098 u16 vlan,
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +010099 unsigned int *port_id_out)
100{
101 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ALLOC_IN_LEN);
102 MCDI_DECLARE_BUF(outbuf, MC_CMD_VPORT_ALLOC_OUT_LEN);
103 size_t outlen;
104 int rc;
105
106 EFX_WARN_ON_PARANOID(!port_id_out);
107
108 MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_UPSTREAM_PORT_ID, port_id_in);
109 MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_TYPE, vport_type);
Shradha Shah2d432f22015-05-20 11:11:54 +0100110 MCDI_SET_DWORD(inbuf, VPORT_ALLOC_IN_NUM_VLAN_TAGS,
111 (vlan != EFX_EF10_NO_VLAN));
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100112 MCDI_POPULATE_DWORD_1(inbuf, VPORT_ALLOC_IN_FLAGS,
113 VPORT_ALLOC_IN_FLAG_AUTO_PORT, 0);
Shradha Shah2d432f22015-05-20 11:11:54 +0100114 if (vlan != EFX_EF10_NO_VLAN)
115 MCDI_POPULATE_DWORD_1(inbuf, VPORT_ALLOC_IN_VLAN_TAGS,
116 VPORT_ALLOC_IN_VLAN_TAG_0, vlan);
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100117
118 rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_ALLOC, inbuf, sizeof(inbuf),
119 outbuf, sizeof(outbuf), &outlen);
120 if (rc)
121 return rc;
122 if (outlen < MC_CMD_VPORT_ALLOC_OUT_LEN)
123 return -EIO;
124
125 *port_id_out = MCDI_DWORD(outbuf, VPORT_ALLOC_OUT_VPORT_ID);
126 return 0;
127}
128
129static int efx_ef10_vport_free(struct efx_nic *efx, unsigned int port_id)
130{
131 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_FREE_IN_LEN);
132
133 MCDI_SET_DWORD(inbuf, VPORT_FREE_IN_VPORT_ID, port_id);
134
135 return efx_mcdi_rpc(efx, MC_CMD_VPORT_FREE, inbuf, sizeof(inbuf),
136 NULL, 0, NULL);
137}
138
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100139static int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
140{
141 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
142
143 MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
144 return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
145 NULL, 0, NULL);
146}
147
148static int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
149{
150 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
151
152 MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
153 return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
154 NULL, 0, NULL);
155}
156
Shradha Shah3c5eb872015-05-06 00:58:31 +0100157static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
158{
159 struct efx_ef10_nic_data *nic_data = efx->nic_data;
160 int i;
161
162 if (!nic_data->vf)
163 return;
164
165 for (i = 0; i < efx->vf_count; i++) {
166 struct ef10_vf *vf = nic_data->vf + i;
167
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100168 /* If VF is assigned, do not free the vport */
169 if (vf->pci_dev &&
170 vf->pci_dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
171 continue;
172
Shradha Shah3c5eb872015-05-06 00:58:31 +0100173 if (vf->vport_assigned) {
174 efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, i);
175 vf->vport_assigned = 0;
176 }
177
178 if (!is_zero_ether_addr(vf->mac)) {
179 efx_ef10_vport_del_mac(efx, vf->vport_id, vf->mac);
180 eth_zero_addr(vf->mac);
181 }
182
183 if (vf->vport_id) {
184 efx_ef10_vport_free(efx, vf->vport_id);
185 vf->vport_id = 0;
186 }
Shradha Shahf1122a32015-05-20 11:09:46 +0100187
188 vf->efx = NULL;
Shradha Shah3c5eb872015-05-06 00:58:31 +0100189 }
190}
191
192static void efx_ef10_sriov_free_vf_vswitching(struct efx_nic *efx)
193{
194 struct efx_ef10_nic_data *nic_data = efx->nic_data;
195
196 efx_ef10_sriov_free_vf_vports(efx);
197 kfree(nic_data->vf);
198 nic_data->vf = NULL;
199}
200
201static int efx_ef10_sriov_assign_vf_vport(struct efx_nic *efx,
202 unsigned int vf_i)
203{
204 struct efx_ef10_nic_data *nic_data = efx->nic_data;
205 struct ef10_vf *vf = nic_data->vf + vf_i;
206 int rc;
207
208 if (WARN_ON_ONCE(!nic_data->vf))
209 return -EOPNOTSUPP;
210
211 rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
212 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
Shradha Shah2d432f22015-05-20 11:11:54 +0100213 vf->vlan, &vf->vport_id);
Shradha Shah3c5eb872015-05-06 00:58:31 +0100214 if (rc)
215 return rc;
216
217 rc = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac);
218 if (rc) {
219 eth_zero_addr(vf->mac);
220 return rc;
221 }
222
223 rc = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
224 if (rc)
225 return rc;
226
227 vf->vport_assigned = 1;
228 return 0;
229}
230
231static int efx_ef10_sriov_alloc_vf_vswitching(struct efx_nic *efx)
232{
233 struct efx_ef10_nic_data *nic_data = efx->nic_data;
234 unsigned int i;
235 int rc;
236
237 nic_data->vf = kcalloc(efx->vf_count, sizeof(struct ef10_vf),
238 GFP_KERNEL);
239 if (!nic_data->vf)
240 return -ENOMEM;
241
242 for (i = 0; i < efx->vf_count; i++) {
243 random_ether_addr(nic_data->vf[i].mac);
Shradha Shahf1122a32015-05-20 11:09:46 +0100244 nic_data->vf[i].efx = NULL;
Shradha Shah2d432f22015-05-20 11:11:54 +0100245 nic_data->vf[i].vlan = EFX_EF10_NO_VLAN;
Shradha Shah3c5eb872015-05-06 00:58:31 +0100246
247 rc = efx_ef10_sriov_assign_vf_vport(efx, i);
248 if (rc)
249 goto fail;
250 }
251
252 return 0;
253fail:
254 efx_ef10_sriov_free_vf_vports(efx);
255 kfree(nic_data->vf);
256 nic_data->vf = NULL;
257 return rc;
258}
259
260static int efx_ef10_sriov_restore_vf_vswitching(struct efx_nic *efx)
261{
262 unsigned int i;
263 int rc;
264
265 for (i = 0; i < efx->vf_count; i++) {
266 rc = efx_ef10_sriov_assign_vf_vport(efx, i);
267 if (rc)
268 goto fail;
269 }
270
271 return 0;
272fail:
273 efx_ef10_sriov_free_vf_vswitching(efx);
274 return rc;
275}
276
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100277/* On top of the default firmware vswitch setup, create a VEB vswitch and
278 * expansion vport for use by this function.
279 */
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100280int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100281{
282 struct efx_ef10_nic_data *nic_data = efx->nic_data;
Shradha Shah3c5eb872015-05-06 00:58:31 +0100283 struct net_device *net_dev = efx->net_dev;
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100284 int rc;
285
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100286 if (pci_sriov_get_totalvfs(efx->pci_dev) <= 0) {
287 /* vswitch not needed as we have no VFs */
288 efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
289 return 0;
290 }
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100291
292 rc = efx_ef10_vswitch_alloc(efx, EVB_PORT_ID_ASSIGNED,
293 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VEB);
294 if (rc)
295 goto fail1;
296
297 rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
298 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
Shradha Shah2d432f22015-05-20 11:11:54 +0100299 EFX_EF10_NO_VLAN, &nic_data->vport_id);
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100300 if (rc)
301 goto fail2;
302
Shradha Shah3c5eb872015-05-06 00:58:31 +0100303 rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, net_dev->dev_addr);
304 if (rc)
305 goto fail3;
Shradha Shah3c5eb872015-05-06 00:58:31 +0100306 ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr);
307
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100308 rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
309 if (rc)
310 goto fail4;
311
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100312 return 0;
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100313fail4:
314 efx_ef10_vport_del_mac(efx, nic_data->vport_id, nic_data->vport_mac);
315 eth_zero_addr(nic_data->vport_mac);
Shradha Shah3c5eb872015-05-06 00:58:31 +0100316fail3:
317 efx_ef10_vport_free(efx, nic_data->vport_id);
318 nic_data->vport_id = EVB_PORT_ID_ASSIGNED;
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100319fail2:
320 efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED);
321fail1:
322 return rc;
323}
324
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100325int efx_ef10_vswitching_probe_vf(struct efx_nic *efx)
326{
327 struct efx_ef10_nic_data *nic_data = efx->nic_data;
328
329 return efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
330}
331
332int efx_ef10_vswitching_restore_pf(struct efx_nic *efx)
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100333{
334 struct efx_ef10_nic_data *nic_data = efx->nic_data;
335 int rc;
336
337 if (!nic_data->must_probe_vswitching)
338 return 0;
339
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100340 rc = efx_ef10_vswitching_probe_pf(efx);
Shradha Shah3c5eb872015-05-06 00:58:31 +0100341 if (rc)
342 goto fail;
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100343
Shradha Shah3c5eb872015-05-06 00:58:31 +0100344 rc = efx_ef10_sriov_restore_vf_vswitching(efx);
345 if (rc)
346 goto fail;
347
348 nic_data->must_probe_vswitching = false;
349fail:
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100350 return rc;
351}
352
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100353int efx_ef10_vswitching_restore_vf(struct efx_nic *efx)
354{
355 struct efx_ef10_nic_data *nic_data = efx->nic_data;
356 int rc;
357
358 if (!nic_data->must_probe_vswitching)
359 return 0;
360
361 rc = efx_ef10_vadaptor_free(efx, EVB_PORT_ID_ASSIGNED);
362 if (rc)
363 return rc;
364
365 nic_data->must_probe_vswitching = false;
366 return 0;
367}
368
369void efx_ef10_vswitching_remove_pf(struct efx_nic *efx)
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100370{
371 struct efx_ef10_nic_data *nic_data = efx->nic_data;
372
Shradha Shah3c5eb872015-05-06 00:58:31 +0100373 efx_ef10_sriov_free_vf_vswitching(efx);
374
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100375 efx_ef10_vadaptor_free(efx, nic_data->vport_id);
376
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100377 if (nic_data->vport_id == EVB_PORT_ID_ASSIGNED)
378 return; /* No vswitch was ever created */
379
Shradha Shah3c5eb872015-05-06 00:58:31 +0100380 if (!is_zero_ether_addr(nic_data->vport_mac)) {
381 efx_ef10_vport_del_mac(efx, nic_data->vport_id,
382 efx->net_dev->dev_addr);
383 eth_zero_addr(nic_data->vport_mac);
384 }
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100385 efx_ef10_vport_free(efx, nic_data->vport_id);
386 nic_data->vport_id = EVB_PORT_ID_ASSIGNED;
387
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100388 /* Only free the vswitch if no VFs are assigned */
389 if (!pci_vfs_assigned(efx->pci_dev))
390 efx_ef10_vswitch_free(efx, nic_data->vport_id);
Daniel Pieczko6d8aaaf2015-05-06 00:57:34 +0100391}
Shradha Shah3c5eb872015-05-06 00:58:31 +0100392
Shradha Shah7b8c7b52015-05-06 00:58:54 +0100393void efx_ef10_vswitching_remove_vf(struct efx_nic *efx)
394{
395 efx_ef10_vadaptor_free(efx, EVB_PORT_ID_ASSIGNED);
396}
397
Shradha Shah3c5eb872015-05-06 00:58:31 +0100398static int efx_ef10_pci_sriov_enable(struct efx_nic *efx, int num_vfs)
399{
400 int rc = 0;
401 struct pci_dev *dev = efx->pci_dev;
402
403 efx->vf_count = num_vfs;
404
405 rc = efx_ef10_sriov_alloc_vf_vswitching(efx);
406 if (rc)
407 goto fail1;
408
409 rc = pci_enable_sriov(dev, num_vfs);
410 if (rc)
411 goto fail2;
412
413 return 0;
414fail2:
415 efx_ef10_sriov_free_vf_vswitching(efx);
416fail1:
417 efx->vf_count = 0;
418 netif_err(efx, probe, efx->net_dev,
419 "Failed to enable SRIOV VFs\n");
420 return rc;
421}
422
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100423static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force)
Shradha Shah3c5eb872015-05-06 00:58:31 +0100424{
425 struct pci_dev *dev = efx->pci_dev;
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100426 unsigned int vfs_assigned = 0;
Shradha Shah3c5eb872015-05-06 00:58:31 +0100427
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100428 vfs_assigned = pci_vfs_assigned(dev);
Daniel Pieczko71158bf2015-06-02 11:40:31 +0100429
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100430 if (vfs_assigned && !force) {
431 netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; "
432 "please detach them before disabling SR-IOV\n");
Daniel Pieczko71158bf2015-06-02 11:40:31 +0100433 return -EBUSY;
434 }
435
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100436 if (!vfs_assigned)
437 pci_disable_sriov(dev);
438
Shradha Shah3c5eb872015-05-06 00:58:31 +0100439 efx_ef10_sriov_free_vf_vswitching(efx);
440 efx->vf_count = 0;
441 return 0;
442}
443
444int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs)
445{
446 if (num_vfs == 0)
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100447 return efx_ef10_pci_sriov_disable(efx, false);
Shradha Shah3c5eb872015-05-06 00:58:31 +0100448 else
449 return efx_ef10_pci_sriov_enable(efx, num_vfs);
450}
451
452int efx_ef10_sriov_init(struct efx_nic *efx)
453{
454 return 0;
455}
456
457void efx_ef10_sriov_fini(struct efx_nic *efx)
458{
459 struct efx_ef10_nic_data *nic_data = efx->nic_data;
Daniel Pieczko2a3fc312015-06-02 11:40:46 +0100460 unsigned int i;
Shradha Shah3c5eb872015-05-06 00:58:31 +0100461 int rc;
462
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100463 if (!nic_data->vf) {
464 /* Remove any un-assigned orphaned VFs */
465 if (pci_num_vf(efx->pci_dev) && !pci_vfs_assigned(efx->pci_dev))
466 pci_disable_sriov(efx->pci_dev);
Shradha Shah3c5eb872015-05-06 00:58:31 +0100467 return;
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100468 }
Shradha Shah3c5eb872015-05-06 00:58:31 +0100469
Daniel Pieczko2a3fc312015-06-02 11:40:46 +0100470 /* Remove any VFs in the host */
471 for (i = 0; i < efx->vf_count; ++i) {
472 struct efx_nic *vf_efx = nic_data->vf[i].efx;
473
474 if (vf_efx)
475 vf_efx->pci_dev->driver->remove(vf_efx->pci_dev);
476 }
477
Daniel Pieczko6598dad2015-06-02 11:41:00 +0100478 rc = efx_ef10_pci_sriov_disable(efx, true);
Shradha Shah3c5eb872015-05-06 00:58:31 +0100479 if (rc)
480 netif_dbg(efx, drv, efx->net_dev,
481 "Disabling SRIOV was not successful rc=%d\n", rc);
482 else
483 netif_dbg(efx, drv, efx->net_dev, "SRIOV disabled\n");
484}
Shradha Shahe340be92015-05-20 11:11:03 +0100485
486static int efx_ef10_vport_del_vf_mac(struct efx_nic *efx, unsigned int port_id,
487 u8 *mac)
488{
489 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
490 MCDI_DECLARE_BUF_ERR(outbuf);
491 size_t outlen;
492 int rc;
493
494 MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
495 ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
496
497 rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
498 sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
499
500 return rc;
501}
502
503int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, u8 *mac)
504{
505 struct efx_ef10_nic_data *nic_data = efx->nic_data;
506 struct ef10_vf *vf;
507 int rc;
508
509 if (!nic_data->vf)
510 return -EOPNOTSUPP;
511
512 if (vf_i >= efx->vf_count)
513 return -EINVAL;
514 vf = nic_data->vf + vf_i;
515
516 if (vf->efx) {
517 efx_device_detach_sync(vf->efx);
518 efx_net_stop(vf->efx->net_dev);
519
520 down_write(&vf->efx->filter_sem);
521 vf->efx->type->filter_table_remove(vf->efx);
522
523 rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED);
524 if (rc) {
525 up_write(&vf->efx->filter_sem);
526 return rc;
527 }
528 }
529
530 rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i);
531 if (rc)
532 return rc;
533
534 if (!is_zero_ether_addr(vf->mac)) {
535 rc = efx_ef10_vport_del_vf_mac(efx, vf->vport_id, vf->mac);
536 if (rc)
537 return rc;
538 }
539
540 if (!is_zero_ether_addr(mac)) {
541 rc = efx_ef10_vport_add_mac(efx, vf->vport_id, mac);
542 if (rc) {
543 eth_zero_addr(vf->mac);
544 goto fail;
545 }
546 if (vf->efx)
547 ether_addr_copy(vf->efx->net_dev->dev_addr, mac);
548 }
549
550 ether_addr_copy(vf->mac, mac);
551
552 rc = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
553 if (rc)
554 goto fail;
555
556 if (vf->efx) {
557 /* VF cannot use the vport_id that the PF created */
558 rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
559 if (rc) {
560 up_write(&vf->efx->filter_sem);
561 return rc;
562 }
563 vf->efx->type->filter_table_probe(vf->efx);
564 up_write(&vf->efx->filter_sem);
565 efx_net_open(vf->efx->net_dev);
566 netif_device_attach(vf->efx->net_dev);
567 }
568
569 return 0;
570
571fail:
572 memset(vf->mac, 0, ETH_ALEN);
573 return rc;
574}
Shradha Shahb9af9042015-05-20 11:11:18 +0100575
Shradha Shah2d432f22015-05-20 11:11:54 +0100576int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
577 u8 qos)
578{
579 struct efx_ef10_nic_data *nic_data = efx->nic_data;
580 struct ef10_vf *vf;
581 u16 old_vlan, new_vlan;
582 int rc = 0, rc2 = 0;
583
584 if (vf_i >= efx->vf_count)
585 return -EINVAL;
586 if (qos != 0)
587 return -EINVAL;
588
589 vf = nic_data->vf + vf_i;
590
591 new_vlan = (vlan == 0) ? EFX_EF10_NO_VLAN : vlan;
592 if (new_vlan == vf->vlan)
593 return 0;
594
595 if (vf->efx) {
596 efx_device_detach_sync(vf->efx);
597 efx_net_stop(vf->efx->net_dev);
598
599 down_write(&vf->efx->filter_sem);
600 vf->efx->type->filter_table_remove(vf->efx);
601
602 rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED);
603 if (rc)
604 goto restore_filters;
605 }
606
607 if (vf->vport_assigned) {
608 rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i);
609 if (rc) {
610 netif_warn(efx, drv, efx->net_dev,
611 "Failed to change vlan on VF %d.\n", vf_i);
612 netif_warn(efx, drv, efx->net_dev,
613 "This is likely because the VF is bound to a driver in a VM.\n");
614 netif_warn(efx, drv, efx->net_dev,
615 "Please unload the driver in the VM.\n");
616 goto restore_vadaptor;
617 }
618 vf->vport_assigned = 0;
619 }
620
621 if (!is_zero_ether_addr(vf->mac)) {
622 rc = efx_ef10_vport_del_mac(efx, vf->vport_id, vf->mac);
623 if (rc)
624 goto restore_evb_port;
625 }
626
627 if (vf->vport_id) {
628 rc = efx_ef10_vport_free(efx, vf->vport_id);
629 if (rc)
630 goto restore_mac;
631 vf->vport_id = 0;
632 }
633
634 /* Do the actual vlan change */
635 old_vlan = vf->vlan;
636 vf->vlan = new_vlan;
637
638 /* Restore everything in reverse order */
639 rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
640 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
641 vf->vlan, &vf->vport_id);
642 if (rc)
643 goto reset_nic;
644
645restore_mac:
646 if (!is_zero_ether_addr(vf->mac)) {
647 rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac);
648 if (rc2) {
649 eth_zero_addr(vf->mac);
650 goto reset_nic;
651 }
652 }
653
654restore_evb_port:
655 rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
656 if (rc2)
657 goto reset_nic;
658 else
659 vf->vport_assigned = 1;
660
661restore_vadaptor:
662 if (vf->efx) {
663 rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
664 if (rc2)
665 goto reset_nic;
666 }
667
668restore_filters:
669 if (vf->efx) {
670 rc2 = vf->efx->type->filter_table_probe(vf->efx);
671 if (rc2)
672 goto reset_nic;
673
674 up_write(&vf->efx->filter_sem);
675
676 rc2 = efx_net_open(vf->efx->net_dev);
677 if (rc2)
678 goto reset_nic;
679
680 netif_device_attach(vf->efx->net_dev);
681 }
682 return rc;
683
684reset_nic:
685 if (vf->efx) {
686 up_write(&vf->efx->filter_sem);
687 netif_err(efx, drv, efx->net_dev,
688 "Failed to restore VF - scheduling reset.\n");
689 efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH);
690 } else {
691 netif_err(efx, drv, efx->net_dev,
692 "Failed to restore the VF and cannot reset the VF "
693 "- VF is not functional.\n");
694 netif_err(efx, drv, efx->net_dev,
695 "Please reload the driver attached to the VF.\n");
696 }
697
698 return rc ? rc : rc2;
699}
700
Shradha Shah860d2ff2015-05-20 11:12:30 +0100701int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i,
702 bool spoofchk)
703{
704 return spoofchk ? -EOPNOTSUPP : 0;
705}
706
Edward Cree4392dc62015-05-20 11:12:13 +0100707int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i,
708 int link_state)
709{
710 MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN);
711 struct efx_ef10_nic_data *nic_data = efx->nic_data;
712
713 BUILD_BUG_ON(IFLA_VF_LINK_STATE_AUTO !=
714 MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_AUTO);
715 BUILD_BUG_ON(IFLA_VF_LINK_STATE_ENABLE !=
716 MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_UP);
717 BUILD_BUG_ON(IFLA_VF_LINK_STATE_DISABLE !=
718 MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_DOWN);
719 MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION,
720 LINK_STATE_MODE_IN_FUNCTION_PF,
721 nic_data->pf_index,
722 LINK_STATE_MODE_IN_FUNCTION_VF, vf_i);
723 MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE, link_state);
724 return efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf),
725 NULL, 0, NULL); /* don't care what old mode was */
726}
727
Shradha Shahb9af9042015-05-20 11:11:18 +0100728int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
729 struct ifla_vf_info *ivf)
730{
Edward Cree4392dc62015-05-20 11:12:13 +0100731 MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN);
732 MCDI_DECLARE_BUF(outbuf, MC_CMD_LINK_STATE_MODE_OUT_LEN);
733
Shradha Shahb9af9042015-05-20 11:11:18 +0100734 struct efx_ef10_nic_data *nic_data = efx->nic_data;
735 struct ef10_vf *vf;
Edward Cree4392dc62015-05-20 11:12:13 +0100736 size_t outlen;
737 int rc;
Shradha Shahb9af9042015-05-20 11:11:18 +0100738
739 if (vf_i >= efx->vf_count)
740 return -EINVAL;
741
742 if (!nic_data->vf)
743 return -EOPNOTSUPP;
744
745 vf = nic_data->vf + vf_i;
746
747 ivf->vf = vf_i;
748 ivf->min_tx_rate = 0;
749 ivf->max_tx_rate = 0;
750 ether_addr_copy(ivf->mac, vf->mac);
Shradha Shah2d432f22015-05-20 11:11:54 +0100751 ivf->vlan = (vf->vlan == EFX_EF10_NO_VLAN) ? 0 : vf->vlan;
Shradha Shahb9af9042015-05-20 11:11:18 +0100752 ivf->qos = 0;
753
Edward Cree4392dc62015-05-20 11:12:13 +0100754 MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION,
755 LINK_STATE_MODE_IN_FUNCTION_PF,
756 nic_data->pf_index,
757 LINK_STATE_MODE_IN_FUNCTION_VF, vf_i);
758 MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE,
759 MC_CMD_LINK_STATE_MODE_IN_DO_NOT_CHANGE);
760 rc = efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf),
761 outbuf, sizeof(outbuf), &outlen);
762 if (rc)
763 return rc;
764 if (outlen < MC_CMD_LINK_STATE_MODE_OUT_LEN)
765 return -EIO;
766 ivf->linkstate = MCDI_DWORD(outbuf, LINK_STATE_MODE_OUT_OLD_MODE);
767
Shradha Shahb9af9042015-05-20 11:11:18 +0100768 return 0;
769}
Shradha Shah1d051e02015-06-02 11:38:16 +0100770
771int efx_ef10_sriov_get_phys_port_id(struct efx_nic *efx,
772 struct netdev_phys_item_id *ppid)
773{
774 struct efx_ef10_nic_data *nic_data = efx->nic_data;
775
776 if (!is_valid_ether_addr(nic_data->port_id))
777 return -EOPNOTSUPP;
778
779 ppid->id_len = ETH_ALEN;
780 memcpy(ppid->id, nic_data->port_id, ppid->id_len);
781
782 return 0;
783}