1175645Sjhb/*-
2175645Sjhb * SPDX-License-Identifier: BSD-2-Clause
3175645Sjhb *
4175645Sjhb * Copyright (c) 2007-2016 Solarflare Communications Inc.
5175645Sjhb * All rights reserved.
6175645Sjhb *
7175645Sjhb * Redistribution and use in source and binary forms, with or without
8175645Sjhb * modification, are permitted provided that the following conditions are met:
9175645Sjhb *
10175645Sjhb * 1. Redistributions of source code must retain the above copyright notice,
11175645Sjhb *    this list of conditions and the following disclaimer.
12175645Sjhb * 2. Redistributions in binary form must reproduce the above copyright notice,
13175645Sjhb *    this list of conditions and the following disclaimer in the documentation
14175645Sjhb *    and/or other materials provided with the distribution.
15175645Sjhb *
16175645Sjhb * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17175645Sjhb * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18175645Sjhb * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19175645Sjhb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20175645Sjhb * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21175645Sjhb * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22175645Sjhb * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23175645Sjhb * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24175645Sjhb * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25175645Sjhb * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26175645Sjhb * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27175645Sjhb *
28175645Sjhb * The views and conclusions contained in the software and documentation are
29175645Sjhb * those of the authors and should not be interpreted as representing official
30175645Sjhb * policies, either expressed or implied, of the FreeBSD Project.
31175645Sjhb */
32175809Sjhb
33175809Sjhb#include <sys/cdefs.h>
34175645Sjhb#include "efx.h"
35175645Sjhb#include "efx_impl.h"
36175645Sjhb
37175809Sjhb	__checkReturn	efx_rc_t
38175809Sjhbefx_sram_buf_tbl_set(
39175809Sjhb	__in		efx_nic_t *enp,
40183359Sjhb	__in		uint32_t id,
41175645Sjhb	__in		efsys_mem_t *esmp,
42175645Sjhb	__in		size_t n)
43175645Sjhb{
44175645Sjhb	efx_qword_t qword;
45175645Sjhb	uint32_t start = id;
46175809Sjhb	uint32_t stop = start + n;
47175645Sjhb	efsys_dma_addr_t addr;
48175645Sjhb	efx_oword_t oword;
49175645Sjhb	unsigned int count;
50175809Sjhb	efx_rc_t rc;
51175809Sjhb
52175809Sjhb	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
53175774Sjhb	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
54175774Sjhb
55175774Sjhb#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
56175774Sjhb	if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
57175809Sjhb	    enp->en_family == EFX_FAMILY_MEDFORD ||
58175809Sjhb	    enp->en_family == EFX_FAMILY_MEDFORD2) {
59178670Sjhb		/*
60178670Sjhb		 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be
61175809Sjhb		 * pulled inside the Falcon/Siena queue create/destroy code,
62175809Sjhb		 * and then the original functions can be removed (see bug30834
63175809Sjhb		 * comment #1).  But, for now, we just ensure that they are
64175645Sjhb		 * no-ops for EF10, to allow bringing up existing drivers
65175645Sjhb		 * without modification.
66175645Sjhb		 */
67175645Sjhb
68175645Sjhb		return (0);
69175645Sjhb	}
70175645Sjhb#endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
71175645Sjhb
72175645Sjhb	if (stop >= EFX_BUF_TBL_SIZE) {
73175645Sjhb		rc = EFBIG;
74175645Sjhb		goto fail1;
75175774Sjhb	}
76175645Sjhb
77175645Sjhb	/* Add the entries into the buffer table */
78175645Sjhb	addr = EFSYS_MEM_ADDR(esmp);
79175774Sjhb	for (id = start; id != stop; id++) {
80175774Sjhb		EFX_POPULATE_QWORD_5(qword,
81175774Sjhb		    FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0,
82175774Sjhb		    FRF_AZ_BUF_ADR_FBUF_DW0,
83175774Sjhb		    (uint32_t)((addr >> 12) & 0xffffffff),
84175774Sjhb		    FRF_AZ_BUF_ADR_FBUF_DW1,
85175645Sjhb		    (uint32_t)((addr >> 12) >> 32),
86175774Sjhb		    FRF_AZ_BUF_OWNER_ID_FBUF, 0);
87175774Sjhb
88175774Sjhb		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL,
89175774Sjhb				    id, &qword);
90175774Sjhb
91175774Sjhb		addr += EFX_BUF_SIZE;
92175774Sjhb	}
93175774Sjhb
94175774Sjhb	EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
95175774Sjhb
96175774Sjhb	/* Flush the write buffer */
97175774Sjhb	EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1,
98175774Sjhb	    FRF_AZ_BUF_CLR_CMD, 0);
99175774Sjhb	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
100175774Sjhb
101175774Sjhb	/* Poll for the last entry being written to the buffer table */
102175774Sjhb	EFSYS_ASSERT3U(id, ==, stop);
103175774Sjhb	addr -= EFX_BUF_SIZE;
104175774Sjhb
105175774Sjhb	count = 0;
106175774Sjhb	do {
107175774Sjhb		EFSYS_PROBE1(wait, unsigned int, count);
108175774Sjhb
109175774Sjhb		/* Spin for 1 ms */
110175774Sjhb		EFSYS_SPIN(1000);
111175645Sjhb
112175645Sjhb		EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
113175774Sjhb				    id - 1, &qword);
114175645Sjhb
115175774Sjhb		if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) ==
116175645Sjhb		    (uint32_t)((addr >> 12) & 0xffffffff) &&
117178670Sjhb		    EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) ==
118178670Sjhb		    (uint32_t)((addr >> 12) >> 32))
119178670Sjhb			goto verify;
120178670Sjhb
121178670Sjhb	} while (++count < 100);
122178670Sjhb
123178670Sjhb	rc = ETIMEDOUT;
124178670Sjhb	goto fail2;
125175645Sjhb
126175774Sjhbverify:
127175774Sjhb	/* Verify the rest of the entries in the buffer table */
128175774Sjhb	while (--id != start) {
129175774Sjhb		addr -= EFX_BUF_SIZE;
130175774Sjhb
131175774Sjhb		/* Read the buffer table entry */
132175774Sjhb		EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
133175774Sjhb				    id - 1, &qword);
134175774Sjhb
135175774Sjhb		if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) !=
136175774Sjhb		    (uint32_t)((addr >> 12) & 0xffffffff) ||
137175774Sjhb		    EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) !=
138175645Sjhb		    (uint32_t)((addr >> 12) >> 32)) {
139175774Sjhb			rc = EFAULT;
140175645Sjhb			goto fail3;
141175645Sjhb		}
142175645Sjhb	}
143175645Sjhb
144175645Sjhb	return (0);
145175645Sjhb
146175645Sjhbfail3:
147175645Sjhb	EFSYS_PROBE(fail3);
148175645Sjhb
149175807Sjhb	id = stop;
150175645Sjhb
151175807Sjhbfail2:
152175807Sjhb	EFSYS_PROBE(fail2);
153175807Sjhb
154175807Sjhb	EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
155175645Sjhb	    FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1,
156175645Sjhb	    FRF_AZ_BUF_CLR_START_ID, start);
157175645Sjhb	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
158175645Sjhb
159175645Sjhbfail1:
160175645Sjhb	EFSYS_PROBE1(fail1, efx_rc_t, rc);
161175645Sjhb
162175645Sjhb	return (rc);
163175774Sjhb}
164175774Sjhb
165175645Sjhb		void
166175774Sjhbefx_sram_buf_tbl_clear(
167175645Sjhb	__in	efx_nic_t *enp,
168178670Sjhb	__in	uint32_t id,
169178670Sjhb	__in	size_t n)
170175645Sjhb{
171175645Sjhb	efx_oword_t oword;
172175645Sjhb	uint32_t start = id;
173178670Sjhb	uint32_t stop = start + n;
174175775Sjhb
175175645Sjhb	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
176175774Sjhb	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
177175774Sjhb
178175774Sjhb#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
179175775Sjhb	if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
180175645Sjhb	    enp->en_family == EFX_FAMILY_MEDFORD ||
181175645Sjhb	    enp->en_family == EFX_FAMILY_MEDFORD2) {
182175774Sjhb		/*
183175774Sjhb		 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be
184175775Sjhb		 * pulled inside the Falcon/Siena queue create/destroy code,
185175774Sjhb		 * and then the original functions can be removed (see bug30834
186175774Sjhb		 * comment #1).  But, for now, we just ensure that they are
187175645Sjhb		 * no-ops for EF10, to allow bringing up existing drivers
188175645Sjhb		 * without modification.
189175645Sjhb		 */
190175645Sjhb
191175645Sjhb		return;
192175645Sjhb	}
193175645Sjhb#endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
194175645Sjhb
195175645Sjhb	EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE);
196175645Sjhb
197175645Sjhb	EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
198175645Sjhb
199175645Sjhb	EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
200175645Sjhb	    FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1,
201210424Savg	    FRF_AZ_BUF_CLR_START_ID, start);
202210424Savg	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
203210424Savg}
204210424Savg
205210424Savg#if EFSYS_OPT_DIAG
206210424Savg
207210424Savgstatic			void
208210424Savgefx_sram_byte_increment_set(
209210424Savg	__in		size_t row,
210210424Savg	__in		boolean_t negate,
211210424Savg	__out		efx_qword_t *eqp)
212210424Savg{
213210424Savg	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
214210424Savg	unsigned int index;
215210424Savg
216210424Savg	_NOTE(ARGUNUSED(negate))
217210424Savg
218210424Savg	for (index = 0; index < sizeof (efx_qword_t); index++)
219210424Savg		eqp->eq_u8[index] = offset + index;
220178634Sjhb}
221175645Sjhb
222183359Sjhbstatic			void
223183556Sjhbefx_sram_all_the_same_set(
224175645Sjhb	__in		size_t row,
225175645Sjhb	__in		boolean_t negate,
226210424Savg	__out		efx_qword_t *eqp)
227183359Sjhb{
228175645Sjhb	_NOTE(ARGUNUSED(row))
229175774Sjhb
230175645Sjhb	if (negate)
231175774Sjhb		EFX_SET_QWORD(*eqp);
232175645Sjhb	else
233175645Sjhb		EFX_ZERO_QWORD(*eqp);
234175645Sjhb}
235175645Sjhb
236175774Sjhbstatic			void
237175645Sjhbefx_sram_bit_alternate_set(
238175645Sjhb	__in		size_t row,
239175774Sjhb	__in		boolean_t negate,
240175774Sjhb	__out		efx_qword_t *eqp)
241175645Sjhb{
242175645Sjhb	_NOTE(ARGUNUSED(row))
243183359Sjhb
244183359Sjhb	EFX_POPULATE_QWORD_2(*eqp,
245183359Sjhb	    EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa,
246183359Sjhb	    EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa);
247210424Savg}
248210424Savg
249210424Savgstatic			void
250183359Sjhbefx_sram_byte_alternate_set(
251183359Sjhb	__in		size_t row,
252183359Sjhb	__in		boolean_t negate,
253183359Sjhb	__out		efx_qword_t *eqp)
254183359Sjhb{
255183359Sjhb	_NOTE(ARGUNUSED(row))
256183359Sjhb
257178634Sjhb	EFX_POPULATE_QWORD_2(*eqp,
258183359Sjhb	    EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00,
259183359Sjhb	    EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00);
260183359Sjhb}
261175774Sjhb
262175774Sjhbstatic			void
263175774Sjhbefx_sram_byte_changing_set(
264175774Sjhb	__in		size_t row,
265183359Sjhb	__in		boolean_t negate,
266175774Sjhb	__out		efx_qword_t *eqp)
267175774Sjhb{
268175774Sjhb	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
269175774Sjhb	unsigned int index;
270178670Sjhb
271175774Sjhb	for (index = 0; index < sizeof (efx_qword_t); index++) {
272175774Sjhb		uint8_t byte;
273175774Sjhb
274175774Sjhb		if (offset / 256 == 0)
275175774Sjhb			byte = (uint8_t)((offset % 257) % 256);
276178670Sjhb		else
277178670Sjhb			byte = (uint8_t)(~((offset - 8) % 257) % 256);
278178670Sjhb
279175774Sjhb		eqp->eq_u8[index] = (negate) ? ~byte : byte;
280175774Sjhb	}
281175774Sjhb}
282175774Sjhb
283175774Sjhbstatic			void
284175774Sjhbefx_sram_bit_sweep_set(
285175774Sjhb	__in		size_t row,
286175774Sjhb	__in		boolean_t negate,
287175774Sjhb	__out		efx_qword_t *eqp)
288175774Sjhb{
289175774Sjhb	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
290175774Sjhb
291175645Sjhb	if (negate) {
292175645Sjhb		EFX_SET_QWORD(*eqp);
293175774Sjhb		EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
294175774Sjhb	} else {
295175774Sjhb		EFX_ZERO_QWORD(*eqp);
296175645Sjhb		EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
297175645Sjhb	}
298178634Sjhb}
299175774Sjhb
300175774Sjhbefx_sram_pattern_fn_t	__efx_sram_pattern_fns[] = {
301175774Sjhb	efx_sram_byte_increment_set,
302175774Sjhb	efx_sram_all_the_same_set,
303175774Sjhb	efx_sram_bit_alternate_set,
304175809Sjhb	efx_sram_byte_alternate_set,
305175774Sjhb	efx_sram_byte_changing_set,
306210424Savg	efx_sram_bit_sweep_set
307175809Sjhb};
308210424Savg
309210424Savg	__checkReturn	efx_rc_t
310210424Savgefx_sram_test(
311210424Savg	__in		efx_nic_t *enp,
312175774Sjhb	__in		efx_pattern_type_t type)
313175774Sjhb{
314175774Sjhb	efx_sram_pattern_fn_t func;
315175809Sjhb
316175774Sjhb	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
317175774Sjhb
318175809Sjhb	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
319175809Sjhb
320175774Sjhb	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
321175809Sjhb	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
322175809Sjhb	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
323175809Sjhb
324175809Sjhb	/* SRAM testing is only available on Siena. */
325175774Sjhb	if (enp->en_family != EFX_FAMILY_SIENA)
326175809Sjhb		return (0);
327175809Sjhb
328175809Sjhb	/* Select pattern generator */
329175809Sjhb	EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES);
330175774Sjhb	func = __efx_sram_pattern_fns[type];
331175809Sjhb
332175809Sjhb	return (siena_sram_test(enp, func));
333175809Sjhb}
334175809Sjhb
335175645Sjhb#endif	/* EFSYS_OPT_DIAG */
336175809Sjhb