]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/ethernet/mellanox/mlxsw/item.h
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[karo-tx-linux.git] / drivers / net / ethernet / mellanox / mlxsw / item.h
1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/item.h
3  * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
5  * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the names of the copyright holders nor the names of its
16  *    contributors may be used to endorse or promote products derived from
17  *    this software without specific prior written permission.
18  *
19  * Alternatively, this software may be distributed under the terms of the
20  * GNU General Public License ("GPL") version 2 as published by the Free
21  * Software Foundation.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 #ifndef _MLXSW_ITEM_H
37 #define _MLXSW_ITEM_H
38
39 #include <linux/types.h>
40 #include <linux/string.h>
41 #include <linux/bitops.h>
42
43 struct mlxsw_item {
44         unsigned short  offset;         /* bytes in container */
45         unsigned short  step;           /* step in bytes for indexed items */
46         unsigned short  in_step_offset; /* offset within one step */
47         unsigned char   shift;          /* shift in bits */
48         unsigned char   element_size;   /* size of element in bit array */
49         bool            no_real_shift;
50         union {
51                 unsigned char   bits;
52                 unsigned short  bytes;
53         } size;
54         const char      *name;
55 };
56
57 static inline unsigned int
58 __mlxsw_item_offset(struct mlxsw_item *item, unsigned short index,
59                     size_t typesize)
60 {
61         BUG_ON(index && !item->step);
62         if (item->offset % typesize != 0 ||
63             item->step % typesize != 0 ||
64             item->in_step_offset % typesize != 0) {
65                 pr_err("mlxsw: item bug (name=%s,offset=%x,step=%x,in_step_offset=%x,typesize=%zx)\n",
66                        item->name, item->offset, item->step,
67                        item->in_step_offset, typesize);
68                 BUG();
69         }
70
71         return ((item->offset + item->step * index + item->in_step_offset) /
72                 typesize);
73 }
74
75 static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item,
76                                      unsigned short index)
77 {
78         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16));
79         __be16 *b = (__be16 *) buf;
80         u16 tmp;
81
82         tmp = be16_to_cpu(b[offset]);
83         tmp >>= item->shift;
84         tmp &= GENMASK(item->size.bits - 1, 0);
85         if (item->no_real_shift)
86                 tmp <<= item->shift;
87         return tmp;
88 }
89
90 static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item,
91                                       unsigned short index, u16 val)
92 {
93         unsigned int offset = __mlxsw_item_offset(item, index,
94                                                   sizeof(u16));
95         __be16 *b = (__be16 *) buf;
96         u16 mask = GENMASK(item->size.bits - 1, 0) << item->shift;
97         u16 tmp;
98
99         if (!item->no_real_shift)
100                 val <<= item->shift;
101         val &= mask;
102         tmp = be16_to_cpu(b[offset]);
103         tmp &= ~mask;
104         tmp |= val;
105         b[offset] = cpu_to_be16(tmp);
106 }
107
108 static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item,
109                                      unsigned short index)
110 {
111         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32));
112         __be32 *b = (__be32 *) buf;
113         u32 tmp;
114
115         tmp = be32_to_cpu(b[offset]);
116         tmp >>= item->shift;
117         tmp &= GENMASK(item->size.bits - 1, 0);
118         if (item->no_real_shift)
119                 tmp <<= item->shift;
120         return tmp;
121 }
122
123 static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item,
124                                       unsigned short index, u32 val)
125 {
126         unsigned int offset = __mlxsw_item_offset(item, index,
127                                                   sizeof(u32));
128         __be32 *b = (__be32 *) buf;
129         u32 mask = GENMASK(item->size.bits - 1, 0) << item->shift;
130         u32 tmp;
131
132         if (!item->no_real_shift)
133                 val <<= item->shift;
134         val &= mask;
135         tmp = be32_to_cpu(b[offset]);
136         tmp &= ~mask;
137         tmp |= val;
138         b[offset] = cpu_to_be32(tmp);
139 }
140
141 static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item,
142                                      unsigned short index)
143 {
144         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
145         __be64 *b = (__be64 *) buf;
146         u64 tmp;
147
148         tmp = be64_to_cpu(b[offset]);
149         tmp >>= item->shift;
150         tmp &= GENMASK_ULL(item->size.bits - 1, 0);
151         if (item->no_real_shift)
152                 tmp <<= item->shift;
153         return tmp;
154 }
155
156 static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
157                                       unsigned short index, u64 val)
158 {
159         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
160         __be64 *b = (__be64 *) buf;
161         u64 mask = GENMASK_ULL(item->size.bits - 1, 0) << item->shift;
162         u64 tmp;
163
164         if (!item->no_real_shift)
165                 val <<= item->shift;
166         val &= mask;
167         tmp = be64_to_cpu(b[offset]);
168         tmp &= ~mask;
169         tmp |= val;
170         b[offset] = cpu_to_be64(tmp);
171 }
172
173 static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
174                                             struct mlxsw_item *item,
175                                             unsigned short index)
176 {
177         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
178
179         memcpy(dst, &buf[offset], item->size.bytes);
180 }
181
182 static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
183                                           struct mlxsw_item *item,
184                                           unsigned short index)
185 {
186         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
187
188         memcpy(&buf[offset], src, item->size.bytes);
189 }
190
191 static inline u16
192 __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
193 {
194         u16 max_index, be_index;
195         u16 offset;             /* byte offset inside the array */
196         u8 in_byte_index;
197
198         BUG_ON(index && !item->element_size);
199         if (item->offset % sizeof(u32) != 0 ||
200             BITS_PER_BYTE % item->element_size != 0) {
201                 pr_err("mlxsw: item bug (name=%s,offset=%x,element_size=%x)\n",
202                        item->name, item->offset, item->element_size);
203                 BUG();
204         }
205
206         max_index = (item->size.bytes << 3) / item->element_size - 1;
207         be_index = max_index - index;
208         offset = be_index * item->element_size >> 3;
209         in_byte_index  = index % (BITS_PER_BYTE / item->element_size);
210         *shift = in_byte_index * item->element_size;
211
212         return item->offset + offset;
213 }
214
215 static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item,
216                                             u16 index)
217 {
218         u8 shift, tmp;
219         u16 offset = __mlxsw_item_bit_array_offset(item, index, &shift);
220
221         tmp = buf[offset];
222         tmp >>= shift;
223         tmp &= GENMASK(item->element_size - 1, 0);
224         return tmp;
225 }
226
227 static inline void __mlxsw_item_bit_array_set(char *buf, struct mlxsw_item *item,
228                                               u16 index, u8 val)
229 {
230         u8 shift, tmp;
231         u16 offset = __mlxsw_item_bit_array_offset(item, index, &shift);
232         u8 mask = GENMASK(item->element_size - 1, 0) << shift;
233
234         val <<= shift;
235         val &= mask;
236         tmp = buf[offset];
237         tmp &= ~mask;
238         tmp |= val;
239         buf[offset] = tmp;
240 }
241
242 #define __ITEM_NAME(_type, _cname, _iname)                                      \
243         mlxsw_##_type##_##_cname##_##_iname##_item
244
245 /* _type: cmd_mbox, reg, etc.
246  * _cname: containter name (e.g. command name, register name)
247  * _iname: item name within the container
248  */
249
250 #define MLXSW_ITEM16(_type, _cname, _iname, _offset, _shift, _sizebits)         \
251 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
252         .offset = _offset,                                                      \
253         .shift = _shift,                                                        \
254         .size = {.bits = _sizebits,},                                           \
255         .name = #_type "_" #_cname "_" #_iname,                                 \
256 };                                                                              \
257 static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)          \
258 {                                                                               \
259         return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
260 }                                                                               \
261 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u16 val)\
262 {                                                                               \
263         __mlxsw_item_set16(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);   \
264 }
265
266 #define MLXSW_ITEM16_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits, \
267                              _step, _instepoffset, _norealshift)                \
268 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
269         .offset = _offset,                                                      \
270         .step = _step,                                                          \
271         .in_step_offset = _instepoffset,                                        \
272         .shift = _shift,                                                        \
273         .no_real_shift = _norealshift,                                          \
274         .size = {.bits = _sizebits,},                                           \
275         .name = #_type "_" #_cname "_" #_iname,                                 \
276 };                                                                              \
277 static inline u16                                                               \
278 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)      \
279 {                                                                               \
280         return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname),     \
281                                   index);                                       \
282 }                                                                               \
283 static inline void                                                              \
284 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
285                                           u16 val)                              \
286 {                                                                               \
287         __mlxsw_item_set16(buf, &__ITEM_NAME(_type, _cname, _iname),            \
288                            index, val);                                         \
289 }
290
291 #define MLXSW_ITEM32(_type, _cname, _iname, _offset, _shift, _sizebits)         \
292 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
293         .offset = _offset,                                                      \
294         .shift = _shift,                                                        \
295         .size = {.bits = _sizebits,},                                           \
296         .name = #_type "_" #_cname "_" #_iname,                                 \
297 };                                                                              \
298 static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)          \
299 {                                                                               \
300         return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
301 }                                                                               \
302 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u32 val)\
303 {                                                                               \
304         __mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);   \
305 }
306
307 #define MLXSW_ITEM32_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits, \
308                              _step, _instepoffset, _norealshift)                \
309 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
310         .offset = _offset,                                                      \
311         .step = _step,                                                          \
312         .in_step_offset = _instepoffset,                                        \
313         .shift = _shift,                                                        \
314         .no_real_shift = _norealshift,                                          \
315         .size = {.bits = _sizebits,},                                           \
316         .name = #_type "_" #_cname "_" #_iname,                                 \
317 };                                                                              \
318 static inline u32                                                               \
319 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)      \
320 {                                                                               \
321         return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname),     \
322                                   index);                                       \
323 }                                                                               \
324 static inline void                                                              \
325 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
326                                           u32 val)                              \
327 {                                                                               \
328         __mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, _iname),            \
329                            index, val);                                         \
330 }
331
332 #define MLXSW_ITEM64(_type, _cname, _iname, _offset, _shift, _sizebits)         \
333 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
334         .offset = _offset,                                                      \
335         .shift = _shift,                                                        \
336         .size = {.bits = _sizebits,},                                           \
337         .name = #_type "_" #_cname "_" #_iname,                                 \
338 };                                                                              \
339 static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)          \
340 {                                                                               \
341         return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
342 }                                                                               \
343 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u64 val)\
344 {                                                                               \
345         __mlxsw_item_set64(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);   \
346 }
347
348 #define MLXSW_ITEM64_INDEXED(_type, _cname, _iname, _offset, _shift,            \
349                              _sizebits, _step, _instepoffset, _norealshift)     \
350 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
351         .offset = _offset,                                                      \
352         .step = _step,                                                          \
353         .in_step_offset = _instepoffset,                                        \
354         .shift = _shift,                                                        \
355         .no_real_shift = _norealshift,                                          \
356         .size = {.bits = _sizebits,},                                           \
357         .name = #_type "_" #_cname "_" #_iname,                                 \
358 };                                                                              \
359 static inline u64                                                               \
360 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)      \
361 {                                                                               \
362         return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname),     \
363                                   index);                                       \
364 }                                                                               \
365 static inline void                                                              \
366 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
367                                           u64 val)                              \
368 {                                                                               \
369         __mlxsw_item_set64(buf, &__ITEM_NAME(_type, _cname, _iname),            \
370                            index, val);                                         \
371 }
372
373 #define MLXSW_ITEM_BUF(_type, _cname, _iname, _offset, _sizebytes)              \
374 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
375         .offset = _offset,                                                      \
376         .size = {.bytes = _sizebytes,},                                         \
377         .name = #_type "_" #_cname "_" #_iname,                                 \
378 };                                                                              \
379 static inline void                                                              \
380 mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst)         \
381 {                                                                               \
382         __mlxsw_item_memcpy_from(buf, dst,                                      \
383                                  &__ITEM_NAME(_type, _cname, _iname), 0);       \
384 }                                                                               \
385 static inline void                                                              \
386 mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, const char *src)     \
387 {                                                                               \
388         __mlxsw_item_memcpy_to(buf, src,                                        \
389                                &__ITEM_NAME(_type, _cname, _iname), 0);         \
390 }
391
392 #define MLXSW_ITEM_BUF_INDEXED(_type, _cname, _iname, _offset, _sizebytes,      \
393                                _step, _instepoffset)                            \
394 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
395         .offset = _offset,                                                      \
396         .step = _step,                                                          \
397         .in_step_offset = _instepoffset,                                        \
398         .size = {.bytes = _sizebytes,},                                         \
399         .name = #_type "_" #_cname "_" #_iname,                                 \
400 };                                                                              \
401 static inline void                                                              \
402 mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf,                    \
403                                                   unsigned short index,         \
404                                                   char *dst)                    \
405 {                                                                               \
406         __mlxsw_item_memcpy_from(buf, dst,                                      \
407                                  &__ITEM_NAME(_type, _cname, _iname), index);   \
408 }                                                                               \
409 static inline void                                                              \
410 mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf,                      \
411                                                 unsigned short index,           \
412                                                 const char *src)                \
413 {                                                                               \
414         __mlxsw_item_memcpy_to(buf, src,                                        \
415                                &__ITEM_NAME(_type, _cname, _iname), index);     \
416 }
417
418 #define MLXSW_ITEM_BIT_ARRAY(_type, _cname, _iname, _offset, _sizebytes,        \
419                              _element_size)                                     \
420 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
421         .offset = _offset,                                                      \
422         .element_size = _element_size,                                          \
423         .size = {.bytes = _sizebytes,},                                         \
424         .name = #_type "_" #_cname "_" #_iname,                                 \
425 };                                                                              \
426 static inline u8                                                                \
427 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, u16 index)                 \
428 {                                                                               \
429         return __mlxsw_item_bit_array_get(buf,                                  \
430                                           &__ITEM_NAME(_type, _cname, _iname),  \
431                                           index);                               \
432 }                                                                               \
433 static inline void                                                              \
434 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u16 index, u8 val)         \
435 {                                                                               \
436         return __mlxsw_item_bit_array_set(buf,                                  \
437                                           &__ITEM_NAME(_type, _cname, _iname),  \
438                                           index, val);                          \
439 }                                                                               \
440
441 #endif