net/failsafe: fix crash on slave queue release
[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 /* Enable SFN2xxx support */
155 #define EFSYS_OPT_MEDFORD2 1
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 1
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_RX_ES_SUPER_BUFFER 1
202
203 #define EFSYS_OPT_TUNNEL 1
204
205 #define EFSYS_OPT_FW_SUBVARIANT_AWARE 1
206
207 /* ID */
208
209 typedef struct __efsys_identifier_s efsys_identifier_t;
210
211
212 #define EFSYS_PROBE(_name)                                              \
213         do { } while (0)
214
215 #define EFSYS_PROBE1(_name, _type1, _arg1)                              \
216         do { } while (0)
217
218 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)               \
219         do { } while (0)
220
221 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,               \
222                      _type3, _arg3)                                     \
223         do { } while (0)
224
225 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,               \
226                      _type3, _arg3, _type4, _arg4)                      \
227         do { } while (0)
228
229 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
230                      _type3, _arg3, _type4, _arg4, _type5, _arg5)       \
231         do { } while (0)
232
233 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
234                      _type3, _arg3, _type4, _arg4, _type5, _arg5,       \
235                      _type6, _arg6)                                     \
236         do { } while (0)
237
238 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,               \
239                      _type3, _arg3, _type4, _arg4, _type5, _arg5,       \
240                      _type6, _arg6, _type7, _arg7)                      \
241         do { } while (0)
242
243
244 /* DMA */
245
246 typedef rte_iova_t efsys_dma_addr_t;
247
248 typedef struct efsys_mem_s {
249         const struct rte_memzone        *esm_mz;
250         /*
251          * Ideally it should have volatile qualifier to denote that
252          * the memory may be updated by someone else. However, it adds
253          * qualifier discard warnings when the pointer or its derivative
254          * is passed to memset() or rte_mov16().
255          * So, skip the qualifier here, but make sure that it is added
256          * below in access macros.
257          */
258         void                            *esm_base;
259         efsys_dma_addr_t                esm_addr;
260 } efsys_mem_t;
261
262
263 #define EFSYS_MEM_ZERO(_esmp, _size)                                    \
264         do {                                                            \
265                 (void)memset((void *)(_esmp)->esm_base, 0, (_size));    \
266                                                                         \
267                 _NOTE(CONSTANTCONDITION);                               \
268         } while (B_FALSE)
269
270 #define EFSYS_MEM_READD(_esmp, _offset, _edp)                           \
271         do {                                                            \
272                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
273                 volatile uint32_t *_addr;                               \
274                                                                         \
275                 _NOTE(CONSTANTCONDITION);                               \
276                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
277                                                                         \
278                 _addr = (volatile uint32_t *)(_base + (_offset));       \
279                 (_edp)->ed_u32[0] = _addr[0];                           \
280                                                                         \
281                 EFSYS_PROBE2(mem_readl, unsigned int, (_offset),        \
282                                          uint32_t, (_edp)->ed_u32[0]);  \
283                                                                         \
284                 _NOTE(CONSTANTCONDITION);                               \
285         } while (B_FALSE)
286
287 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp)                           \
288         do {                                                            \
289                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
290                 volatile uint64_t *_addr;                               \
291                                                                         \
292                 _NOTE(CONSTANTCONDITION);                               \
293                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
294                                                                         \
295                 _addr = (volatile uint64_t *)(_base + (_offset));       \
296                 (_eqp)->eq_u64[0] = _addr[0];                           \
297                                                                         \
298                 EFSYS_PROBE3(mem_readq, unsigned int, (_offset),        \
299                                          uint32_t, (_eqp)->eq_u32[1],   \
300                                          uint32_t, (_eqp)->eq_u32[0]);  \
301                                                                         \
302                 _NOTE(CONSTANTCONDITION);                               \
303         } while (B_FALSE)
304
305 #define EFSYS_MEM_READO(_esmp, _offset, _eop)                           \
306         do {                                                            \
307                 volatile uint8_t *_base = (_esmp)->esm_base;            \
308                 volatile __m128i *_addr;                                \
309                                                                         \
310                 _NOTE(CONSTANTCONDITION);                               \
311                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
312                                                                         \
313                 _addr = (volatile __m128i *)(_base + (_offset));        \
314                 (_eop)->eo_u128[0] = _addr[0];                          \
315                                                                         \
316                 EFSYS_PROBE5(mem_reado, unsigned int, (_offset),        \
317                                          uint32_t, (_eop)->eo_u32[3],   \
318                                          uint32_t, (_eop)->eo_u32[2],   \
319                                          uint32_t, (_eop)->eo_u32[1],   \
320                                          uint32_t, (_eop)->eo_u32[0]);  \
321                                                                         \
322                 _NOTE(CONSTANTCONDITION);                               \
323         } while (B_FALSE)
324
325
326 #define EFSYS_MEM_WRITED(_esmp, _offset, _edp)                          \
327         do {                                                            \
328                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
329                 volatile uint32_t *_addr;                               \
330                                                                         \
331                 _NOTE(CONSTANTCONDITION);                               \
332                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
333                                                                         \
334                 EFSYS_PROBE2(mem_writed, unsigned int, (_offset),       \
335                                          uint32_t, (_edp)->ed_u32[0]);  \
336                                                                         \
337                 _addr = (volatile uint32_t *)(_base + (_offset));       \
338                 _addr[0] = (_edp)->ed_u32[0];                           \
339                                                                         \
340                 _NOTE(CONSTANTCONDITION);                               \
341         } while (B_FALSE)
342
343 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)                          \
344         do {                                                            \
345                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
346                 volatile uint64_t *_addr;                               \
347                                                                         \
348                 _NOTE(CONSTANTCONDITION);                               \
349                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
350                                                                         \
351                 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),       \
352                                          uint32_t, (_eqp)->eq_u32[1],   \
353                                          uint32_t, (_eqp)->eq_u32[0]);  \
354                                                                         \
355                 _addr = (volatile uint64_t *)(_base + (_offset));       \
356                 _addr[0] = (_eqp)->eq_u64[0];                           \
357                                                                         \
358                 _NOTE(CONSTANTCONDITION);                               \
359         } while (B_FALSE)
360
361 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop)                          \
362         do {                                                            \
363                 volatile uint8_t *_base = (_esmp)->esm_base;            \
364                 volatile __m128i *_addr;                                \
365                                                                         \
366                 _NOTE(CONSTANTCONDITION);                               \
367                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
368                                                                         \
369                                                                         \
370                 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),       \
371                                          uint32_t, (_eop)->eo_u32[3],   \
372                                          uint32_t, (_eop)->eo_u32[2],   \
373                                          uint32_t, (_eop)->eo_u32[1],   \
374                                          uint32_t, (_eop)->eo_u32[0]);  \
375                                                                         \
376                 _addr = (volatile __m128i *)(_base + (_offset));        \
377                 _addr[0] = (_eop)->eo_u128[0];                          \
378                                                                         \
379                 _NOTE(CONSTANTCONDITION);                               \
380         } while (B_FALSE)
381
382
383 #define EFSYS_MEM_SIZE(_esmp)                                           \
384         ((_esmp)->esm_mz->len)
385
386 #define EFSYS_MEM_ADDR(_esmp)                                           \
387         ((_esmp)->esm_addr)
388
389 #define EFSYS_MEM_IS_NULL(_esmp)                                        \
390         ((_esmp)->esm_base == NULL)
391
392 #define EFSYS_MEM_PREFETCH(_esmp, _offset)                              \
393         do {                                                            \
394                 volatile uint8_t *_base = (_esmp)->esm_base;            \
395                                                                         \
396                 rte_prefetch0(_base + (_offset));                       \
397         } while (0)
398
399
400 /* BAR */
401
402 typedef struct efsys_bar_s {
403         rte_spinlock_t          esb_lock;
404         int                     esb_rid;
405         struct rte_pci_device   *esb_dev;
406         /*
407          * Ideally it should have volatile qualifier to denote that
408          * the memory may be updated by someone else. However, it adds
409          * qualifier discard warnings when the pointer or its derivative
410          * is passed to memset() or rte_mov16().
411          * So, skip the qualifier here, but make sure that it is added
412          * below in access macros.
413          */
414         void                    *esb_base;
415 } efsys_bar_t;
416
417 #define SFC_BAR_LOCK_INIT(_esbp, _ifname)                               \
418         do {                                                            \
419                 rte_spinlock_init(&(_esbp)->esb_lock);                  \
420                 _NOTE(CONSTANTCONDITION);                               \
421         } while (B_FALSE)
422 #define SFC_BAR_LOCK_DESTROY(_esbp)     ((void)0)
423 #define SFC_BAR_LOCK(_esbp)             rte_spinlock_lock(&(_esbp)->esb_lock)
424 #define SFC_BAR_UNLOCK(_esbp)           rte_spinlock_unlock(&(_esbp)->esb_lock)
425
426 #define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)                    \
427         do {                                                            \
428                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
429                 volatile uint32_t *_addr;                               \
430                                                                         \
431                 _NOTE(CONSTANTCONDITION);                               \
432                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
433                 _NOTE(CONSTANTCONDITION);                               \
434                 if (_lock)                                              \
435                         SFC_BAR_LOCK(_esbp);                            \
436                                                                         \
437                 _addr = (volatile uint32_t *)(_base + (_offset));       \
438                 rte_rmb();                                              \
439                 (_edp)->ed_u32[0] = rte_read32_relaxed(_addr);          \
440                                                                         \
441                 EFSYS_PROBE2(bar_readd, unsigned int, (_offset),        \
442                                          uint32_t, (_edp)->ed_u32[0]);  \
443                                                                         \
444                 _NOTE(CONSTANTCONDITION);                               \
445                 if (_lock)                                              \
446                         SFC_BAR_UNLOCK(_esbp);                          \
447                 _NOTE(CONSTANTCONDITION);                               \
448         } while (B_FALSE)
449
450 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp)                           \
451         do {                                                            \
452                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
453                 volatile uint64_t *_addr;                               \
454                                                                         \
455                 _NOTE(CONSTANTCONDITION);                               \
456                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
457                                                                         \
458                 SFC_BAR_LOCK(_esbp);                                    \
459                                                                         \
460                 _addr = (volatile uint64_t *)(_base + (_offset));       \
461                 rte_rmb();                                              \
462                 (_eqp)->eq_u64[0] = rte_read64_relaxed(_addr);          \
463                                                                         \
464                 EFSYS_PROBE3(bar_readq, unsigned int, (_offset),        \
465                                          uint32_t, (_eqp)->eq_u32[1],   \
466                                          uint32_t, (_eqp)->eq_u32[0]);  \
467                                                                         \
468                 SFC_BAR_UNLOCK(_esbp);                                  \
469                 _NOTE(CONSTANTCONDITION);                               \
470         } while (B_FALSE)
471
472 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)                    \
473         do {                                                            \
474                 volatile uint8_t *_base = (_esbp)->esb_base;            \
475                 volatile __m128i *_addr;                                \
476                                                                         \
477                 _NOTE(CONSTANTCONDITION);                               \
478                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
479                                                                         \
480                 _NOTE(CONSTANTCONDITION);                               \
481                 if (_lock)                                              \
482                         SFC_BAR_LOCK(_esbp);                            \
483                                                                         \
484                 _addr = (volatile __m128i *)(_base + (_offset));        \
485                 rte_rmb();                                              \
486                 /* There is no rte_read128_relaxed() yet */             \
487                 (_eop)->eo_u128[0] = _addr[0];                          \
488                                                                         \
489                 EFSYS_PROBE5(bar_reado, unsigned int, (_offset),        \
490                                          uint32_t, (_eop)->eo_u32[3],   \
491                                          uint32_t, (_eop)->eo_u32[2],   \
492                                          uint32_t, (_eop)->eo_u32[1],   \
493                                          uint32_t, (_eop)->eo_u32[0]);  \
494                                                                         \
495                 _NOTE(CONSTANTCONDITION);                               \
496                 if (_lock)                                              \
497                         SFC_BAR_UNLOCK(_esbp);                          \
498                 _NOTE(CONSTANTCONDITION);                               \
499         } while (B_FALSE)
500
501
502 #define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)                   \
503         do {                                                            \
504                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
505                 volatile uint32_t *_addr;                               \
506                                                                         \
507                 _NOTE(CONSTANTCONDITION);                               \
508                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
509                                                                         \
510                 _NOTE(CONSTANTCONDITION);                               \
511                 if (_lock)                                              \
512                         SFC_BAR_LOCK(_esbp);                            \
513                                                                         \
514                 EFSYS_PROBE2(bar_writed, unsigned int, (_offset),       \
515                                          uint32_t, (_edp)->ed_u32[0]);  \
516                                                                         \
517                 _addr = (volatile uint32_t *)(_base + (_offset));       \
518                 rte_write32_relaxed((_edp)->ed_u32[0], _addr);          \
519                 rte_wmb();                                              \
520                                                                         \
521                 _NOTE(CONSTANTCONDITION);                               \
522                 if (_lock)                                              \
523                         SFC_BAR_UNLOCK(_esbp);                          \
524                 _NOTE(CONSTANTCONDITION);                               \
525         } while (B_FALSE)
526
527 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)                          \
528         do {                                                            \
529                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
530                 volatile uint64_t *_addr;                               \
531                                                                         \
532                 _NOTE(CONSTANTCONDITION);                               \
533                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
534                                                                         \
535                 SFC_BAR_LOCK(_esbp);                                    \
536                                                                         \
537                 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),       \
538                                          uint32_t, (_eqp)->eq_u32[1],   \
539                                          uint32_t, (_eqp)->eq_u32[0]);  \
540                                                                         \
541                 _addr = (volatile uint64_t *)(_base + (_offset));       \
542                 rte_write64_relaxed((_eqp)->eq_u64[0], _addr);          \
543                 rte_wmb();                                              \
544                                                                         \
545                 SFC_BAR_UNLOCK(_esbp);                                  \
546                 _NOTE(CONSTANTCONDITION);                               \
547         } while (B_FALSE)
548
549 /*
550  * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
551  * (required by PIO hardware).
552  *
553  * Neither VFIO, nor UIO, nor NIC UIO (on FreeBSD) support
554  * write-combined memory mapped to user-land, so just abort if used.
555  */
556 #define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp)                       \
557         do {                                                            \
558                 rte_panic("Write-combined BAR access not supported");   \
559         } while (B_FALSE)
560
561 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)                   \
562         do {                                                            \
563                 volatile uint8_t *_base = (_esbp)->esb_base;            \
564                 volatile __m128i *_addr;                                \
565                                                                         \
566                 _NOTE(CONSTANTCONDITION);                               \
567                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
568                                                                         \
569                 _NOTE(CONSTANTCONDITION);                               \
570                 if (_lock)                                              \
571                         SFC_BAR_LOCK(_esbp);                            \
572                                                                         \
573                 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),       \
574                                          uint32_t, (_eop)->eo_u32[3],   \
575                                          uint32_t, (_eop)->eo_u32[2],   \
576                                          uint32_t, (_eop)->eo_u32[1],   \
577                                          uint32_t, (_eop)->eo_u32[0]);  \
578                                                                         \
579                 _addr = (volatile __m128i *)(_base + (_offset));        \
580                 /* There is no rte_write128_relaxed() yet */            \
581                 _addr[0] = (_eop)->eo_u128[0];                          \
582                 rte_wmb();                                              \
583                                                                         \
584                 _NOTE(CONSTANTCONDITION);                               \
585                 if (_lock)                                              \
586                         SFC_BAR_UNLOCK(_esbp);                          \
587                 _NOTE(CONSTANTCONDITION);                               \
588         } while (B_FALSE)
589
590 /* Use the standard octo-word write for doorbell writes */
591 #define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop)                 \
592         do {                                                            \
593                 EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE);  \
594                 _NOTE(CONSTANTCONDITION);                               \
595         } while (B_FALSE)
596
597 /* SPIN */
598
599 #define EFSYS_SPIN(_us)                                                 \
600         do {                                                            \
601                 rte_delay_us(_us);                                      \
602                 _NOTE(CONSTANTCONDITION);                               \
603         } while (B_FALSE)
604
605 #define EFSYS_SLEEP EFSYS_SPIN
606
607 /* BARRIERS */
608
609 #define EFSYS_MEM_READ_BARRIER()        rte_rmb()
610 #define EFSYS_PIO_WRITE_BARRIER()       rte_io_wmb()
611
612 /* DMA SYNC */
613
614 /*
615  * DPDK does not provide any DMA syncing API, and no PMD drivers
616  * have any traces of explicit DMA syncing.
617  * DMA mapping is assumed to be coherent.
618  */
619
620 #define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size)        ((void)0)
621
622 /* Just avoid store and compiler (impliciltly) reordering */
623 #define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size)        rte_wmb()
624
625 /* TIMESTAMP */
626
627 typedef uint64_t efsys_timestamp_t;
628
629 #define EFSYS_TIMESTAMP(_usp)                                           \
630         do {                                                            \
631                 *(_usp) = rte_get_timer_cycles() * 1000000 /            \
632                         rte_get_timer_hz();                             \
633                 _NOTE(CONSTANTCONDITION);                               \
634         } while (B_FALSE)
635
636 /* KMEM */
637
638 #define EFSYS_KMEM_ALLOC(_esip, _size, _p)                              \
639         do {                                                            \
640                 (_esip) = (_esip);                                      \
641                 (_p) = rte_zmalloc("sfc", (_size), 0);                  \
642                 _NOTE(CONSTANTCONDITION);                               \
643         } while (B_FALSE)
644
645 #define EFSYS_KMEM_FREE(_esip, _size, _p)                               \
646         do {                                                            \
647                 (void)(_esip);                                          \
648                 (void)(_size);                                          \
649                 rte_free((_p));                                         \
650                 _NOTE(CONSTANTCONDITION);                               \
651         } while (B_FALSE)
652
653 /* LOCK */
654
655 typedef rte_spinlock_t efsys_lock_t;
656
657 #define SFC_EFSYS_LOCK_INIT(_eslp, _ifname, _label)     \
658         rte_spinlock_init((_eslp))
659 #define SFC_EFSYS_LOCK_DESTROY(_eslp) ((void)0)
660 #define SFC_EFSYS_LOCK(_eslp)                           \
661         rte_spinlock_lock((_eslp))
662 #define SFC_EFSYS_UNLOCK(_eslp)                         \
663         rte_spinlock_unlock((_eslp))
664 #define SFC_EFSYS_LOCK_ASSERT_OWNED(_eslp)              \
665         SFC_ASSERT(rte_spinlock_is_locked((_eslp)))
666
667 typedef int efsys_lock_state_t;
668
669 #define EFSYS_LOCK_MAGIC        0x000010c4
670
671 #define EFSYS_LOCK(_lockp, _state)                              \
672         do {                                                    \
673                 SFC_EFSYS_LOCK(_lockp);                         \
674                 (_state) = EFSYS_LOCK_MAGIC;                    \
675                 _NOTE(CONSTANTCONDITION);                       \
676         } while (B_FALSE)
677
678 #define EFSYS_UNLOCK(_lockp, _state)                            \
679         do {                                                    \
680                 SFC_ASSERT((_state) == EFSYS_LOCK_MAGIC);       \
681                 SFC_EFSYS_UNLOCK(_lockp);                       \
682                 _NOTE(CONSTANTCONDITION);                       \
683         } while (B_FALSE)
684
685 /* STAT */
686
687 typedef uint64_t        efsys_stat_t;
688
689 #define EFSYS_STAT_INCR(_knp, _delta)                           \
690         do {                                                    \
691                 *(_knp) += (_delta);                            \
692                 _NOTE(CONSTANTCONDITION);                       \
693         } while (B_FALSE)
694
695 #define EFSYS_STAT_DECR(_knp, _delta)                           \
696         do {                                                    \
697                 *(_knp) -= (_delta);                            \
698                 _NOTE(CONSTANTCONDITION);                       \
699         } while (B_FALSE)
700
701 #define EFSYS_STAT_SET(_knp, _val)                              \
702         do {                                                    \
703                 *(_knp) = (_val);                               \
704                 _NOTE(CONSTANTCONDITION);                       \
705         } while (B_FALSE)
706
707 #define EFSYS_STAT_SET_QWORD(_knp, _valp)                       \
708         do {                                                    \
709                 *(_knp) = rte_le_to_cpu_64((_valp)->eq_u64[0]); \
710                 _NOTE(CONSTANTCONDITION);                       \
711         } while (B_FALSE)
712
713 #define EFSYS_STAT_SET_DWORD(_knp, _valp)                       \
714         do {                                                    \
715                 *(_knp) = rte_le_to_cpu_32((_valp)->ed_u32[0]); \
716                 _NOTE(CONSTANTCONDITION);                       \
717         } while (B_FALSE)
718
719 #define EFSYS_STAT_INCR_QWORD(_knp, _valp)                              \
720         do {                                                            \
721                 *(_knp) += rte_le_to_cpu_64((_valp)->eq_u64[0]);        \
722                 _NOTE(CONSTANTCONDITION);                               \
723         } while (B_FALSE)
724
725 #define EFSYS_STAT_SUBR_QWORD(_knp, _valp)                              \
726         do {                                                            \
727                 *(_knp) -= rte_le_to_cpu_64((_valp)->eq_u64[0]);        \
728                 _NOTE(CONSTANTCONDITION);                               \
729         } while (B_FALSE)
730
731 /* ERR */
732
733 #if EFSYS_OPT_DECODE_INTR_FATAL
734 #define EFSYS_ERR(_esip, _code, _dword0, _dword1)                       \
735         do {                                                            \
736                 (void)(_esip);                                          \
737                 SFC_GENERIC_LOG(ERR, "FATAL ERROR #%u (0x%08x%08x)",    \
738                         (_code), (_dword0), (_dword1));                 \
739                 _NOTE(CONSTANTCONDITION);                               \
740         } while (B_FALSE)
741 #endif
742
743 /* ASSERT */
744
745 /* RTE_VERIFY from DPDK treats expressions with % operator incorrectly,
746  * so we re-implement it here
747  */
748 #ifdef RTE_LIBRTE_SFC_EFX_DEBUG
749 #define EFSYS_ASSERT(_exp)                                              \
750         do {                                                            \
751                 if (unlikely(!(_exp)))                                  \
752                         rte_panic("line %d\tassert \"%s\" failed\n",    \
753                                   __LINE__, (#_exp));                   \
754         } while (0)
755 #else
756 #define EFSYS_ASSERT(_exp)              (void)(_exp)
757 #endif
758
759 #define EFSYS_ASSERT3(_x, _op, _y, _t)  EFSYS_ASSERT((_t)(_x) _op (_t)(_y))
760
761 #define EFSYS_ASSERT3U(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, uint64_t)
762 #define EFSYS_ASSERT3S(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, int64_t)
763 #define EFSYS_ASSERT3P(_x, _op, _y)     EFSYS_ASSERT3(_x, _op, _y, uintptr_t)
764
765 /* ROTATE */
766
767 #define EFSYS_HAS_ROTL_DWORD    0
768
769 #ifdef __cplusplus
770 }
771 #endif
772
773 #endif  /* _SFC_COMMON_EFSYS_H */