1 /*-
2 * Copyright 2007-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
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include "efsys.h"
30 #include "efx.h"
31 #include "efx_types.h"
32 #include "efx_regs.h"
33 #include "efx_impl.h"
34
35 __checkReturn int
efx_sram_buf_tbl_set(__in efx_nic_t * enp,__in uint32_t id,__in efsys_mem_t * esmp,__in size_t n)36 efx_sram_buf_tbl_set(
37 __in efx_nic_t *enp,
38 __in uint32_t id,
39 __in efsys_mem_t *esmp,
40 __in size_t n)
41 {
42 efx_qword_t qword;
43 uint32_t start = id;
44 uint32_t stop = start + n;
45 efsys_dma_addr_t addr;
46 efx_oword_t oword;
47 unsigned int count;
48 int rc;
49
50 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
51 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
52
53 if (stop >= EFX_BUF_TBL_SIZE) {
54 rc = EFBIG;
55 goto fail1;
56 }
57
58 /* Add the entries into the buffer table */
59 addr = EFSYS_MEM_ADDR(esmp);
60 for (id = start; id != stop; id++) {
61 EFX_POPULATE_QWORD_5(qword,
62 FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0,
63 FRF_AZ_BUF_ADR_FBUF_DW0,
64 (uint32_t)((addr >> 12) & 0xffffffff),
65 FRF_AZ_BUF_ADR_FBUF_DW1,
66 (uint32_t)((addr >> 12) >> 32),
67 FRF_AZ_BUF_OWNER_ID_FBUF, 0);
68
69 EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL,
70 id, &qword);
71
72 addr += EFX_BUF_SIZE;
73 }
74
75 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
76
77 /* Flush the write buffer */
78 EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1,
79 FRF_AZ_BUF_CLR_CMD, 0);
80 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
81
82 /* Poll for the last entry being written to the buffer table */
83 EFSYS_ASSERT3U(id, ==, stop);
84 addr -= EFX_BUF_SIZE;
85
86 count = 0;
87 do {
88 EFSYS_PROBE1(wait, unsigned int, count);
89
90 /* Spin for 1 ms */
91 EFSYS_SPIN(1000);
92
93 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
94 id - 1, &qword);
95
96 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) ==
97 (uint32_t)((addr >> 12) & 0xffffffff) &&
98 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) ==
99 (uint32_t)((addr >> 12) >> 32))
100 goto verify;
101
102 } while (++count < 100);
103
104 rc = ETIMEDOUT;
105 goto fail2;
106
107 verify:
108 /* Verify the rest of the entries in the buffer table */
109 while (--id != start) {
110 addr -= EFX_BUF_SIZE;
111
112 /* Read the buffer table entry */
113 EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
114 id - 1, &qword);
115
116 if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) !=
117 (uint32_t)((addr >> 12) & 0xffffffff) ||
118 EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) !=
119 (uint32_t)((addr >> 12) >> 32)) {
120 rc = EFAULT;
121 goto fail3;
122 }
123 }
124
125 return (0);
126
127 fail3:
128 EFSYS_PROBE(fail3);
129
130 id = stop;
131
132 fail2:
133 EFSYS_PROBE(fail2);
134
135 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
136 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1,
137 FRF_AZ_BUF_CLR_START_ID, start);
138 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
139
140 fail1:
141 EFSYS_PROBE1(fail1, int, rc);
142
143 return (rc);
144 }
145
146 void
efx_sram_buf_tbl_clear(__in efx_nic_t * enp,__in uint32_t id,__in size_t n)147 efx_sram_buf_tbl_clear(
148 __in efx_nic_t *enp,
149 __in uint32_t id,
150 __in size_t n)
151 {
152 efx_oword_t oword;
153 uint32_t start = id;
154 uint32_t stop = start + n;
155
156 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
157 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
158
159 EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE);
160
161 EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
162
163 EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
164 FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1,
165 FRF_AZ_BUF_CLR_START_ID, start);
166 EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
167 }
168
169
170 #if EFSYS_OPT_DIAG
171
172 static void
efx_sram_byte_increment_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)173 efx_sram_byte_increment_set(
174 __in size_t row,
175 __in boolean_t negate,
176 __out efx_qword_t *eqp)
177 {
178 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
179 unsigned int index;
180
181 _NOTE(ARGUNUSED(negate))
182
183 for (index = 0; index < sizeof (efx_qword_t); index++)
184 eqp->eq_u8[index] = offset + index;
185 }
186
187 static void
efx_sram_all_the_same_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)188 efx_sram_all_the_same_set(
189 __in size_t row,
190 __in boolean_t negate,
191 __out efx_qword_t *eqp)
192 {
193 _NOTE(ARGUNUSED(row))
194
195 if (negate)
196 EFX_SET_QWORD(*eqp);
197 else
198 EFX_ZERO_QWORD(*eqp);
199 }
200
201 static void
efx_sram_bit_alternate_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)202 efx_sram_bit_alternate_set(
203 __in size_t row,
204 __in boolean_t negate,
205 __out efx_qword_t *eqp)
206 {
207 _NOTE(ARGUNUSED(row))
208
209 EFX_POPULATE_QWORD_2(*eqp,
210 EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa,
211 EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa);
212 }
213
214 static void
efx_sram_byte_alternate_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)215 efx_sram_byte_alternate_set(
216 __in size_t row,
217 __in boolean_t negate,
218 __out efx_qword_t *eqp)
219 {
220 _NOTE(ARGUNUSED(row))
221
222 EFX_POPULATE_QWORD_2(*eqp,
223 EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00,
224 EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00);
225 }
226
227 static void
efx_sram_byte_changing_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)228 efx_sram_byte_changing_set(
229 __in size_t row,
230 __in boolean_t negate,
231 __out efx_qword_t *eqp)
232 {
233 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
234 unsigned int index;
235
236 for (index = 0; index < sizeof (efx_qword_t); index++) {
237 uint8_t byte;
238
239 if (offset / 256 == 0)
240 byte = (uint8_t)((offset % 257) % 256);
241 else
242 byte = (uint8_t)(~((offset - 8) % 257) % 256);
243
244 eqp->eq_u8[index] = (negate) ? ~byte : byte;
245 }
246 }
247
248 static void
efx_sram_bit_sweep_set(__in size_t row,__in boolean_t negate,__out efx_qword_t * eqp)249 efx_sram_bit_sweep_set(
250 __in size_t row,
251 __in boolean_t negate,
252 __out efx_qword_t *eqp)
253 {
254 size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
255
256 if (negate) {
257 EFX_SET_QWORD(*eqp);
258 EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
259 } else {
260 EFX_ZERO_QWORD(*eqp);
261 EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
262 }
263 }
264
265 efx_sram_pattern_fn_t __cs __efx_sram_pattern_fns[] = {
266 efx_sram_byte_increment_set,
267 efx_sram_all_the_same_set,
268 efx_sram_bit_alternate_set,
269 efx_sram_byte_alternate_set,
270 efx_sram_byte_changing_set,
271 efx_sram_bit_sweep_set
272 };
273
274 __checkReturn int
efx_sram_test(__in efx_nic_t * enp,__in efx_pattern_type_t type)275 efx_sram_test(
276 __in efx_nic_t *enp,
277 __in efx_pattern_type_t type)
278 {
279 efx_nic_ops_t *enop = enp->en_enop;
280 efx_sram_pattern_fn_t func;
281
282 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
283
284 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
285
286 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
287 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
288 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
289
290 /* Select pattern generator */
291 EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES);
292 func = __efx_sram_pattern_fns[type];
293
294 return (enop->eno_sram_test(enp, func));
295 }
296
297 #endif /* EFSYS_OPT_DIAG */
298