siena_nic.c revision 284555
1/*-
2 * Copyright (c) 2009-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 *    this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 *    this list of conditions and the following disclaimer in the documentation
12 *    and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/common/siena_nic.c 284555 2015-06-18 15:46:39Z arybchik $");
33
34#include "efsys.h"
35#include "efx.h"
36#include "efx_impl.h"
37#include "mcdi_mon.h"
38
39#if EFSYS_OPT_SIENA
40
41static	__checkReturn		int
42siena_nic_get_partn_mask(
43	__in			efx_nic_t *enp,
44	__out			unsigned int *maskp)
45{
46	efx_mcdi_req_t req;
47	uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
48			    MC_CMD_NVRAM_TYPES_OUT_LEN)];
49	int rc;
50
51	(void) memset(payload, 0, sizeof (payload));
52	req.emr_cmd = MC_CMD_NVRAM_TYPES;
53	req.emr_in_buf = payload;
54	req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
55	req.emr_out_buf = payload;
56	req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
57
58	efx_mcdi_execute(enp, &req);
59
60	if (req.emr_rc != 0) {
61		rc = req.emr_rc;
62		goto fail1;
63	}
64
65	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
66		rc = EMSGSIZE;
67		goto fail2;
68	}
69
70	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
71
72	return (0);
73
74fail2:
75	EFSYS_PROBE(fail2);
76fail1:
77	EFSYS_PROBE1(fail1, int, rc);
78
79	return (rc);
80}
81
82#if EFSYS_OPT_PCIE_TUNE
83
84	__checkReturn	int
85siena_nic_pcie_extended_sync(
86	__in		efx_nic_t *enp)
87{
88	int rc;
89
90	if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
91		    B_TRUE, NULL) != 0))
92		goto fail1;
93
94	return (0);
95
96fail1:
97	EFSYS_PROBE1(fail1, int, rc);
98
99	return (rc);
100}
101
102#endif	/* EFSYS_OPT_PCIE_TUNE */
103
104static	__checkReturn	int
105siena_board_cfg(
106	__in		efx_nic_t *enp)
107{
108	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
109	uint8_t mac_addr[6];
110	efx_dword_t capabilities;
111	uint32_t board_type;
112	uint32_t nevq, nrxq, ntxq;
113	int rc;
114
115	/* External port identifier using one-based port numbering */
116	encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
117
118	/* Board configuration */
119	if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
120		    &capabilities, mac_addr)) != 0)
121		goto fail1;
122
123	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
124
125	encp->enc_board_type = board_type;
126
127	/* Additional capabilities */
128	encp->enc_clk_mult = 1;
129	if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
130		enp->en_features |= EFX_FEATURE_TURBO;
131
132		if (EFX_DWORD_FIELD(capabilities,
133			MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
134			encp->enc_clk_mult = 2;
135		}
136	}
137
138	encp->enc_evq_timer_quantum_ns =
139		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
140	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
141		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
142
143	/* When hash header insertion is enabled, Siena inserts 16 bytes */
144	encp->enc_rx_prefix_size = 16;
145
146	/* Alignment for receive packet DMA buffers */
147	encp->enc_rx_buf_align_start = 1;
148	encp->enc_rx_buf_align_end = 1;
149
150	/* Alignment for WPTR updates */
151	encp->enc_rx_push_align = 1;
152
153	/* Resource limits */
154	rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
155	if (rc != 0) {
156		if (rc != ENOTSUP)
157			goto fail2;
158
159		nevq = 1024;
160		nrxq = EFX_RXQ_LIMIT_TARGET;
161		ntxq = EFX_TXQ_LIMIT_TARGET;
162	}
163	encp->enc_evq_limit = nevq;
164	encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
165	encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
166
167	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
168	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
169	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
170
171	encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
172	encp->enc_fw_assisted_tso_enabled = B_FALSE;
173
174	return (0);
175
176fail2:
177	EFSYS_PROBE(fail2);
178fail1:
179	EFSYS_PROBE1(fail1, int, rc);
180
181	return (rc);
182}
183
184static	__checkReturn	int
185siena_phy_cfg(
186	__in		efx_nic_t *enp)
187{
188	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
189	int rc;
190
191	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
192	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
193		goto fail1;
194
195#if EFSYS_OPT_PHY_STATS
196	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
197	siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
198			    NULL, &encp->enc_phy_stat_mask, NULL);
199#endif	/* EFSYS_OPT_PHY_STATS */
200
201	return (0);
202
203fail1:
204	EFSYS_PROBE1(fail1, int, rc);
205
206	return (rc);
207}
208
209	__checkReturn	int
210siena_nic_probe(
211	__in		efx_nic_t *enp)
212{
213	efx_port_t *epp = &(enp->en_port);
214	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
215	siena_link_state_t sls;
216	unsigned int mask;
217	efx_oword_t oword;
218	int rc;
219
220	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
221
222	/* Test BIU */
223	if ((rc = efx_nic_biu_test(enp)) != 0)
224		goto fail1;
225
226	/* Clear the region register */
227	EFX_POPULATE_OWORD_4(oword,
228	    FRF_AZ_ADR_REGION0, 0,
229	    FRF_AZ_ADR_REGION1, (1 << 16),
230	    FRF_AZ_ADR_REGION2, (2 << 16),
231	    FRF_AZ_ADR_REGION3, (3 << 16));
232	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
233
234	/* Read clear any assertion state */
235	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
236		goto fail2;
237
238	/* Exit the assertion handler */
239	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
240		goto fail3;
241
242	/* Wrestle control from the BMC */
243	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
244		goto fail4;
245
246	if ((rc = siena_board_cfg(enp)) != 0)
247		goto fail5;
248
249	if ((rc = siena_phy_cfg(enp)) != 0)
250		goto fail6;
251
252	/* Obtain the default PHY advertised capabilities */
253	if ((rc = siena_nic_reset(enp)) != 0)
254		goto fail7;
255	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
256		goto fail8;
257	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
258	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
259
260#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
261	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
262		goto fail9;
263	enp->en_u.siena.enu_partn_mask = mask;
264#endif
265
266#if EFSYS_OPT_MAC_STATS
267	/* Wipe the MAC statistics */
268	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
269		goto fail10;
270#endif
271
272#if EFSYS_OPT_LOOPBACK
273	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
274		goto fail11;
275#endif
276
277#if EFSYS_OPT_MON_STATS
278	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
279		goto fail12;
280#endif
281
282	encp->enc_features = enp->en_features;
283
284	return (0);
285
286#if EFSYS_OPT_MON_STATS
287fail12:
288	EFSYS_PROBE(fail12);
289#endif
290#if EFSYS_OPT_LOOPBACK
291fail11:
292	EFSYS_PROBE(fail11);
293#endif
294#if EFSYS_OPT_MAC_STATS
295fail10:
296	EFSYS_PROBE(fail10);
297#endif
298#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
299fail9:
300	EFSYS_PROBE(fail9);
301#endif
302fail8:
303	EFSYS_PROBE(fail8);
304fail7:
305	EFSYS_PROBE(fail7);
306fail6:
307	EFSYS_PROBE(fail6);
308fail5:
309	EFSYS_PROBE(fail5);
310fail4:
311	EFSYS_PROBE(fail4);
312fail3:
313	EFSYS_PROBE(fail3);
314fail2:
315	EFSYS_PROBE(fail2);
316fail1:
317	EFSYS_PROBE1(fail1, int, rc);
318
319	return (rc);
320}
321
322	__checkReturn	int
323siena_nic_reset(
324	__in		efx_nic_t *enp)
325{
326	efx_mcdi_req_t req;
327	int rc;
328
329	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
330
331	/* siena_nic_reset() is called to recover from BADASSERT failures. */
332	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
333		goto fail1;
334	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
335		goto fail2;
336
337	/*
338	 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
339	 * for backwards compatibility with PORT_RESET_IN_LEN.
340	 */
341	EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
342
343	req.emr_cmd = MC_CMD_ENTITY_RESET;
344	req.emr_in_buf = NULL;
345	req.emr_in_length = 0;
346	req.emr_out_buf = NULL;
347	req.emr_out_length = 0;
348
349	efx_mcdi_execute(enp, &req);
350
351	if (req.emr_rc != 0) {
352		rc = req.emr_rc;
353		goto fail3;
354	}
355
356	return (0);
357
358fail3:
359	EFSYS_PROBE(fail3);
360fail2:
361	EFSYS_PROBE(fail2);
362fail1:
363	EFSYS_PROBE1(fail1, int, rc);
364
365	return (0);
366}
367
368static			void
369siena_nic_rx_cfg(
370	__in		efx_nic_t *enp)
371{
372	efx_oword_t oword;
373
374	/*
375	 * RX_INGR_EN is always enabled on Siena, because we rely on
376	 * the RX parser to be resiliant to missing SOP/EOP.
377	 */
378	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
379	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
380	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
381
382	/* Disable parsing of additional 802.1Q in Q packets */
383	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
384	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
385	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
386}
387
388static			void
389siena_nic_usrev_dis(
390	__in		efx_nic_t *enp)
391{
392	efx_oword_t	oword;
393
394	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
395	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
396}
397
398	__checkReturn	int
399siena_nic_init(
400	__in		efx_nic_t *enp)
401{
402	int rc;
403
404	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
405
406	/* Enable reporting of some events (e.g. link change) */
407	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
408		goto fail1;
409
410	siena_sram_init(enp);
411
412	/* Configure Siena's RX block */
413	siena_nic_rx_cfg(enp);
414
415	/* Disable USR_EVents for now */
416	siena_nic_usrev_dis(enp);
417
418	/* bug17057: Ensure set_link is called */
419	if ((rc = siena_phy_reconfigure(enp)) != 0)
420		goto fail2;
421
422	return (0);
423
424fail2:
425	EFSYS_PROBE(fail2);
426fail1:
427	EFSYS_PROBE1(fail1, int, rc);
428
429	return (rc);
430}
431
432			void
433siena_nic_fini(
434	__in		efx_nic_t *enp)
435{
436	_NOTE(ARGUNUSED(enp))
437}
438
439			void
440siena_nic_unprobe(
441	__in		efx_nic_t *enp)
442{
443#if EFSYS_OPT_MON_STATS
444	mcdi_mon_cfg_free(enp);
445#endif /* EFSYS_OPT_MON_STATS */
446	(void) efx_mcdi_drv_attach(enp, B_FALSE);
447}
448
449#if EFSYS_OPT_DIAG
450
451static efx_register_set_t __siena_registers[] = {
452	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
453	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
454	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
455	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
456	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
457	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
458	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
459	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
460	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
461	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
462	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
463	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
464	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
465};
466
467static const uint32_t __siena_register_masks[] = {
468	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
469	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
470	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
471	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
472	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
473	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
474	0x00000003, 0x00000000, 0x00000000, 0x00000000,
475	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
476	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
477	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
478	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
479	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
480	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
481};
482
483static efx_register_set_t __siena_tables[] = {
484	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
485	    FR_AZ_RX_FILTER_TBL0_ROWS },
486	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
487	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
488	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
489	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
490	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
491	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
492	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
493	{ FR_CZ_TX_FILTER_TBL0_OFST,
494	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
495	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
496	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
497};
498
499static const uint32_t __siena_table_masks[] = {
500	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
501	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
502	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
503	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
504	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
505	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
506	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
507};
508
509	__checkReturn	int
510siena_nic_register_test(
511	__in		efx_nic_t *enp)
512{
513	efx_register_set_t *rsp;
514	const uint32_t *dwordp;
515	unsigned int nitems;
516	unsigned int count;
517	int rc;
518
519	/* Fill out the register mask entries */
520	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
521		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
522
523	nitems = EFX_ARRAY_SIZE(__siena_registers);
524	dwordp = __siena_register_masks;
525	for (count = 0; count < nitems; ++count) {
526		rsp = __siena_registers + count;
527		rsp->mask.eo_u32[0] = *dwordp++;
528		rsp->mask.eo_u32[1] = *dwordp++;
529		rsp->mask.eo_u32[2] = *dwordp++;
530		rsp->mask.eo_u32[3] = *dwordp++;
531	}
532
533	/* Fill out the register table entries */
534	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
535		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
536
537	nitems = EFX_ARRAY_SIZE(__siena_tables);
538	dwordp = __siena_table_masks;
539	for (count = 0; count < nitems; ++count) {
540		rsp = __siena_tables + count;
541		rsp->mask.eo_u32[0] = *dwordp++;
542		rsp->mask.eo_u32[1] = *dwordp++;
543		rsp->mask.eo_u32[2] = *dwordp++;
544		rsp->mask.eo_u32[3] = *dwordp++;
545	}
546
547	if ((rc = efx_nic_test_registers(enp, __siena_registers,
548	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
549		goto fail1;
550
551	if ((rc = efx_nic_test_tables(enp, __siena_tables,
552	    EFX_PATTERN_BYTE_ALTERNATE,
553	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
554		goto fail2;
555
556	if ((rc = efx_nic_test_tables(enp, __siena_tables,
557	    EFX_PATTERN_BYTE_CHANGING,
558	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
559		goto fail3;
560
561	if ((rc = efx_nic_test_tables(enp, __siena_tables,
562	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
563		goto fail4;
564
565	return (0);
566
567fail4:
568	EFSYS_PROBE(fail4);
569fail3:
570	EFSYS_PROBE(fail3);
571fail2:
572	EFSYS_PROBE(fail2);
573fail1:
574	EFSYS_PROBE1(fail1, int, rc);
575
576	return (rc);
577}
578
579#endif	/* EFSYS_OPT_DIAG */
580
581#endif	/* EFSYS_OPT_SIENA */
582