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