1e2018e37SChaoyong He /* SPDX-License-Identifier: BSD-3-Clause 2e2018e37SChaoyong He * Copyright (c) 2023 Corigine Systems, Inc. 3e2018e37SChaoyong He * All rights reserved. 4e2018e37SChaoyong He */ 5e2018e37SChaoyong He 6e2018e37SChaoyong He #include "nfp_net_ctrl.h" 7e2018e37SChaoyong He 8e2018e37SChaoyong He #include <ethdev_pci.h> 9a3460357SChaoyong He #include <nfp_platform.h> 10e2018e37SChaoyong He 11e2018e37SChaoyong He #include "nfp_logs.h" 12e2018e37SChaoyong He #include "nfp_net_common.h" 13e2018e37SChaoyong He 14e2018e37SChaoyong He static void 15e2018e37SChaoyong He nfp_net_tlv_caps_reset(struct nfp_net_tlv_caps *caps) 16e2018e37SChaoyong He { 17e2018e37SChaoyong He memset(caps, 0, sizeof(*caps)); 18e2018e37SChaoyong He caps->mbox_off = NFP_NET_CFG_MBOX_BASE; 19e2018e37SChaoyong He caps->mbox_len = NFP_NET_CFG_MBOX_VAL_MAX_SZ; 20e2018e37SChaoyong He } 21e2018e37SChaoyong He 22e2018e37SChaoyong He int 23e2018e37SChaoyong He nfp_net_tlv_caps_parse(struct rte_eth_dev *dev) 24e2018e37SChaoyong He { 25e2018e37SChaoyong He uint32_t hdr; 26e2018e37SChaoyong He uint8_t *end; 27e2018e37SChaoyong He uint8_t *data; 28e2018e37SChaoyong He uint32_t length; 29e2018e37SChaoyong He uint32_t offset; 30e2018e37SChaoyong He uint32_t tlv_type; 314a9bb682SChaoyong He struct nfp_net_hw *net_hw; 32e2018e37SChaoyong He struct nfp_net_tlv_caps *caps; 3319bd7cceSChaoyong He struct nfp_net_hw_priv *hw_priv; 34e2018e37SChaoyong He 359d723baaSChaoyong He net_hw = dev->data->dev_private; 3619bd7cceSChaoyong He hw_priv = dev->process_private; 374a9bb682SChaoyong He caps = &net_hw->tlv_caps; 38e2018e37SChaoyong He nfp_net_tlv_caps_reset(caps); 39e2018e37SChaoyong He 404a9bb682SChaoyong He data = net_hw->super.ctrl_bar + NFP_NET_CFG_TLV_BASE; 4119bd7cceSChaoyong He end = net_hw->super.ctrl_bar + hw_priv->pf_dev->ctrl_bar_size; 42e2018e37SChaoyong He 43e2018e37SChaoyong He hdr = rte_read32(data); 44e2018e37SChaoyong He if (hdr == 0) { 45e2018e37SChaoyong He PMD_DRV_LOG(INFO, "TLV is empty!"); 46e2018e37SChaoyong He return 0; 47e2018e37SChaoyong He } 48e2018e37SChaoyong He 49e2018e37SChaoyong He for (; ; data += length) { 504a9bb682SChaoyong He offset = data - net_hw->super.ctrl_bar; 51e2018e37SChaoyong He 52e2018e37SChaoyong He if (data + NFP_NET_CFG_TLV_VALUE > end) { 53*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV."); 54e2018e37SChaoyong He return -EINVAL; 55e2018e37SChaoyong He } 56e2018e37SChaoyong He 57e2018e37SChaoyong He hdr = rte_read32(data); 58e2018e37SChaoyong He 59e2018e37SChaoyong He length = FIELD_GET(NFP_NET_CFG_TLV_HEADER_LENGTH, hdr); 60e2018e37SChaoyong He if ((length & (NFP_NET_CFG_TLV_LENGTH_INC - 1)) != 0) { 61*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "TLV size not multiple of 4B len: %u.", length); 62e2018e37SChaoyong He return -EINVAL; 63e2018e37SChaoyong He } 64e2018e37SChaoyong He 65e2018e37SChaoyong He /* Advance past the header */ 66e2018e37SChaoyong He data += NFP_NET_CFG_TLV_VALUE; 67e2018e37SChaoyong He if (data + length > end) { 68*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Oversized TLV offset: %u len: %u.", 69e2018e37SChaoyong He offset, length); 70e2018e37SChaoyong He return -EINVAL; 71e2018e37SChaoyong He } 72e2018e37SChaoyong He 73e2018e37SChaoyong He tlv_type = FIELD_GET(NFP_NET_CFG_TLV_HEADER_TYPE, hdr); 74e2018e37SChaoyong He 75e2018e37SChaoyong He switch (tlv_type) { 76e2018e37SChaoyong He case NFP_NET_CFG_TLV_TYPE_UNKNOWN: 77*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Unknown TLV at offset: %u.", offset); 78e2018e37SChaoyong He return -EINVAL; 79e2018e37SChaoyong He case NFP_NET_CFG_TLV_TYPE_RESERVED: 80e2018e37SChaoyong He break; 81e2018e37SChaoyong He case NFP_NET_CFG_TLV_TYPE_END: 82e2018e37SChaoyong He if (length == 0) 83e2018e37SChaoyong He return 0; 84e2018e37SChaoyong He 85*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "END TLV should be empty, has len: %u.", length); 86e2018e37SChaoyong He return -EINVAL; 87e2018e37SChaoyong He case NFP_NET_CFG_TLV_TYPE_MBOX: 88e2018e37SChaoyong He caps->mbox_len = length; 89e2018e37SChaoyong He 90e2018e37SChaoyong He if (length != 0) 914a9bb682SChaoyong He caps->mbox_off = data - net_hw->super.ctrl_bar; 92e2018e37SChaoyong He else 93e2018e37SChaoyong He caps->mbox_off = 0; 94e2018e37SChaoyong He break; 95e2018e37SChaoyong He case NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES: 96e2018e37SChaoyong He if (length != 0) 97e2018e37SChaoyong He caps->mbox_cmsg_types = rte_read32(data); 98e2018e37SChaoyong He break; 99e2018e37SChaoyong He default: 100e2018e37SChaoyong He if (FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr) == 0) 101e2018e37SChaoyong He break; 102e2018e37SChaoyong He 103*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Unknown TLV type: %u offset: %u len: %u.", 104e2018e37SChaoyong He tlv_type, offset, length); 105e2018e37SChaoyong He return -EINVAL; 106e2018e37SChaoyong He } 107e2018e37SChaoyong He } 108e2018e37SChaoyong He 109*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV."); 110e2018e37SChaoyong He return -EINVAL; 111e2018e37SChaoyong He } 112