18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drivers/net/ethernet/rocker/rocker_tlv.h - Rocker switch device driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2014-2016 Jiri Pirko <jiri@mellanox.com> 58c2ecf20Sopenharmony_ci * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ROCKER_TLV_H 98c2ecf20Sopenharmony_ci#define _ROCKER_TLV_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/types.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "rocker_hw.h" 148c2ecf20Sopenharmony_ci#include "rocker.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define ROCKER_TLV_ALIGNTO 8U 178c2ecf20Sopenharmony_ci#define ROCKER_TLV_ALIGN(len) \ 188c2ecf20Sopenharmony_ci (((len) + ROCKER_TLV_ALIGNTO - 1) & ~(ROCKER_TLV_ALIGNTO - 1)) 198c2ecf20Sopenharmony_ci#define ROCKER_TLV_HDRLEN ROCKER_TLV_ALIGN(sizeof(struct rocker_tlv)) 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* <------- ROCKER_TLV_HDRLEN -------> <--- ROCKER_TLV_ALIGN(payload) ---> 228c2ecf20Sopenharmony_ci * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+ 238c2ecf20Sopenharmony_ci * | Header | Pad | Payload | Pad | 248c2ecf20Sopenharmony_ci * | (struct rocker_tlv) | ing | | ing | 258c2ecf20Sopenharmony_ci * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+ 268c2ecf20Sopenharmony_ci * <--------------------------- tlv->len --------------------------> 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic inline struct rocker_tlv *rocker_tlv_next(const struct rocker_tlv *tlv, 308c2ecf20Sopenharmony_ci int *remaining) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci int totlen = ROCKER_TLV_ALIGN(tlv->len); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci *remaining -= totlen; 358c2ecf20Sopenharmony_ci return (struct rocker_tlv *) ((char *) tlv + totlen); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic inline int rocker_tlv_ok(const struct rocker_tlv *tlv, int remaining) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci return remaining >= (int) ROCKER_TLV_HDRLEN && 418c2ecf20Sopenharmony_ci tlv->len >= ROCKER_TLV_HDRLEN && 428c2ecf20Sopenharmony_ci tlv->len <= remaining; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define rocker_tlv_for_each(pos, head, len, rem) \ 468c2ecf20Sopenharmony_ci for (pos = head, rem = len; \ 478c2ecf20Sopenharmony_ci rocker_tlv_ok(pos, rem); \ 488c2ecf20Sopenharmony_ci pos = rocker_tlv_next(pos, &(rem))) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define rocker_tlv_for_each_nested(pos, tlv, rem) \ 518c2ecf20Sopenharmony_ci rocker_tlv_for_each(pos, rocker_tlv_data(tlv), \ 528c2ecf20Sopenharmony_ci rocker_tlv_len(tlv), rem) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic inline int rocker_tlv_attr_size(int payload) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci return ROCKER_TLV_HDRLEN + payload; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic inline int rocker_tlv_total_size(int payload) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci return ROCKER_TLV_ALIGN(rocker_tlv_attr_size(payload)); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline int rocker_tlv_padlen(int payload) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci return rocker_tlv_total_size(payload) - rocker_tlv_attr_size(payload); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic inline int rocker_tlv_type(const struct rocker_tlv *tlv) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci return tlv->type; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic inline void *rocker_tlv_data(const struct rocker_tlv *tlv) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci return (char *) tlv + ROCKER_TLV_HDRLEN; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic inline int rocker_tlv_len(const struct rocker_tlv *tlv) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci return tlv->len - ROCKER_TLV_HDRLEN; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic inline u8 rocker_tlv_get_u8(const struct rocker_tlv *tlv) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci return *(u8 *) rocker_tlv_data(tlv); 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic inline u16 rocker_tlv_get_u16(const struct rocker_tlv *tlv) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci return *(u16 *) rocker_tlv_data(tlv); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic inline __be16 rocker_tlv_get_be16(const struct rocker_tlv *tlv) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci return *(__be16 *) rocker_tlv_data(tlv); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic inline u32 rocker_tlv_get_u32(const struct rocker_tlv *tlv) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci return *(u32 *) rocker_tlv_data(tlv); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic inline u64 rocker_tlv_get_u64(const struct rocker_tlv *tlv) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci return *(u64 *) rocker_tlv_data(tlv); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_civoid rocker_tlv_parse(const struct rocker_tlv **tb, int maxtype, 1108c2ecf20Sopenharmony_ci const char *buf, int buf_len); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic inline void rocker_tlv_parse_nested(const struct rocker_tlv **tb, 1138c2ecf20Sopenharmony_ci int maxtype, 1148c2ecf20Sopenharmony_ci const struct rocker_tlv *tlv) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci rocker_tlv_parse(tb, maxtype, rocker_tlv_data(tlv), 1178c2ecf20Sopenharmony_ci rocker_tlv_len(tlv)); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic inline void 1218c2ecf20Sopenharmony_cirocker_tlv_parse_desc(const struct rocker_tlv **tb, int maxtype, 1228c2ecf20Sopenharmony_ci const struct rocker_desc_info *desc_info) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci rocker_tlv_parse(tb, maxtype, desc_info->data, 1258c2ecf20Sopenharmony_ci desc_info->desc->tlv_size); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic inline struct rocker_tlv * 1298c2ecf20Sopenharmony_cirocker_tlv_start(struct rocker_desc_info *desc_info) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci return (struct rocker_tlv *) ((char *) desc_info->data + 1328c2ecf20Sopenharmony_ci desc_info->tlv_size); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ciint rocker_tlv_put(struct rocker_desc_info *desc_info, 1368c2ecf20Sopenharmony_ci int attrtype, int attrlen, const void *data); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic inline int 1398c2ecf20Sopenharmony_cirocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci u8 tmp = value; /* work around GCC PR81715 */ 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic inline int 1478c2ecf20Sopenharmony_cirocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci u16 tmp = value; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp); 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic inline int 1558c2ecf20Sopenharmony_cirocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci __be16 tmp = value; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp); 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic inline int 1638c2ecf20Sopenharmony_cirocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci u32 tmp = value; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic inline int 1718c2ecf20Sopenharmony_cirocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci __be32 tmp = value; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic inline int 1798c2ecf20Sopenharmony_cirocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci u64 tmp = value; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic inline struct rocker_tlv * 1878c2ecf20Sopenharmony_cirocker_tlv_nest_start(struct rocker_desc_info *desc_info, int attrtype) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci struct rocker_tlv *start = rocker_tlv_start(desc_info); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (rocker_tlv_put(desc_info, attrtype, 0, NULL) < 0) 1928c2ecf20Sopenharmony_ci return NULL; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return start; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic inline void rocker_tlv_nest_end(struct rocker_desc_info *desc_info, 1988c2ecf20Sopenharmony_ci struct rocker_tlv *start) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci start->len = (char *) rocker_tlv_start(desc_info) - (char *) start; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic inline void rocker_tlv_nest_cancel(struct rocker_desc_info *desc_info, 2048c2ecf20Sopenharmony_ci const struct rocker_tlv *start) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci desc_info->tlv_size = (const char *) start - desc_info->data; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci#endif 210