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