1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2020 Xilinx, Inc.
4 * Copyright(c) 2018-2019 Solarflare Communications Inc.
11 #if EFSYS_OPT_RIVERHEAD
13 __checkReturn efx_rc_t
17 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
22 if ((rc = efx_mcdi_nic_board_cfg(enp)) != 0)
25 encp->enc_clk_mult = 1; /* not used for Riverhead */
28 * FIXME There are TxSend and TxSeg descriptors on Riverhead.
29 * TxSeg is bigger than TxSend.
31 encp->enc_tx_dma_desc_size_max = EFX_MASK32(ESF_GZ_TX_SEND_LEN);
32 /* No boundary crossing limits */
33 encp->enc_tx_dma_desc_boundary = 0;
36 * Maximum number of bytes into the frame the TCP header can start for
37 * firmware assisted TSO to work.
38 * FIXME Get from design parameter DP_TSO_MAX_HDR_LEN.
40 encp->enc_tx_tso_tcp_header_offset_limit = 0;
43 * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
44 * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
45 * resources (allocated to this PCIe function), which is zero until
46 * after we have allocated VIs.
48 encp->enc_evq_limit = 1024;
49 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
50 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
52 encp->enc_buftbl_limit = UINT32_MAX;
55 * Riverhead event queue creation completes
56 * immediately (no initial event).
58 encp->enc_evq_init_done_ev_supported = B_FALSE;
61 * Enable firmware workarounds for hardware errata.
62 * Expected responses are:
64 * Success: workaround enabled or disabled as requested.
65 * - MC_CMD_ERR_ENOSYS (reported as ENOTSUP):
66 * Firmware does not support the MC_CMD_WORKAROUND request.
67 * (assume that the workaround is not supported).
68 * - MC_CMD_ERR_ENOENT (reported as ENOENT):
69 * Firmware does not support the requested workaround.
70 * - MC_CMD_ERR_EPERM (reported as EACCES):
71 * Unprivileged function cannot enable/disable workarounds.
73 * See efx_mcdi_request_errcode() for MCDI error translations.
77 * Replay engine on Riverhead should suppress duplicate packets
78 * (e.g. because of exact multicast and all-multicast filters
79 * match) to the same RxQ.
81 encp->enc_bug26807_workaround = B_FALSE;
84 * Checksums for TSO sends should always be correct on Riverhead.
85 * FIXME: revisit when TSO support is implemented.
87 encp->enc_bug61297_workaround = B_FALSE;
89 encp->enc_evq_max_nevs = RHEAD_EVQ_MAXNEVS;
90 encp->enc_evq_min_nevs = RHEAD_EVQ_MINNEVS;
91 encp->enc_rxq_max_ndescs = RHEAD_RXQ_MAXNDESCS;
92 encp->enc_rxq_min_ndescs = RHEAD_RXQ_MINNDESCS;
93 encp->enc_txq_max_ndescs = RHEAD_TXQ_MAXNDESCS;
94 encp->enc_txq_min_ndescs = RHEAD_TXQ_MINNDESCS;
96 /* Riverhead FW does not support event queue timers yet. */
97 encp->enc_evq_timer_quantum_ns = 0;
98 encp->enc_evq_timer_max_us = 0;
100 encp->enc_ev_desc_size = RHEAD_EVQ_DESC_SIZE;
101 encp->enc_rx_desc_size = RHEAD_RXQ_DESC_SIZE;
102 encp->enc_tx_desc_size = RHEAD_TXQ_DESC_SIZE;
104 /* No required alignment for WPTR updates */
105 encp->enc_rx_push_align = 1;
107 /* Riverhead supports a single Rx prefix size. */
108 encp->enc_rx_prefix_size = ESE_GZ_RX_PKT_PREFIX_LEN;
110 /* Alignment for receive packet DMA buffers. */
111 encp->enc_rx_buf_align_start = 1;
113 /* Get the RX DMA end padding alignment configuration. */
114 if ((rc = efx_mcdi_get_rxdp_config(enp, &end_padding)) != 0) {
118 /* Assume largest tail padding size supported by hardware. */
121 encp->enc_rx_buf_align_end = end_padding;
124 * Riverhead stores a single global copy of VPD, not per-PF as on
127 encp->enc_vpd_is_global = B_TRUE;
129 rc = ef10_nic_get_port_mode_bandwidth(enp, &bandwidth);
132 encp->enc_required_pcie_bandwidth_mbps = bandwidth;
133 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
142 EFSYS_PROBE1(fail1, efx_rc_t, rc);
147 __checkReturn efx_rc_t
151 const efx_nic_ops_t *enop = enp->en_enop;
152 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
153 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
156 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp));
158 /* Read and clear any assertion state */
159 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
162 /* Exit the assertion handler */
163 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
167 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
170 /* Get remaining controller-specific board config */
171 if ((rc = enop->eno_board_cfg(enp)) != 0)
175 * Set default driver config limits (based on board config).
177 * FIXME: For now allocate a fixed number of VIs which is likely to be
178 * sufficient and small enough to allow multiple functions on the same
181 edcp->edc_min_vi_count = edcp->edc_max_vi_count =
182 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
185 * The client driver must configure and enable PIO buffer support,
186 * but there is no PIO support on Riverhead anyway.
188 edcp->edc_max_piobuf_count = 0;
189 edcp->edc_pio_alloc_size = 0;
191 #if EFSYS_OPT_MAC_STATS
192 /* Wipe the MAC statistics */
193 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
197 #if EFSYS_OPT_LOOPBACK
198 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
204 #if EFSYS_OPT_LOOPBACK
208 #if EFSYS_OPT_MAC_STATS
219 EFSYS_PROBE1(fail1, efx_rc_t, rc);
224 __checkReturn efx_rc_t
225 rhead_nic_set_drv_limits(
226 __inout efx_nic_t *enp,
227 __in efx_drv_limits_t *edlp)
229 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
230 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
231 uint32_t min_evq_count, max_evq_count;
232 uint32_t min_rxq_count, max_rxq_count;
233 uint32_t min_txq_count, max_txq_count;
241 /* Get minimum required and maximum usable VI limits */
242 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
243 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
244 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
246 edcp->edc_min_vi_count =
247 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
249 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
250 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
251 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
253 edcp->edc_max_vi_count =
254 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
256 /* There is no PIO support on Riverhead */
257 edcp->edc_max_piobuf_count = 0;
258 edcp->edc_pio_alloc_size = 0;
263 EFSYS_PROBE1(fail1, efx_rc_t, rc);
268 __checkReturn efx_rc_t
274 /* ef10_nic_reset() is called to recover from BADASSERT failures. */
275 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
277 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
280 if ((rc = efx_mcdi_entity_reset(enp)) != 0)
283 /* Clear RX/TX DMA queue errors */
284 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
293 EFSYS_PROBE1(fail1, efx_rc_t, rc);
298 __checkReturn efx_rc_t
302 const efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
303 uint32_t min_vi_count, max_vi_count;
304 uint32_t vi_count, vi_base, vi_shift;
305 uint32_t vi_window_size;
308 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp));
309 EFSYS_ASSERT3U(edcp->edc_max_piobuf_count, ==, 0);
311 /* Enable reporting of some events (e.g. link change) */
312 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
315 min_vi_count = edcp->edc_min_vi_count;
316 max_vi_count = edcp->edc_max_vi_count;
318 /* Ensure that the previously attached driver's VIs are freed */
319 if ((rc = efx_mcdi_free_vis(enp)) != 0)
323 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
324 * fails then retrying the request for fewer VI resources may succeed.
327 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
328 &vi_base, &vi_count, &vi_shift)) != 0)
331 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
333 if (vi_count < min_vi_count) {
338 enp->en_arch.ef10.ena_vi_base = vi_base;
339 enp->en_arch.ef10.ena_vi_count = vi_count;
340 enp->en_arch.ef10.ena_vi_shift = vi_shift;
342 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, !=,
343 EFX_VI_WINDOW_SHIFT_INVALID);
344 EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, <=,
345 EFX_VI_WINDOW_SHIFT_64K);
346 vi_window_size = 1U << enp->en_nic_cfg.enc_vi_window_shift;
348 /* Save UC memory mapping details */
349 enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
350 enp->en_arch.ef10.ena_uc_mem_map_size =
351 vi_window_size * enp->en_arch.ef10.ena_vi_count;
353 /* No WC memory mapping since PIO is not supported */
354 enp->en_arch.ef10.ena_pio_write_vi_base = 0;
355 enp->en_arch.ef10.ena_wc_mem_map_offset = 0;
356 enp->en_arch.ef10.ena_wc_mem_map_size = 0;
358 enp->en_vport_id = EVB_PORT_ID_NULL;
360 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
367 (void) efx_mcdi_free_vis(enp);
374 EFSYS_PROBE1(fail1, efx_rc_t, rc);
379 __checkReturn efx_rc_t
380 rhead_nic_get_vi_pool(
382 __out uint32_t *vi_countp)
385 * Report VIs that the client driver can use.
386 * Do not include VIs used for PIO buffer writes.
388 *vi_countp = enp->en_arch.ef10.ena_vi_count;
393 __checkReturn efx_rc_t
394 rhead_nic_get_bar_region(
396 __in efx_nic_region_t region,
397 __out uint32_t *offsetp,
402 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp));
405 * TODO: Specify host memory mapping alignment and granularity
406 * in efx_drv_limits_t so that they can be taken into account
407 * when allocating extra VIs for PIO writes.
411 /* UC mapped memory BAR region for VI registers */
412 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
413 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
416 case EFX_REGION_PIO_WRITE_VI:
417 /* WC mapped memory BAR region for piobuf writes */
418 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
419 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
430 EFSYS_PROBE1(fail1, efx_rc_t, rc);
435 __checkReturn boolean_t
436 rhead_nic_hw_unavailable(
441 if (enp->en_reset_flags & EFX_RESET_HW_UNAVAIL)
444 EFX_BAR_READD(enp, ER_GZ_MC_SFT_STATUS, &dword, B_FALSE);
445 if (EFX_DWORD_FIELD(dword, EFX_DWORD_0) == 0xffffffff)
451 rhead_nic_set_hw_unavailable(enp);
457 rhead_nic_set_hw_unavailable(
460 EFSYS_PROBE(hw_unavail);
461 enp->en_reset_flags |= EFX_RESET_HW_UNAVAIL;
468 (void) efx_mcdi_free_vis(enp);
469 enp->en_arch.ef10.ena_vi_count = 0;
476 (void) efx_mcdi_drv_attach(enp, B_FALSE);
481 __checkReturn efx_rc_t
482 rhead_nic_register_test(
488 _NOTE(ARGUNUSED(enp))
489 _NOTE(CONSTANTCONDITION)
499 EFSYS_PROBE1(fail1, efx_rc_t, rc);
504 #endif /* EFSYS_OPT_DIAG */
506 #endif /* EFSYS_OPT_RIVERHEAD */