root/drivers/net/ethernet/mellanox/mlxsw/item.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. __mlxsw_item_offset
  2. __mlxsw_item_get8
  3. __mlxsw_item_set8
  4. __mlxsw_item_get16
  5. __mlxsw_item_set16
  6. __mlxsw_item_get32
  7. __mlxsw_item_set32
  8. __mlxsw_item_get64
  9. __mlxsw_item_set64
  10. __mlxsw_item_memcpy_from
  11. __mlxsw_item_memcpy_to
  12. __mlxsw_item_data
  13. __mlxsw_item_bit_array_offset
  14. __mlxsw_item_bit_array_get
  15. __mlxsw_item_bit_array_set

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

/* [<][>][^][v][top][bottom][index][help] */