18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drivers/net/ethernet/rocker/rocker_tlv.c - 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#include <linux/types.h> 98c2ecf20Sopenharmony_ci#include <linux/string.h> 108c2ecf20Sopenharmony_ci#include <linux/errno.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "rocker_hw.h" 138c2ecf20Sopenharmony_ci#include "rocker_tlv.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_civoid rocker_tlv_parse(const struct rocker_tlv **tb, int maxtype, 168c2ecf20Sopenharmony_ci const char *buf, int buf_len) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci const struct rocker_tlv *tlv; 198c2ecf20Sopenharmony_ci const struct rocker_tlv *head = (const struct rocker_tlv *) buf; 208c2ecf20Sopenharmony_ci int rem; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci memset(tb, 0, sizeof(struct rocker_tlv *) * (maxtype + 1)); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci rocker_tlv_for_each(tlv, head, buf_len, rem) { 258c2ecf20Sopenharmony_ci u32 type = rocker_tlv_type(tlv); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci if (type > 0 && type <= maxtype) 288c2ecf20Sopenharmony_ci tb[type] = tlv; 298c2ecf20Sopenharmony_ci } 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciint rocker_tlv_put(struct rocker_desc_info *desc_info, 338c2ecf20Sopenharmony_ci int attrtype, int attrlen, const void *data) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci int tail_room = desc_info->data_size - desc_info->tlv_size; 368c2ecf20Sopenharmony_ci int total_size = rocker_tlv_total_size(attrlen); 378c2ecf20Sopenharmony_ci struct rocker_tlv *tlv; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci if (unlikely(tail_room < total_size)) 408c2ecf20Sopenharmony_ci return -EMSGSIZE; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci tlv = rocker_tlv_start(desc_info); 438c2ecf20Sopenharmony_ci desc_info->tlv_size += total_size; 448c2ecf20Sopenharmony_ci tlv->type = attrtype; 458c2ecf20Sopenharmony_ci tlv->len = rocker_tlv_attr_size(attrlen); 468c2ecf20Sopenharmony_ci memcpy(rocker_tlv_data(tlv), data, attrlen); 478c2ecf20Sopenharmony_ci memset((char *) tlv + tlv->len, 0, rocker_tlv_padlen(attrlen)); 488c2ecf20Sopenharmony_ci return 0; 498c2ecf20Sopenharmony_ci} 50