1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3  * Driver for Solarflare network controllers and boards
4  * Copyright 2019 Solarflare Communications Inc.
5  * Copyright 2020-2022 Xilinx Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 as published
9  * by the Free Software Foundation, incorporated herein by reference.
10  */
11 
12 #include "ef100_sriov.h"
13 #include "ef100_nic.h"
14 #include "ef100_rep.h"
15 
efx_ef100_pci_sriov_enable(struct efx_nic * efx,int num_vfs)16 static int efx_ef100_pci_sriov_enable(struct efx_nic *efx, int num_vfs)
17 {
18 	struct ef100_nic_data *nic_data = efx->nic_data;
19 	struct pci_dev *dev = efx->pci_dev;
20 	struct efx_rep *efv, *next;
21 	int rc, i;
22 
23 	efx->vf_count = num_vfs;
24 	rc = pci_enable_sriov(dev, num_vfs);
25 	if (rc)
26 		goto fail1;
27 
28 	if (!nic_data->grp_mae)
29 		return 0;
30 
31 	for (i = 0; i < num_vfs; i++) {
32 		rc = efx_ef100_vfrep_create(efx, i);
33 		if (rc)
34 			goto fail2;
35 	}
36 	return 0;
37 
38 fail2:
39 	list_for_each_entry_safe(efv, next, &efx->vf_reps, list)
40 		efx_ef100_vfrep_destroy(efx, efv);
41 	pci_disable_sriov(dev);
42 fail1:
43 	netif_err(efx, probe, efx->net_dev, "Failed to enable SRIOV VFs\n");
44 	efx->vf_count = 0;
45 	return rc;
46 }
47 
efx_ef100_pci_sriov_disable(struct efx_nic * efx,bool force)48 int efx_ef100_pci_sriov_disable(struct efx_nic *efx, bool force)
49 {
50 	struct pci_dev *dev = efx->pci_dev;
51 	unsigned int vfs_assigned;
52 
53 	vfs_assigned = pci_vfs_assigned(dev);
54 	if (vfs_assigned && !force) {
55 		netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; "
56 			   "please detach them before disabling SR-IOV\n");
57 		return -EBUSY;
58 	}
59 
60 	efx_ef100_fini_vfreps(efx);
61 	if (!vfs_assigned)
62 		pci_disable_sriov(dev);
63 	return 0;
64 }
65 
efx_ef100_sriov_configure(struct efx_nic * efx,int num_vfs)66 int efx_ef100_sriov_configure(struct efx_nic *efx, int num_vfs)
67 {
68 	if (num_vfs == 0)
69 		return efx_ef100_pci_sriov_disable(efx, false);
70 	else
71 		return efx_ef100_pci_sriov_enable(efx, num_vfs);
72 }
73