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