1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2007-2016 Solarflare Communications Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * The views and conclusions contained in the software and documentation are
29 * those of the authors and should not be interpreted as representing official
30 * policies, either expressed or implied, of the FreeBSD Project.
31 */
32
33 #include <sys/cdefs.h>
34 #include "efx.h"
35 #include "efx_impl.h"
36
37 __checkReturn efx_rc_t
efx_sram_buf_tbl_set(__in efx_nic_t * enp,__in uint32_t id,__in efsys_mem_t * esmp,__in size_t n)38 efx_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 || EFSYS_OPT_MEDFORD2
56 if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
57 enp->en_family == EFX_FAMILY_MEDFORD ||
58 enp->en_family == EFX_FAMILY_MEDFORD2) {
59 /*
60 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be
61 * pulled inside the Falcon/Siena queue create/destroy code,
62 * and then the original functions can be removed (see bug30834
63 * comment #1). But, for now, we just ensure that they are
64 * no-ops for EF10, to allow bringing up existing drivers
65 * without modification.
66 */
67
68 return (0);
69 }
70 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
71
72 if (stop >= EFX_BUF_TBL_SIZE) {
73 rc = EFBIG;
74 goto fail1;
75 }
76
77 /* Add the entries into the buffer table */
78 addr = EFSYS_MEM_ADDR(esmp);
79 for (id = start; id != stop; id++) {
80 EFX_POPULATE_QWORD_5(qword,
81 FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0,
82 FRF_AZ_BUF_ADR_FBUF_DW0,
83 (uint32_t)((addr >> 12) & 0xffffffff),
84 FRF_AZ_BUF_ADR_FBUF_DW1,
85 (uint32_t)((addr >> 12) >> 32),
86 FRF_AZ_BUF_OWNER_ID_FBUF, 0);
87
88 EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL,
89 id, &qword);
90
91 addr += EFX_BUF_SIZE;
92 }
93
94 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
95
96 /* Flush the write buffer */
97 EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1,
98 FRF_AZ_BUF_CLR_CMD, 0);
99 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
100
101 /* Poll for the last entry being written to the buffer table */
102 EFSYS_ASSERT3U(id, ==, stop);
103 addr -= EFX_BUF_SIZE;
104
105 count = 0;
106 do {
107 EFSYS_PROBE1(wait, unsigned int, count);
108
109 /* Spin for 1 ms */
110 EFSYS_SPIN(1000);
111
112 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
113 id - 1, &qword);
114
115 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) ==
116 (uint32_t)((addr >> 12) & 0xffffffff) &&
117 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) ==
118 (uint32_t)((addr >> 12) >> 32))
119 goto verify;
120
121 } while (++count < 100);
122
123 rc = ETIMEDOUT;
124 goto fail2;
125
126 verify:
127 /* Verify the rest of the entries in the buffer table */
128 while (--id != start) {
129 addr -= EFX_BUF_SIZE;
130
131 /* Read the buffer table entry */
132 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
133 id - 1, &qword);
134
135 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) !=
136 (uint32_t)((addr >> 12) & 0xffffffff) ||
137 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) !=
138 (uint32_t)((addr >> 12) >> 32)) {
139 rc = EFAULT;
140 goto fail3;
141 }
142 }
143
144 return (0);
145
146 fail3:
147 EFSYS_PROBE(fail3);
148
149 id = stop;
150
151 fail2:
152 EFSYS_PROBE(fail2);
153
154 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
155 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1,
156 FRF_AZ_BUF_CLR_START_ID, start);
157 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
158
159 fail1:
160 EFSYS_PROBE1(fail1, efx_rc_t, rc);
161
162 return (rc);
163 }
164
165 void
efx_sram_buf_tbl_clear(__in efx_nic_t * enp,__in uint32_t id,__in size_t n)166 efx_sram_buf_tbl_clear(
167 __in efx_nic_t *enp,
168 __in uint32_t id,
169 __in size_t n)
170 {
171 efx_oword_t oword;
172 uint32_t start = id;
173 uint32_t stop = start + n;
174
175 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
177
178 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
179 if (enp->en_family == EFX_FAMILY_HUNTINGTON ||
180 enp->en_family == EFX_FAMILY_MEDFORD ||
181 enp->en_family == EFX_FAMILY_MEDFORD2) {
182 /*
183 * FIXME: the efx_sram_buf_tbl_*() functionality needs to be
184 * pulled inside the Falcon/Siena queue create/destroy code,
185 * and then the original functions can be removed (see bug30834
186 * comment #1). But, for now, we just ensure that they are
187 * no-ops for EF10, to allow bringing up existing drivers
188 * without modification.
189 */
190
191 return;
192 }
193 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
194
195 EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE);
196
197 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
198
199 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
200 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1,
201 FRF_AZ_BUF_CLR_START_ID, start);
202 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
203 }
204
205 #if EFSYS_OPT_DIAG
206
207 static void
efx_sram_byte_increment_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)208 efx_sram_byte_increment_set(
209 __in size_t row,
210 __in boolean_t negate,
211 __out efx_qword_t *eqp)
212 {
213 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
214 unsigned int index;
215
216 _NOTE(ARGUNUSED(negate))
217
218 for (index = 0; index < sizeof (efx_qword_t); index++)
219 eqp->eq_u8[index] = offset + index;
220 }
221
222 static void
efx_sram_all_the_same_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)223 efx_sram_all_the_same_set(
224 __in size_t row,
225 __in boolean_t negate,
226 __out efx_qword_t *eqp)
227 {
228 _NOTE(ARGUNUSED(row))
229
230 if (negate)
231 EFX_SET_QWORD(*eqp);
232 else
233 EFX_ZERO_QWORD(*eqp);
234 }
235
236 static void
efx_sram_bit_alternate_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)237 efx_sram_bit_alternate_set(
238 __in size_t row,
239 __in boolean_t negate,
240 __out efx_qword_t *eqp)
241 {
242 _NOTE(ARGUNUSED(row))
243
244 EFX_POPULATE_QWORD_2(*eqp,
245 EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa,
246 EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa);
247 }
248
249 static void
efx_sram_byte_alternate_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)250 efx_sram_byte_alternate_set(
251 __in size_t row,
252 __in boolean_t negate,
253 __out efx_qword_t *eqp)
254 {
255 _NOTE(ARGUNUSED(row))
256
257 EFX_POPULATE_QWORD_2(*eqp,
258 EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00,
259 EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00);
260 }
261
262 static void
efx_sram_byte_changing_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)263 efx_sram_byte_changing_set(
264 __in size_t row,
265 __in boolean_t negate,
266 __out efx_qword_t *eqp)
267 {
268 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
269 unsigned int index;
270
271 for (index = 0; index < sizeof (efx_qword_t); index++) {
272 uint8_t byte;
273
274 if (offset / 256 == 0)
275 byte = (uint8_t)((offset % 257) % 256);
276 else
277 byte = (uint8_t)(~((offset - 8) % 257) % 256);
278
279 eqp->eq_u8[index] = (negate) ? ~byte : byte;
280 }
281 }
282
283 static void
efx_sram_bit_sweep_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)284 efx_sram_bit_sweep_set(
285 __in size_t row,
286 __in boolean_t negate,
287 __out efx_qword_t *eqp)
288 {
289 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
290
291 if (negate) {
292 EFX_SET_QWORD(*eqp);
293 EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
294 } else {
295 EFX_ZERO_QWORD(*eqp);
296 EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
297 }
298 }
299
300 efx_sram_pattern_fn_t __efx_sram_pattern_fns[] = {
301 efx_sram_byte_increment_set,
302 efx_sram_all_the_same_set,
303 efx_sram_bit_alternate_set,
304 efx_sram_byte_alternate_set,
305 efx_sram_byte_changing_set,
306 efx_sram_bit_sweep_set
307 };
308
309 __checkReturn efx_rc_t
efx_sram_test(__in efx_nic_t * enp,__in efx_pattern_type_t type)310 efx_sram_test(
311 __in efx_nic_t *enp,
312 __in efx_pattern_type_t type)
313 {
314 efx_sram_pattern_fn_t func;
315
316 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
317
318 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
319
320 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
321 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
322 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
323
324 /* SRAM testing is only available on Siena. */
325 if (enp->en_family != EFX_FAMILY_SIENA)
326 return (0);
327
328 /* Select pattern generator */
329 EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES);
330 func = __efx_sram_pattern_fns[type];
331
332 return (siena_sram_test(enp, func));
333 }
334
335 #endif /* EFSYS_OPT_DIAG */
336