common/sfc_efx/base: choose smallest Rx prefix on Riverhead
[dpdk.git] / drivers / common / sfc_efx / efsys.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2016-2019 Solarflare Communications Inc.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 #ifndef _SFC_COMMON_EFSYS_H
11 #define _SFC_COMMON_EFSYS_H
12
13 #include <stdbool.h>
14
15 #include <rte_spinlock.h>
16 #include <rte_byteorder.h>
17 #include <rte_debug.h>
18 #include <rte_memzone.h>
19 #include <rte_memory.h>
20 #include <rte_memcpy.h>
21 #include <rte_cycles.h>
22 #include <rte_prefetch.h>
23 #include <rte_common.h>
24 #include <rte_malloc.h>
25 #include <rte_log.h>
26 #include <rte_io.h>
27
28 #include "sfc_efx_debug.h"
29 #include "sfc_efx_log.h"
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 #define LIBEFX_API              __rte_internal
36
37 /* No specific decorations required since functions are local by default */
38 #define LIBEFX_INTERNAL
39
40 #define EFSYS_HAS_UINT64 1
41 #define EFSYS_USE_UINT64 1
42 #define EFSYS_HAS_SSE2_M128 1
43
44 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
45 #define EFSYS_IS_BIG_ENDIAN 1
46 #define EFSYS_IS_LITTLE_ENDIAN 0
47 #elif RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
48 #define EFSYS_IS_BIG_ENDIAN 0
49 #define EFSYS_IS_LITTLE_ENDIAN 1
50 #else
51 #error "Cannot determine system endianness"
52 #endif
53
54
55 typedef bool boolean_t;
56
57 #ifndef B_FALSE
58 #define B_FALSE false
59 #endif
60 #ifndef B_TRUE
61 #define B_TRUE  true
62 #endif
63
64 /*
65  * RTE_MAX() and RTE_MIN() cannot be used since braced-group within
66  * expression allowed only inside a function, but MAX() is used as
67  * a number of elements in array.
68  */
69 #ifndef MAX
70 #define MAX(v1, v2)     ((v1) > (v2) ? (v1) : (v2))
71 #endif
72 #ifndef MIN
73 #define MIN(v1, v2)     ((v1) < (v2) ? (v1) : (v2))
74 #endif
75
76 #ifndef ISP2
77 #define ISP2(x)                 rte_is_power_of_2(x)
78 #endif
79
80 #define ENOTACTIVE      ENOTCONN
81
82 static inline void
83 prefetch_read_many(const volatile void *addr)
84 {
85         rte_prefetch0(addr);
86 }
87
88 static inline void
89 prefetch_read_once(const volatile void *addr)
90 {
91         rte_prefetch_non_temporal(addr);
92 }
93
94 /* Code inclusion options */
95
96
97 #define EFSYS_OPT_NAMES 1
98
99 /* Disable SFN5xxx/SFN6xxx since it requires specific support in the PMD */
100 #define EFSYS_OPT_SIENA 0
101 /* Enable SFN7xxx support */
102 #define EFSYS_OPT_HUNTINGTON 1
103 /* Enable SFN8xxx support */
104 #define EFSYS_OPT_MEDFORD 1
105 /* Enable SFN2xxx support */
106 #define EFSYS_OPT_MEDFORD2 1
107 /* Disable Riverhead support */
108 #define EFSYS_OPT_RIVERHEAD 0
109
110 #ifdef RTE_LIBRTE_SFC_EFX_DEBUG
111 #define EFSYS_OPT_CHECK_REG 1
112 #else
113 #define EFSYS_OPT_CHECK_REG 0
114 #endif
115
116 /* MCDI is required for SFN7xxx and SFN8xx */
117 #define EFSYS_OPT_MCDI 1
118 #define EFSYS_OPT_MCDI_LOGGING 1
119 #define EFSYS_OPT_MCDI_PROXY_AUTH 1
120
121 #define EFSYS_OPT_MAC_STATS 1
122
123 #define EFSYS_OPT_LOOPBACK 1
124
125 #define EFSYS_OPT_MON_MCDI 0
126 #define EFSYS_OPT_MON_STATS 0
127
128 #define EFSYS_OPT_PHY_STATS 0
129 #define EFSYS_OPT_BIST 0
130 #define EFSYS_OPT_PHY_LED_CONTROL 0
131 #define EFSYS_OPT_PHY_FLAGS 0
132
133 #define EFSYS_OPT_VPD 0
134 #define EFSYS_OPT_NVRAM 0
135 #define EFSYS_OPT_BOOTCFG 0
136 #define EFSYS_OPT_IMAGE_LAYOUT 0
137
138 #define EFSYS_OPT_DIAG 0
139 #define EFSYS_OPT_RX_SCALE 1
140 #define EFSYS_OPT_QSTATS 0
141 /* Filters support is required for SFN7xxx and SFN8xx */
142 #define EFSYS_OPT_FILTER 1
143 #define EFSYS_OPT_RX_SCATTER 0
144
145 #define EFSYS_OPT_EV_PREFETCH 0
146
147 #define EFSYS_OPT_DECODE_INTR_FATAL 0
148
149 #define EFSYS_OPT_LICENSING 0
150
151 #define EFSYS_OPT_ALLOW_UNCONFIGURED_NIC 0
152
153 #define EFSYS_OPT_RX_PACKED_STREAM 0
154
155 #define EFSYS_OPT_RX_ES_SUPER_BUFFER 1
156
157 #define EFSYS_OPT_TUNNEL 1
158
159 #define EFSYS_OPT_FW_SUBVARIANT_AWARE 1
160
161 #define EFSYS_OPT_EVB 0
162
163 #define EFSYS_OPT_MCDI_PROXY_AUTH_SERVER 0
164
165 /* ID */
166
167 typedef struct __efsys_identifier_s efsys_identifier_t;
168
169
170 #define EFSYS_PROBE(_name)                                              \
171         do { } while (0)
172
173 #define EFSYS_PROBE1(_name, _type1, _arg1)                              \
174         do { } while (0)
175
176 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)               \
177         do { } while (0)
178
179 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,               \
180                      _type3, _arg3)                                     \
181         do { } while (0)
182
183 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,               \
184                      _type3, _arg3, _type4, _arg4)                      \
185         do { } while (0)
186
187 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
188                      _type3, _arg3, _type4, _arg4, _type5, _arg5)       \
189         do { } while (0)
190
191 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
192                      _type3, _arg3, _type4, _arg4, _type5, _arg5,       \
193                      _type6, _arg6)                                     \
194         do { } while (0)
195
196 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,               \
197                      _type3, _arg3, _type4, _arg4, _type5, _arg5,       \
198                      _type6, _arg6, _type7, _arg7)                      \
199         do { } while (0)
200
201
202 /* DMA */
203
204 typedef rte_iova_t efsys_dma_addr_t;
205
206 typedef struct efsys_mem_s {
207         const struct rte_memzone        *esm_mz;
208         /*
209          * Ideally it should have volatile qualifier to denote that
210          * the memory may be updated by someone else. However, it adds
211          * qualifier discard warnings when the pointer or its derivative
212          * is passed to memset() or rte_mov16().
213          * So, skip the qualifier here, but make sure that it is added
214          * below in access macros.
215          */
216         void                            *esm_base;
217         efsys_dma_addr_t                esm_addr;
218 } efsys_mem_t;
219
220
221 #define EFSYS_MEM_ZERO(_esmp, _size)                                    \
222         do {                                                            \
223                 (void)memset((void *)(_esmp)->esm_base, 0, (_size));    \
224                                                                         \
225                 _NOTE(CONSTANTCONDITION);                               \
226         } while (B_FALSE)
227
228 #define EFSYS_MEM_READD(_esmp, _offset, _edp)                           \
229         do {                                                            \
230                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
231                 volatile uint32_t *_addr;                               \
232                                                                         \
233                 _NOTE(CONSTANTCONDITION);                               \
234                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
235                                                 sizeof(efx_dword_t)));  \
236                                                                         \
237                 _addr = (volatile uint32_t *)(_base + (_offset));       \
238                 (_edp)->ed_u32[0] = _addr[0];                           \
239                                                                         \
240                 EFSYS_PROBE2(mem_readl, unsigned int, (_offset),        \
241                                          uint32_t, (_edp)->ed_u32[0]);  \
242                                                                         \
243                 _NOTE(CONSTANTCONDITION);                               \
244         } while (B_FALSE)
245
246 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp)                           \
247         do {                                                            \
248                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
249                 volatile uint64_t *_addr;                               \
250                                                                         \
251                 _NOTE(CONSTANTCONDITION);                               \
252                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
253                                                 sizeof(efx_qword_t)));  \
254                                                                         \
255                 _addr = (volatile uint64_t *)(_base + (_offset));       \
256                 (_eqp)->eq_u64[0] = _addr[0];                           \
257                                                                         \
258                 EFSYS_PROBE3(mem_readq, unsigned int, (_offset),        \
259                                          uint32_t, (_eqp)->eq_u32[1],   \
260                                          uint32_t, (_eqp)->eq_u32[0]);  \
261                                                                         \
262                 _NOTE(CONSTANTCONDITION);                               \
263         } while (B_FALSE)
264
265 #define EFSYS_MEM_READO(_esmp, _offset, _eop)                           \
266         do {                                                            \
267                 volatile uint8_t *_base = (_esmp)->esm_base;            \
268                 volatile __m128i *_addr;                                \
269                                                                         \
270                 _NOTE(CONSTANTCONDITION);                               \
271                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
272                                                 sizeof(efx_oword_t)));  \
273                                                                         \
274                 _addr = (volatile __m128i *)(_base + (_offset));        \
275                 (_eop)->eo_u128[0] = _addr[0];                          \
276                                                                         \
277                 EFSYS_PROBE5(mem_reado, unsigned int, (_offset),        \
278                                          uint32_t, (_eop)->eo_u32[3],   \
279                                          uint32_t, (_eop)->eo_u32[2],   \
280                                          uint32_t, (_eop)->eo_u32[1],   \
281                                          uint32_t, (_eop)->eo_u32[0]);  \
282                                                                         \
283                 _NOTE(CONSTANTCONDITION);                               \
284         } while (B_FALSE)
285
286
287 #define EFSYS_MEM_WRITED(_esmp, _offset, _edp)                          \
288         do {                                                            \
289                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
290                 volatile uint32_t *_addr;                               \
291                                                                         \
292                 _NOTE(CONSTANTCONDITION);                               \
293                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
294                                                 sizeof(efx_dword_t)));  \
295                                                                         \
296                 EFSYS_PROBE2(mem_writed, unsigned int, (_offset),       \
297                                          uint32_t, (_edp)->ed_u32[0]);  \
298                                                                         \
299                 _addr = (volatile uint32_t *)(_base + (_offset));       \
300                 _addr[0] = (_edp)->ed_u32[0];                           \
301                                                                         \
302                 _NOTE(CONSTANTCONDITION);                               \
303         } while (B_FALSE)
304
305 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)                          \
306         do {                                                            \
307                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
308                 volatile uint64_t *_addr;                               \
309                                                                         \
310                 _NOTE(CONSTANTCONDITION);                               \
311                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
312                                                 sizeof(efx_qword_t)));  \
313                                                                         \
314                 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),       \
315                                          uint32_t, (_eqp)->eq_u32[1],   \
316                                          uint32_t, (_eqp)->eq_u32[0]);  \
317                                                                         \
318                 _addr = (volatile uint64_t *)(_base + (_offset));       \
319                 _addr[0] = (_eqp)->eq_u64[0];                           \
320                                                                         \
321                 _NOTE(CONSTANTCONDITION);                               \
322         } while (B_FALSE)
323
324 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop)                          \
325         do {                                                            \
326                 volatile uint8_t *_base = (_esmp)->esm_base;            \
327                 volatile __m128i *_addr;                                \
328                                                                         \
329                 _NOTE(CONSTANTCONDITION);                               \
330                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
331                                                 sizeof(efx_oword_t)));  \
332                                                                         \
333                                                                         \
334                 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),       \
335                                          uint32_t, (_eop)->eo_u32[3],   \
336                                          uint32_t, (_eop)->eo_u32[2],   \
337                                          uint32_t, (_eop)->eo_u32[1],   \
338                                          uint32_t, (_eop)->eo_u32[0]);  \
339                                                                         \
340                 _addr = (volatile __m128i *)(_base + (_offset));        \
341                 _addr[0] = (_eop)->eo_u128[0];                          \
342                                                                         \
343                 _NOTE(CONSTANTCONDITION);                               \
344         } while (B_FALSE)
345
346
347 #define EFSYS_MEM_SIZE(_esmp)                                           \
348         ((_esmp)->esm_mz->len)
349
350 #define EFSYS_MEM_ADDR(_esmp)                                           \
351         ((_esmp)->esm_addr)
352
353 #define EFSYS_MEM_IS_NULL(_esmp)                                        \
354         ((_esmp)->esm_base == NULL)
355
356 #define EFSYS_MEM_PREFETCH(_esmp, _offset)                              \
357         do {                                                            \
358                 volatile uint8_t *_base = (_esmp)->esm_base;            \
359                                                                         \
360                 rte_prefetch0(_base + (_offset));                       \
361         } while (0)
362
363
364 /* BAR */
365
366 typedef struct efsys_bar_s {
367         rte_spinlock_t          esb_lock;
368         int                     esb_rid;
369         struct rte_pci_device   *esb_dev;
370         /*
371          * Ideally it should have volatile qualifier to denote that
372          * the memory may be updated by someone else. However, it adds
373          * qualifier discard warnings when the pointer or its derivative
374          * is passed to memset() or rte_mov16().
375          * So, skip the qualifier here, but make sure that it is added
376          * below in access macros.
377          */
378         void                    *esb_base;
379 } efsys_bar_t;
380
381 #define SFC_BAR_LOCK_INIT(_esbp, _ifname)                               \
382         do {                                                            \
383                 rte_spinlock_init(&(_esbp)->esb_lock);                  \
384                 _NOTE(CONSTANTCONDITION);                               \
385         } while (B_FALSE)
386 #define SFC_BAR_LOCK_DESTROY(_esbp)     ((void)0)
387 #define SFC_BAR_LOCK(_esbp)             rte_spinlock_lock(&(_esbp)->esb_lock)
388 #define SFC_BAR_UNLOCK(_esbp)           rte_spinlock_unlock(&(_esbp)->esb_lock)
389
390 #define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)                    \
391         do {                                                            \
392                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
393                 volatile uint32_t *_addr;                               \
394                                                                         \
395                 _NOTE(CONSTANTCONDITION);                               \
396                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
397                                                 sizeof(efx_dword_t)));  \
398                 _NOTE(CONSTANTCONDITION);                               \
399                 if (_lock)                                              \
400                         SFC_BAR_LOCK(_esbp);                            \
401                                                                         \
402                 _addr = (volatile uint32_t *)(_base + (_offset));       \
403                 rte_rmb();                                              \
404                 (_edp)->ed_u32[0] = rte_read32_relaxed(_addr);          \
405                                                                         \
406                 EFSYS_PROBE2(bar_readd, unsigned int, (_offset),        \
407                                          uint32_t, (_edp)->ed_u32[0]);  \
408                                                                         \
409                 _NOTE(CONSTANTCONDITION);                               \
410                 if (_lock)                                              \
411                         SFC_BAR_UNLOCK(_esbp);                          \
412                 _NOTE(CONSTANTCONDITION);                               \
413         } while (B_FALSE)
414
415 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp)                           \
416         do {                                                            \
417                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
418                 volatile uint64_t *_addr;                               \
419                                                                         \
420                 _NOTE(CONSTANTCONDITION);                               \
421                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
422                                                 sizeof(efx_qword_t)));  \
423                                                                         \
424                 SFC_BAR_LOCK(_esbp);                                    \
425                                                                         \
426                 _addr = (volatile uint64_t *)(_base + (_offset));       \
427                 rte_rmb();                                              \
428                 (_eqp)->eq_u64[0] = rte_read64_relaxed(_addr);          \
429                                                                         \
430                 EFSYS_PROBE3(bar_readq, unsigned int, (_offset),        \
431                                          uint32_t, (_eqp)->eq_u32[1],   \
432                                          uint32_t, (_eqp)->eq_u32[0]);  \
433                                                                         \
434                 SFC_BAR_UNLOCK(_esbp);                                  \
435                 _NOTE(CONSTANTCONDITION);                               \
436         } while (B_FALSE)
437
438 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)                    \
439         do {                                                            \
440                 volatile uint8_t *_base = (_esbp)->esb_base;            \
441                 volatile __m128i *_addr;                                \
442                                                                         \
443                 _NOTE(CONSTANTCONDITION);                               \
444                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
445                                                 sizeof(efx_oword_t)));  \
446                                                                         \
447                 _NOTE(CONSTANTCONDITION);                               \
448                 if (_lock)                                              \
449                         SFC_BAR_LOCK(_esbp);                            \
450                                                                         \
451                 _addr = (volatile __m128i *)(_base + (_offset));        \
452                 rte_rmb();                                              \
453                 /* There is no rte_read128_relaxed() yet */             \
454                 (_eop)->eo_u128[0] = _addr[0];                          \
455                                                                         \
456                 EFSYS_PROBE5(bar_reado, unsigned int, (_offset),        \
457                                          uint32_t, (_eop)->eo_u32[3],   \
458                                          uint32_t, (_eop)->eo_u32[2],   \
459                                          uint32_t, (_eop)->eo_u32[1],   \
460                                          uint32_t, (_eop)->eo_u32[0]);  \
461                                                                         \
462                 _NOTE(CONSTANTCONDITION);                               \
463                 if (_lock)                                              \
464                         SFC_BAR_UNLOCK(_esbp);                          \
465                 _NOTE(CONSTANTCONDITION);                               \
466         } while (B_FALSE)
467
468
469 #define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)                   \
470         do {                                                            \
471                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
472                 volatile uint32_t *_addr;                               \
473                                                                         \
474                 _NOTE(CONSTANTCONDITION);                               \
475                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
476                                                 sizeof(efx_dword_t)));  \
477                                                                         \
478                 _NOTE(CONSTANTCONDITION);                               \
479                 if (_lock)                                              \
480                         SFC_BAR_LOCK(_esbp);                            \
481                                                                         \
482                 EFSYS_PROBE2(bar_writed, unsigned int, (_offset),       \
483                                          uint32_t, (_edp)->ed_u32[0]);  \
484                                                                         \
485                 _addr = (volatile uint32_t *)(_base + (_offset));       \
486                 rte_write32_relaxed((_edp)->ed_u32[0], _addr);          \
487                 rte_wmb();                                              \
488                                                                         \
489                 _NOTE(CONSTANTCONDITION);                               \
490                 if (_lock)                                              \
491                         SFC_BAR_UNLOCK(_esbp);                          \
492                 _NOTE(CONSTANTCONDITION);                               \
493         } while (B_FALSE)
494
495 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)                          \
496         do {                                                            \
497                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
498                 volatile uint64_t *_addr;                               \
499                                                                         \
500                 _NOTE(CONSTANTCONDITION);                               \
501                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
502                                                 sizeof(efx_qword_t)));  \
503                                                                         \
504                 SFC_BAR_LOCK(_esbp);                                    \
505                                                                         \
506                 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),       \
507                                          uint32_t, (_eqp)->eq_u32[1],   \
508                                          uint32_t, (_eqp)->eq_u32[0]);  \
509                                                                         \
510                 _addr = (volatile uint64_t *)(_base + (_offset));       \
511                 rte_write64_relaxed((_eqp)->eq_u64[0], _addr);          \
512                 rte_wmb();                                              \
513                                                                         \
514                 SFC_BAR_UNLOCK(_esbp);                                  \
515                 _NOTE(CONSTANTCONDITION);                               \
516         } while (B_FALSE)
517
518 /*
519  * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
520  * (required by PIO hardware).
521  *
522  * Neither VFIO, nor UIO, nor NIC UIO (on FreeBSD) support
523  * write-combined memory mapped to user-land, so just abort if used.
524  */
525 #define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp)                       \
526         do {                                                            \
527                 rte_panic("Write-combined BAR access not supported");   \
528         } while (B_FALSE)
529
530 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)                   \
531         do {                                                            \
532                 volatile uint8_t *_base = (_esbp)->esb_base;            \
533                 volatile __m128i *_addr;                                \
534                                                                         \
535                 _NOTE(CONSTANTCONDITION);                               \
536                 SFC_EFX_ASSERT(EFX_IS_P2ALIGNED(size_t, _offset,        \
537                                                 sizeof(efx_oword_t)));  \
538                                                                         \
539                 _NOTE(CONSTANTCONDITION);                               \
540                 if (_lock)                                              \
541                         SFC_BAR_LOCK(_esbp);                            \
542                                                                         \
543                 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),       \
544                                          uint32_t, (_eop)->eo_u32[3],   \
545                                          uint32_t, (_eop)->eo_u32[2],   \
546                                          uint32_t, (_eop)->eo_u32[1],   \
547                                          uint32_t, (_eop)->eo_u32[0]);  \
548                                                                         \
549                 _addr = (volatile __m128i *)(_base + (_offset));        \
550                 /* There is no rte_write128_relaxed() yet */            \
551                 _addr[0] = (_eop)->eo_u128[0];                          \
552                 rte_wmb();                                              \
553                                                                         \
554                 _NOTE(CONSTANTCONDITION);                               \
555                 if (_lock)                                              \
556                         SFC_BAR_UNLOCK(_esbp);                          \
557                 _NOTE(CONSTANTCONDITION);                               \
558         } while (B_FALSE)
559
560 /* Use the standard octo-word write for doorbell writes */
561 #define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop)                 \
562         do {                                                            \
563                 EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE);  \
564                 _NOTE(CONSTANTCONDITION);                               \
565         } while (B_FALSE)
566
567 /* SPIN */
568
569 #define EFSYS_SPIN(_us)                                                 \
570         do {                                                            \
571                 rte_delay_us(_us);                                      \
572                 _NOTE(CONSTANTCONDITION);                               \
573         } while (B_FALSE)
574
575 #define EFSYS_SLEEP EFSYS_SPIN
576
577 /* BARRIERS */
578
579 #define EFSYS_MEM_READ_BARRIER()        rte_rmb()
580 #define EFSYS_PIO_WRITE_BARRIER()       rte_io_wmb()
581
582 /* DMA SYNC */
583
584 /*
585  * DPDK does not provide any DMA syncing API, and no PMD drivers
586  * have any traces of explicit DMA syncing.
587  * DMA mapping is assumed to be coherent.
588  */
589
590 #define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size)        ((void)0)
591
592 /* Just avoid store and compiler (impliciltly) reordering */
593 #define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size)        rte_wmb()
594
595 /* TIMESTAMP */
596
597 typedef uint64_t efsys_timestamp_t;
598
599 #define EFSYS_TIMESTAMP(_usp)                                           \
600         do {                                                            \
601                 *(_usp) = rte_get_timer_cycles() * 1000000 /            \
602                         rte_get_timer_hz();                             \
603                 _NOTE(CONSTANTCONDITION);                               \
604         } while (B_FALSE)
605
606 /* KMEM */
607
608 #define EFSYS_KMEM_ALLOC(_esip, _size, _p)                              \
609         do {                                                            \
610                 (_esip) = (_esip);                                      \
611                 (_p) = rte_zmalloc("sfc", (_size), 0);                  \
612                 _NOTE(CONSTANTCONDITION);                               \
613         } while (B_FALSE)
614
615 #define EFSYS_KMEM_FREE(_esip, _size, _p)                               \
616         do {                                                            \
617                 (void)(_esip);                                          \
618                 (void)(_size);                                          \
619                 rte_free((_p));                                         \
620                 _NOTE(CONSTANTCONDITION);                               \
621         } while (B_FALSE)
622
623 /* LOCK */
624
625 typedef rte_spinlock_t efsys_lock_t;
626
627 #define SFC_EFSYS_LOCK_INIT(_eslp, _ifname, _label)     \
628         rte_spinlock_init((_eslp))
629 #define SFC_EFSYS_LOCK_DESTROY(_eslp) ((void)0)
630 #define SFC_EFSYS_LOCK(_eslp)                           \
631         rte_spinlock_lock((_eslp))
632 #define SFC_EFSYS_UNLOCK(_eslp)                         \
633         rte_spinlock_unlock((_eslp))
634 #define SFC_EFSYS_LOCK_ASSERT_OWNED(_eslp)              \
635         SFC_EFX_ASSERT(rte_spinlock_is_locked((_eslp)))
636
637 typedef int efsys_lock_state_t;
638
639 #define EFSYS_LOCK_MAGIC        0x000010c4
640
641 #define EFSYS_LOCK(_lockp, _state)                              \
642         do {                                                    \
643                 SFC_EFSYS_LOCK(_lockp);                         \
644                 (_state) = EFSYS_LOCK_MAGIC;                    \
645                 _NOTE(CONSTANTCONDITION);                       \
646         } while (B_FALSE)
647
648 #define EFSYS_UNLOCK(_lockp, _state)                            \
649         do {                                                    \
650                 SFC_EFX_ASSERT((_state) == EFSYS_LOCK_MAGIC);   \
651                 SFC_EFSYS_UNLOCK(_lockp);                       \
652                 _NOTE(CONSTANTCONDITION);                       \
653         } while (B_FALSE)
654
655 /* STAT */
656
657 typedef uint64_t        efsys_stat_t;
658
659 #define EFSYS_STAT_INCR(_knp, _delta)                           \
660         do {                                                    \
661                 *(_knp) += (_delta);                            \
662                 _NOTE(CONSTANTCONDITION);                       \
663         } while (B_FALSE)
664
665 #define EFSYS_STAT_DECR(_knp, _delta)                           \
666         do {                                                    \
667                 *(_knp) -= (_delta);                            \
668                 _NOTE(CONSTANTCONDITION);                       \
669         } while (B_FALSE)
670
671 #define EFSYS_STAT_SET(_knp, _val)                              \
672         do {                                                    \
673                 *(_knp) = (_val);                               \
674                 _NOTE(CONSTANTCONDITION);                       \
675         } while (B_FALSE)
676
677 #define EFSYS_STAT_SET_QWORD(_knp, _valp)                       \
678         do {                                                    \
679                 *(_knp) = rte_le_to_cpu_64((_valp)->eq_u64[0]); \
680                 _NOTE(CONSTANTCONDITION);                       \
681         } while (B_FALSE)
682
683 #define EFSYS_STAT_SET_DWORD(_knp, _valp)                       \
684         do {                                                    \
685                 *(_knp) = rte_le_to_cpu_32((_valp)->ed_u32[0]); \
686                 _NOTE(CONSTANTCONDITION);                       \
687         } while (B_FALSE)
688
689 #define EFSYS_STAT_INCR_QWORD(_knp, _valp)                              \
690         do {                                                            \
691                 *(_knp) += rte_le_to_cpu_64((_valp)->eq_u64[0]);        \
692                 _NOTE(CONSTANTCONDITION);                               \
693         } while (B_FALSE)
694
695 #define EFSYS_STAT_SUBR_QWORD(_knp, _valp)                              \
696         do {                                                            \
697                 *(_knp) -= rte_le_to_cpu_64((_valp)->eq_u64[0]);        \
698                 _NOTE(CONSTANTCONDITION);                               \
699         } while (B_FALSE)
700
701 /* ERR */
702
703 #if EFSYS_OPT_DECODE_INTR_FATAL
704 #define EFSYS_ERR(_esip, _code, _dword0, _dword1)                       \
705         do {                                                            \
706                 (void)(_esip);                                          \
707                 SFC_EFX_LOG(ERR, "FATAL ERROR #%u (0x%08x%08x)",        \
708                         (_code), (_dword0), (_dword1));                 \
709                 _NOTE(CONSTANTCONDITION);                               \
710         } while (B_FALSE)
711 #endif
712
713 /* ASSERT */
714
715 /* RTE_VERIFY from DPDK treats expressions with % operator incorrectly,
716  * so we re-implement it here
717  */
718 #ifdef RTE_LIBRTE_SFC_EFX_DEBUG
719 #define EFSYS_ASSERT(_exp)                                              \
720         do {                                                            \
721                 if (unlikely(!(_exp)))                                  \
722                         rte_panic("line %d\tassert \"%s\" failed\n",    \
723                                   __LINE__, (#_exp));                   \
724         } while (0)
725 #else
726 #define EFSYS_ASSERT(_exp)              (void)(_exp)
727 #endif
728
729 #define EFSYS_ASSERT3(_x, _op, _y, _t)  EFSYS_ASSERT((_t)(_x) _op (_t)(_y))
730
731 #define EFSYS_ASSERT3U(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, uint64_t)
732 #define EFSYS_ASSERT3S(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, int64_t)
733 #define EFSYS_ASSERT3P(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
734
735 /* ROTATE */
736
737 #define EFSYS_HAS_ROTL_DWORD    0
738
739 #ifdef __cplusplus
740 }
741 #endif
742
743 #endif  /* _SFC_COMMON_EFSYS_H */