]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * | |
f67539c2 TL |
3 | * Copyright(c) 2019-2020 Xilinx, Inc. |
4 | * Copyright(c) 2009-2019 Solarflare Communications Inc. | |
11fdf7f2 TL |
5 | */ |
6 | ||
7 | #include "efx.h" | |
8 | #include "efx_impl.h" | |
9 | #include "mcdi_mon.h" | |
10 | ||
11 | #if EFSYS_OPT_SIENA | |
12 | ||
13 | #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM | |
14 | ||
15 | static __checkReturn efx_rc_t | |
16 | siena_nic_get_partn_mask( | |
17 | __in efx_nic_t *enp, | |
18 | __out unsigned int *maskp) | |
19 | { | |
20 | efx_mcdi_req_t req; | |
9f95a23c TL |
21 | EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TYPES_IN_LEN, |
22 | MC_CMD_NVRAM_TYPES_OUT_LEN); | |
11fdf7f2 TL |
23 | efx_rc_t rc; |
24 | ||
11fdf7f2 TL |
25 | req.emr_cmd = MC_CMD_NVRAM_TYPES; |
26 | req.emr_in_buf = payload; | |
27 | req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN; | |
28 | req.emr_out_buf = payload; | |
29 | req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN; | |
30 | ||
31 | efx_mcdi_execute(enp, &req); | |
32 | ||
33 | if (req.emr_rc != 0) { | |
34 | rc = req.emr_rc; | |
35 | goto fail1; | |
36 | } | |
37 | ||
38 | if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { | |
39 | rc = EMSGSIZE; | |
40 | goto fail2; | |
41 | } | |
42 | ||
43 | *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); | |
44 | ||
45 | return (0); | |
46 | ||
47 | fail2: | |
48 | EFSYS_PROBE(fail2); | |
49 | fail1: | |
50 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
51 | ||
52 | return (rc); | |
53 | } | |
54 | ||
55 | #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ | |
56 | ||
57 | static __checkReturn efx_rc_t | |
58 | siena_board_cfg( | |
59 | __in efx_nic_t *enp) | |
60 | { | |
61 | efx_nic_cfg_t *encp = &(enp->en_nic_cfg); | |
62 | uint8_t mac_addr[6]; | |
63 | efx_dword_t capabilities; | |
64 | uint32_t board_type; | |
65 | uint32_t nevq, nrxq, ntxq; | |
66 | efx_rc_t rc; | |
67 | ||
68 | /* Siena has a fixed 8Kbyte VI window size */ | |
69 | EFX_STATIC_ASSERT(1U << EFX_VI_WINDOW_SHIFT_8K == 8192); | |
70 | encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K; | |
71 | ||
72 | /* External port identifier using one-based port numbering */ | |
73 | encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port; | |
74 | ||
75 | /* Board configuration */ | |
76 | if ((rc = efx_mcdi_get_board_cfg(enp, &board_type, | |
77 | &capabilities, mac_addr)) != 0) | |
78 | goto fail1; | |
79 | ||
80 | EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); | |
81 | ||
82 | encp->enc_board_type = board_type; | |
83 | ||
84 | /* | |
85 | * There is no possibility to determine the number of PFs on Siena | |
86 | * by issuing MCDI request, and it is not an easy task to find the | |
87 | * value based on the board type, so 'enc_hw_pf_count' is set to 1 | |
88 | */ | |
89 | encp->enc_hw_pf_count = 1; | |
90 | ||
91 | /* Additional capabilities */ | |
92 | encp->enc_clk_mult = 1; | |
93 | if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) { | |
94 | enp->en_features |= EFX_FEATURE_TURBO; | |
95 | ||
96 | if (EFX_DWORD_FIELD(capabilities, | |
97 | MC_CMD_CAPABILITIES_TURBO_ACTIVE)) { | |
98 | encp->enc_clk_mult = 2; | |
99 | } | |
100 | } | |
101 | ||
102 | encp->enc_evq_timer_quantum_ns = | |
103 | EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; | |
104 | encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << | |
105 | FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; | |
106 | ||
9f95a23c TL |
107 | encp->enc_ev_desc_size = SIENA_EVQ_DESC_SIZE; |
108 | encp->enc_rx_desc_size = SIENA_RXQ_DESC_SIZE; | |
109 | encp->enc_tx_desc_size = SIENA_TXQ_DESC_SIZE; | |
110 | ||
11fdf7f2 TL |
111 | /* When hash header insertion is enabled, Siena inserts 16 bytes */ |
112 | encp->enc_rx_prefix_size = 16; | |
113 | ||
114 | /* Alignment for receive packet DMA buffers */ | |
115 | encp->enc_rx_buf_align_start = 1; | |
116 | encp->enc_rx_buf_align_end = 1; | |
117 | ||
118 | /* Alignment for WPTR updates */ | |
119 | encp->enc_rx_push_align = 1; | |
120 | ||
9f95a23c | 121 | #if EFSYS_OPT_RX_SCALE |
11fdf7f2 TL |
122 | /* There is one RSS context per function */ |
123 | encp->enc_rx_scale_max_exclusive_contexts = 1; | |
124 | ||
125 | encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_LFSR); | |
126 | encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_TOEPLITZ); | |
127 | ||
128 | /* | |
129 | * It is always possible to use port numbers | |
130 | * as the input data for hash computation. | |
131 | */ | |
132 | encp->enc_rx_scale_l4_hash_supported = B_TRUE; | |
133 | ||
134 | /* There is no support for additional RSS modes */ | |
135 | encp->enc_rx_scale_additional_modes_supported = B_FALSE; | |
9f95a23c | 136 | #endif /* EFSYS_OPT_RX_SCALE */ |
11fdf7f2 TL |
137 | |
138 | encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT); | |
139 | /* Fragments must not span 4k boundaries. */ | |
140 | encp->enc_tx_dma_desc_boundary = 4096; | |
141 | ||
142 | /* Resource limits */ | |
143 | rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq); | |
144 | if (rc != 0) { | |
145 | if (rc != ENOTSUP) | |
146 | goto fail2; | |
147 | ||
148 | nevq = 1024; | |
149 | nrxq = EFX_RXQ_LIMIT_TARGET; | |
150 | ntxq = EFX_TXQ_LIMIT_TARGET; | |
151 | } | |
152 | encp->enc_evq_limit = nevq; | |
153 | encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq); | |
154 | encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq); | |
155 | ||
9f95a23c TL |
156 | encp->enc_evq_max_nevs = SIENA_EVQ_MAXNEVS; |
157 | encp->enc_evq_min_nevs = SIENA_EVQ_MINNEVS; | |
158 | ||
159 | encp->enc_rxq_max_ndescs = EF10_RXQ_MAXNDESCS; | |
160 | encp->enc_rxq_min_ndescs = EF10_RXQ_MINNDESCS; | |
161 | ||
162 | encp->enc_txq_max_ndescs = SIENA_TXQ_MAXNDESCS; | |
163 | encp->enc_txq_min_ndescs = SIENA_TXQ_MINNDESCS; | |
11fdf7f2 TL |
164 | |
165 | encp->enc_buftbl_limit = SIENA_SRAM_ROWS - | |
166 | (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - | |
167 | (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); | |
168 | ||
169 | encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; | |
170 | encp->enc_fw_assisted_tso_enabled = B_FALSE; | |
171 | encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; | |
172 | encp->enc_fw_assisted_tso_v2_n_contexts = 0; | |
173 | encp->enc_allow_set_mac_with_installed_filters = B_TRUE; | |
174 | encp->enc_rx_packed_stream_supported = B_FALSE; | |
175 | encp->enc_rx_var_packed_stream_supported = B_FALSE; | |
176 | encp->enc_rx_es_super_buffer_supported = B_FALSE; | |
177 | encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE; | |
178 | ||
179 | /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */ | |
180 | encp->enc_required_pcie_bandwidth_mbps = 2 * 10000; | |
181 | encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2; | |
182 | ||
183 | encp->enc_nvram_update_verify_result_supported = B_FALSE; | |
184 | ||
185 | encp->enc_mac_stats_nstats = MC_CMD_MAC_NSTATS; | |
186 | ||
187 | encp->enc_filter_action_flag_supported = B_FALSE; | |
188 | encp->enc_filter_action_mark_supported = B_FALSE; | |
189 | encp->enc_filter_action_mark_max = 0; | |
190 | ||
191 | return (0); | |
192 | ||
193 | fail2: | |
194 | EFSYS_PROBE(fail2); | |
195 | fail1: | |
196 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
197 | ||
198 | return (rc); | |
199 | } | |
200 | ||
201 | static __checkReturn efx_rc_t | |
202 | siena_phy_cfg( | |
203 | __in efx_nic_t *enp) | |
204 | { | |
205 | #if EFSYS_OPT_PHY_STATS | |
206 | efx_nic_cfg_t *encp = &(enp->en_nic_cfg); | |
207 | #endif /* EFSYS_OPT_PHY_STATS */ | |
208 | efx_rc_t rc; | |
209 | ||
210 | /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ | |
211 | if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) | |
212 | goto fail1; | |
213 | ||
214 | #if EFSYS_OPT_PHY_STATS | |
215 | /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ | |
216 | siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask, | |
217 | NULL, &encp->enc_phy_stat_mask, NULL); | |
218 | #endif /* EFSYS_OPT_PHY_STATS */ | |
219 | ||
220 | return (0); | |
221 | ||
222 | fail1: | |
223 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
224 | ||
225 | return (rc); | |
226 | } | |
227 | ||
228 | #define SIENA_BIU_MAGIC0 0x01234567 | |
229 | #define SIENA_BIU_MAGIC1 0xfedcba98 | |
230 | ||
231 | static __checkReturn efx_rc_t | |
232 | siena_nic_biu_test( | |
233 | __in efx_nic_t *enp) | |
234 | { | |
235 | efx_oword_t oword; | |
236 | efx_rc_t rc; | |
237 | ||
238 | /* | |
239 | * Write magic values to scratch registers 0 and 1, then | |
240 | * verify that the values were written correctly. Interleave | |
241 | * the accesses to ensure that the BIU is not just reading | |
242 | * back the cached value that was last written. | |
243 | */ | |
244 | EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0); | |
245 | EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); | |
246 | ||
247 | EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1); | |
248 | EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); | |
249 | ||
250 | EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); | |
251 | if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) { | |
252 | rc = EIO; | |
253 | goto fail1; | |
254 | } | |
255 | ||
256 | EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); | |
257 | if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) { | |
258 | rc = EIO; | |
259 | goto fail2; | |
260 | } | |
261 | ||
262 | /* | |
263 | * Perform the same test, with the values swapped. This | |
264 | * ensures that subsequent tests don't start with the correct | |
265 | * values already written into the scratch registers. | |
266 | */ | |
267 | EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1); | |
268 | EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); | |
269 | ||
270 | EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0); | |
271 | EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); | |
272 | ||
273 | EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); | |
274 | if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) { | |
275 | rc = EIO; | |
276 | goto fail3; | |
277 | } | |
278 | ||
279 | EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); | |
280 | if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) { | |
281 | rc = EIO; | |
282 | goto fail4; | |
283 | } | |
284 | ||
285 | return (0); | |
286 | ||
287 | fail4: | |
288 | EFSYS_PROBE(fail4); | |
289 | fail3: | |
290 | EFSYS_PROBE(fail3); | |
291 | fail2: | |
292 | EFSYS_PROBE(fail2); | |
293 | fail1: | |
294 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
295 | ||
296 | return (rc); | |
297 | } | |
298 | ||
299 | __checkReturn efx_rc_t | |
300 | siena_nic_probe( | |
301 | __in efx_nic_t *enp) | |
302 | { | |
303 | efx_port_t *epp = &(enp->en_port); | |
304 | efx_nic_cfg_t *encp = &(enp->en_nic_cfg); | |
305 | siena_link_state_t sls; | |
306 | unsigned int mask; | |
307 | efx_oword_t oword; | |
308 | efx_rc_t rc; | |
309 | ||
310 | EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); | |
311 | ||
312 | /* Test BIU */ | |
313 | if ((rc = siena_nic_biu_test(enp)) != 0) | |
314 | goto fail1; | |
315 | ||
316 | /* Clear the region register */ | |
317 | EFX_POPULATE_OWORD_4(oword, | |
318 | FRF_AZ_ADR_REGION0, 0, | |
319 | FRF_AZ_ADR_REGION1, (1 << 16), | |
320 | FRF_AZ_ADR_REGION2, (2 << 16), | |
321 | FRF_AZ_ADR_REGION3, (3 << 16)); | |
322 | EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword); | |
323 | ||
324 | /* Read clear any assertion state */ | |
325 | if ((rc = efx_mcdi_read_assertion(enp)) != 0) | |
326 | goto fail2; | |
327 | ||
328 | /* Exit the assertion handler */ | |
329 | if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) | |
330 | goto fail3; | |
331 | ||
332 | /* Wrestle control from the BMC */ | |
333 | if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) | |
334 | goto fail4; | |
335 | ||
336 | if ((rc = siena_board_cfg(enp)) != 0) | |
337 | goto fail5; | |
338 | ||
339 | if ((rc = siena_phy_cfg(enp)) != 0) | |
340 | goto fail6; | |
341 | ||
342 | /* Obtain the default PHY advertised capabilities */ | |
343 | if ((rc = siena_nic_reset(enp)) != 0) | |
344 | goto fail7; | |
345 | if ((rc = siena_phy_get_link(enp, &sls)) != 0) | |
346 | goto fail8; | |
347 | epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; | |
348 | epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; | |
349 | ||
350 | #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM | |
351 | if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) | |
352 | goto fail9; | |
353 | enp->en_u.siena.enu_partn_mask = mask; | |
354 | #endif | |
355 | ||
356 | #if EFSYS_OPT_MAC_STATS | |
357 | /* Wipe the MAC statistics */ | |
358 | if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) | |
359 | goto fail10; | |
360 | #endif | |
361 | ||
362 | #if EFSYS_OPT_LOOPBACK | |
363 | if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) | |
364 | goto fail11; | |
365 | #endif | |
366 | ||
367 | #if EFSYS_OPT_MON_STATS | |
368 | if ((rc = mcdi_mon_cfg_build(enp)) != 0) | |
369 | goto fail12; | |
370 | #endif | |
371 | ||
372 | encp->enc_features = enp->en_features; | |
373 | ||
374 | return (0); | |
375 | ||
376 | #if EFSYS_OPT_MON_STATS | |
377 | fail12: | |
378 | EFSYS_PROBE(fail12); | |
379 | #endif | |
380 | #if EFSYS_OPT_LOOPBACK | |
381 | fail11: | |
382 | EFSYS_PROBE(fail11); | |
383 | #endif | |
384 | #if EFSYS_OPT_MAC_STATS | |
385 | fail10: | |
386 | EFSYS_PROBE(fail10); | |
387 | #endif | |
388 | #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM | |
389 | fail9: | |
390 | EFSYS_PROBE(fail9); | |
391 | #endif | |
392 | fail8: | |
393 | EFSYS_PROBE(fail8); | |
394 | fail7: | |
395 | EFSYS_PROBE(fail7); | |
396 | fail6: | |
397 | EFSYS_PROBE(fail6); | |
398 | fail5: | |
399 | EFSYS_PROBE(fail5); | |
400 | fail4: | |
401 | EFSYS_PROBE(fail4); | |
402 | fail3: | |
403 | EFSYS_PROBE(fail3); | |
404 | fail2: | |
405 | EFSYS_PROBE(fail2); | |
406 | fail1: | |
407 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
408 | ||
409 | return (rc); | |
410 | } | |
411 | ||
412 | __checkReturn efx_rc_t | |
413 | siena_nic_reset( | |
414 | __in efx_nic_t *enp) | |
415 | { | |
416 | efx_mcdi_req_t req; | |
417 | efx_rc_t rc; | |
418 | ||
419 | EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); | |
420 | ||
421 | /* siena_nic_reset() is called to recover from BADASSERT failures. */ | |
422 | if ((rc = efx_mcdi_read_assertion(enp)) != 0) | |
423 | goto fail1; | |
424 | if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) | |
425 | goto fail2; | |
426 | ||
427 | /* | |
428 | * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied | |
429 | * for backwards compatibility with PORT_RESET_IN_LEN. | |
430 | */ | |
431 | EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0); | |
432 | ||
433 | req.emr_cmd = MC_CMD_ENTITY_RESET; | |
434 | req.emr_in_buf = NULL; | |
435 | req.emr_in_length = 0; | |
436 | req.emr_out_buf = NULL; | |
437 | req.emr_out_length = 0; | |
438 | ||
439 | efx_mcdi_execute(enp, &req); | |
440 | ||
441 | if (req.emr_rc != 0) { | |
442 | rc = req.emr_rc; | |
443 | goto fail3; | |
444 | } | |
445 | ||
446 | return (0); | |
447 | ||
448 | fail3: | |
449 | EFSYS_PROBE(fail3); | |
450 | fail2: | |
451 | EFSYS_PROBE(fail2); | |
452 | fail1: | |
453 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
454 | ||
455 | return (0); | |
456 | } | |
457 | ||
458 | static void | |
459 | siena_nic_rx_cfg( | |
460 | __in efx_nic_t *enp) | |
461 | { | |
462 | efx_oword_t oword; | |
463 | ||
464 | /* | |
465 | * RX_INGR_EN is always enabled on Siena, because we rely on | |
466 | * the RX parser to be resiliant to missing SOP/EOP. | |
467 | */ | |
468 | EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); | |
469 | EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); | |
470 | EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); | |
471 | ||
472 | /* Disable parsing of additional 802.1Q in Q packets */ | |
473 | EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); | |
474 | EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); | |
475 | EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); | |
476 | } | |
477 | ||
478 | static void | |
479 | siena_nic_usrev_dis( | |
480 | __in efx_nic_t *enp) | |
481 | { | |
482 | efx_oword_t oword; | |
483 | ||
484 | EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); | |
485 | EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); | |
486 | } | |
487 | ||
488 | __checkReturn efx_rc_t | |
489 | siena_nic_init( | |
490 | __in efx_nic_t *enp) | |
491 | { | |
492 | efx_rc_t rc; | |
493 | ||
494 | EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); | |
495 | ||
496 | /* Enable reporting of some events (e.g. link change) */ | |
497 | if ((rc = efx_mcdi_log_ctrl(enp)) != 0) | |
498 | goto fail1; | |
499 | ||
500 | siena_sram_init(enp); | |
501 | ||
502 | /* Configure Siena's RX block */ | |
503 | siena_nic_rx_cfg(enp); | |
504 | ||
505 | /* Disable USR_EVents for now */ | |
506 | siena_nic_usrev_dis(enp); | |
507 | ||
508 | /* bug17057: Ensure set_link is called */ | |
509 | if ((rc = siena_phy_reconfigure(enp)) != 0) | |
510 | goto fail2; | |
511 | ||
512 | enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1; | |
513 | ||
514 | return (0); | |
515 | ||
516 | fail2: | |
517 | EFSYS_PROBE(fail2); | |
518 | fail1: | |
519 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
520 | ||
521 | return (rc); | |
522 | } | |
523 | ||
524 | void | |
525 | siena_nic_fini( | |
526 | __in efx_nic_t *enp) | |
527 | { | |
528 | _NOTE(ARGUNUSED(enp)) | |
529 | } | |
530 | ||
531 | void | |
532 | siena_nic_unprobe( | |
533 | __in efx_nic_t *enp) | |
534 | { | |
535 | #if EFSYS_OPT_MON_STATS | |
536 | mcdi_mon_cfg_free(enp); | |
537 | #endif /* EFSYS_OPT_MON_STATS */ | |
538 | (void) efx_mcdi_drv_attach(enp, B_FALSE); | |
539 | } | |
540 | ||
541 | #if EFSYS_OPT_DIAG | |
542 | ||
543 | static siena_register_set_t __siena_registers[] = { | |
544 | { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, | |
545 | { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, | |
546 | { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, | |
547 | { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, | |
548 | { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, | |
549 | { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, | |
550 | { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, | |
551 | { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, | |
552 | { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, | |
553 | { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, | |
554 | { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, | |
555 | { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, | |
556 | { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} | |
557 | }; | |
558 | ||
559 | static const uint32_t __siena_register_masks[] = { | |
560 | 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, | |
561 | 0x000103FF, 0x00000000, 0x00000000, 0x00000000, | |
562 | 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, | |
563 | 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, | |
564 | 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, | |
565 | 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, | |
566 | 0x00000003, 0x00000000, 0x00000000, 0x00000000, | |
567 | 0x000003FF, 0x00000000, 0x00000000, 0x00000000, | |
568 | 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, | |
569 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | |
570 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | |
571 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | |
572 | 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 | |
573 | }; | |
574 | ||
575 | static siena_register_set_t __siena_tables[] = { | |
576 | { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, | |
577 | FR_AZ_RX_FILTER_TBL0_ROWS }, | |
578 | { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, | |
579 | FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, | |
580 | { FR_AZ_RX_DESC_PTR_TBL_OFST, | |
581 | FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, | |
582 | { FR_AZ_TX_DESC_PTR_TBL_OFST, | |
583 | FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, | |
584 | { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, | |
585 | { FR_CZ_TX_FILTER_TBL0_OFST, | |
586 | FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, | |
587 | { FR_CZ_TX_MAC_FILTER_TBL0_OFST, | |
588 | FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } | |
589 | }; | |
590 | ||
591 | static const uint32_t __siena_table_masks[] = { | |
592 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, | |
593 | 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, | |
594 | 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, | |
595 | 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, | |
596 | 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, | |
597 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, | |
598 | 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, | |
599 | }; | |
600 | ||
601 | __checkReturn efx_rc_t | |
602 | siena_nic_test_registers( | |
603 | __in efx_nic_t *enp, | |
604 | __in siena_register_set_t *rsp, | |
605 | __in size_t count) | |
606 | { | |
607 | unsigned int bit; | |
608 | efx_oword_t original; | |
609 | efx_oword_t reg; | |
610 | efx_oword_t buf; | |
611 | efx_rc_t rc; | |
612 | ||
613 | while (count > 0) { | |
614 | /* This function is only suitable for registers */ | |
615 | EFSYS_ASSERT(rsp->rows == 1); | |
616 | ||
617 | /* bit sweep on and off */ | |
618 | EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, | |
619 | B_TRUE); | |
620 | for (bit = 0; bit < 128; bit++) { | |
621 | /* Is this bit in the mask? */ | |
622 | if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) | |
623 | continue; | |
624 | ||
625 | /* Test this bit can be set in isolation */ | |
626 | reg = original; | |
627 | EFX_AND_OWORD(reg, rsp->mask); | |
628 | EFX_SET_OWORD_BIT(reg, bit); | |
629 | ||
630 | EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, | |
631 | B_TRUE); | |
632 | EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, | |
633 | B_TRUE); | |
634 | ||
635 | EFX_AND_OWORD(buf, rsp->mask); | |
636 | if (memcmp(®, &buf, sizeof (reg))) { | |
637 | rc = EIO; | |
638 | goto fail1; | |
639 | } | |
640 | ||
641 | /* Test this bit can be cleared in isolation */ | |
642 | EFX_OR_OWORD(reg, rsp->mask); | |
643 | EFX_CLEAR_OWORD_BIT(reg, bit); | |
644 | ||
645 | EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, | |
646 | B_TRUE); | |
647 | EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, | |
648 | B_TRUE); | |
649 | ||
650 | EFX_AND_OWORD(buf, rsp->mask); | |
651 | if (memcmp(®, &buf, sizeof (reg))) { | |
652 | rc = EIO; | |
653 | goto fail2; | |
654 | } | |
655 | } | |
656 | ||
657 | /* Restore the old value */ | |
658 | EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, | |
659 | B_TRUE); | |
660 | ||
661 | --count; | |
662 | ++rsp; | |
663 | } | |
664 | ||
665 | return (0); | |
666 | ||
667 | fail2: | |
668 | EFSYS_PROBE(fail2); | |
669 | fail1: | |
670 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
671 | ||
672 | /* Restore the old value */ | |
673 | EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); | |
674 | ||
675 | return (rc); | |
676 | } | |
677 | ||
678 | __checkReturn efx_rc_t | |
679 | siena_nic_test_tables( | |
680 | __in efx_nic_t *enp, | |
681 | __in siena_register_set_t *rsp, | |
682 | __in efx_pattern_type_t pattern, | |
683 | __in size_t count) | |
684 | { | |
685 | efx_sram_pattern_fn_t func; | |
686 | unsigned int index; | |
687 | unsigned int address; | |
688 | efx_oword_t reg; | |
689 | efx_oword_t buf; | |
690 | efx_rc_t rc; | |
691 | ||
692 | EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); | |
693 | func = __efx_sram_pattern_fns[pattern]; | |
694 | ||
695 | while (count > 0) { | |
696 | /* Write */ | |
697 | address = rsp->address; | |
698 | for (index = 0; index < rsp->rows; ++index) { | |
699 | func(2 * index + 0, B_FALSE, ®.eo_qword[0]); | |
700 | func(2 * index + 1, B_FALSE, ®.eo_qword[1]); | |
701 | EFX_AND_OWORD(reg, rsp->mask); | |
702 | EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); | |
703 | ||
704 | address += rsp->step; | |
705 | } | |
706 | ||
707 | /* Read */ | |
708 | address = rsp->address; | |
709 | for (index = 0; index < rsp->rows; ++index) { | |
710 | func(2 * index + 0, B_FALSE, ®.eo_qword[0]); | |
711 | func(2 * index + 1, B_FALSE, ®.eo_qword[1]); | |
712 | EFX_AND_OWORD(reg, rsp->mask); | |
713 | EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); | |
714 | if (memcmp(®, &buf, sizeof (reg))) { | |
715 | rc = EIO; | |
716 | goto fail1; | |
717 | } | |
718 | ||
719 | address += rsp->step; | |
720 | } | |
721 | ||
722 | ++rsp; | |
723 | --count; | |
724 | } | |
725 | ||
726 | return (0); | |
727 | ||
728 | fail1: | |
729 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
730 | ||
731 | return (rc); | |
732 | } | |
733 | ||
734 | ||
735 | __checkReturn efx_rc_t | |
736 | siena_nic_register_test( | |
737 | __in efx_nic_t *enp) | |
738 | { | |
739 | siena_register_set_t *rsp; | |
740 | const uint32_t *dwordp; | |
741 | unsigned int nitems; | |
742 | unsigned int count; | |
743 | efx_rc_t rc; | |
744 | ||
745 | /* Fill out the register mask entries */ | |
746 | EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) | |
747 | == EFX_ARRAY_SIZE(__siena_registers) * 4); | |
748 | ||
749 | nitems = EFX_ARRAY_SIZE(__siena_registers); | |
750 | dwordp = __siena_register_masks; | |
751 | for (count = 0; count < nitems; ++count) { | |
752 | rsp = __siena_registers + count; | |
753 | rsp->mask.eo_u32[0] = *dwordp++; | |
754 | rsp->mask.eo_u32[1] = *dwordp++; | |
755 | rsp->mask.eo_u32[2] = *dwordp++; | |
756 | rsp->mask.eo_u32[3] = *dwordp++; | |
757 | } | |
758 | ||
759 | /* Fill out the register table entries */ | |
760 | EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) | |
761 | == EFX_ARRAY_SIZE(__siena_tables) * 4); | |
762 | ||
763 | nitems = EFX_ARRAY_SIZE(__siena_tables); | |
764 | dwordp = __siena_table_masks; | |
765 | for (count = 0; count < nitems; ++count) { | |
766 | rsp = __siena_tables + count; | |
767 | rsp->mask.eo_u32[0] = *dwordp++; | |
768 | rsp->mask.eo_u32[1] = *dwordp++; | |
769 | rsp->mask.eo_u32[2] = *dwordp++; | |
770 | rsp->mask.eo_u32[3] = *dwordp++; | |
771 | } | |
772 | ||
773 | if ((rc = siena_nic_test_registers(enp, __siena_registers, | |
774 | EFX_ARRAY_SIZE(__siena_registers))) != 0) | |
775 | goto fail1; | |
776 | ||
777 | if ((rc = siena_nic_test_tables(enp, __siena_tables, | |
778 | EFX_PATTERN_BYTE_ALTERNATE, | |
779 | EFX_ARRAY_SIZE(__siena_tables))) != 0) | |
780 | goto fail2; | |
781 | ||
782 | if ((rc = siena_nic_test_tables(enp, __siena_tables, | |
783 | EFX_PATTERN_BYTE_CHANGING, | |
784 | EFX_ARRAY_SIZE(__siena_tables))) != 0) | |
785 | goto fail3; | |
786 | ||
787 | if ((rc = siena_nic_test_tables(enp, __siena_tables, | |
788 | EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) | |
789 | goto fail4; | |
790 | ||
791 | return (0); | |
792 | ||
793 | fail4: | |
794 | EFSYS_PROBE(fail4); | |
795 | fail3: | |
796 | EFSYS_PROBE(fail3); | |
797 | fail2: | |
798 | EFSYS_PROBE(fail2); | |
799 | fail1: | |
800 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
801 | ||
802 | return (rc); | |
803 | } | |
804 | ||
805 | #endif /* EFSYS_OPT_DIAG */ | |
806 | ||
807 | #endif /* EFSYS_OPT_SIENA */ |