Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright(c) 2019-2021 Xilinx, Inc.
4 : : * Copyright(c) 2016-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 : : /* sysconf() */
11 : : #include <unistd.h>
12 : :
13 : : #include <rte_errno.h>
14 : : #include <rte_alarm.h>
15 : :
16 : : #include "efx.h"
17 : :
18 : : #include "sfc.h"
19 : : #include "sfc_debug.h"
20 : : #include "sfc_log.h"
21 : : #include "sfc_ev.h"
22 : : #include "sfc_rx.h"
23 : : #include "sfc_mae_counter.h"
24 : : #include "sfc_tx.h"
25 : : #include "sfc_kvargs.h"
26 : : #include "sfc_tweak.h"
27 : : #include "sfc_sw_stats.h"
28 : : #include "sfc_switch.h"
29 : : #include "sfc_nic_dma.h"
30 : :
31 : : bool
32 : 0 : sfc_repr_supported(const struct sfc_adapter *sa)
33 : : {
34 [ # # ]: 0 : if (!sa->switchdev)
35 : : return false;
36 : :
37 : : /*
38 : : * Representor proxy should use service lcore on PF's socket
39 : : * (sa->socket_id) to be efficient. But the proxy will fall back
40 : : * to any socket if it is not possible to get the service core
41 : : * on the same socket. Check that at least service core on any
42 : : * socket is available.
43 : : */
44 [ # # ]: 0 : if (sfc_get_service_lcore(SOCKET_ID_ANY) == RTE_MAX_LCORE)
45 : 0 : return false;
46 : :
47 : : return true;
48 : : }
49 : :
50 : : bool
51 : 0 : sfc_repr_available(const struct sfc_adapter_shared *sas)
52 : : {
53 [ # # # # ]: 0 : return sas->nb_repr_rxq > 0 && sas->nb_repr_txq > 0;
54 : : }
55 : :
56 : : int
57 : 0 : sfc_dma_alloc(struct sfc_adapter *sa, const char *name, uint16_t id,
58 : : efx_nic_dma_addr_type_t addr_type, size_t len, int socket_id,
59 : : efsys_mem_t *esmp)
60 : : {
61 : : const struct rte_memzone *mz;
62 : : int rc;
63 : :
64 : 0 : sfc_log_init(sa, "name=%s id=%u len=%zu socket_id=%d",
65 : : name, id, len, socket_id);
66 : :
67 : 0 : mz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,
68 : 0 : sysconf(_SC_PAGESIZE), socket_id);
69 [ # # ]: 0 : if (mz == NULL) {
70 : 0 : sfc_err(sa, "cannot reserve DMA zone for %s:%u %#x@%d: %s",
71 : : name, (unsigned int)id, (unsigned int)len, socket_id,
72 : : rte_strerror(rte_errno));
73 : 0 : return ENOMEM;
74 : : }
75 [ # # ]: 0 : if (mz->iova == RTE_BAD_IOVA) {
76 : 0 : (void)rte_memzone_free(mz);
77 : 0 : return EFAULT;
78 : : }
79 : :
80 : 0 : rc = sfc_nic_dma_mz_map(sa, mz, addr_type, &esmp->esm_addr);
81 [ # # ]: 0 : if (rc != 0) {
82 : 0 : (void)rte_memzone_free(mz);
83 : 0 : return rc;
84 : : }
85 : :
86 : 0 : esmp->esm_mz = mz;
87 : 0 : esmp->esm_base = mz->addr;
88 : :
89 : 0 : sfc_info(sa,
90 : : "DMA name=%s id=%u len=%lu socket_id=%d => virt=%p iova=%lx",
91 : : name, id, len, socket_id, esmp->esm_base,
92 : : (unsigned long)esmp->esm_addr);
93 : :
94 : 0 : return 0;
95 : : }
96 : :
97 : : void
98 : 0 : sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp)
99 : : {
100 : : int rc;
101 : :
102 : 0 : sfc_log_init(sa, "name=%s", esmp->esm_mz->name);
103 : :
104 : 0 : rc = rte_memzone_free(esmp->esm_mz);
105 [ # # ]: 0 : if (rc != 0)
106 : 0 : sfc_err(sa, "rte_memzone_free(() failed: %d", rc);
107 : :
108 : : memset(esmp, 0, sizeof(*esmp));
109 : 0 : }
110 : :
111 : : static uint32_t
112 : 0 : sfc_phy_cap_from_link_speeds(uint32_t speeds)
113 : : {
114 : : uint32_t phy_caps = 0;
115 : :
116 [ # # ]: 0 : if (~speeds & RTE_ETH_LINK_SPEED_FIXED) {
117 : : phy_caps |= (1 << EFX_PHY_CAP_AN);
118 : : /*
119 : : * If no speeds are specified in the mask, any supported
120 : : * may be negotiated
121 : : */
122 [ # # ]: 0 : if (speeds == RTE_ETH_LINK_SPEED_AUTONEG)
123 : : phy_caps |=
124 : : (1 << EFX_PHY_CAP_1000FDX) |
125 : : (1 << EFX_PHY_CAP_10000FDX) |
126 : : (1 << EFX_PHY_CAP_25000FDX) |
127 : : (1 << EFX_PHY_CAP_40000FDX) |
128 : : (1 << EFX_PHY_CAP_50000FDX) |
129 : : (1 << EFX_PHY_CAP_100000FDX) |
130 : : (1 << EFX_PHY_CAP_200000FDX);
131 : : }
132 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_1G)
133 : 0 : phy_caps |= (1 << EFX_PHY_CAP_1000FDX);
134 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_10G)
135 : 0 : phy_caps |= (1 << EFX_PHY_CAP_10000FDX);
136 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_25G)
137 : 0 : phy_caps |= (1 << EFX_PHY_CAP_25000FDX);
138 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_40G)
139 : 0 : phy_caps |= (1 << EFX_PHY_CAP_40000FDX);
140 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_50G)
141 : 0 : phy_caps |= (1 << EFX_PHY_CAP_50000FDX);
142 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_100G)
143 : 0 : phy_caps |= (1 << EFX_PHY_CAP_100000FDX);
144 [ # # ]: 0 : if (speeds & RTE_ETH_LINK_SPEED_200G)
145 : 0 : phy_caps |= (1 << EFX_PHY_CAP_200000FDX);
146 : :
147 : 0 : return phy_caps;
148 : : }
149 : :
150 : : /*
151 : : * Check requested device level configuration.
152 : : * Receive and transmit configuration is checked in corresponding
153 : : * modules.
154 : : */
155 : : static int
156 : 0 : sfc_check_conf(struct sfc_adapter *sa)
157 : : {
158 : 0 : const struct rte_eth_conf *conf = &sa->eth_dev->data->dev_conf;
159 : : int rc = 0;
160 : :
161 : 0 : sa->port.phy_adv_cap =
162 : 0 : sfc_phy_cap_from_link_speeds(conf->link_speeds) &
163 : 0 : sa->port.phy_adv_cap_mask;
164 [ # # ]: 0 : if ((sa->port.phy_adv_cap & ~(1 << EFX_PHY_CAP_AN)) == 0) {
165 : 0 : sfc_err(sa, "No link speeds from mask %#x are supported",
166 : : conf->link_speeds);
167 : : rc = EINVAL;
168 : : }
169 : :
170 : : #if !EFSYS_OPT_LOOPBACK
171 : : if (conf->lpbk_mode != 0) {
172 : : sfc_err(sa, "Loopback not supported");
173 : : rc = EINVAL;
174 : : }
175 : : #endif
176 : :
177 [ # # ]: 0 : if (conf->dcb_capability_en != 0) {
178 : 0 : sfc_err(sa, "Priority-based flow control not supported");
179 : : rc = EINVAL;
180 : : }
181 : :
182 [ # # ]: 0 : if ((conf->intr_conf.lsc != 0) &&
183 [ # # # # ]: 0 : (sa->intr.type != EFX_INTR_LINE) &&
184 : : (sa->intr.type != EFX_INTR_MESSAGE)) {
185 : 0 : sfc_err(sa, "Link status change interrupt not supported");
186 : : rc = EINVAL;
187 : : }
188 : :
189 [ # # ]: 0 : if (conf->intr_conf.rxq != 0 &&
190 [ # # ]: 0 : (sa->priv.dp_rx->features & SFC_DP_RX_FEAT_INTR) == 0) {
191 : 0 : sfc_err(sa, "Receive queue interrupt not supported");
192 : : rc = EINVAL;
193 : : }
194 : :
195 : 0 : return rc;
196 : : }
197 : :
198 : : /*
199 : : * Find out maximum number of receive and transmit queues which could be
200 : : * advertised.
201 : : *
202 : : * NIC is kept initialized on success to allow other modules acquire
203 : : * defaults and capabilities.
204 : : */
205 : : static int
206 : 0 : sfc_estimate_resource_limits(struct sfc_adapter *sa)
207 : : {
208 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
209 : : struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
210 : : efx_drv_limits_t limits;
211 : : int rc;
212 : : uint32_t evq_allocated;
213 : : uint32_t rxq_allocated;
214 : : uint32_t txq_allocated;
215 : :
216 : : memset(&limits, 0, sizeof(limits));
217 : :
218 : : /* Request at least one Rx and Tx queue */
219 : 0 : limits.edl_min_rxq_count = 1;
220 : 0 : limits.edl_min_txq_count = 1;
221 : : /* Management event queue plus event queue for each Tx and Rx queue */
222 : 0 : limits.edl_min_evq_count =
223 : : 1 + limits.edl_min_rxq_count + limits.edl_min_txq_count;
224 : :
225 : : /* Divide by number of functions to guarantee that all functions
226 : : * will get promised resources
227 : : */
228 : : /* FIXME Divide by number of functions (not 2) below */
229 : 0 : limits.edl_max_evq_count = encp->enc_evq_limit / 2;
230 : : SFC_ASSERT(limits.edl_max_evq_count >= limits.edl_min_rxq_count);
231 : :
232 : : /* Split equally between receive and transmit */
233 : 0 : limits.edl_max_rxq_count =
234 : 0 : MIN(encp->enc_rxq_limit, (limits.edl_max_evq_count - 1) / 2);
235 : : SFC_ASSERT(limits.edl_max_rxq_count >= limits.edl_min_rxq_count);
236 : :
237 : 0 : limits.edl_max_txq_count =
238 : 0 : MIN(encp->enc_txq_limit,
239 : : limits.edl_max_evq_count - 1 - limits.edl_max_rxq_count);
240 : :
241 [ # # # # ]: 0 : if (sa->tso && encp->enc_fw_assisted_tso_v2_enabled)
242 : 0 : limits.edl_max_txq_count =
243 : 0 : MIN(limits.edl_max_txq_count,
244 : : encp->enc_fw_assisted_tso_v2_n_contexts /
245 : : encp->enc_hw_pf_count);
246 : :
247 : : SFC_ASSERT(limits.edl_max_txq_count >= limits.edl_min_rxq_count);
248 : :
249 : : /* Configure the minimum required resources needed for the
250 : : * driver to operate, and the maximum desired resources that the
251 : : * driver is capable of using.
252 : : */
253 : 0 : efx_nic_set_drv_limits(sa->nic, &limits);
254 : :
255 : 0 : sfc_log_init(sa, "init nic");
256 : 0 : rc = efx_nic_init(sa->nic);
257 [ # # ]: 0 : if (rc != 0)
258 : 0 : goto fail_nic_init;
259 : :
260 : : /* Find resource dimensions assigned by firmware to this function */
261 : 0 : rc = efx_nic_get_vi_pool(sa->nic, &evq_allocated, &rxq_allocated,
262 : : &txq_allocated);
263 [ # # ]: 0 : if (rc != 0)
264 : 0 : goto fail_get_vi_pool;
265 : :
266 : : /* It still may allocate more than maximum, ensure limit */
267 : 0 : evq_allocated = MIN(evq_allocated, limits.edl_max_evq_count);
268 : 0 : rxq_allocated = MIN(rxq_allocated, limits.edl_max_rxq_count);
269 : 0 : txq_allocated = MIN(txq_allocated, limits.edl_max_txq_count);
270 : :
271 : : /*
272 : : * Subtract management EVQ not used for traffic
273 : : * The resource allocation strategy is as follows:
274 : : * - one EVQ for management
275 : : * - one EVQ for each ethdev RXQ
276 : : * - one EVQ for each ethdev TXQ
277 : : * - one EVQ and one RXQ for optional MAE counters.
278 : : */
279 [ # # ]: 0 : if (evq_allocated == 0) {
280 : 0 : sfc_err(sa, "count of allocated EvQ is 0");
281 : : rc = ENOMEM;
282 : 0 : goto fail_allocate_evq;
283 : : }
284 : 0 : evq_allocated--;
285 : :
286 : : /*
287 : : * Reserve absolutely required minimum.
288 : : * Right now we use separate EVQ for Rx and Tx.
289 : : */
290 [ # # # # ]: 0 : if (rxq_allocated > 0 && evq_allocated > 0) {
291 : 0 : sa->rxq_max = 1;
292 : 0 : rxq_allocated--;
293 : 0 : evq_allocated--;
294 : : }
295 [ # # # # ]: 0 : if (txq_allocated > 0 && evq_allocated > 0) {
296 : 0 : sa->txq_max = 1;
297 : 0 : txq_allocated--;
298 : 0 : evq_allocated--;
299 : : }
300 : :
301 [ # # ]: 0 : if (sfc_mae_counter_rxq_required(sa) &&
302 [ # # # # ]: 0 : rxq_allocated > 0 && evq_allocated > 0) {
303 : 0 : rxq_allocated--;
304 : 0 : evq_allocated--;
305 : 0 : sas->counters_rxq_allocated = true;
306 : : } else {
307 : 0 : sas->counters_rxq_allocated = false;
308 : : }
309 : :
310 [ # # ]: 0 : if (sfc_repr_supported(sa) &&
311 [ # # ]: 0 : evq_allocated >= SFC_REPR_PROXY_NB_RXQ_MIN +
312 : 0 : SFC_REPR_PROXY_NB_TXQ_MIN &&
313 [ # # ]: 0 : rxq_allocated >= SFC_REPR_PROXY_NB_RXQ_MIN &&
314 [ # # ]: 0 : txq_allocated >= SFC_REPR_PROXY_NB_TXQ_MIN) {
315 : : unsigned int extra;
316 : :
317 : 0 : txq_allocated -= SFC_REPR_PROXY_NB_TXQ_MIN;
318 : 0 : rxq_allocated -= SFC_REPR_PROXY_NB_RXQ_MIN;
319 : 0 : evq_allocated -= SFC_REPR_PROXY_NB_RXQ_MIN +
320 : : SFC_REPR_PROXY_NB_TXQ_MIN;
321 : :
322 : 0 : sas->nb_repr_rxq = SFC_REPR_PROXY_NB_RXQ_MIN;
323 : 0 : sas->nb_repr_txq = SFC_REPR_PROXY_NB_TXQ_MIN;
324 : :
325 : : /* Allocate extra representor RxQs up to the maximum */
326 : : extra = MIN(evq_allocated, rxq_allocated);
327 : : extra = MIN(extra,
328 : : SFC_REPR_PROXY_NB_RXQ_MAX - sas->nb_repr_rxq);
329 : : evq_allocated -= extra;
330 : : rxq_allocated -= extra;
331 : : sas->nb_repr_rxq += extra;
332 : :
333 : : /* Allocate extra representor TxQs up to the maximum */
334 : : extra = MIN(evq_allocated, txq_allocated);
335 : : extra = MIN(extra,
336 : : SFC_REPR_PROXY_NB_TXQ_MAX - sas->nb_repr_txq);
337 : : evq_allocated -= extra;
338 : : txq_allocated -= extra;
339 : : sas->nb_repr_txq += extra;
340 : : } else {
341 : 0 : sas->nb_repr_rxq = 0;
342 : 0 : sas->nb_repr_txq = 0;
343 : : }
344 : :
345 : : /* Add remaining allocated queues */
346 : 0 : sa->rxq_max += MIN(rxq_allocated, evq_allocated / 2);
347 : 0 : sa->txq_max += MIN(txq_allocated, evq_allocated - sa->rxq_max);
348 : :
349 : : /* Keep NIC initialized */
350 : 0 : return 0;
351 : :
352 : : fail_allocate_evq:
353 : 0 : fail_get_vi_pool:
354 : 0 : efx_nic_fini(sa->nic);
355 : : fail_nic_init:
356 : : return rc;
357 : : }
358 : :
359 : : static int
360 : 0 : sfc_set_drv_limits(struct sfc_adapter *sa)
361 : : {
362 : : struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
363 : 0 : const struct rte_eth_dev_data *data = sa->eth_dev->data;
364 : : uint32_t rxq_reserved = sfc_nb_reserved_rxq(sas);
365 : : uint32_t txq_reserved = sfc_nb_txq_reserved(sas);
366 : : efx_drv_limits_t lim;
367 : :
368 : : memset(&lim, 0, sizeof(lim));
369 : :
370 : : /*
371 : : * Limits are strict since take into account initial estimation.
372 : : * Resource allocation strategy is described in
373 : : * sfc_estimate_resource_limits().
374 : : */
375 : 0 : lim.edl_min_evq_count = lim.edl_max_evq_count =
376 : 0 : 1 + data->nb_rx_queues + data->nb_tx_queues +
377 : 0 : rxq_reserved + txq_reserved;
378 : 0 : lim.edl_min_rxq_count = lim.edl_max_rxq_count =
379 : 0 : data->nb_rx_queues + rxq_reserved;
380 : 0 : lim.edl_min_txq_count = lim.edl_max_txq_count =
381 : 0 : data->nb_tx_queues + txq_reserved;
382 : :
383 : 0 : return efx_nic_set_drv_limits(sa->nic, &lim);
384 : : }
385 : :
386 : : static int
387 : 0 : sfc_set_fw_subvariant(struct sfc_adapter *sa)
388 : : {
389 : : struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
390 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
391 : 0 : uint64_t tx_offloads = sa->eth_dev->data->dev_conf.txmode.offloads;
392 : : unsigned int txq_index;
393 : : efx_nic_fw_subvariant_t req_fw_subvariant;
394 : : efx_nic_fw_subvariant_t cur_fw_subvariant;
395 : : int rc;
396 : :
397 [ # # ]: 0 : if (!encp->enc_fw_subvariant_no_tx_csum_supported) {
398 : 0 : sfc_info(sa, "no-Tx-checksum subvariant not supported");
399 : 0 : return 0;
400 : : }
401 : :
402 [ # # ]: 0 : for (txq_index = 0; txq_index < sas->txq_count; ++txq_index) {
403 : 0 : struct sfc_txq_info *txq_info = &sas->txq_info[txq_index];
404 : :
405 [ # # ]: 0 : if (txq_info->state & SFC_TXQ_INITIALIZED)
406 : 0 : tx_offloads |= txq_info->offloads;
407 : : }
408 : :
409 [ # # ]: 0 : if (tx_offloads & (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
410 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
411 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
412 : : RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM))
413 : : req_fw_subvariant = EFX_NIC_FW_SUBVARIANT_DEFAULT;
414 : : else
415 : : req_fw_subvariant = EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM;
416 : :
417 : 0 : rc = efx_nic_get_fw_subvariant(sa->nic, &cur_fw_subvariant);
418 [ # # ]: 0 : if (rc != 0) {
419 : 0 : sfc_err(sa, "failed to get FW subvariant: %d", rc);
420 : 0 : return rc;
421 : : }
422 : 0 : sfc_info(sa, "FW subvariant is %u vs required %u",
423 : : cur_fw_subvariant, req_fw_subvariant);
424 : :
425 [ # # ]: 0 : if (cur_fw_subvariant == req_fw_subvariant)
426 : : return 0;
427 : :
428 : 0 : rc = efx_nic_set_fw_subvariant(sa->nic, req_fw_subvariant);
429 [ # # ]: 0 : if (rc != 0) {
430 : 0 : sfc_err(sa, "failed to set FW subvariant %u: %d",
431 : : req_fw_subvariant, rc);
432 : 0 : return rc;
433 : : }
434 : 0 : sfc_info(sa, "FW subvariant set to %u", req_fw_subvariant);
435 : :
436 : 0 : return 0;
437 : : }
438 : :
439 : : static int
440 : 0 : sfc_try_start(struct sfc_adapter *sa)
441 : : {
442 : : const efx_nic_cfg_t *encp;
443 : : int rc;
444 : :
445 : 0 : sfc_log_init(sa, "entry");
446 : :
447 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
448 : : SFC_ASSERT(sa->state == SFC_ETHDEV_STARTING);
449 : :
450 : 0 : sfc_log_init(sa, "set FW subvariant");
451 : 0 : rc = sfc_set_fw_subvariant(sa);
452 [ # # ]: 0 : if (rc != 0)
453 : 0 : goto fail_set_fw_subvariant;
454 : :
455 : 0 : sfc_log_init(sa, "set resource limits");
456 : 0 : rc = sfc_set_drv_limits(sa);
457 [ # # ]: 0 : if (rc != 0)
458 : 0 : goto fail_set_drv_limits;
459 : :
460 : 0 : sfc_log_init(sa, "init nic");
461 : 0 : rc = efx_nic_init(sa->nic);
462 [ # # ]: 0 : if (rc != 0)
463 : 0 : goto fail_nic_init;
464 : :
465 : 0 : sfc_log_init(sa, "reconfigure NIC DMA");
466 : 0 : rc = efx_nic_dma_reconfigure(sa->nic);
467 [ # # ]: 0 : if (rc != 0) {
468 : 0 : sfc_err(sa, "cannot reconfigure NIC DMA: %s", rte_strerror(rc));
469 : 0 : goto fail_nic_dma_reconfigure;
470 : : }
471 : :
472 : 0 : encp = efx_nic_cfg_get(sa->nic);
473 : :
474 : : /*
475 : : * Refresh (since it may change on NIC reset/restart) a copy of
476 : : * supported tunnel encapsulations in shared memory to be used
477 : : * on supported Rx packet type classes get.
478 : : */
479 : 0 : sa->priv.shared->tunnel_encaps =
480 : 0 : encp->enc_tunnel_encapsulations_supported;
481 : :
482 [ # # ]: 0 : if (encp->enc_tunnel_encapsulations_supported != 0) {
483 : 0 : sfc_log_init(sa, "apply tunnel config");
484 : 0 : rc = efx_tunnel_reconfigure(sa->nic);
485 [ # # ]: 0 : if (rc != 0)
486 : 0 : goto fail_tunnel_reconfigure;
487 : : }
488 : :
489 : 0 : rc = sfc_intr_start(sa);
490 [ # # ]: 0 : if (rc != 0)
491 : 0 : goto fail_intr_start;
492 : :
493 : 0 : rc = sfc_ev_start(sa);
494 [ # # ]: 0 : if (rc != 0)
495 : 0 : goto fail_ev_start;
496 : :
497 : 0 : rc = sfc_tbls_start(sa);
498 [ # # ]: 0 : if (rc != 0)
499 : 0 : goto fail_tbls_start;
500 : :
501 : 0 : rc = sfc_port_start(sa);
502 [ # # ]: 0 : if (rc != 0)
503 : 0 : goto fail_port_start;
504 : :
505 : 0 : rc = sfc_rx_start(sa);
506 [ # # ]: 0 : if (rc != 0)
507 : 0 : goto fail_rx_start;
508 : :
509 : 0 : rc = sfc_tx_start(sa);
510 [ # # ]: 0 : if (rc != 0)
511 : 0 : goto fail_tx_start;
512 : :
513 : 0 : rc = sfc_flow_start(sa);
514 [ # # ]: 0 : if (rc != 0)
515 : 0 : goto fail_flows_insert;
516 : :
517 : 0 : rc = sfc_repr_proxy_start(sa);
518 [ # # ]: 0 : if (rc != 0)
519 : 0 : goto fail_repr_proxy_start;
520 : :
521 : 0 : sfc_log_init(sa, "done");
522 : 0 : return 0;
523 : :
524 : : fail_repr_proxy_start:
525 : 0 : sfc_flow_stop(sa);
526 : :
527 : 0 : fail_flows_insert:
528 : 0 : sfc_tx_stop(sa);
529 : :
530 : 0 : fail_tx_start:
531 : 0 : sfc_rx_stop(sa);
532 : :
533 : 0 : fail_rx_start:
534 : 0 : sfc_port_stop(sa);
535 : :
536 : 0 : fail_port_start:
537 : : sfc_tbls_stop(sa);
538 : :
539 : 0 : fail_tbls_start:
540 : 0 : sfc_ev_stop(sa);
541 : :
542 : 0 : fail_ev_start:
543 : 0 : sfc_intr_stop(sa);
544 : :
545 : 0 : fail_intr_start:
546 : 0 : fail_tunnel_reconfigure:
547 : 0 : fail_nic_dma_reconfigure:
548 : 0 : efx_nic_fini(sa->nic);
549 : :
550 : 0 : fail_nic_init:
551 : 0 : fail_set_drv_limits:
552 : 0 : fail_set_fw_subvariant:
553 : 0 : sfc_log_init(sa, "failed %d", rc);
554 : 0 : return rc;
555 : : }
556 : :
557 : : int
558 : 0 : sfc_start(struct sfc_adapter *sa)
559 : : {
560 : : unsigned int start_tries = 3;
561 : : int rc;
562 : :
563 : 0 : sfc_log_init(sa, "entry");
564 : :
565 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
566 : :
567 [ # # # ]: 0 : switch (sa->state) {
568 : : case SFC_ETHDEV_CONFIGURED:
569 : : break;
570 : 0 : case SFC_ETHDEV_STARTED:
571 : 0 : sfc_notice(sa, "already started");
572 : 0 : return 0;
573 : 0 : default:
574 : : rc = EINVAL;
575 : 0 : goto fail_bad_state;
576 : : }
577 : :
578 : 0 : sa->state = SFC_ETHDEV_STARTING;
579 : :
580 : : rc = 0;
581 : : do {
582 : : /*
583 : : * FIXME Try to recreate vSwitch on start retry.
584 : : * vSwitch is absent after MC reboot like events and
585 : : * we should recreate it. May be we need proper
586 : : * indication instead of guessing.
587 : : */
588 [ # # ]: 0 : if (rc != 0) {
589 : 0 : sfc_sriov_vswitch_destroy(sa);
590 : 0 : rc = sfc_sriov_vswitch_create(sa);
591 [ # # ]: 0 : if (rc != 0)
592 : 0 : goto fail_sriov_vswitch_create;
593 : : }
594 : 0 : rc = sfc_try_start(sa);
595 [ # # ]: 0 : } while ((--start_tries > 0) &&
596 [ # # ]: 0 : (rc == EIO || rc == EAGAIN || rc == ENOENT || rc == EINVAL));
597 : :
598 [ # # ]: 0 : if (rc != 0)
599 : 0 : goto fail_try_start;
600 : :
601 : 0 : sa->state = SFC_ETHDEV_STARTED;
602 : 0 : sfc_log_init(sa, "done");
603 : 0 : return 0;
604 : :
605 : : fail_try_start:
606 : 0 : fail_sriov_vswitch_create:
607 : 0 : sa->state = SFC_ETHDEV_CONFIGURED;
608 : 0 : fail_bad_state:
609 : 0 : sfc_log_init(sa, "failed %d", rc);
610 : 0 : return rc;
611 : : }
612 : :
613 : : void
614 : 0 : sfc_stop(struct sfc_adapter *sa)
615 : : {
616 : 0 : sfc_log_init(sa, "entry");
617 : :
618 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
619 : :
620 [ # # # ]: 0 : switch (sa->state) {
621 : : case SFC_ETHDEV_STARTED:
622 : : break;
623 : 0 : case SFC_ETHDEV_CONFIGURED:
624 : 0 : sfc_notice(sa, "already stopped");
625 : 0 : return;
626 : 0 : default:
627 : 0 : sfc_err(sa, "stop in unexpected state %u", sa->state);
628 : : SFC_ASSERT(B_FALSE);
629 : 0 : return;
630 : : }
631 : :
632 : 0 : sa->state = SFC_ETHDEV_STOPPING;
633 : :
634 : 0 : sfc_repr_proxy_stop(sa);
635 : 0 : sfc_flow_stop(sa);
636 : 0 : sfc_tx_stop(sa);
637 : 0 : sfc_rx_stop(sa);
638 : 0 : sfc_port_stop(sa);
639 : : sfc_tbls_stop(sa);
640 : 0 : sfc_ev_stop(sa);
641 : 0 : sfc_intr_stop(sa);
642 : 0 : efx_nic_fini(sa->nic);
643 : :
644 : 0 : sa->state = SFC_ETHDEV_CONFIGURED;
645 : 0 : sfc_log_init(sa, "done");
646 : : }
647 : :
648 : : static int
649 : 0 : sfc_restart(struct sfc_adapter *sa)
650 : : {
651 : : int rc;
652 : :
653 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
654 : :
655 [ # # ]: 0 : if (sa->state != SFC_ETHDEV_STARTED)
656 : : return EINVAL;
657 : :
658 : 0 : sfc_stop(sa);
659 : :
660 : 0 : rc = sfc_start(sa);
661 [ # # ]: 0 : if (rc != 0)
662 : 0 : sfc_err(sa, "restart failed");
663 : :
664 : : return rc;
665 : : }
666 : :
667 : : static void
668 : 0 : sfc_restart_if_required(void *arg)
669 : : {
670 : : struct sfc_adapter *sa = arg;
671 : :
672 : : /* If restart is scheduled, clear the flag and do it */
673 [ # # ]: 0 : if (rte_atomic32_cmpset((volatile uint32_t *)&sa->restart_required,
674 : : 1, 0)) {
675 : 0 : sfc_adapter_lock(sa);
676 [ # # ]: 0 : if (sa->state == SFC_ETHDEV_STARTED)
677 : 0 : (void)sfc_restart(sa);
678 : : sfc_adapter_unlock(sa);
679 : : }
680 : 0 : }
681 : :
682 : : void
683 : 0 : sfc_schedule_restart(struct sfc_adapter *sa)
684 : : {
685 : : int rc;
686 : :
687 : : /* Schedule restart alarm if it is not scheduled yet */
688 [ # # ]: 0 : if (!rte_atomic32_test_and_set(&sa->restart_required))
689 : : return;
690 : :
691 : 0 : rc = rte_eal_alarm_set(1, sfc_restart_if_required, sa);
692 [ # # ]: 0 : if (rc == -ENOTSUP)
693 : 0 : sfc_warn(sa, "alarms are not supported, restart is pending");
694 [ # # ]: 0 : else if (rc != 0)
695 : 0 : sfc_err(sa, "cannot arm restart alarm (rc=%d)", rc);
696 : : else
697 : 0 : sfc_notice(sa, "restart scheduled");
698 : : }
699 : :
700 : : int
701 : 0 : sfc_configure(struct sfc_adapter *sa)
702 : : {
703 : : int rc;
704 : :
705 : 0 : sfc_log_init(sa, "entry");
706 : :
707 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
708 : :
709 : : SFC_ASSERT(sa->state == SFC_ETHDEV_INITIALIZED ||
710 : : sa->state == SFC_ETHDEV_CONFIGURED);
711 : 0 : sa->state = SFC_ETHDEV_CONFIGURING;
712 : :
713 : 0 : rc = sfc_check_conf(sa);
714 [ # # ]: 0 : if (rc != 0)
715 : 0 : goto fail_check_conf;
716 : :
717 : 0 : rc = sfc_intr_configure(sa);
718 [ # # ]: 0 : if (rc != 0)
719 : 0 : goto fail_intr_configure;
720 : :
721 : 0 : rc = sfc_port_configure(sa);
722 [ # # ]: 0 : if (rc != 0)
723 : 0 : goto fail_port_configure;
724 : :
725 : 0 : rc = sfc_rx_configure(sa);
726 [ # # ]: 0 : if (rc != 0)
727 : 0 : goto fail_rx_configure;
728 : :
729 : 0 : rc = sfc_tx_configure(sa);
730 [ # # ]: 0 : if (rc != 0)
731 : 0 : goto fail_tx_configure;
732 : :
733 : 0 : rc = sfc_sw_xstats_configure(sa);
734 [ # # ]: 0 : if (rc != 0)
735 : 0 : goto fail_sw_xstats_configure;
736 : :
737 : 0 : sa->state = SFC_ETHDEV_CONFIGURED;
738 : 0 : sfc_log_init(sa, "done");
739 : 0 : return 0;
740 : :
741 : : fail_sw_xstats_configure:
742 : 0 : sfc_tx_close(sa);
743 : :
744 : 0 : fail_tx_configure:
745 : 0 : sfc_rx_close(sa);
746 : :
747 : 0 : fail_rx_configure:
748 : 0 : sfc_port_close(sa);
749 : :
750 : 0 : fail_port_configure:
751 : 0 : sfc_intr_close(sa);
752 : :
753 : 0 : fail_intr_configure:
754 : 0 : fail_check_conf:
755 : 0 : sa->state = SFC_ETHDEV_INITIALIZED;
756 : 0 : sfc_log_init(sa, "failed %d", rc);
757 : 0 : return rc;
758 : : }
759 : :
760 : : void
761 : 0 : sfc_close(struct sfc_adapter *sa)
762 : : {
763 : 0 : sfc_log_init(sa, "entry");
764 : :
765 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
766 : :
767 : : SFC_ASSERT(sa->state == SFC_ETHDEV_CONFIGURED);
768 : 0 : sa->state = SFC_ETHDEV_CLOSING;
769 : :
770 : 0 : sfc_sw_xstats_close(sa);
771 : 0 : sfc_tx_close(sa);
772 : 0 : sfc_rx_close(sa);
773 : 0 : sfc_port_close(sa);
774 : 0 : sfc_intr_close(sa);
775 : :
776 : 0 : sa->state = SFC_ETHDEV_INITIALIZED;
777 : 0 : sfc_log_init(sa, "done");
778 : 0 : }
779 : :
780 : : static int
781 : : sfc_mem_bar_init(struct sfc_adapter *sa, const efx_bar_region_t *mem_ebrp)
782 : : {
783 : 0 : struct rte_eth_dev *eth_dev = sa->eth_dev;
784 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
785 : : efsys_bar_t *ebp = &sa->mem_bar;
786 : : struct rte_mem_resource *res =
787 : 0 : &pci_dev->mem_resource[mem_ebrp->ebr_index];
788 : :
789 : : SFC_BAR_LOCK_INIT(ebp, eth_dev->data->name);
790 : 0 : ebp->esb_rid = mem_ebrp->ebr_index;
791 : 0 : ebp->esb_dev = pci_dev;
792 : 0 : ebp->esb_base = res->addr;
793 : :
794 : 0 : sa->fcw_offset = mem_ebrp->ebr_offset;
795 : :
796 : : return 0;
797 : : }
798 : :
799 : : static void
800 : : sfc_mem_bar_fini(struct sfc_adapter *sa)
801 : : {
802 : 0 : efsys_bar_t *ebp = &sa->mem_bar;
803 : :
804 : : SFC_BAR_LOCK_DESTROY(ebp);
805 : : memset(ebp, 0, sizeof(*ebp));
806 : 0 : }
807 : :
808 : : /*
809 : : * A fixed RSS key which has a property of being symmetric
810 : : * (symmetrical flows are distributed to the same CPU)
811 : : * and also known to give a uniform distribution
812 : : * (a good distribution of traffic between different CPUs)
813 : : */
814 : : static const uint8_t default_rss_key[EFX_RSS_KEY_SIZE] = {
815 : : 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
816 : : 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
817 : : 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
818 : : 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
819 : : 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
820 : : };
821 : :
822 : : static int
823 : 0 : sfc_rss_attach(struct sfc_adapter *sa)
824 : : {
825 : : struct sfc_rss *rss = &sfc_sa2shared(sa)->rss;
826 : : int rc;
827 : :
828 : 0 : rc = efx_intr_init(sa->nic, sa->intr.type, NULL);
829 [ # # ]: 0 : if (rc != 0)
830 : 0 : goto fail_intr_init;
831 : :
832 : 0 : rc = efx_ev_init(sa->nic);
833 [ # # ]: 0 : if (rc != 0)
834 : 0 : goto fail_ev_init;
835 : :
836 : 0 : rc = efx_rx_init(sa->nic);
837 [ # # ]: 0 : if (rc != 0)
838 : 0 : goto fail_rx_init;
839 : :
840 : 0 : rc = efx_rx_scale_default_support_get(sa->nic, &rss->context_type);
841 [ # # ]: 0 : if (rc != 0)
842 : 0 : goto fail_scale_support_get;
843 : :
844 : 0 : rc = efx_rx_hash_default_support_get(sa->nic, &rss->hash_support);
845 [ # # ]: 0 : if (rc != 0)
846 : 0 : goto fail_hash_support_get;
847 : :
848 : 0 : rc = sfc_rx_hash_init(sa);
849 [ # # ]: 0 : if (rc != 0)
850 : 0 : goto fail_rx_hash_init;
851 : :
852 : 0 : efx_rx_fini(sa->nic);
853 : 0 : efx_ev_fini(sa->nic);
854 : 0 : efx_intr_fini(sa->nic);
855 : :
856 [ # # ]: 0 : rte_memcpy(rss->key, default_rss_key, sizeof(rss->key));
857 : 0 : memset(&rss->dummy_ctx, 0, sizeof(rss->dummy_ctx));
858 : 0 : rss->dummy_ctx.conf.qid_span = 1;
859 : 0 : rss->dummy_ctx.dummy = true;
860 : :
861 : 0 : return 0;
862 : :
863 : : fail_rx_hash_init:
864 : 0 : fail_hash_support_get:
865 : 0 : fail_scale_support_get:
866 : 0 : efx_rx_fini(sa->nic);
867 : :
868 : 0 : fail_rx_init:
869 : 0 : efx_ev_fini(sa->nic);
870 : :
871 : 0 : fail_ev_init:
872 : 0 : efx_intr_fini(sa->nic);
873 : :
874 : : fail_intr_init:
875 : : return rc;
876 : : }
877 : :
878 : : static void
879 : : sfc_rss_detach(struct sfc_adapter *sa)
880 : : {
881 : 0 : sfc_rx_hash_fini(sa);
882 : 0 : }
883 : :
884 : : int
885 : 0 : sfc_attach(struct sfc_adapter *sa)
886 : : {
887 : : const efx_nic_cfg_t *encp;
888 : 0 : efx_nic_t *enp = sa->nic;
889 : : int rc;
890 : :
891 : 0 : sfc_log_init(sa, "entry");
892 : :
893 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
894 : :
895 : 0 : efx_mcdi_new_epoch(enp);
896 : :
897 : 0 : sfc_log_init(sa, "reset nic");
898 : 0 : rc = efx_nic_reset(enp);
899 [ # # ]: 0 : if (rc != 0)
900 : 0 : goto fail_nic_reset;
901 : :
902 : 0 : rc = sfc_sriov_attach(sa);
903 [ # # ]: 0 : if (rc != 0)
904 : 0 : goto fail_sriov_attach;
905 : :
906 : : /*
907 : : * Probed NIC is sufficient for tunnel init.
908 : : * Initialize tunnel support to be able to use libefx
909 : : * efx_tunnel_config_udp_{add,remove}() in any state and
910 : : * efx_tunnel_reconfigure() on start up.
911 : : */
912 : 0 : rc = efx_tunnel_init(enp);
913 [ # # ]: 0 : if (rc != 0)
914 : 0 : goto fail_tunnel_init;
915 : :
916 : 0 : encp = efx_nic_cfg_get(sa->nic);
917 : :
918 : : /*
919 : : * Make a copy of supported tunnel encapsulations in shared
920 : : * memory to be used on supported Rx packet type classes get.
921 : : */
922 : 0 : sa->priv.shared->tunnel_encaps =
923 : 0 : encp->enc_tunnel_encapsulations_supported;
924 : :
925 [ # # ]: 0 : if (sfc_dp_tx_offload_capa(sa->priv.dp_tx) & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
926 : 0 : sa->tso = encp->enc_fw_assisted_tso_v2_enabled ||
927 : : encp->enc_tso_v3_enabled;
928 [ # # ]: 0 : if (!sa->tso)
929 : 0 : sfc_info(sa, "TSO support isn't available on this adapter");
930 : : }
931 : :
932 [ # # # # ]: 0 : if (sa->tso &&
933 [ # # ]: 0 : (sfc_dp_tx_offload_capa(sa->priv.dp_tx) &
934 : : (RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
935 : : RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO)) != 0) {
936 : 0 : sa->tso_encap = encp->enc_fw_assisted_tso_v2_encap_enabled ||
937 : : encp->enc_tso_v3_enabled;
938 [ # # ]: 0 : if (!sa->tso_encap)
939 : 0 : sfc_info(sa, "Encapsulated TSO support isn't available on this adapter");
940 : : }
941 : :
942 : 0 : sfc_log_init(sa, "estimate resource limits");
943 : 0 : rc = sfc_estimate_resource_limits(sa);
944 [ # # ]: 0 : if (rc != 0)
945 : 0 : goto fail_estimate_rsrc_limits;
946 : :
947 : 0 : sa->evq_max_entries = encp->enc_evq_max_nevs;
948 : : SFC_ASSERT(rte_is_power_of_2(sa->evq_max_entries));
949 : :
950 : 0 : sa->evq_min_entries = encp->enc_evq_min_nevs;
951 : : SFC_ASSERT(rte_is_power_of_2(sa->evq_min_entries));
952 : :
953 : 0 : sa->rxq_max_entries = encp->enc_rxq_max_ndescs;
954 : : SFC_ASSERT(rte_is_power_of_2(sa->rxq_max_entries));
955 : :
956 : 0 : sa->rxq_min_entries = encp->enc_rxq_min_ndescs;
957 : : SFC_ASSERT(rte_is_power_of_2(sa->rxq_min_entries));
958 : :
959 : 0 : sa->txq_max_entries = encp->enc_txq_max_ndescs;
960 : : SFC_ASSERT(rte_is_power_of_2(sa->txq_max_entries));
961 : :
962 : 0 : sa->txq_min_entries = encp->enc_txq_min_ndescs;
963 : : SFC_ASSERT(rte_is_power_of_2(sa->txq_min_entries));
964 : :
965 : 0 : rc = sfc_intr_attach(sa);
966 [ # # ]: 0 : if (rc != 0)
967 : 0 : goto fail_intr_attach;
968 : :
969 : 0 : rc = sfc_ev_attach(sa);
970 [ # # ]: 0 : if (rc != 0)
971 : 0 : goto fail_ev_attach;
972 : :
973 : 0 : rc = sfc_port_attach(sa);
974 [ # # ]: 0 : if (rc != 0)
975 : 0 : goto fail_port_attach;
976 : :
977 : 0 : rc = sfc_rss_attach(sa);
978 [ # # ]: 0 : if (rc != 0)
979 : 0 : goto fail_rss_attach;
980 : :
981 : 0 : sfc_flow_init(sa);
982 : :
983 : 0 : rc = sfc_flow_rss_attach(sa);
984 [ # # ]: 0 : if (rc != 0)
985 : 0 : goto fail_flow_rss_attach;
986 : :
987 : 0 : rc = sfc_filter_attach(sa);
988 [ # # ]: 0 : if (rc != 0)
989 : 0 : goto fail_filter_attach;
990 : :
991 : 0 : rc = sfc_mae_counter_rxq_attach(sa);
992 [ # # ]: 0 : if (rc != 0)
993 : 0 : goto fail_mae_counter_rxq_attach;
994 : :
995 : 0 : rc = sfc_mae_attach(sa);
996 [ # # ]: 0 : if (rc != 0)
997 : 0 : goto fail_mae_attach;
998 : :
999 : 0 : rc = sfc_tbls_attach(sa);
1000 [ # # ]: 0 : if (rc != 0)
1001 : 0 : goto fail_tables_attach;
1002 : :
1003 : 0 : rc = sfc_mae_switchdev_init(sa);
1004 [ # # ]: 0 : if (rc != 0)
1005 : 0 : goto fail_mae_switchdev_init;
1006 : :
1007 : 0 : rc = sfc_repr_proxy_attach(sa);
1008 [ # # ]: 0 : if (rc != 0)
1009 : 0 : goto fail_repr_proxy_attach;
1010 : :
1011 : 0 : sfc_log_init(sa, "fini nic");
1012 : 0 : efx_nic_fini(enp);
1013 : :
1014 : 0 : rc = sfc_sw_xstats_init(sa);
1015 [ # # ]: 0 : if (rc != 0)
1016 : 0 : goto fail_sw_xstats_init;
1017 : :
1018 : : /*
1019 : : * Create vSwitch to be able to use VFs when PF is not started yet
1020 : : * as DPDK port. VFs should be able to talk to each other even
1021 : : * if PF is down.
1022 : : */
1023 : 0 : rc = sfc_sriov_vswitch_create(sa);
1024 [ # # ]: 0 : if (rc != 0)
1025 : 0 : goto fail_sriov_vswitch_create;
1026 : :
1027 : 0 : sa->state = SFC_ETHDEV_INITIALIZED;
1028 : :
1029 : 0 : sfc_log_init(sa, "done");
1030 : 0 : return 0;
1031 : :
1032 : : fail_sriov_vswitch_create:
1033 : 0 : sfc_sw_xstats_close(sa);
1034 : :
1035 : 0 : fail_sw_xstats_init:
1036 : 0 : sfc_repr_proxy_detach(sa);
1037 : :
1038 : 0 : fail_repr_proxy_attach:
1039 : 0 : sfc_mae_switchdev_fini(sa);
1040 : :
1041 : 0 : fail_mae_switchdev_init:
1042 : 0 : sfc_tbls_detach(sa);
1043 : :
1044 : 0 : fail_tables_attach:
1045 : 0 : sfc_mae_detach(sa);
1046 : :
1047 : 0 : fail_mae_attach:
1048 : 0 : sfc_mae_counter_rxq_detach(sa);
1049 : :
1050 : 0 : fail_mae_counter_rxq_attach:
1051 : 0 : sfc_filter_detach(sa);
1052 : :
1053 : 0 : fail_filter_attach:
1054 : 0 : sfc_flow_rss_detach(sa);
1055 : :
1056 : 0 : fail_flow_rss_attach:
1057 : 0 : sfc_flow_fini(sa);
1058 : : sfc_rss_detach(sa);
1059 : :
1060 : 0 : fail_rss_attach:
1061 : 0 : sfc_port_detach(sa);
1062 : :
1063 : 0 : fail_port_attach:
1064 : 0 : sfc_ev_detach(sa);
1065 : :
1066 : 0 : fail_ev_attach:
1067 : 0 : sfc_intr_detach(sa);
1068 : :
1069 : 0 : fail_intr_attach:
1070 : 0 : efx_nic_fini(sa->nic);
1071 : :
1072 : 0 : fail_estimate_rsrc_limits:
1073 : 0 : fail_tunnel_init:
1074 : 0 : efx_tunnel_fini(sa->nic);
1075 : 0 : sfc_sriov_detach(sa);
1076 : :
1077 : 0 : fail_sriov_attach:
1078 : 0 : fail_nic_reset:
1079 : :
1080 : 0 : sfc_log_init(sa, "failed %d", rc);
1081 : 0 : return rc;
1082 : : }
1083 : :
1084 : : void
1085 : 0 : sfc_pre_detach(struct sfc_adapter *sa)
1086 : : {
1087 : 0 : sfc_log_init(sa, "entry");
1088 : :
1089 : : SFC_ASSERT(!sfc_adapter_is_locked(sa));
1090 : :
1091 : 0 : sfc_repr_proxy_pre_detach(sa);
1092 : :
1093 : 0 : sfc_log_init(sa, "done");
1094 : 0 : }
1095 : :
1096 : : void
1097 : 0 : sfc_detach(struct sfc_adapter *sa)
1098 : : {
1099 : 0 : sfc_log_init(sa, "entry");
1100 : :
1101 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
1102 : :
1103 : 0 : sfc_sriov_vswitch_destroy(sa);
1104 : :
1105 : 0 : sfc_repr_proxy_detach(sa);
1106 : 0 : sfc_mae_switchdev_fini(sa);
1107 : 0 : sfc_tbls_detach(sa);
1108 : 0 : sfc_mae_detach(sa);
1109 : 0 : sfc_mae_counter_rxq_detach(sa);
1110 : 0 : sfc_filter_detach(sa);
1111 : 0 : sfc_flow_rss_detach(sa);
1112 : 0 : sfc_flow_fini(sa);
1113 : : sfc_rss_detach(sa);
1114 : 0 : sfc_port_detach(sa);
1115 : 0 : sfc_ev_detach(sa);
1116 : 0 : sfc_intr_detach(sa);
1117 : 0 : efx_tunnel_fini(sa->nic);
1118 : 0 : sfc_sriov_detach(sa);
1119 : :
1120 : 0 : sa->state = SFC_ETHDEV_UNINITIALIZED;
1121 : 0 : }
1122 : :
1123 : : static int
1124 : 0 : sfc_kvarg_fv_variant_handler(__rte_unused const char *key,
1125 : : const char *value_str, void *opaque)
1126 : : {
1127 : : uint32_t *value = opaque;
1128 : :
1129 [ # # ]: 0 : if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_DONT_CARE) == 0)
1130 : 0 : *value = EFX_FW_VARIANT_DONT_CARE;
1131 [ # # ]: 0 : else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_FULL_FEATURED) == 0)
1132 : 0 : *value = EFX_FW_VARIANT_FULL_FEATURED;
1133 [ # # ]: 0 : else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_LOW_LATENCY) == 0)
1134 : 0 : *value = EFX_FW_VARIANT_LOW_LATENCY;
1135 [ # # ]: 0 : else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_PACKED_STREAM) == 0)
1136 : 0 : *value = EFX_FW_VARIANT_PACKED_STREAM;
1137 [ # # ]: 0 : else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_DPDK) == 0)
1138 : 0 : *value = EFX_FW_VARIANT_DPDK;
1139 : : else
1140 : : return -EINVAL;
1141 : :
1142 : : return 0;
1143 : : }
1144 : :
1145 : : static int
1146 : 0 : sfc_get_fw_variant(struct sfc_adapter *sa, efx_fw_variant_t *efv)
1147 : : {
1148 : : efx_nic_fw_info_t enfi;
1149 : : int rc;
1150 : :
1151 : 0 : rc = efx_nic_get_fw_version(sa->nic, &enfi);
1152 [ # # ]: 0 : if (rc != 0)
1153 : : return rc;
1154 [ # # ]: 0 : else if (!enfi.enfi_dpcpu_fw_ids_valid)
1155 : : return ENOTSUP;
1156 : :
1157 : : /*
1158 : : * Firmware variant can be uniquely identified by the RxDPCPU
1159 : : * firmware id
1160 : : */
1161 [ # # # # : 0 : switch (enfi.enfi_rx_dpcpu_fw_id) {
# ]
1162 : 0 : case EFX_RXDP_FULL_FEATURED_FW_ID:
1163 : 0 : *efv = EFX_FW_VARIANT_FULL_FEATURED;
1164 : 0 : break;
1165 : :
1166 : 0 : case EFX_RXDP_LOW_LATENCY_FW_ID:
1167 : 0 : *efv = EFX_FW_VARIANT_LOW_LATENCY;
1168 : 0 : break;
1169 : :
1170 : 0 : case EFX_RXDP_PACKED_STREAM_FW_ID:
1171 : 0 : *efv = EFX_FW_VARIANT_PACKED_STREAM;
1172 : 0 : break;
1173 : :
1174 : 0 : case EFX_RXDP_DPDK_FW_ID:
1175 : 0 : *efv = EFX_FW_VARIANT_DPDK;
1176 : 0 : break;
1177 : :
1178 : 0 : default:
1179 : : /*
1180 : : * Other firmware variants are not considered, since they are
1181 : : * not supported in the device parameters
1182 : : */
1183 : 0 : *efv = EFX_FW_VARIANT_DONT_CARE;
1184 : 0 : break;
1185 : : }
1186 : :
1187 : : return 0;
1188 : : }
1189 : :
1190 : : static const char *
1191 : : sfc_fw_variant2str(efx_fw_variant_t efv)
1192 : : {
1193 : 0 : switch (efv) {
1194 : : case EFX_RXDP_FULL_FEATURED_FW_ID:
1195 : : return SFC_KVARG_FW_VARIANT_FULL_FEATURED;
1196 : 0 : case EFX_RXDP_LOW_LATENCY_FW_ID:
1197 : 0 : return SFC_KVARG_FW_VARIANT_LOW_LATENCY;
1198 : 0 : case EFX_RXDP_PACKED_STREAM_FW_ID:
1199 : 0 : return SFC_KVARG_FW_VARIANT_PACKED_STREAM;
1200 : 0 : case EFX_RXDP_DPDK_FW_ID:
1201 : 0 : return SFC_KVARG_FW_VARIANT_DPDK;
1202 : 0 : default:
1203 : 0 : return "unknown";
1204 : : }
1205 : : }
1206 : :
1207 : : static int
1208 : 0 : sfc_kvarg_rxd_wait_timeout_ns(struct sfc_adapter *sa)
1209 : : {
1210 : : int rc;
1211 : : long value;
1212 : :
1213 : 0 : value = SFC_RXD_WAIT_TIMEOUT_NS_DEF;
1214 : :
1215 : 0 : rc = sfc_kvargs_process(sa, SFC_KVARG_RXD_WAIT_TIMEOUT_NS,
1216 : : sfc_kvarg_long_handler, &value);
1217 [ # # ]: 0 : if (rc != 0)
1218 : : return rc;
1219 : :
1220 [ # # ]: 0 : if (value < 0 ||
1221 : : (unsigned long)value > EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX) {
1222 : 0 : sfc_err(sa, "wrong '" SFC_KVARG_RXD_WAIT_TIMEOUT_NS "' "
1223 : : "was set (%ld);", value);
1224 : 0 : sfc_err(sa, "it must not be less than 0 or greater than %u",
1225 : : EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX);
1226 : 0 : return EINVAL;
1227 : : }
1228 : :
1229 : 0 : sa->rxd_wait_timeout_ns = value;
1230 : 0 : return 0;
1231 : : }
1232 : :
1233 : : static int
1234 : 0 : sfc_nic_probe(struct sfc_adapter *sa)
1235 : : {
1236 : 0 : efx_nic_t *enp = sa->nic;
1237 : : efx_fw_variant_t preferred_efv;
1238 : : efx_fw_variant_t efv;
1239 : : int rc;
1240 : :
1241 : 0 : preferred_efv = EFX_FW_VARIANT_DONT_CARE;
1242 : 0 : rc = sfc_kvargs_process(sa, SFC_KVARG_FW_VARIANT,
1243 : : sfc_kvarg_fv_variant_handler,
1244 : : &preferred_efv);
1245 [ # # ]: 0 : if (rc != 0) {
1246 : 0 : sfc_err(sa, "invalid %s parameter value", SFC_KVARG_FW_VARIANT);
1247 : 0 : return rc;
1248 : : }
1249 : :
1250 : 0 : rc = sfc_kvarg_rxd_wait_timeout_ns(sa);
1251 [ # # ]: 0 : if (rc != 0)
1252 : : return rc;
1253 : :
1254 : 0 : rc = efx_nic_probe(enp, preferred_efv);
1255 [ # # ]: 0 : if (rc == EACCES) {
1256 : : /* Unprivileged functions cannot set FW variant */
1257 : 0 : rc = efx_nic_probe(enp, EFX_FW_VARIANT_DONT_CARE);
1258 : : }
1259 [ # # ]: 0 : if (rc != 0)
1260 : : return rc;
1261 : :
1262 : 0 : rc = sfc_get_fw_variant(sa, &efv);
1263 [ # # ]: 0 : if (rc == ENOTSUP) {
1264 : 0 : sfc_warn(sa, "FW variant can not be obtained");
1265 : 0 : return 0;
1266 : : }
1267 [ # # ]: 0 : if (rc != 0)
1268 : : return rc;
1269 : :
1270 : : /* Check that firmware variant was changed to the requested one */
1271 [ # # # # ]: 0 : if (preferred_efv != EFX_FW_VARIANT_DONT_CARE && preferred_efv != efv) {
1272 [ # # # # : 0 : sfc_warn(sa, "FW variant has not changed to the requested %s",
# ]
1273 : : sfc_fw_variant2str(preferred_efv));
1274 : : }
1275 : :
1276 [ # # # # : 0 : sfc_notice(sa, "running FW variant is %s", sfc_fw_variant2str(efv));
# ]
1277 : :
1278 : 0 : return 0;
1279 : : }
1280 : :
1281 : : int
1282 : 0 : sfc_probe(struct sfc_adapter *sa)
1283 : : {
1284 : : efx_bar_region_t mem_ebrp;
1285 : 0 : struct rte_eth_dev *eth_dev = sa->eth_dev;
1286 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
1287 : : efx_nic_t *enp;
1288 : : int rc;
1289 : :
1290 : 0 : sfc_log_init(sa, "entry");
1291 : :
1292 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
1293 : :
1294 : 0 : sa->socket_id = rte_socket_id();
1295 : : rte_atomic32_init(&sa->restart_required);
1296 : :
1297 : 0 : sfc_log_init(sa, "get family");
1298 : 0 : rc = sfc_efx_family(pci_dev, &mem_ebrp, &sa->family);
1299 : :
1300 [ # # ]: 0 : if (rc != 0)
1301 : 0 : goto fail_family;
1302 : 0 : sfc_log_init(sa,
1303 : : "family is %u, membar is %u, function control window offset is %lu",
1304 : : sa->family, mem_ebrp.ebr_index, mem_ebrp.ebr_offset);
1305 : :
1306 : 0 : sfc_log_init(sa, "init mem bar");
1307 : : rc = sfc_mem_bar_init(sa, &mem_ebrp);
1308 : : if (rc != 0)
1309 : : goto fail_mem_bar_init;
1310 : :
1311 : 0 : sfc_log_init(sa, "create nic");
1312 : : rte_spinlock_init(&sa->nic_lock);
1313 : 0 : rc = efx_nic_create(sa->family, (efsys_identifier_t *)sa,
1314 : 0 : &sa->mem_bar, mem_ebrp.ebr_offset,
1315 : 0 : &sa->nic_lock, &enp);
1316 [ # # ]: 0 : if (rc != 0)
1317 : 0 : goto fail_nic_create;
1318 : 0 : sa->nic = enp;
1319 : :
1320 : 0 : rc = sfc_mcdi_init(sa);
1321 [ # # ]: 0 : if (rc != 0)
1322 : 0 : goto fail_mcdi_init;
1323 : :
1324 : 0 : sfc_log_init(sa, "probe nic");
1325 : 0 : rc = sfc_nic_probe(sa);
1326 [ # # ]: 0 : if (rc != 0)
1327 : 0 : goto fail_nic_probe;
1328 : :
1329 : 0 : sfc_log_init(sa, "done");
1330 : 0 : return 0;
1331 : :
1332 : : fail_nic_probe:
1333 : 0 : sfc_mcdi_fini(sa);
1334 : :
1335 : 0 : fail_mcdi_init:
1336 : 0 : sfc_log_init(sa, "destroy nic");
1337 : 0 : sa->nic = NULL;
1338 : 0 : efx_nic_destroy(enp);
1339 : :
1340 : 0 : fail_nic_create:
1341 : : sfc_mem_bar_fini(sa);
1342 : :
1343 : 0 : fail_mem_bar_init:
1344 : 0 : fail_family:
1345 : 0 : sfc_log_init(sa, "failed %d", rc);
1346 : 0 : return rc;
1347 : : }
1348 : :
1349 : : void
1350 : 0 : sfc_unprobe(struct sfc_adapter *sa)
1351 : : {
1352 : 0 : efx_nic_t *enp = sa->nic;
1353 : :
1354 : 0 : sfc_log_init(sa, "entry");
1355 : :
1356 : : SFC_ASSERT(sfc_adapter_is_locked(sa));
1357 : :
1358 : 0 : sfc_log_init(sa, "unprobe nic");
1359 : 0 : efx_nic_unprobe(enp);
1360 : :
1361 : 0 : sfc_mcdi_fini(sa);
1362 : :
1363 : : /*
1364 : : * Make sure there is no pending alarm to restart since we are
1365 : : * going to free device private which is passed as the callback
1366 : : * opaque data. A new alarm cannot be scheduled since MCDI is
1367 : : * shut down.
1368 : : */
1369 : 0 : rte_eal_alarm_cancel(sfc_restart_if_required, sa);
1370 : :
1371 : 0 : sfc_mae_clear_switch_port(sa->mae.switch_domain_id,
1372 : 0 : sa->mae.switch_port_id);
1373 : :
1374 : 0 : sfc_log_init(sa, "destroy nic");
1375 : 0 : sa->nic = NULL;
1376 : 0 : efx_nic_destroy(enp);
1377 : :
1378 : : sfc_mem_bar_fini(sa);
1379 : :
1380 : 0 : sfc_flow_fini(sa);
1381 : 0 : sa->state = SFC_ETHDEV_UNINITIALIZED;
1382 : 0 : }
1383 : :
1384 : : uint32_t
1385 : 0 : sfc_register_logtype(const struct rte_pci_addr *pci_addr,
1386 : : const char *lt_prefix_str, uint32_t ll_default)
1387 : : {
1388 : 0 : size_t lt_prefix_str_size = strlen(lt_prefix_str);
1389 : : size_t lt_str_size_max;
1390 : : char *lt_str = NULL;
1391 : : int ret;
1392 : :
1393 : : if (SIZE_MAX - PCI_PRI_STR_SIZE - 1 > lt_prefix_str_size) {
1394 : 0 : ++lt_prefix_str_size; /* Reserve space for prefix separator */
1395 : 0 : lt_str_size_max = lt_prefix_str_size + PCI_PRI_STR_SIZE + 1;
1396 : : } else {
1397 : : return sfc_logtype_driver;
1398 : : }
1399 : :
1400 : 0 : lt_str = rte_zmalloc("logtype_str", lt_str_size_max, 0);
1401 [ # # ]: 0 : if (lt_str == NULL)
1402 : 0 : return sfc_logtype_driver;
1403 : :
1404 : : strncpy(lt_str, lt_prefix_str, lt_prefix_str_size);
1405 : 0 : lt_str[lt_prefix_str_size - 1] = '.';
1406 : 0 : rte_pci_device_name(pci_addr, lt_str + lt_prefix_str_size,
1407 : : lt_str_size_max - lt_prefix_str_size);
1408 : 0 : lt_str[lt_str_size_max - 1] = '\0';
1409 : :
1410 : 0 : ret = rte_log_register_type_and_pick_level(lt_str, ll_default);
1411 : 0 : rte_free(lt_str);
1412 : :
1413 [ # # ]: 0 : if (ret < 0)
1414 : 0 : return sfc_logtype_driver;
1415 : :
1416 : 0 : return ret;
1417 : : }
1418 : :
1419 : : struct sfc_hw_switch_id {
1420 : : char board_sn[RTE_SIZEOF_FIELD(efx_nic_board_info_t, enbi_serial)];
1421 : : };
1422 : :
1423 : : int
1424 : 0 : sfc_hw_switch_id_init(struct sfc_adapter *sa,
1425 : : struct sfc_hw_switch_id **idp)
1426 : : {
1427 : : efx_nic_board_info_t board_info;
1428 : : struct sfc_hw_switch_id *id;
1429 : : int rc;
1430 : :
1431 [ # # ]: 0 : if (idp == NULL)
1432 : : return EINVAL;
1433 : :
1434 : 0 : id = rte_zmalloc("sfc_hw_switch_id", sizeof(*id), 0);
1435 [ # # ]: 0 : if (id == NULL)
1436 : : return ENOMEM;
1437 : :
1438 : 0 : rc = efx_nic_get_board_info(sa->nic, &board_info);
1439 [ # # ]: 0 : if (rc != 0)
1440 : : return rc;
1441 : :
1442 : 0 : memcpy(id->board_sn, board_info.enbi_serial, sizeof(id->board_sn));
1443 : :
1444 : 0 : *idp = id;
1445 : :
1446 : 0 : return 0;
1447 : : }
1448 : :
1449 : : void
1450 : 0 : sfc_hw_switch_id_fini(__rte_unused struct sfc_adapter *sa,
1451 : : struct sfc_hw_switch_id *id)
1452 : : {
1453 : 0 : rte_free(id);
1454 : 0 : }
1455 : :
1456 : : bool
1457 : 0 : sfc_hw_switch_ids_equal(const struct sfc_hw_switch_id *left,
1458 : : const struct sfc_hw_switch_id *right)
1459 : : {
1460 : 0 : return strncmp(left->board_sn, right->board_sn,
1461 : 0 : sizeof(left->board_sn)) == 0;
1462 : : }
|