siena_nic.c revision 283514
1227569Sphilip/*-
2283514Sarybchik * Copyright (c) 2009-2015 Solarflare Communications Inc.
3283514Sarybchik * All rights reserved.
4227569Sphilip *
5227569Sphilip * Redistribution and use in source and binary forms, with or without
6283514Sarybchik * modification, are permitted provided that the following conditions are met:
7227569Sphilip *
8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice,
9283514Sarybchik *    this list of conditions and the following disclaimer.
10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice,
11283514Sarybchik *    this list of conditions and the following disclaimer in the documentation
12283514Sarybchik *    and/or other materials provided with the distribution.
13283514Sarybchik *
14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25283514Sarybchik *
26283514Sarybchik * The views and conclusions contained in the software and documentation are
27283514Sarybchik * those of the authors and should not be interpreted as representing official
28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project.
29227569Sphilip */
30228078Sphilip
31228078Sphilip#include <sys/cdefs.h>
32228078Sphilip__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/siena_nic.c 283514 2015-05-25 08:34:55Z arybchik $");
33228078Sphilip
34227569Sphilip#include "efsys.h"
35227569Sphilip#include "efx.h"
36227569Sphilip#include "efx_impl.h"
37283514Sarybchik#include "mcdi_mon.h"
38227569Sphilip
39227569Sphilip#if EFSYS_OPT_SIENA
40227569Sphilip
41227569Sphilipstatic	__checkReturn		int
42227569Sphilipsiena_nic_get_partn_mask(
43227569Sphilip	__in			efx_nic_t *enp,
44227569Sphilip	__out			unsigned int *maskp)
45227569Sphilip{
46227569Sphilip	efx_mcdi_req_t req;
47283514Sarybchik	uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
48283514Sarybchik			    MC_CMD_NVRAM_TYPES_OUT_LEN)];
49227569Sphilip	int rc;
50227569Sphilip
51283514Sarybchik	(void) memset(payload, 0, sizeof (payload));
52227569Sphilip	req.emr_cmd = MC_CMD_NVRAM_TYPES;
53283514Sarybchik	req.emr_in_buf = payload;
54283514Sarybchik	req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
55283514Sarybchik	req.emr_out_buf = payload;
56283514Sarybchik	req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
57227569Sphilip
58227569Sphilip	efx_mcdi_execute(enp, &req);
59227569Sphilip
60227569Sphilip	if (req.emr_rc != 0) {
61227569Sphilip		rc = req.emr_rc;
62227569Sphilip		goto fail1;
63227569Sphilip	}
64227569Sphilip
65227569Sphilip	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
66227569Sphilip		rc = EMSGSIZE;
67227569Sphilip		goto fail2;
68227569Sphilip	}
69227569Sphilip
70227569Sphilip	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
71227569Sphilip
72227569Sphilip	return (0);
73227569Sphilip
74227569Sphilipfail2:
75227569Sphilip	EFSYS_PROBE(fail2);
76227569Sphilipfail1:
77227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
78227569Sphilip
79227569Sphilip	return (rc);
80227569Sphilip}
81227569Sphilip
82227569Sphilip#if EFSYS_OPT_PCIE_TUNE
83227569Sphilip
84227569Sphilip	__checkReturn	int
85227569Sphilipsiena_nic_pcie_extended_sync(
86227569Sphilip	__in		efx_nic_t *enp)
87227569Sphilip{
88227569Sphilip	int rc;
89227569Sphilip
90283514Sarybchik	if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
91283514Sarybchik		    B_TRUE, NULL) != 0))
92227569Sphilip		goto fail1;
93227569Sphilip
94227569Sphilip	return (0);
95227569Sphilip
96227569Sphilipfail1:
97227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
98227569Sphilip
99227569Sphilip	return (rc);
100227569Sphilip}
101227569Sphilip
102227569Sphilip#endif	/* EFSYS_OPT_PCIE_TUNE */
103227569Sphilip
104227569Sphilipstatic	__checkReturn	int
105227569Sphilipsiena_board_cfg(
106227569Sphilip	__in		efx_nic_t *enp)
107227569Sphilip{
108227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
109283514Sarybchik	uint8_t mac_addr[6];
110283514Sarybchik	efx_dword_t capabilities;
111283514Sarybchik	uint32_t board_type;
112283514Sarybchik	uint32_t nevq, nrxq, ntxq;
113227569Sphilip	int rc;
114227569Sphilip
115283514Sarybchik	/* External port identifier using one-based port numbering */
116283514Sarybchik	encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
117283514Sarybchik
118227569Sphilip	/* Board configuration */
119283514Sarybchik	if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
120283514Sarybchik		    &capabilities, mac_addr)) != 0)
121227569Sphilip		goto fail1;
122227569Sphilip
123279048Sarybchik	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
124227569Sphilip
125283514Sarybchik	encp->enc_board_type = board_type;
126227569Sphilip
127279048Sarybchik	/* Additional capabilities */
128279048Sarybchik	encp->enc_clk_mult = 1;
129283514Sarybchik	if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
130279048Sarybchik		enp->en_features |= EFX_FEATURE_TURBO;
131279048Sarybchik
132283514Sarybchik		if (EFX_DWORD_FIELD(capabilities,
133283514Sarybchik			MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
134279048Sarybchik			encp->enc_clk_mult = 2;
135283514Sarybchik		}
136279048Sarybchik	}
137279048Sarybchik
138279182Sarybchik	encp->enc_evq_timer_quantum_ns =
139279182Sarybchik		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
140279182Sarybchik	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
141279182Sarybchik		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
142279048Sarybchik
143283514Sarybchik	/* When hash header insertion is enabled, Siena inserts 16 bytes */
144283514Sarybchik	encp->enc_rx_prefix_size = 16;
145227569Sphilip
146283514Sarybchik	/* Alignment for receive packet DMA buffers */
147283514Sarybchik	encp->enc_rx_buf_align_start = 1;
148283514Sarybchik	encp->enc_rx_buf_align_end = 1;
149227569Sphilip
150283514Sarybchik	/* Alignment for WPTR updates */
151283514Sarybchik	encp->enc_rx_push_align = 1;
152227569Sphilip
153283514Sarybchik	/* Resource limits */
154283514Sarybchik	rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
155283514Sarybchik	if (rc != 0) {
156283514Sarybchik		if (rc != ENOTSUP)
157283514Sarybchik			goto fail2;
158283514Sarybchik
159283514Sarybchik		nevq = 1024;
160283514Sarybchik		nrxq = EFX_RXQ_LIMIT_TARGET;
161283514Sarybchik		ntxq = EFX_TXQ_LIMIT_TARGET;
162227569Sphilip	}
163283514Sarybchik	encp->enc_evq_limit = nevq;
164283514Sarybchik	encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
165283514Sarybchik	encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
166227569Sphilip
167227569Sphilip	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
168279098Sarybchik	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
169279098Sarybchik	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
170227569Sphilip
171283514Sarybchik	encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
172283514Sarybchik	encp->enc_fw_assisted_tso_enabled = B_FALSE;
173283514Sarybchik
174227569Sphilip	return (0);
175227569Sphilip
176227569Sphilipfail2:
177227569Sphilip	EFSYS_PROBE(fail2);
178227569Sphilipfail1:
179227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
180227569Sphilip
181227569Sphilip	return (rc);
182227569Sphilip}
183227569Sphilip
184227569Sphilipstatic	__checkReturn	int
185227569Sphilipsiena_phy_cfg(
186227569Sphilip	__in		efx_nic_t *enp)
187227569Sphilip{
188227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
189227569Sphilip	int rc;
190227569Sphilip
191283514Sarybchik	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
192283514Sarybchik	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
193227569Sphilip		goto fail1;
194227569Sphilip
195227569Sphilip#if EFSYS_OPT_PHY_STATS
196227569Sphilip	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
197283514Sarybchik	siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
198227569Sphilip			    NULL, &encp->enc_phy_stat_mask, NULL);
199227569Sphilip#endif	/* EFSYS_OPT_PHY_STATS */
200227569Sphilip
201227569Sphilip	return (0);
202227569Sphilip
203227569Sphilipfail1:
204227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
205227569Sphilip
206227569Sphilip	return (rc);
207227569Sphilip}
208227569Sphilip
209227569Sphilip	__checkReturn	int
210227569Sphilipsiena_nic_probe(
211227569Sphilip	__in		efx_nic_t *enp)
212227569Sphilip{
213227569Sphilip	efx_port_t *epp = &(enp->en_port);
214227569Sphilip	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
215227569Sphilip	siena_link_state_t sls;
216227569Sphilip	unsigned int mask;
217283514Sarybchik	efx_oword_t oword;
218227569Sphilip	int rc;
219227569Sphilip
220227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
221227569Sphilip
222283514Sarybchik	/* Test BIU */
223283514Sarybchik	if ((rc = efx_nic_biu_test(enp)) != 0)
224227569Sphilip		goto fail1;
225227569Sphilip
226283514Sarybchik	/* Clear the region register */
227283514Sarybchik	EFX_POPULATE_OWORD_4(oword,
228283514Sarybchik	    FRF_AZ_ADR_REGION0, 0,
229283514Sarybchik	    FRF_AZ_ADR_REGION1, (1 << 16),
230283514Sarybchik	    FRF_AZ_ADR_REGION2, (2 << 16),
231283514Sarybchik	    FRF_AZ_ADR_REGION3, (3 << 16));
232283514Sarybchik	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
233283514Sarybchik
234283514Sarybchik	/* Read clear any assertion state */
235283514Sarybchik	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
236227569Sphilip		goto fail2;
237227569Sphilip
238283514Sarybchik	/* Exit the assertion handler */
239283514Sarybchik	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
240227569Sphilip		goto fail3;
241227569Sphilip
242283514Sarybchik	/* Wrestle control from the BMC */
243283514Sarybchik	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
244227569Sphilip		goto fail4;
245227569Sphilip
246283514Sarybchik	if ((rc = siena_board_cfg(enp)) != 0)
247227569Sphilip		goto fail5;
248227569Sphilip
249283514Sarybchik	if ((rc = siena_phy_cfg(enp)) != 0)
250283514Sarybchik		goto fail6;
251283514Sarybchik
252227569Sphilip	/* Obtain the default PHY advertised capabilities */
253227569Sphilip	if ((rc = siena_nic_reset(enp)) != 0)
254283514Sarybchik		goto fail7;
255227569Sphilip	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
256283514Sarybchik		goto fail8;
257227569Sphilip	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
258227569Sphilip	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
259227569Sphilip
260227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
261227569Sphilip	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
262283514Sarybchik		goto fail9;
263227569Sphilip	enp->en_u.siena.enu_partn_mask = mask;
264227569Sphilip#endif
265227569Sphilip
266227569Sphilip#if EFSYS_OPT_MAC_STATS
267227569Sphilip	/* Wipe the MAC statistics */
268283514Sarybchik	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
269283514Sarybchik		goto fail10;
270227569Sphilip#endif
271227569Sphilip
272227569Sphilip#if EFSYS_OPT_LOOPBACK
273283514Sarybchik	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
274283514Sarybchik		goto fail11;
275227569Sphilip#endif
276227569Sphilip
277227569Sphilip#if EFSYS_OPT_MON_STATS
278283514Sarybchik	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
279283514Sarybchik		goto fail12;
280227569Sphilip#endif
281227569Sphilip
282227569Sphilip	encp->enc_features = enp->en_features;
283227569Sphilip
284227569Sphilip	return (0);
285227569Sphilip
286227569Sphilip#if EFSYS_OPT_MON_STATS
287283514Sarybchikfail12:
288283514Sarybchik	EFSYS_PROBE(fail12);
289283514Sarybchik#endif
290283514Sarybchik#if EFSYS_OPT_LOOPBACK
291227569Sphilipfail11:
292227569Sphilip	EFSYS_PROBE(fail11);
293227569Sphilip#endif
294283514Sarybchik#if EFSYS_OPT_MAC_STATS
295227569Sphilipfail10:
296227569Sphilip	EFSYS_PROBE(fail10);
297227569Sphilip#endif
298283514Sarybchik#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
299227569Sphilipfail9:
300227569Sphilip	EFSYS_PROBE(fail9);
301227569Sphilip#endif
302227569Sphilipfail8:
303227569Sphilip	EFSYS_PROBE(fail8);
304227569Sphilipfail7:
305227569Sphilip	EFSYS_PROBE(fail7);
306227569Sphilipfail6:
307227569Sphilip	EFSYS_PROBE(fail6);
308227569Sphilipfail5:
309227569Sphilip	EFSYS_PROBE(fail5);
310227569Sphilipfail4:
311227569Sphilip	EFSYS_PROBE(fail4);
312227569Sphilipfail3:
313227569Sphilip	EFSYS_PROBE(fail3);
314227569Sphilipfail2:
315227569Sphilip	EFSYS_PROBE(fail2);
316227569Sphilipfail1:
317227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
318227569Sphilip
319227569Sphilip	return (rc);
320227569Sphilip}
321227569Sphilip
322227569Sphilip	__checkReturn	int
323227569Sphilipsiena_nic_reset(
324227569Sphilip	__in		efx_nic_t *enp)
325227569Sphilip{
326227569Sphilip	efx_mcdi_req_t req;
327227569Sphilip	int rc;
328227569Sphilip
329227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
330227569Sphilip
331227569Sphilip	/* siena_nic_reset() is called to recover from BADASSERT failures. */
332283514Sarybchik	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
333227569Sphilip		goto fail1;
334283514Sarybchik	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
335227569Sphilip		goto fail2;
336227569Sphilip
337283514Sarybchik	/*
338283514Sarybchik	 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
339283514Sarybchik	 * for backwards compatibility with PORT_RESET_IN_LEN.
340283514Sarybchik	 */
341283514Sarybchik	EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
342283514Sarybchik
343283514Sarybchik	req.emr_cmd = MC_CMD_ENTITY_RESET;
344227569Sphilip	req.emr_in_buf = NULL;
345227569Sphilip	req.emr_in_length = 0;
346227569Sphilip	req.emr_out_buf = NULL;
347227569Sphilip	req.emr_out_length = 0;
348227569Sphilip
349227569Sphilip	efx_mcdi_execute(enp, &req);
350227569Sphilip
351227569Sphilip	if (req.emr_rc != 0) {
352227569Sphilip		rc = req.emr_rc;
353227569Sphilip		goto fail3;
354227569Sphilip	}
355227569Sphilip
356227569Sphilip	return (0);
357227569Sphilip
358227569Sphilipfail3:
359227569Sphilip	EFSYS_PROBE(fail3);
360227569Sphilipfail2:
361227569Sphilip	EFSYS_PROBE(fail2);
362227569Sphilipfail1:
363227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
364227569Sphilip
365227569Sphilip	return (0);
366227569Sphilip}
367227569Sphilip
368227569Sphilipstatic			void
369227569Sphilipsiena_nic_rx_cfg(
370227569Sphilip	__in		efx_nic_t *enp)
371227569Sphilip{
372227569Sphilip	efx_oword_t oword;
373227569Sphilip
374227569Sphilip	/*
375227569Sphilip	 * RX_INGR_EN is always enabled on Siena, because we rely on
376227569Sphilip	 * the RX parser to be resiliant to missing SOP/EOP.
377227569Sphilip	 */
378227569Sphilip	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
379227569Sphilip	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
380227569Sphilip	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
381227569Sphilip
382227569Sphilip	/* Disable parsing of additional 802.1Q in Q packets */
383227569Sphilip	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
384227569Sphilip	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
385227569Sphilip	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
386227569Sphilip}
387227569Sphilip
388227569Sphilipstatic			void
389227569Sphilipsiena_nic_usrev_dis(
390227569Sphilip	__in		efx_nic_t *enp)
391227569Sphilip{
392227569Sphilip	efx_oword_t	oword;
393227569Sphilip
394227569Sphilip	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
395227569Sphilip	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
396227569Sphilip}
397227569Sphilip
398227569Sphilip	__checkReturn	int
399227569Sphilipsiena_nic_init(
400227569Sphilip	__in		efx_nic_t *enp)
401227569Sphilip{
402227569Sphilip	int rc;
403227569Sphilip
404227569Sphilip	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
405227569Sphilip
406283514Sarybchik	/* Enable reporting of some events (e.g. link change) */
407283514Sarybchik	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
408227569Sphilip		goto fail1;
409227569Sphilip
410227569Sphilip	siena_sram_init(enp);
411227569Sphilip
412227569Sphilip	/* Configure Siena's RX block */
413227569Sphilip	siena_nic_rx_cfg(enp);
414227569Sphilip
415227569Sphilip	/* Disable USR_EVents for now */
416227569Sphilip	siena_nic_usrev_dis(enp);
417227569Sphilip
418227569Sphilip	/* bug17057: Ensure set_link is called */
419227569Sphilip	if ((rc = siena_phy_reconfigure(enp)) != 0)
420227569Sphilip		goto fail2;
421227569Sphilip
422227569Sphilip	return (0);
423227569Sphilip
424227569Sphilipfail2:
425227569Sphilip	EFSYS_PROBE(fail2);
426227569Sphilipfail1:
427227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
428227569Sphilip
429227569Sphilip	return (rc);
430227569Sphilip}
431227569Sphilip
432227569Sphilip			void
433227569Sphilipsiena_nic_fini(
434227569Sphilip	__in		efx_nic_t *enp)
435227569Sphilip{
436227569Sphilip	_NOTE(ARGUNUSED(enp))
437227569Sphilip}
438227569Sphilip
439227569Sphilip			void
440227569Sphilipsiena_nic_unprobe(
441227569Sphilip	__in		efx_nic_t *enp)
442227569Sphilip{
443283514Sarybchik#if EFSYS_OPT_MON_STATS
444283514Sarybchik	mcdi_mon_cfg_free(enp);
445283514Sarybchik#endif /* EFSYS_OPT_MON_STATS */
446283514Sarybchik	(void) efx_mcdi_drv_attach(enp, B_FALSE);
447227569Sphilip}
448227569Sphilip
449227569Sphilip#if EFSYS_OPT_DIAG
450227569Sphilip
451283514Sarybchikstatic efx_register_set_t __siena_registers[] = {
452227569Sphilip	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
453227569Sphilip	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
454227569Sphilip	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
455227569Sphilip	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
456227569Sphilip	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
457227569Sphilip	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
458227569Sphilip	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
459227569Sphilip	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
460227569Sphilip	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
461227569Sphilip	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
462227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
463227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
464227569Sphilip	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
465227569Sphilip};
466227569Sphilip
467283514Sarybchikstatic const uint32_t __siena_register_masks[] = {
468227569Sphilip	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
469227569Sphilip	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
470227569Sphilip	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
471227569Sphilip	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
472227569Sphilip	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
473227569Sphilip	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
474227569Sphilip	0x00000003, 0x00000000, 0x00000000, 0x00000000,
475227569Sphilip	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
476227569Sphilip	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
477227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
478227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
479227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
480227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
481227569Sphilip};
482227569Sphilip
483283514Sarybchikstatic efx_register_set_t __siena_tables[] = {
484227569Sphilip	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
485227569Sphilip	    FR_AZ_RX_FILTER_TBL0_ROWS },
486227569Sphilip	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
487227569Sphilip	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
488227569Sphilip	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
489227569Sphilip	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
490227569Sphilip	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
491227569Sphilip	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
492227569Sphilip	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
493227569Sphilip	{ FR_CZ_TX_FILTER_TBL0_OFST,
494227569Sphilip	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
495227569Sphilip	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
496227569Sphilip	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
497227569Sphilip};
498227569Sphilip
499283514Sarybchikstatic const uint32_t __siena_table_masks[] = {
500227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
501227569Sphilip	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
502279095Sarybchik	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
503227569Sphilip	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
504227569Sphilip	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
505227569Sphilip	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
506227569Sphilip	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
507227569Sphilip};
508227569Sphilip
509227569Sphilip	__checkReturn	int
510227569Sphilipsiena_nic_register_test(
511227569Sphilip	__in		efx_nic_t *enp)
512227569Sphilip{
513227569Sphilip	efx_register_set_t *rsp;
514227569Sphilip	const uint32_t *dwordp;
515227569Sphilip	unsigned int nitems;
516227569Sphilip	unsigned int count;
517227569Sphilip	int rc;
518227569Sphilip
519227569Sphilip	/* Fill out the register mask entries */
520227569Sphilip	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
521227569Sphilip		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
522227569Sphilip
523227569Sphilip	nitems = EFX_ARRAY_SIZE(__siena_registers);
524227569Sphilip	dwordp = __siena_register_masks;
525227569Sphilip	for (count = 0; count < nitems; ++count) {
526227569Sphilip		rsp = __siena_registers + count;
527227569Sphilip		rsp->mask.eo_u32[0] = *dwordp++;
528227569Sphilip		rsp->mask.eo_u32[1] = *dwordp++;
529227569Sphilip		rsp->mask.eo_u32[2] = *dwordp++;
530227569Sphilip		rsp->mask.eo_u32[3] = *dwordp++;
531227569Sphilip	}
532227569Sphilip
533227569Sphilip	/* Fill out the register table entries */
534227569Sphilip	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
535227569Sphilip		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
536227569Sphilip
537227569Sphilip	nitems = EFX_ARRAY_SIZE(__siena_tables);
538227569Sphilip	dwordp = __siena_table_masks;
539227569Sphilip	for (count = 0; count < nitems; ++count) {
540227569Sphilip		rsp = __siena_tables + count;
541227569Sphilip		rsp->mask.eo_u32[0] = *dwordp++;
542227569Sphilip		rsp->mask.eo_u32[1] = *dwordp++;
543227569Sphilip		rsp->mask.eo_u32[2] = *dwordp++;
544227569Sphilip		rsp->mask.eo_u32[3] = *dwordp++;
545227569Sphilip	}
546227569Sphilip
547227569Sphilip	if ((rc = efx_nic_test_registers(enp, __siena_registers,
548227569Sphilip	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
549227569Sphilip		goto fail1;
550227569Sphilip
551227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
552227569Sphilip	    EFX_PATTERN_BYTE_ALTERNATE,
553227569Sphilip	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
554227569Sphilip		goto fail2;
555227569Sphilip
556227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
557227569Sphilip	    EFX_PATTERN_BYTE_CHANGING,
558227569Sphilip	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
559227569Sphilip		goto fail3;
560227569Sphilip
561227569Sphilip	if ((rc = efx_nic_test_tables(enp, __siena_tables,
562227569Sphilip	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
563227569Sphilip		goto fail4;
564227569Sphilip
565227569Sphilip	return (0);
566227569Sphilip
567227569Sphilipfail4:
568227569Sphilip	EFSYS_PROBE(fail4);
569227569Sphilipfail3:
570227569Sphilip	EFSYS_PROBE(fail3);
571227569Sphilipfail2:
572227569Sphilip	EFSYS_PROBE(fail2);
573227569Sphilipfail1:
574227569Sphilip	EFSYS_PROBE1(fail1, int, rc);
575227569Sphilip
576227569Sphilip	return (rc);
577227569Sphilip}
578227569Sphilip
579227569Sphilip#endif	/* EFSYS_OPT_DIAG */
580227569Sphilip
581227569Sphilip#endif	/* EFSYS_OPT_SIENA */
582