162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * drivers/net/ethernet/rocker/rocker_tlv.c - Rocker switch device driver 462306a36Sopenharmony_ci * Copyright (c) 2014-2016 Jiri Pirko <jiri@mellanox.com> 562306a36Sopenharmony_ci * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/string.h> 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "rocker_hw.h" 1362306a36Sopenharmony_ci#include "rocker_tlv.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_civoid rocker_tlv_parse(const struct rocker_tlv **tb, int maxtype, 1662306a36Sopenharmony_ci const char *buf, int buf_len) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci const struct rocker_tlv *tlv; 1962306a36Sopenharmony_ci const struct rocker_tlv *head = (const struct rocker_tlv *) buf; 2062306a36Sopenharmony_ci int rem; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci memset(tb, 0, sizeof(struct rocker_tlv *) * (maxtype + 1)); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci rocker_tlv_for_each(tlv, head, buf_len, rem) { 2562306a36Sopenharmony_ci u32 type = rocker_tlv_type(tlv); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if (type > 0 && type <= maxtype) 2862306a36Sopenharmony_ci tb[type] = tlv; 2962306a36Sopenharmony_ci } 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciint rocker_tlv_put(struct rocker_desc_info *desc_info, 3362306a36Sopenharmony_ci int attrtype, int attrlen, const void *data) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci int tail_room = desc_info->data_size - desc_info->tlv_size; 3662306a36Sopenharmony_ci int total_size = rocker_tlv_total_size(attrlen); 3762306a36Sopenharmony_ci struct rocker_tlv *tlv; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci if (unlikely(tail_room < total_size)) 4062306a36Sopenharmony_ci return -EMSGSIZE; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci tlv = rocker_tlv_start(desc_info); 4362306a36Sopenharmony_ci desc_info->tlv_size += total_size; 4462306a36Sopenharmony_ci tlv->type = attrtype; 4562306a36Sopenharmony_ci tlv->len = rocker_tlv_attr_size(attrlen); 4662306a36Sopenharmony_ci memcpy(rocker_tlv_data(tlv), data, attrlen); 4762306a36Sopenharmony_ci memset((char *) tlv + tlv->len, 0, rocker_tlv_padlen(attrlen)); 4862306a36Sopenharmony_ci return 0; 4962306a36Sopenharmony_ci} 50