efx_sram.c revision 301336
1/*-
2 * Copyright (c) 2007-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/efx_sram.c 301336 2016-06-04 14:52:32Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36
37	__checkReturn	efx_rc_t
38efx_sram_buf_tbl_set(
39	__in		efx_nic_t *enp,
40	__in		uint32_t id,
41	__in		efsys_mem_t *esmp,
42	__in		size_t n)
43{
44	efx_qword_t qword;
45	uint32_t start = id;
46	uint32_t stop = start + n;
47	efsys_dma_addr_t addr;
48	efx_oword_t oword;
49	unsigned int count;
50	efx_rc_t rc;
51
52	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
53	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
54
55#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
56	if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
57	    enp->en_family == EFX_FAMILY_MEDFORD) {
58		/*
59		 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be
60		 * pulled inside the Falcon/Siena queue create/destroy code,
61		 * and then the original functions can be removed (see bug30834
62		 * comment #1).  But, for now, we just ensure that they are
63		 * no-ops for EF10, to allow bringing up existing drivers
64		 * without modification.
65		 */
66
67		return (0);
68	}
69#endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
70
71	if (stop >= EFX_BUF_TBL_SIZE) {
72		rc = EFBIG;
73		goto fail1;
74	}
75
76	/* Add the entries into the buffer table */
77	addr = EFSYS_MEM_ADDR(esmp);
78	for (id = start; id != stop; id++) {
79		EFX_POPULATE_QWORD_5(qword,
80		    FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0,
81		    FRF_AZ_BUF_ADR_FBUF_DW0,
82		    (uint32_t)((addr >> 12) & 0xffffffff),
83		    FRF_AZ_BUF_ADR_FBUF_DW1,
84		    (uint32_t)((addr >> 12) >> 32),
85		    FRF_AZ_BUF_OWNER_ID_FBUF, 0);
86
87		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL,
88				    id, &qword);
89
90		addr += EFX_BUF_SIZE;
91	}
92
93	EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
94
95	/* Flush the write buffer */
96	EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1,
97	    FRF_AZ_BUF_CLR_CMD, 0);
98	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
99
100	/* Poll for the last entry being written to the buffer table */
101	EFSYS_ASSERT3U(id, ==, stop);
102	addr -= EFX_BUF_SIZE;
103
104	count = 0;
105	do {
106		EFSYS_PROBE1(wait, unsigned int, count);
107
108		/* Spin for 1 ms */
109		EFSYS_SPIN(1000);
110
111		EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
112				    id - 1, &qword);
113
114		if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) ==
115		    (uint32_t)((addr >> 12) & 0xffffffff) &&
116		    EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) ==
117		    (uint32_t)((addr >> 12) >> 32))
118			goto verify;
119
120	} while (++count < 100);
121
122	rc = ETIMEDOUT;
123	goto fail2;
124
125verify:
126	/* Verify the rest of the entries in the buffer table */
127	while (--id != start) {
128		addr -= EFX_BUF_SIZE;
129
130		/* Read the buffer table entry */
131		EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
132				    id - 1, &qword);
133
134		if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) !=
135		    (uint32_t)((addr >> 12) & 0xffffffff) ||
136		    EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) !=
137		    (uint32_t)((addr >> 12) >> 32)) {
138			rc = EFAULT;
139			goto fail3;
140		}
141	}
142
143	return (0);
144
145fail3:
146	EFSYS_PROBE(fail3);
147
148	id = stop;
149
150fail2:
151	EFSYS_PROBE(fail2);
152
153	EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
154	    FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1,
155	    FRF_AZ_BUF_CLR_START_ID, start);
156	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
157
158fail1:
159	EFSYS_PROBE1(fail1, efx_rc_t, rc);
160
161	return (rc);
162}
163
164		void
165efx_sram_buf_tbl_clear(
166	__in	efx_nic_t *enp,
167	__in	uint32_t id,
168	__in	size_t n)
169{
170	efx_oword_t oword;
171	uint32_t start = id;
172	uint32_t stop = start + n;
173
174	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
175	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
176
177#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
178	if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
179	    enp->en_family == EFX_FAMILY_MEDFORD) {
180		/*
181		 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be
182		 * pulled inside the Falcon/Siena queue create/destroy code,
183		 * and then the original functions can be removed (see bug30834
184		 * comment #1).  But, for now, we just ensure that they are
185		 * no-ops for EF10, to allow bringing up existing drivers
186		 * without modification.
187		 */
188
189		return;
190	}
191#endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
192
193	EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE);
194
195	EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
196
197	EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
198	    FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1,
199	    FRF_AZ_BUF_CLR_START_ID, start);
200	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
201}
202
203
204#if EFSYS_OPT_DIAG
205
206static			void
207efx_sram_byte_increment_set(
208	__in		size_t row,
209	__in		boolean_t negate,
210	__out		efx_qword_t *eqp)
211{
212	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
213	unsigned int index;
214
215	_NOTE(ARGUNUSED(negate))
216
217	for (index = 0; index < sizeof (efx_qword_t); index++)
218		eqp->eq_u8[index] = offset + index;
219}
220
221static			void
222efx_sram_all_the_same_set(
223	__in		size_t row,
224	__in		boolean_t negate,
225	__out		efx_qword_t *eqp)
226{
227	_NOTE(ARGUNUSED(row))
228
229	if (negate)
230		EFX_SET_QWORD(*eqp);
231	else
232		EFX_ZERO_QWORD(*eqp);
233}
234
235static			void
236efx_sram_bit_alternate_set(
237	__in		size_t row,
238	__in		boolean_t negate,
239	__out		efx_qword_t *eqp)
240{
241	_NOTE(ARGUNUSED(row))
242
243	EFX_POPULATE_QWORD_2(*eqp,
244	    EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa,
245	    EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa);
246}
247
248static			void
249efx_sram_byte_alternate_set(
250	__in		size_t row,
251	__in		boolean_t negate,
252	__out		efx_qword_t *eqp)
253{
254	_NOTE(ARGUNUSED(row))
255
256	EFX_POPULATE_QWORD_2(*eqp,
257	    EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00,
258	    EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00);
259}
260
261static			void
262efx_sram_byte_changing_set(
263	__in		size_t row,
264	__in		boolean_t negate,
265	__out		efx_qword_t *eqp)
266{
267	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
268	unsigned int index;
269
270	for (index = 0; index < sizeof (efx_qword_t); index++) {
271		uint8_t byte;
272
273		if (offset / 256 == 0)
274			byte = (uint8_t)((offset % 257) % 256);
275		else
276			byte = (uint8_t)(~((offset - 8) % 257) % 256);
277
278		eqp->eq_u8[index] = (negate) ? ~byte : byte;
279	}
280}
281
282static			void
283efx_sram_bit_sweep_set(
284	__in		size_t row,
285	__in		boolean_t negate,
286	__out		efx_qword_t *eqp)
287{
288	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
289
290	if (negate) {
291		EFX_SET_QWORD(*eqp);
292		EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
293	} else {
294		EFX_ZERO_QWORD(*eqp);
295		EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
296	}
297}
298
299efx_sram_pattern_fn_t	__efx_sram_pattern_fns[] = {
300	efx_sram_byte_increment_set,
301	efx_sram_all_the_same_set,
302	efx_sram_bit_alternate_set,
303	efx_sram_byte_alternate_set,
304	efx_sram_byte_changing_set,
305	efx_sram_bit_sweep_set
306};
307
308	__checkReturn	efx_rc_t
309efx_sram_test(
310	__in		efx_nic_t *enp,
311	__in		efx_pattern_type_t type)
312{
313	efx_sram_pattern_fn_t func;
314
315	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
316
317	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
318
319	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
320	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
321	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
322
323	/* SRAM testing is only available on Siena. */
324	if (enp->en_family != EFX_FAMILY_SIENA)
325		return (0);
326
327	/* Select pattern generator */
328	EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES);
329	func = __efx_sram_pattern_fns[type];
330
331	return (siena_sram_test(enp, func));
332}
333
334#endif	/* EFSYS_OPT_DIAG */
335