linux/drivers/net/ethernet/rocker/rocker_tlv.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * drivers/net/ethernet/rocker/rocker_tlv.h - Rocker switch device driver
   4 * Copyright (c) 2014-2016 Jiri Pirko <jiri@mellanox.com>
   5 * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com>
   6 */
   7
   8#ifndef _ROCKER_TLV_H
   9#define _ROCKER_TLV_H
  10
  11#include <linux/types.h>
  12
  13#include "rocker_hw.h"
  14#include "rocker.h"
  15
  16#define ROCKER_TLV_ALIGNTO 8U
  17#define ROCKER_TLV_ALIGN(len) \
  18        (((len) + ROCKER_TLV_ALIGNTO - 1) & ~(ROCKER_TLV_ALIGNTO - 1))
  19#define ROCKER_TLV_HDRLEN ROCKER_TLV_ALIGN(sizeof(struct rocker_tlv))
  20
  21/*  <------- ROCKER_TLV_HDRLEN -------> <--- ROCKER_TLV_ALIGN(payload) --->
  22 * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+
  23 * |             Header          | Pad |           Payload           | Pad |
  24 * |      (struct rocker_tlv)    | ing |                             | ing |
  25 * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+
  26 *  <--------------------------- tlv->len -------------------------->
  27 */
  28
  29static inline struct rocker_tlv *rocker_tlv_next(const struct rocker_tlv *tlv,
  30                                                 int *remaining)
  31{
  32        int totlen = ROCKER_TLV_ALIGN(tlv->len);
  33
  34        *remaining -= totlen;
  35        return (struct rocker_tlv *) ((char *) tlv + totlen);
  36}
  37
  38static inline int rocker_tlv_ok(const struct rocker_tlv *tlv, int remaining)
  39{
  40        return remaining >= (int) ROCKER_TLV_HDRLEN &&
  41               tlv->len >= ROCKER_TLV_HDRLEN &&
  42               tlv->len <= remaining;
  43}
  44
  45#define rocker_tlv_for_each(pos, head, len, rem)        \
  46        for (pos = head, rem = len;                     \
  47             rocker_tlv_ok(pos, rem);                   \
  48             pos = rocker_tlv_next(pos, &(rem)))
  49
  50#define rocker_tlv_for_each_nested(pos, tlv, rem)       \
  51        rocker_tlv_for_each(pos, rocker_tlv_data(tlv),  \
  52                            rocker_tlv_len(tlv), rem)
  53
  54static inline int rocker_tlv_attr_size(int payload)
  55{
  56        return ROCKER_TLV_HDRLEN + payload;
  57}
  58
  59static inline int rocker_tlv_total_size(int payload)
  60{
  61        return ROCKER_TLV_ALIGN(rocker_tlv_attr_size(payload));
  62}
  63
  64static inline int rocker_tlv_padlen(int payload)
  65{
  66        return rocker_tlv_total_size(payload) - rocker_tlv_attr_size(payload);
  67}
  68
  69static inline int rocker_tlv_type(const struct rocker_tlv *tlv)
  70{
  71        return tlv->type;
  72}
  73
  74static inline void *rocker_tlv_data(const struct rocker_tlv *tlv)
  75{
  76        return (char *) tlv + ROCKER_TLV_HDRLEN;
  77}
  78
  79static inline int rocker_tlv_len(const struct rocker_tlv *tlv)
  80{
  81        return tlv->len - ROCKER_TLV_HDRLEN;
  82}
  83
  84static inline u8 rocker_tlv_get_u8(const struct rocker_tlv *tlv)
  85{
  86        return *(u8 *) rocker_tlv_data(tlv);
  87}
  88
  89static inline u16 rocker_tlv_get_u16(const struct rocker_tlv *tlv)
  90{
  91        return *(u16 *) rocker_tlv_data(tlv);
  92}
  93
  94static inline __be16 rocker_tlv_get_be16(const struct rocker_tlv *tlv)
  95{
  96        return *(__be16 *) rocker_tlv_data(tlv);
  97}
  98
  99static inline u32 rocker_tlv_get_u32(const struct rocker_tlv *tlv)
 100{
 101        return *(u32 *) rocker_tlv_data(tlv);
 102}
 103
 104static inline u64 rocker_tlv_get_u64(const struct rocker_tlv *tlv)
 105{
 106        return *(u64 *) rocker_tlv_data(tlv);
 107}
 108
 109void rocker_tlv_parse(const struct rocker_tlv **tb, int maxtype,
 110                      const char *buf, int buf_len);
 111
 112static inline void rocker_tlv_parse_nested(const struct rocker_tlv **tb,
 113                                           int maxtype,
 114                                           const struct rocker_tlv *tlv)
 115{
 116        rocker_tlv_parse(tb, maxtype, rocker_tlv_data(tlv),
 117                         rocker_tlv_len(tlv));
 118}
 119
 120static inline void
 121rocker_tlv_parse_desc(const struct rocker_tlv **tb, int maxtype,
 122                      const struct rocker_desc_info *desc_info)
 123{
 124        rocker_tlv_parse(tb, maxtype, desc_info->data,
 125                         desc_info->desc->tlv_size);
 126}
 127
 128static inline struct rocker_tlv *
 129rocker_tlv_start(struct rocker_desc_info *desc_info)
 130{
 131        return (struct rocker_tlv *) ((char *) desc_info->data +
 132                                               desc_info->tlv_size);
 133}
 134
 135int rocker_tlv_put(struct rocker_desc_info *desc_info,
 136                   int attrtype, int attrlen, const void *data);
 137
 138static inline int
 139rocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value)
 140{
 141        u8 tmp = value; /* work around GCC PR81715 */
 142
 143        return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp);
 144}
 145
 146static inline int
 147rocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value)
 148{
 149        u16 tmp = value;
 150
 151        return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp);
 152}
 153
 154static inline int
 155rocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value)
 156{
 157        __be16 tmp = value;
 158
 159        return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp);
 160}
 161
 162static inline int
 163rocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value)
 164{
 165        u32 tmp = value;
 166
 167        return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp);
 168}
 169
 170static inline int
 171rocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value)
 172{
 173        __be32 tmp = value;
 174
 175        return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp);
 176}
 177
 178static inline int
 179rocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value)
 180{
 181        u64 tmp = value;
 182
 183        return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp);
 184}
 185
 186static inline struct rocker_tlv *
 187rocker_tlv_nest_start(struct rocker_desc_info *desc_info, int attrtype)
 188{
 189        struct rocker_tlv *start = rocker_tlv_start(desc_info);
 190
 191        if (rocker_tlv_put(desc_info, attrtype, 0, NULL) < 0)
 192                return NULL;
 193
 194        return start;
 195}
 196
 197static inline void rocker_tlv_nest_end(struct rocker_desc_info *desc_info,
 198                                       struct rocker_tlv *start)
 199{
 200        start->len = (char *) rocker_tlv_start(desc_info) - (char *) start;
 201}
 202
 203static inline void rocker_tlv_nest_cancel(struct rocker_desc_info *desc_info,
 204                                          const struct rocker_tlv *start)
 205{
 206        desc_info->tlv_size = (const char *) start - desc_info->data;
 207}
 208
 209#endif
 210