net/sfc: support extended statistics
[dpdk.git] / drivers / net / sfc / efsys.h
1 /*-
2  * Copyright (c) 2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * This software was jointly developed between OKTET Labs (under contract
6  * for Solarflare) and Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifndef _SFC_COMMON_EFSYS_H
31 #define _SFC_COMMON_EFSYS_H
32
33 #include <stdbool.h>
34
35 #include <rte_spinlock.h>
36 #include <rte_byteorder.h>
37 #include <rte_debug.h>
38 #include <rte_memzone.h>
39 #include <rte_memory.h>
40 #include <rte_memcpy.h>
41 #include <rte_cycles.h>
42 #include <rte_prefetch.h>
43 #include <rte_common.h>
44 #include <rte_malloc.h>
45 #include <rte_log.h>
46
47 #include "sfc_debug.h"
48
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52
53 #define EFSYS_HAS_UINT64 1
54 #define EFSYS_USE_UINT64 1
55 #define EFSYS_HAS_SSE2_M128 1
56
57 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
58 #define EFSYS_IS_BIG_ENDIAN 1
59 #define EFSYS_IS_LITTLE_ENDIAN 0
60 #elif RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
61 #define EFSYS_IS_BIG_ENDIAN 0
62 #define EFSYS_IS_LITTLE_ENDIAN 1
63 #else
64 #error "Cannot determine system endianness"
65 #endif
66 #include "efx_types.h"
67
68
69 #ifndef _NOTE
70 #define _NOTE(s)
71 #endif
72
73 typedef bool boolean_t;
74
75 #ifndef B_FALSE
76 #define B_FALSE false
77 #endif
78 #ifndef B_TRUE
79 #define B_TRUE  true
80 #endif
81
82 /*
83  * RTE_MAX() and RTE_MIN() cannot be used since braced-group within
84  * expression allowed only inside a function, but MAX() is used as
85  * a number of elements in array.
86  */
87 #ifndef MAX
88 #define MAX(v1, v2)     ((v1) > (v2) ? (v1) : (v2))
89 #endif
90 #ifndef MIN
91 #define MIN(v1, v2)     ((v1) < (v2) ? (v1) : (v2))
92 #endif
93
94 /* There are macros for alignment in DPDK, but we need to make a proper
95  * correspondence here, if we want to re-use them at all
96  */
97 #ifndef IS_P2ALIGNED
98 #define IS_P2ALIGNED(v, a)      ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
99 #endif
100
101 #ifndef P2ROUNDUP
102 #define P2ROUNDUP(x, align)     (-(-(x) & -(align)))
103 #endif
104
105 #ifndef P2ALIGN
106 #define P2ALIGN(_x, _a)         ((_x) & -(_a))
107 #endif
108
109 #ifndef IS2P
110 #define ISP2(x)                 rte_is_power_of_2(x)
111 #endif
112
113 #define ENOTACTIVE      ENOTCONN
114
115 static inline void
116 prefetch_read_many(const volatile void *addr)
117 {
118         rte_prefetch0(addr);
119 }
120
121 static inline void
122 prefetch_read_once(const volatile void *addr)
123 {
124         rte_prefetch_non_temporal(addr);
125 }
126
127 /* Modifiers used for Windows builds */
128 #define __in
129 #define __in_opt
130 #define __in_ecount(_n)
131 #define __in_ecount_opt(_n)
132 #define __in_bcount(_n)
133 #define __in_bcount_opt(_n)
134
135 #define __out
136 #define __out_opt
137 #define __out_ecount(_n)
138 #define __out_ecount_opt(_n)
139 #define __out_bcount(_n)
140 #define __out_bcount_opt(_n)
141
142 #define __deref_out
143
144 #define __inout
145 #define __inout_opt
146 #define __inout_ecount(_n)
147 #define __inout_ecount_opt(_n)
148 #define __inout_bcount(_n)
149 #define __inout_bcount_opt(_n)
150 #define __inout_bcount_full_opt(_n)
151
152 #define __deref_out_bcount_opt(n)
153
154 #define __checkReturn
155 #define __success(_x)
156
157 #define __drv_when(_p, _c)
158
159 /* Code inclusion options */
160
161
162 #define EFSYS_OPT_NAMES 1
163
164 /* Disable SFN5xxx/SFN6xxx since it requires specific support in the PMD */
165 #define EFSYS_OPT_SIENA 0
166 /* Enable SFN7xxx support */
167 #define EFSYS_OPT_HUNTINGTON 1
168 /* Enable SFN8xxx support */
169 #define EFSYS_OPT_MEDFORD 1
170 #ifdef RTE_LIBRTE_SFC_EFX_DEBUG
171 #define EFSYS_OPT_CHECK_REG 1
172 #else
173 #define EFSYS_OPT_CHECK_REG 0
174 #endif
175
176 /* MCDI is required for SFN7xxx and SFN8xx */
177 #define EFSYS_OPT_MCDI 1
178 #define EFSYS_OPT_MCDI_LOGGING 1
179 #define EFSYS_OPT_MCDI_PROXY_AUTH 0
180
181 #define EFSYS_OPT_MAC_STATS 1
182
183 #define EFSYS_OPT_LOOPBACK 0
184
185 #define EFSYS_OPT_MON_MCDI 0
186 #define EFSYS_OPT_MON_STATS 0
187
188 #define EFSYS_OPT_PHY_STATS 0
189 #define EFSYS_OPT_BIST 0
190 #define EFSYS_OPT_PHY_LED_CONTROL 0
191 #define EFSYS_OPT_PHY_FLAGS 0
192
193 #define EFSYS_OPT_VPD 0
194 #define EFSYS_OPT_NVRAM 0
195 #define EFSYS_OPT_BOOTCFG 0
196
197 #define EFSYS_OPT_DIAG 0
198 #define EFSYS_OPT_RX_SCALE 0
199 #define EFSYS_OPT_QSTATS 0
200 /* Filters support is required for SFN7xxx and SFN8xx */
201 #define EFSYS_OPT_FILTER 1
202 #define EFSYS_OPT_RX_SCATTER 0
203
204 #define EFSYS_OPT_EV_PREFETCH 0
205
206 #define EFSYS_OPT_DECODE_INTR_FATAL 0
207
208 #define EFSYS_OPT_LICENSING 0
209
210 #define EFSYS_OPT_ALLOW_UNCONFIGURED_NIC 0
211
212 #define EFSYS_OPT_RX_PACKED_STREAM 0
213
214 /* ID */
215
216 typedef struct __efsys_identifier_s efsys_identifier_t;
217
218
219 #define EFSYS_PROBE(_name)                                              \
220         do { } while (0)
221
222 #define EFSYS_PROBE1(_name, _type1, _arg1)                              \
223         do { } while (0)
224
225 #define EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)               \
226         do { } while (0)
227
228 #define EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,               \
229                      _type3, _arg3)                                     \
230         do { } while (0)
231
232 #define EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,               \
233                      _type3, _arg3, _type4, _arg4)                      \
234         do { } while (0)
235
236 #define EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,               \
237                      _type3, _arg3, _type4, _arg4, _type5, _arg5)       \
238         do { } while (0)
239
240 #define EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,               \
241                      _type3, _arg3, _type4, _arg4, _type5, _arg5,       \
242                      _type6, _arg6)                                     \
243         do { } while (0)
244
245 #define EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,               \
246                      _type3, _arg3, _type4, _arg4, _type5, _arg5,       \
247                      _type6, _arg6, _type7, _arg7)                      \
248         do { } while (0)
249
250
251 /* DMA */
252
253 typedef phys_addr_t efsys_dma_addr_t;
254
255 typedef struct efsys_mem_s {
256         const struct rte_memzone        *esm_mz;
257         /*
258          * Ideally it should have volatile qualifier to denote that
259          * the memory may be updated by someone else. However, it adds
260          * qualifier discard warnings when the pointer or its derivative
261          * is passed to memset() or rte_mov16().
262          * So, skip the qualifier here, but make sure that it is added
263          * below in access macros.
264          */
265         void                            *esm_base;
266         efsys_dma_addr_t                esm_addr;
267 } efsys_mem_t;
268
269
270 #define EFSYS_MEM_ZERO(_esmp, _size)                                    \
271         do {                                                            \
272                 (void)memset((void *)(_esmp)->esm_base, 0, (_size));    \
273                                                                         \
274                 _NOTE(CONSTANTCONDITION);                               \
275         } while (B_FALSE)
276
277 #define EFSYS_MEM_READD(_esmp, _offset, _edp)                           \
278         do {                                                            \
279                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
280                 volatile uint32_t *_addr;                               \
281                                                                         \
282                 _NOTE(CONSTANTCONDITION);                               \
283                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
284                                                                         \
285                 _addr = (volatile uint32_t *)(_base + (_offset));       \
286                 (_edp)->ed_u32[0] = _addr[0];                           \
287                                                                         \
288                 EFSYS_PROBE2(mem_readl, unsigned int, (_offset),        \
289                                          uint32_t, (_edp)->ed_u32[0]);  \
290                                                                         \
291                 _NOTE(CONSTANTCONDITION);                               \
292         } while (B_FALSE)
293
294 #define EFSYS_MEM_READQ(_esmp, _offset, _eqp)                           \
295         do {                                                            \
296                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
297                 volatile uint64_t *_addr;                               \
298                                                                         \
299                 _NOTE(CONSTANTCONDITION);                               \
300                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
301                                                                         \
302                 _addr = (volatile uint64_t *)(_base + (_offset));       \
303                 (_eqp)->eq_u64[0] = _addr[0];                           \
304                                                                         \
305                 EFSYS_PROBE3(mem_readq, unsigned int, (_offset),        \
306                                          uint32_t, (_eqp)->eq_u32[1],   \
307                                          uint32_t, (_eqp)->eq_u32[0]);  \
308                                                                         \
309                 _NOTE(CONSTANTCONDITION);                               \
310         } while (B_FALSE)
311
312 #define EFSYS_MEM_READO(_esmp, _offset, _eop)                           \
313         do {                                                            \
314                 volatile uint8_t *_base = (_esmp)->esm_base;            \
315                 volatile __m128i *_addr;                                \
316                                                                         \
317                 _NOTE(CONSTANTCONDITION);                               \
318                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
319                                                                         \
320                 _addr = (volatile __m128i *)(_base + (_offset));        \
321                 (_eop)->eo_u128[0] = _addr[0];                          \
322                                                                         \
323                 EFSYS_PROBE5(mem_reado, unsigned int, (_offset),        \
324                                          uint32_t, (_eop)->eo_u32[3],   \
325                                          uint32_t, (_eop)->eo_u32[2],   \
326                                          uint32_t, (_eop)->eo_u32[1],   \
327                                          uint32_t, (_eop)->eo_u32[0]);  \
328                                                                         \
329                 _NOTE(CONSTANTCONDITION);                               \
330         } while (B_FALSE)
331
332
333 #define EFSYS_MEM_WRITED(_esmp, _offset, _edp)                          \
334         do {                                                            \
335                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
336                 volatile uint32_t *_addr;                               \
337                                                                         \
338                 _NOTE(CONSTANTCONDITION);                               \
339                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
340                                                                         \
341                 EFSYS_PROBE2(mem_writed, unsigned int, (_offset),       \
342                                          uint32_t, (_edp)->ed_u32[0]);  \
343                                                                         \
344                 _addr = (volatile uint32_t *)(_base + (_offset));       \
345                 _addr[0] = (_edp)->ed_u32[0];                           \
346                                                                         \
347                 _NOTE(CONSTANTCONDITION);                               \
348         } while (B_FALSE)
349
350 #define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)                          \
351         do {                                                            \
352                 volatile uint8_t  *_base = (_esmp)->esm_base;           \
353                 volatile uint64_t *_addr;                               \
354                                                                         \
355                 _NOTE(CONSTANTCONDITION);                               \
356                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
357                                                                         \
358                 EFSYS_PROBE3(mem_writeq, unsigned int, (_offset),       \
359                                          uint32_t, (_eqp)->eq_u32[1],   \
360                                          uint32_t, (_eqp)->eq_u32[0]);  \
361                                                                         \
362                 _addr = (volatile uint64_t *)(_base + (_offset));       \
363                 _addr[0] = (_eqp)->eq_u64[0];                           \
364                                                                         \
365                 _NOTE(CONSTANTCONDITION);                               \
366         } while (B_FALSE)
367
368 #define EFSYS_MEM_WRITEO(_esmp, _offset, _eop)                          \
369         do {                                                            \
370                 volatile uint8_t *_base = (_esmp)->esm_base;            \
371                 volatile __m128i *_addr;                                \
372                                                                         \
373                 _NOTE(CONSTANTCONDITION);                               \
374                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
375                                                                         \
376                                                                         \
377                 EFSYS_PROBE5(mem_writeo, unsigned int, (_offset),       \
378                                          uint32_t, (_eop)->eo_u32[3],   \
379                                          uint32_t, (_eop)->eo_u32[2],   \
380                                          uint32_t, (_eop)->eo_u32[1],   \
381                                          uint32_t, (_eop)->eo_u32[0]);  \
382                                                                         \
383                 _addr = (volatile __m128i *)(_base + (_offset));        \
384                 _addr[0] = (_eop)->eo_u128[0];                          \
385                                                                         \
386                 _NOTE(CONSTANTCONDITION);                               \
387         } while (B_FALSE)
388
389
390 #define EFSYS_MEM_ADDR(_esmp)                                           \
391         ((_esmp)->esm_addr)
392
393 #define EFSYS_MEM_IS_NULL(_esmp)                                        \
394         ((_esmp)->esm_base == NULL)
395
396 #define EFSYS_MEM_PREFETCH(_esmp, _offset)                              \
397         do {                                                            \
398                 volatile uint8_t *_base = (_esmp)->esm_base;            \
399                                                                         \
400                 rte_prefetch0(_base + (_offset));                       \
401         } while (0)
402
403
404 /* BAR */
405
406 typedef struct efsys_bar_s {
407         rte_spinlock_t          esb_lock;
408         int                     esb_rid;
409         struct rte_pci_device   *esb_dev;
410         /*
411          * Ideally it should have volatile qualifier to denote that
412          * the memory may be updated by someone else. However, it adds
413          * qualifier discard warnings when the pointer or its derivative
414          * is passed to memset() or rte_mov16().
415          * So, skip the qualifier here, but make sure that it is added
416          * below in access macros.
417          */
418         void                    *esb_base;
419 } efsys_bar_t;
420
421 #define SFC_BAR_LOCK_INIT(_esbp, _ifname)                               \
422         do {                                                            \
423                 rte_spinlock_init(&(_esbp)->esb_lock);                  \
424                 _NOTE(CONSTANTCONDITION);                               \
425         } while (B_FALSE)
426 #define SFC_BAR_LOCK_DESTROY(_esbp)     ((void)0)
427 #define SFC_BAR_LOCK(_esbp)             rte_spinlock_lock(&(_esbp)->esb_lock)
428 #define SFC_BAR_UNLOCK(_esbp)           rte_spinlock_unlock(&(_esbp)->esb_lock)
429
430 #define EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)                    \
431         do {                                                            \
432                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
433                 volatile uint32_t *_addr;                               \
434                                                                         \
435                 _NOTE(CONSTANTCONDITION);                               \
436                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
437                 _NOTE(CONSTANTCONDITION);                               \
438                 if (_lock)                                              \
439                         SFC_BAR_LOCK(_esbp);                            \
440                                                                         \
441                 _addr = (volatile uint32_t *)(_base + (_offset));       \
442                 rte_rmb();                                              \
443                 (_edp)->ed_u32[0] = _addr[0];                           \
444                                                                         \
445                 EFSYS_PROBE2(bar_readd, unsigned int, (_offset),        \
446                                          uint32_t, (_edp)->ed_u32[0]);  \
447                                                                         \
448                 _NOTE(CONSTANTCONDITION);                               \
449                 if (_lock)                                              \
450                         SFC_BAR_UNLOCK(_esbp);                          \
451                 _NOTE(CONSTANTCONDITION);                               \
452         } while (B_FALSE)
453
454 #define EFSYS_BAR_READQ(_esbp, _offset, _eqp)                           \
455         do {                                                            \
456                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
457                 volatile uint64_t *_addr;                               \
458                                                                         \
459                 _NOTE(CONSTANTCONDITION);                               \
460                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
461                                                                         \
462                 SFC_BAR_LOCK(_esbp);                                    \
463                                                                         \
464                 _addr = (volatile uint64_t *)(_base + (_offset));       \
465                 rte_rmb();                                              \
466                 (_eqp)->eq_u64[0] = _addr[0];                           \
467                                                                         \
468                 EFSYS_PROBE3(bar_readq, unsigned int, (_offset),        \
469                                          uint32_t, (_eqp)->eq_u32[1],   \
470                                          uint32_t, (_eqp)->eq_u32[0]);  \
471                                                                         \
472                 SFC_BAR_UNLOCK(_esbp);                                  \
473                 _NOTE(CONSTANTCONDITION);                               \
474         } while (B_FALSE)
475
476 #define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)                    \
477         do {                                                            \
478                 volatile uint8_t *_base = (_esbp)->esb_base;            \
479                 volatile __m128i *_addr;                                \
480                                                                         \
481                 _NOTE(CONSTANTCONDITION);                               \
482                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
483                                                                         \
484                 _NOTE(CONSTANTCONDITION);                               \
485                 if (_lock)                                              \
486                         SFC_BAR_LOCK(_esbp);                            \
487                                                                         \
488                 _addr = (volatile __m128i *)(_base + (_offset));        \
489                 rte_rmb();                                              \
490                 (_eop)->eo_u128[0] = _addr[0];                          \
491                                                                         \
492                 EFSYS_PROBE5(bar_reado, unsigned int, (_offset),        \
493                                          uint32_t, (_eop)->eo_u32[3],   \
494                                          uint32_t, (_eop)->eo_u32[2],   \
495                                          uint32_t, (_eop)->eo_u32[1],   \
496                                          uint32_t, (_eop)->eo_u32[0]);  \
497                                                                         \
498                 _NOTE(CONSTANTCONDITION);                               \
499                 if (_lock)                                              \
500                         SFC_BAR_UNLOCK(_esbp);                          \
501                 _NOTE(CONSTANTCONDITION);                               \
502         } while (B_FALSE)
503
504
505 #define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)                   \
506         do {                                                            \
507                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
508                 volatile uint32_t *_addr;                               \
509                                                                         \
510                 _NOTE(CONSTANTCONDITION);                               \
511                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_dword_t))); \
512                                                                         \
513                 _NOTE(CONSTANTCONDITION);                               \
514                 if (_lock)                                              \
515                         SFC_BAR_LOCK(_esbp);                            \
516                                                                         \
517                 EFSYS_PROBE2(bar_writed, unsigned int, (_offset),       \
518                                          uint32_t, (_edp)->ed_u32[0]);  \
519                                                                         \
520                 _addr = (volatile uint32_t *)(_base + (_offset));       \
521                 _addr[0] = (_edp)->ed_u32[0];                           \
522                 rte_wmb();                                              \
523                                                                         \
524                 _NOTE(CONSTANTCONDITION);                               \
525                 if (_lock)                                              \
526                         SFC_BAR_UNLOCK(_esbp);                          \
527                 _NOTE(CONSTANTCONDITION);                               \
528         } while (B_FALSE)
529
530 #define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)                          \
531         do {                                                            \
532                 volatile uint8_t  *_base = (_esbp)->esb_base;           \
533                 volatile uint64_t *_addr;                               \
534                                                                         \
535                 _NOTE(CONSTANTCONDITION);                               \
536                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_qword_t))); \
537                                                                         \
538                 SFC_BAR_LOCK(_esbp);                                    \
539                                                                         \
540                 EFSYS_PROBE3(bar_writeq, unsigned int, (_offset),       \
541                                          uint32_t, (_eqp)->eq_u32[1],   \
542                                          uint32_t, (_eqp)->eq_u32[0]);  \
543                                                                         \
544                 _addr = (volatile uint64_t *)(_base + (_offset));       \
545                 _addr[0] = (_eqp)->eq_u64[0];                           \
546                 rte_wmb();                                              \
547                                                                         \
548                 SFC_BAR_UNLOCK(_esbp);                                  \
549                 _NOTE(CONSTANTCONDITION);                               \
550         } while (B_FALSE)
551
552 /*
553  * Guarantees 64bit aligned 64bit writes to write combined BAR mapping
554  * (required by PIO hardware).
555  *
556  * Neither VFIO, nor UIO, nor NIC UIO (on FreeBSD) support
557  * write-combined memory mapped to user-land, so just abort if used.
558  */
559 #define EFSYS_BAR_WC_WRITEQ(_esbp, _offset, _eqp)                       \
560         do {                                                            \
561                 rte_panic("Write-combined BAR access not supported");   \
562         } while (B_FALSE)
563
564 #define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)                   \
565         do {                                                            \
566                 volatile uint8_t *_base = (_esbp)->esb_base;            \
567                 volatile __m128i *_addr;                                \
568                                                                         \
569                 _NOTE(CONSTANTCONDITION);                               \
570                 SFC_ASSERT(IS_P2ALIGNED(_offset, sizeof(efx_oword_t))); \
571                                                                         \
572                 _NOTE(CONSTANTCONDITION);                               \
573                 if (_lock)                                              \
574                         SFC_BAR_LOCK(_esbp);                            \
575                                                                         \
576                 EFSYS_PROBE5(bar_writeo, unsigned int, (_offset),       \
577                                          uint32_t, (_eop)->eo_u32[3],   \
578                                          uint32_t, (_eop)->eo_u32[2],   \
579                                          uint32_t, (_eop)->eo_u32[1],   \
580                                          uint32_t, (_eop)->eo_u32[0]);  \
581                                                                         \
582                 _addr = (volatile __m128i *)(_base + (_offset));        \
583                 _addr[0] = (_eop)->eo_u128[0];                          \
584                 rte_wmb();                                              \
585                                                                         \
586                 _NOTE(CONSTANTCONDITION);                               \
587                 if (_lock)                                              \
588                         SFC_BAR_UNLOCK(_esbp);                          \
589                 _NOTE(CONSTANTCONDITION);                               \
590         } while (B_FALSE)
591
592 /* Use the standard octo-word write for doorbell writes */
593 #define EFSYS_BAR_DOORBELL_WRITEO(_esbp, _offset, _eop)                 \
594         do {                                                            \
595                 EFSYS_BAR_WRITEO((_esbp), (_offset), (_eop), B_FALSE);  \
596                 _NOTE(CONSTANTCONDITION);                               \
597         } while (B_FALSE)
598
599 /* SPIN */
600
601 #define EFSYS_SPIN(_us)                                                 \
602         do {                                                            \
603                 rte_delay_us(_us);                                      \
604                 _NOTE(CONSTANTCONDITION);                               \
605         } while (B_FALSE)
606
607 #define EFSYS_SLEEP EFSYS_SPIN
608
609 /* BARRIERS */
610
611 #define EFSYS_MEM_READ_BARRIER()        rte_rmb()
612 #define EFSYS_PIO_WRITE_BARRIER()       rte_wmb()
613
614 /* DMA SYNC */
615
616 /*
617  * DPDK does not provide any DMA syncing API, and no PMD drivers
618  * have any traces of explicit DMA syncing.
619  * DMA mapping is assumed to be coherent.
620  */
621
622 #define EFSYS_DMA_SYNC_FOR_KERNEL(_esmp, _offset, _size)        ((void)0)
623 #define EFSYS_DMA_SYNC_FOR_DEVICE(_esmp, _offset, _size)        ((void)0)
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                 RTE_LOG(ERR, PMD, "FATAL ERROR #%u (0x%08x%08x)\n",     \
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 */