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