Branch data Line data Source code
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 <bus_pci_driver.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 [ # # ]: 0 : for (i = 0; i < num; ++i) {
36 [ # # ]: 0 : 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 : 0 : sfc_sriov_attach(struct sfc_adapter *sa)
46 : : {
47 : 0 : const struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(sa->eth_dev, *pci_dev);
48 : : struct sfc_sriov *sriov = &sa->sriov;
49 : : efx_vport_config_t *vport_config;
50 : : unsigned int i;
51 : : int rc;
52 : :
53 : 0 : sfc_log_init(sa, "entry");
54 : :
55 : 0 : sriov->num_vfs = pci_dev->max_vfs;
56 [ # # # # ]: 0 : if (sa->switchdev || sriov->num_vfs == 0)
57 : 0 : goto done;
58 : :
59 : 0 : vport_config = calloc(sriov->num_vfs + 1, sizeof(*vport_config));
60 [ # # ]: 0 : if (vport_config == NULL) {
61 : : rc = ENOMEM;
62 : 0 : goto fail_alloc_vport_config;
63 : : }
64 : :
65 : 0 : vport_config[0].evc_function = 0xffff;
66 : 0 : vport_config[0].evc_vid = EFX_VF_VID_DEFAULT;
67 : 0 : vport_config[0].evc_vlan_restrict = B_FALSE;
68 : :
69 [ # # ]: 0 : for (i = 1; i <= sriov->num_vfs; ++i) {
70 : 0 : vport_config[i].evc_function = i - 1;
71 : 0 : vport_config[i].evc_vid = EFX_VF_VID_DEFAULT;
72 : 0 : vport_config[i].evc_vlan_restrict = B_FALSE;
73 : : do {
74 : 0 : rte_eth_random_addr(vport_config[i].evc_mac_addr);
75 [ # # ]: 0 : } while (sriov_mac_addr_assigned(vport_config, i,
76 : : vport_config[i].evc_mac_addr));
77 : : }
78 : :
79 : 0 : sriov->vport_config = vport_config;
80 : :
81 : 0 : done:
82 : 0 : sfc_log_init(sa, "done");
83 : 0 : return 0;
84 : :
85 : : fail_alloc_vport_config:
86 : 0 : sriov->num_vfs = 0;
87 : 0 : return rc;
88 : : }
89 : :
90 : : void
91 : 0 : sfc_sriov_detach(struct sfc_adapter *sa)
92 : : {
93 : : struct sfc_sriov *sriov = &sa->sriov;
94 : :
95 : 0 : sfc_log_init(sa, "entry");
96 : :
97 : 0 : free(sriov->vport_config);
98 : 0 : sriov->vport_config = NULL;
99 : 0 : sriov->num_vfs = 0;
100 : :
101 : 0 : sfc_log_init(sa, "done");
102 : 0 : }
103 : :
104 : : int
105 : 0 : sfc_sriov_vswitch_create(struct sfc_adapter *sa)
106 : : {
107 : : struct sfc_sriov *sriov = &sa->sriov;
108 : 0 : efx_vport_config_t *vport_config = sriov->vport_config;
109 : : int rc;
110 : :
111 : 0 : sfc_log_init(sa, "entry");
112 : :
113 [ # # ]: 0 : if (sa->switchdev) {
114 : 0 : sfc_log_init(sa, "don't create vswitch in switchdev mode");
115 : 0 : goto done;
116 : : }
117 : :
118 [ # # ]: 0 : if (sriov->num_vfs == 0) {
119 : 0 : sfc_log_init(sa, "no VFs enabled");
120 : 0 : goto done;
121 : : }
122 : :
123 : 0 : rc = efx_evb_init(sa->nic);
124 [ # # ]: 0 : if (rc != 0) {
125 : 0 : sfc_err(sa, "EVB init failed %d", rc);
126 : 0 : 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 : 0 : rc = efx_evb_vswitch_create(sa->nic, sriov->num_vfs + 1,
135 : : vport_config, &sriov->vswitch);
136 [ # # ]: 0 : if (rc != 0) {
137 : 0 : sfc_err(sa, "EVB vSwitch create failed %d", rc);
138 : 0 : goto fail_evb_vswitch_create;
139 : : }
140 : :
141 : 0 : done:
142 : 0 : sfc_log_init(sa, "done");
143 : 0 : return 0;
144 : :
145 : : fail_evb_vswitch_create:
146 : 0 : efx_evb_fini(sa->nic);
147 : :
148 : : fail_evb_init:
149 : : return rc;
150 : : }
151 : :
152 : : void
153 : 0 : sfc_sriov_vswitch_destroy(struct sfc_adapter *sa)
154 : : {
155 : : struct sfc_sriov *sriov = &sa->sriov;
156 : : int rc;
157 : :
158 : 0 : sfc_log_init(sa, "entry");
159 : :
160 [ # # # # ]: 0 : if (sa->switchdev || sriov->num_vfs == 0)
161 : 0 : goto done;
162 : :
163 : 0 : rc = efx_evb_vswitch_destroy(sa->nic, sriov->vswitch);
164 [ # # ]: 0 : if (rc != 0)
165 : 0 : sfc_err(sa, "efx_evb_vswitch_destroy() failed %d", rc);
166 : :
167 : 0 : sriov->vswitch = NULL;
168 : :
169 : 0 : efx_evb_fini(sa->nic);
170 : :
171 : 0 : done:
172 : 0 : sfc_log_init(sa, "done");
173 : 0 : }
|