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