net/i40e: fix Rx packet statistics
[dpdk.git] / drivers / net / sfc / sfc_sriov.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2019 Solarflare Communications Inc.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 #include <rte_common.h>
11 #include <rte_bus_pci.h>
12
13 #include "sfc.h"
14 #include "sfc_log.h"
15
16 #include "efx.h"
17
18
19 /*
20  * Check if a MAC address is already assigned to one of previously
21  * configured vPorts (either PF itself or one of already configured VFs).
22  *
23  * Typically the first vPort which corresponds to PF has globally
24  * administered unicast address, but it still could be locally
25  * administered if user assigned it or in the case of unconfigured NIC.
26  * So, it is safer to include it as well in uniqueness check.
27  */
28 static bool
29 sriov_mac_addr_assigned(const efx_vport_config_t *vport_config,
30                         unsigned int num, const uint8_t *mac_addr)
31 {
32         unsigned int i;
33
34         /* Check PF's MAC address as well as explained above */
35         for (i = 0; i < num; ++i) {
36                 if (memcmp(mac_addr, vport_config[i].evc_mac_addr,
37                            sizeof(vport_config[i].evc_mac_addr)) == 0)
38                         return true;
39         }
40
41         return false;
42 }
43
44 int
45 sfc_sriov_attach(struct sfc_adapter *sa)
46 {
47         const struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(sa->eth_dev);
48         struct sfc_sriov *sriov = &sa->sriov;
49         efx_vport_config_t *vport_config;
50         unsigned int i;
51         int rc;
52
53         sfc_log_init(sa, "entry");
54
55         sriov->num_vfs = pci_dev->max_vfs;
56         if (sa->switchdev || sriov->num_vfs == 0)
57                 goto done;
58
59         vport_config = calloc(sriov->num_vfs + 1, sizeof(*vport_config));
60         if (vport_config == NULL) {
61                 rc = ENOMEM;
62                 goto fail_alloc_vport_config;
63         }
64
65         vport_config[0].evc_function = 0xffff;
66         vport_config[0].evc_vid = EFX_VF_VID_DEFAULT;
67         vport_config[0].evc_vlan_restrict = B_FALSE;
68
69         for (i = 1; i <= sriov->num_vfs; ++i) {
70                 vport_config[i].evc_function = i - 1;
71                 vport_config[i].evc_vid = EFX_VF_VID_DEFAULT;
72                 vport_config[i].evc_vlan_restrict = B_FALSE;
73                 do {
74                         rte_eth_random_addr(vport_config[i].evc_mac_addr);
75                 } while (sriov_mac_addr_assigned(vport_config, i,
76                                                  vport_config[i].evc_mac_addr));
77         }
78
79         sriov->vport_config = vport_config;
80
81 done:
82         sfc_log_init(sa, "done");
83         return 0;
84
85 fail_alloc_vport_config:
86         sriov->num_vfs = 0;
87         return rc;
88 }
89
90 void
91 sfc_sriov_detach(struct sfc_adapter *sa)
92 {
93         struct sfc_sriov *sriov = &sa->sriov;
94
95         sfc_log_init(sa, "entry");
96
97         free(sriov->vport_config);
98         sriov->vport_config = NULL;
99         sriov->num_vfs = 0;
100
101         sfc_log_init(sa, "done");
102 }
103
104 int
105 sfc_sriov_vswitch_create(struct sfc_adapter *sa)
106 {
107         struct sfc_sriov *sriov = &sa->sriov;
108         efx_vport_config_t *vport_config = sriov->vport_config;
109         int rc;
110
111         sfc_log_init(sa, "entry");
112
113         if (sa->switchdev) {
114                 sfc_log_init(sa, "don't create vswitch in switchdev mode");
115                 goto done;
116         }
117
118         if (sriov->num_vfs == 0) {
119                 sfc_log_init(sa, "no VFs enabled");
120                 goto done;
121         }
122
123         rc = efx_evb_init(sa->nic);
124         if (rc != 0) {
125                 sfc_err(sa, "EVB init failed %d", rc);
126                 goto fail_evb_init;
127         }
128
129         RTE_BUILD_BUG_ON(sizeof(sa->port.default_mac_addr) !=
130                          sizeof(vport_config[0].evc_mac_addr));
131         rte_ether_addr_copy(&sa->port.default_mac_addr,
132                 (struct rte_ether_addr *)vport_config[0].evc_mac_addr);
133
134         rc = efx_evb_vswitch_create(sa->nic, sriov->num_vfs + 1,
135                                     vport_config, &sriov->vswitch);
136         if (rc != 0) {
137                 sfc_err(sa, "EVB vSwitch create failed %d", rc);
138                 goto fail_evb_vswitch_create;
139         }
140
141 done:
142         sfc_log_init(sa, "done");
143         return 0;
144
145 fail_evb_vswitch_create:
146         efx_evb_fini(sa->nic);
147
148 fail_evb_init:
149         return rc;
150 }
151
152 void
153 sfc_sriov_vswitch_destroy(struct sfc_adapter *sa)
154 {
155         struct sfc_sriov *sriov = &sa->sriov;
156         int rc;
157
158         sfc_log_init(sa, "entry");
159
160         if (sa->switchdev || sriov->num_vfs == 0)
161                 goto done;
162
163         rc = efx_evb_vswitch_destroy(sa->nic, sriov->vswitch);
164         if (rc != 0)
165                 sfc_err(sa, "efx_evb_vswitch_destroy() failed %d", rc);
166
167         sriov->vswitch = NULL;
168
169         efx_evb_fini(sa->nic);
170
171 done:
172         sfc_log_init(sa, "done");
173 }