1/*-
2 * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25#include "efsys.h"
26#include "efx.h"
27#include "efx_impl.h"
28
29#if EFSYS_OPT_SIENA
30
31			void
32siena_sram_init(
33	__in		efx_nic_t *enp)
34{
35	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
36	efx_oword_t oword;
37	uint32_t rx_base, tx_base;
38
39	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
40	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
41
42	rx_base = encp->enc_buftbl_limit;
43	tx_base = rx_base + (encp->enc_rxq_limit * 64);
44
45	/* Initialize the transmit descriptor cache */
46	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, tx_base);
47	EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);
48
49	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DC_SIZE, 1); /* 16 descriptors */
50	EFX_BAR_WRITEO(enp, FR_AZ_TX_DC_CFG_REG, &oword);
51
52	/* Initialize the receive descriptor cache */
53	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rx_base);
54	EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);
55
56	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_SIZE, 3); /* 64 descriptors */
57	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_CFG_REG, &oword);
58
59	/* Set receive descriptor pre-fetch low water mark */
60	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_PF_LWM, 56);
61	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_PF_WM_REG, &oword);
62
63	/* Set the event queue to use for SRAM updates */
64	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_UPD_EVQ_ID, 0);
65	EFX_BAR_WRITEO(enp, FR_AZ_SRM_UPD_EVQ_REG, &oword);
66}
67
68#if EFSYS_OPT_DIAG
69
70	__checkReturn	int
71siena_sram_test(
72	__in		efx_nic_t *enp,
73	__in		efx_sram_pattern_fn_t func)
74{
75	efx_oword_t oword;
76	efx_qword_t qword;
77	efx_qword_t verify;
78	size_t rows;
79	unsigned int wptr;
80	unsigned int rptr;
81	int rc;
82
83	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
84
85	/* Reconfigure into HALF buffer table mode */
86	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 0);
87	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
88
89	/*
90	 * Move the descriptor caches up to the top of SRAM, and test
91	 * all of SRAM below them. We only miss out one row here.
92	 */
93	rows = SIENA_SRAM_ROWS - 1;
94	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rows);
95	EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);
96
97	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, rows + 1);
98	EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);
99
100	/*
101	 * Write the pattern through BUF_HALF_TBL. Write
102	 * in 64 entry batches, waiting 1us in between each batch
103	 * to guarantee not to overflow the SRAM fifo
104	 */
105	for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
106		func(wptr, B_FALSE, &qword);
107		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_HALF_TBL, wptr, &qword);
108
109		if ((wptr - rptr) < 64 && wptr < rows - 1)
110			continue;
111
112		EFSYS_SPIN(1);
113
114		for (; rptr <= wptr; ++rptr) {
115			func(rptr, B_FALSE, &qword);
116			EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_HALF_TBL, rptr,
117			    &verify);
118
119			if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
120				rc = EFAULT;
121				goto fail1;
122			}
123		}
124	}
125
126	/* And do the same negated */
127	for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
128		func(wptr, B_TRUE, &qword);
129		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_HALF_TBL, wptr, &qword);
130
131		if ((wptr - rptr) < 64 && wptr < rows - 1)
132			continue;
133
134		EFSYS_SPIN(1);
135
136		for (; rptr <= wptr; ++rptr) {
137			func(rptr, B_TRUE, &qword);
138			EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_HALF_TBL, rptr,
139			    &verify);
140
141			if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
142				rc = EFAULT;
143				goto fail2;
144			}
145		}
146	}
147
148	/* Restore back to FULL buffer table mode */
149	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
150	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
151
152	/*
153	 * We don't need to reconfigure SRAM again because the API
154	 * requires efx_nic_fini() to be called after an sram test.
155	 */
156	return (0);
157
158fail2:
159	EFSYS_PROBE(fail2);
160fail1:
161	EFSYS_PROBE1(fail1, int, rc);
162
163	/* Restore back to FULL buffer table mode */
164	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
165	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
166
167	return (rc);
168}
169
170#endif	/* EFSYS_OPT_DIAG */
171
172#endif	/* EFSYS_OPT_SIENA */
173