Linux-libre 4.14.2-gnu
[librecmc/linux-libre.git] / drivers / net / ethernet / mellanox / mlxsw / item.h
1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/item.h
3  * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2015-2017 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(const 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 u8 __mlxsw_item_get8(const char *buf,
76                                    const struct mlxsw_item *item,
77                                    unsigned short index)
78 {
79         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u8));
80         u8 *b = (u8 *) buf;
81         u8 tmp;
82
83         tmp = b[offset];
84         tmp >>= item->shift;
85         tmp &= GENMASK(item->size.bits - 1, 0);
86         if (item->no_real_shift)
87                 tmp <<= item->shift;
88         return tmp;
89 }
90
91 static inline void __mlxsw_item_set8(char *buf, const struct mlxsw_item *item,
92                                      unsigned short index, u8 val)
93 {
94         unsigned int offset = __mlxsw_item_offset(item, index,
95                                                   sizeof(u8));
96         u8 *b = (u8 *) buf;
97         u8 mask = GENMASK(item->size.bits - 1, 0) << item->shift;
98         u8 tmp;
99
100         if (!item->no_real_shift)
101                 val <<= item->shift;
102         val &= mask;
103         tmp = b[offset];
104         tmp &= ~mask;
105         tmp |= val;
106         b[offset] = tmp;
107 }
108
109 static inline u16 __mlxsw_item_get16(const char *buf,
110                                      const struct mlxsw_item *item,
111                                      unsigned short index)
112 {
113         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16));
114         __be16 *b = (__be16 *) buf;
115         u16 tmp;
116
117         tmp = be16_to_cpu(b[offset]);
118         tmp >>= item->shift;
119         tmp &= GENMASK(item->size.bits - 1, 0);
120         if (item->no_real_shift)
121                 tmp <<= item->shift;
122         return tmp;
123 }
124
125 static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item,
126                                       unsigned short index, u16 val)
127 {
128         unsigned int offset = __mlxsw_item_offset(item, index,
129                                                   sizeof(u16));
130         __be16 *b = (__be16 *) buf;
131         u16 mask = GENMASK(item->size.bits - 1, 0) << item->shift;
132         u16 tmp;
133
134         if (!item->no_real_shift)
135                 val <<= item->shift;
136         val &= mask;
137         tmp = be16_to_cpu(b[offset]);
138         tmp &= ~mask;
139         tmp |= val;
140         b[offset] = cpu_to_be16(tmp);
141 }
142
143 static inline u32 __mlxsw_item_get32(const char *buf,
144                                      const struct mlxsw_item *item,
145                                      unsigned short index)
146 {
147         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32));
148         __be32 *b = (__be32 *) buf;
149         u32 tmp;
150
151         tmp = be32_to_cpu(b[offset]);
152         tmp >>= item->shift;
153         tmp &= GENMASK(item->size.bits - 1, 0);
154         if (item->no_real_shift)
155                 tmp <<= item->shift;
156         return tmp;
157 }
158
159 static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item,
160                                       unsigned short index, u32 val)
161 {
162         unsigned int offset = __mlxsw_item_offset(item, index,
163                                                   sizeof(u32));
164         __be32 *b = (__be32 *) buf;
165         u32 mask = GENMASK(item->size.bits - 1, 0) << item->shift;
166         u32 tmp;
167
168         if (!item->no_real_shift)
169                 val <<= item->shift;
170         val &= mask;
171         tmp = be32_to_cpu(b[offset]);
172         tmp &= ~mask;
173         tmp |= val;
174         b[offset] = cpu_to_be32(tmp);
175 }
176
177 static inline u64 __mlxsw_item_get64(const char *buf,
178                                      const struct mlxsw_item *item,
179                                      unsigned short index)
180 {
181         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
182         __be64 *b = (__be64 *) buf;
183         u64 tmp;
184
185         tmp = be64_to_cpu(b[offset]);
186         tmp >>= item->shift;
187         tmp &= GENMASK_ULL(item->size.bits - 1, 0);
188         if (item->no_real_shift)
189                 tmp <<= item->shift;
190         return tmp;
191 }
192
193 static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item,
194                                       unsigned short index, u64 val)
195 {
196         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
197         __be64 *b = (__be64 *) buf;
198         u64 mask = GENMASK_ULL(item->size.bits - 1, 0) << item->shift;
199         u64 tmp;
200
201         if (!item->no_real_shift)
202                 val <<= item->shift;
203         val &= mask;
204         tmp = be64_to_cpu(b[offset]);
205         tmp &= ~mask;
206         tmp |= val;
207         b[offset] = cpu_to_be64(tmp);
208 }
209
210 static inline void __mlxsw_item_memcpy_from(const char *buf, char *dst,
211                                             const struct mlxsw_item *item,
212                                             unsigned short index)
213 {
214         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
215
216         memcpy(dst, &buf[offset], item->size.bytes);
217 }
218
219 static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
220                                           const struct mlxsw_item *item,
221                                           unsigned short index)
222 {
223         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
224
225         memcpy(&buf[offset], src, item->size.bytes);
226 }
227
228 static inline char *__mlxsw_item_data(char *buf, const struct mlxsw_item *item,
229                                       unsigned short index)
230 {
231         unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
232
233         return &buf[offset];
234 }
235
236 static inline u16
237 __mlxsw_item_bit_array_offset(const struct mlxsw_item *item,
238                               u16 index, u8 *shift)
239 {
240         u16 max_index, be_index;
241         u16 offset;             /* byte offset inside the array */
242         u8 in_byte_index;
243
244         BUG_ON(index && !item->element_size);
245         if (item->offset % sizeof(u32) != 0 ||
246             BITS_PER_BYTE % item->element_size != 0) {
247                 pr_err("mlxsw: item bug (name=%s,offset=%x,element_size=%x)\n",
248                        item->name, item->offset, item->element_size);
249                 BUG();
250         }
251
252         max_index = (item->size.bytes << 3) / item->element_size - 1;
253         be_index = max_index - index;
254         offset = be_index * item->element_size >> 3;
255         in_byte_index  = index % (BITS_PER_BYTE / item->element_size);
256         *shift = in_byte_index * item->element_size;
257
258         return item->offset + offset;
259 }
260
261 static inline u8 __mlxsw_item_bit_array_get(const char *buf,
262                                             const struct mlxsw_item *item,
263                                             u16 index)
264 {
265         u8 shift, tmp;
266         u16 offset = __mlxsw_item_bit_array_offset(item, index, &shift);
267
268         tmp = buf[offset];
269         tmp >>= shift;
270         tmp &= GENMASK(item->element_size - 1, 0);
271         return tmp;
272 }
273
274 static inline void __mlxsw_item_bit_array_set(char *buf,
275                                               const struct mlxsw_item *item,
276                                               u16 index, u8 val)
277 {
278         u8 shift, tmp;
279         u16 offset = __mlxsw_item_bit_array_offset(item, index, &shift);
280         u8 mask = GENMASK(item->element_size - 1, 0) << shift;
281
282         val <<= shift;
283         val &= mask;
284         tmp = buf[offset];
285         tmp &= ~mask;
286         tmp |= val;
287         buf[offset] = tmp;
288 }
289
290 #define __ITEM_NAME(_type, _cname, _iname)                                      \
291         mlxsw_##_type##_##_cname##_##_iname##_item
292
293 /* _type: cmd_mbox, reg, etc.
294  * _cname: containter name (e.g. command name, register name)
295  * _iname: item name within the container
296  */
297
298 #define MLXSW_ITEM8(_type, _cname, _iname, _offset, _shift, _sizebits)          \
299 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
300         .offset = _offset,                                                      \
301         .shift = _shift,                                                        \
302         .size = {.bits = _sizebits,},                                           \
303         .name = #_type "_" #_cname "_" #_iname,                                 \
304 };                                                                              \
305 static inline u8 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)     \
306 {                                                                               \
307         return __mlxsw_item_get8(buf, &__ITEM_NAME(_type, _cname, _iname), 0);  \
308 }                                                                               \
309 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u8 val)\
310 {                                                                               \
311         __mlxsw_item_set8(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);    \
312 }
313
314 #define MLXSW_ITEM8_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits,  \
315                             _step, _instepoffset, _norealshift)                 \
316 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
317         .offset = _offset,                                                      \
318         .step = _step,                                                          \
319         .in_step_offset = _instepoffset,                                        \
320         .shift = _shift,                                                        \
321         .no_real_shift = _norealshift,                                          \
322         .size = {.bits = _sizebits,},                                           \
323         .name = #_type "_" #_cname "_" #_iname,                                 \
324 };                                                                              \
325 static inline u8                                                                \
326 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
327 {                                                                               \
328         return __mlxsw_item_get8(buf, &__ITEM_NAME(_type, _cname, _iname),      \
329                                  index);                                        \
330 }                                                                               \
331 static inline void                                                              \
332 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
333                                           u8 val)                               \
334 {                                                                               \
335         __mlxsw_item_set8(buf, &__ITEM_NAME(_type, _cname, _iname),             \
336                           index, val);                                          \
337 }
338
339 #define MLXSW_ITEM16(_type, _cname, _iname, _offset, _shift, _sizebits)         \
340 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
341         .offset = _offset,                                                      \
342         .shift = _shift,                                                        \
343         .size = {.bits = _sizebits,},                                           \
344         .name = #_type "_" #_cname "_" #_iname,                                 \
345 };                                                                              \
346 static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)    \
347 {                                                                               \
348         return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
349 }                                                                               \
350 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u16 val)\
351 {                                                                               \
352         __mlxsw_item_set16(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);   \
353 }
354
355 #define MLXSW_ITEM16_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits, \
356                              _step, _instepoffset, _norealshift)                \
357 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
358         .offset = _offset,                                                      \
359         .step = _step,                                                          \
360         .in_step_offset = _instepoffset,                                        \
361         .shift = _shift,                                                        \
362         .no_real_shift = _norealshift,                                          \
363         .size = {.bits = _sizebits,},                                           \
364         .name = #_type "_" #_cname "_" #_iname,                                 \
365 };                                                                              \
366 static inline u16                                                               \
367 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
368 {                                                                               \
369         return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname),     \
370                                   index);                                       \
371 }                                                                               \
372 static inline void                                                              \
373 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
374                                           u16 val)                              \
375 {                                                                               \
376         __mlxsw_item_set16(buf, &__ITEM_NAME(_type, _cname, _iname),            \
377                            index, val);                                         \
378 }
379
380 #define MLXSW_ITEM32(_type, _cname, _iname, _offset, _shift, _sizebits)         \
381 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
382         .offset = _offset,                                                      \
383         .shift = _shift,                                                        \
384         .size = {.bits = _sizebits,},                                           \
385         .name = #_type "_" #_cname "_" #_iname,                                 \
386 };                                                                              \
387 static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)    \
388 {                                                                               \
389         return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
390 }                                                                               \
391 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u32 val)\
392 {                                                                               \
393         __mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);   \
394 }
395
396 #define MLXSW_ITEM32_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits, \
397                              _step, _instepoffset, _norealshift)                \
398 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
399         .offset = _offset,                                                      \
400         .step = _step,                                                          \
401         .in_step_offset = _instepoffset,                                        \
402         .shift = _shift,                                                        \
403         .no_real_shift = _norealshift,                                          \
404         .size = {.bits = _sizebits,},                                           \
405         .name = #_type "_" #_cname "_" #_iname,                                 \
406 };                                                                              \
407 static inline u32                                                               \
408 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
409 {                                                                               \
410         return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname),     \
411                                   index);                                       \
412 }                                                                               \
413 static inline void                                                              \
414 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
415                                           u32 val)                              \
416 {                                                                               \
417         __mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, _iname),            \
418                            index, val);                                         \
419 }
420
421 #define MLXSW_ITEM64(_type, _cname, _iname, _offset, _shift, _sizebits)         \
422 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
423         .offset = _offset,                                                      \
424         .shift = _shift,                                                        \
425         .size = {.bits = _sizebits,},                                           \
426         .name = #_type "_" #_cname "_" #_iname,                                 \
427 };                                                                              \
428 static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)    \
429 {                                                                               \
430         return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
431 }                                                                               \
432 static inline void mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u64 val)\
433 {                                                                               \
434         __mlxsw_item_set64(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);   \
435 }
436
437 #define MLXSW_ITEM64_INDEXED(_type, _cname, _iname, _offset, _shift,            \
438                              _sizebits, _step, _instepoffset, _norealshift)     \
439 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
440         .offset = _offset,                                                      \
441         .step = _step,                                                          \
442         .in_step_offset = _instepoffset,                                        \
443         .shift = _shift,                                                        \
444         .no_real_shift = _norealshift,                                          \
445         .size = {.bits = _sizebits,},                                           \
446         .name = #_type "_" #_cname "_" #_iname,                                 \
447 };                                                                              \
448 static inline u64                                                               \
449 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
450 {                                                                               \
451         return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname),     \
452                                   index);                                       \
453 }                                                                               \
454 static inline void                                                              \
455 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,      \
456                                           u64 val)                              \
457 {                                                                               \
458         __mlxsw_item_set64(buf, &__ITEM_NAME(_type, _cname, _iname),            \
459                            index, val);                                         \
460 }
461
462 #define MLXSW_ITEM_BUF(_type, _cname, _iname, _offset, _sizebytes)              \
463 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
464         .offset = _offset,                                                      \
465         .size = {.bytes = _sizebytes,},                                         \
466         .name = #_type "_" #_cname "_" #_iname,                                 \
467 };                                                                              \
468 static inline void                                                              \
469 mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, char *dst)   \
470 {                                                                               \
471         __mlxsw_item_memcpy_from(buf, dst,                                      \
472                                  &__ITEM_NAME(_type, _cname, _iname), 0);       \
473 }                                                                               \
474 static inline void                                                              \
475 mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, const char *src)     \
476 {                                                                               \
477         __mlxsw_item_memcpy_to(buf, src,                                        \
478                                &__ITEM_NAME(_type, _cname, _iname), 0);         \
479 }                                                                               \
480 static inline char *                                                            \
481 mlxsw_##_type##_##_cname##_##_iname##_data(char *buf)                           \
482 {                                                                               \
483         return __mlxsw_item_data(buf, &__ITEM_NAME(_type, _cname, _iname), 0);  \
484 }
485
486 #define MLXSW_ITEM_BUF_INDEXED(_type, _cname, _iname, _offset, _sizebytes,      \
487                                _step, _instepoffset)                            \
488 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
489         .offset = _offset,                                                      \
490         .step = _step,                                                          \
491         .in_step_offset = _instepoffset,                                        \
492         .size = {.bytes = _sizebytes,},                                         \
493         .name = #_type "_" #_cname "_" #_iname,                                 \
494 };                                                                              \
495 static inline void                                                              \
496 mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf,              \
497                                                   unsigned short index,         \
498                                                   char *dst)                    \
499 {                                                                               \
500         __mlxsw_item_memcpy_from(buf, dst,                                      \
501                                  &__ITEM_NAME(_type, _cname, _iname), index);   \
502 }                                                                               \
503 static inline void                                                              \
504 mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf,                      \
505                                                 unsigned short index,           \
506                                                 const char *src)                \
507 {                                                                               \
508         __mlxsw_item_memcpy_to(buf, src,                                        \
509                                &__ITEM_NAME(_type, _cname, _iname), index);     \
510 }                                                                               \
511 static inline char *                                                            \
512 mlxsw_##_type##_##_cname##_##_iname##_data(char *buf, unsigned short index)     \
513 {                                                                               \
514         return __mlxsw_item_data(buf,                                           \
515                                  &__ITEM_NAME(_type, _cname, _iname), index);   \
516 }
517
518 #define MLXSW_ITEM_BIT_ARRAY(_type, _cname, _iname, _offset, _sizebytes,        \
519                              _element_size)                                     \
520 static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                 \
521         .offset = _offset,                                                      \
522         .element_size = _element_size,                                          \
523         .size = {.bytes = _sizebytes,},                                         \
524         .name = #_type "_" #_cname "_" #_iname,                                 \
525 };                                                                              \
526 static inline u8                                                                \
527 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, u16 index)           \
528 {                                                                               \
529         return __mlxsw_item_bit_array_get(buf,                                  \
530                                           &__ITEM_NAME(_type, _cname, _iname),  \
531                                           index);                               \
532 }                                                                               \
533 static inline void                                                              \
534 mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u16 index, u8 val)         \
535 {                                                                               \
536         return __mlxsw_item_bit_array_set(buf,                                  \
537                                           &__ITEM_NAME(_type, _cname, _iname),  \
538                                           index, val);                          \
539 }                                                                               \
540
541 #endif