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 : : 34 : 0 : net_hw = dev->data->dev_private; 35 : 0 : caps = &net_hw->tlv_caps; 36 : : nfp_net_tlv_caps_reset(caps); 37 : : 38 : 0 : data = net_hw->super.ctrl_bar + NFP_NET_CFG_TLV_BASE; 39 : 0 : end = net_hw->super.ctrl_bar + NFP_NET_CFG_BAR_SZ; 40 : : 41 : : hdr = rte_read32(data); 42 [ # # ]: 0 : if (hdr == 0) { 43 : 0 : PMD_DRV_LOG(INFO, "TLV is empty!"); 44 : 0 : return 0; 45 : : } 46 : : 47 : : for (; ; data += length) { 48 : 0 : offset = data - net_hw->super.ctrl_bar; 49 : : 50 [ # # ]: 0 : if (data + NFP_NET_CFG_TLV_VALUE > end) { 51 : 0 : PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV"); 52 : 0 : return -EINVAL; 53 : : } 54 : : 55 : : hdr = rte_read32(data); 56 : : 57 : 0 : length = FIELD_GET(NFP_NET_CFG_TLV_HEADER_LENGTH, hdr); 58 [ # # ]: 0 : if ((length & (NFP_NET_CFG_TLV_LENGTH_INC - 1)) != 0) { 59 : 0 : PMD_DRV_LOG(ERR, "TLV size not multiple of 4B len: %u", length); 60 : 0 : return -EINVAL; 61 : : } 62 : : 63 : : /* Advance past the header */ 64 : : data += NFP_NET_CFG_TLV_VALUE; 65 [ # # ]: 0 : if (data + length > end) { 66 : 0 : PMD_DRV_LOG(ERR, "Oversized TLV offset: %u len: %u", 67 : : offset, length); 68 : 0 : return -EINVAL; 69 : : } 70 : : 71 : 0 : tlv_type = FIELD_GET(NFP_NET_CFG_TLV_HEADER_TYPE, hdr); 72 : : 73 [ # # # # : 0 : switch (tlv_type) { # # ] 74 : 0 : case NFP_NET_CFG_TLV_TYPE_UNKNOWN: 75 : 0 : PMD_DRV_LOG(ERR, "Unknown TLV at offset: %u", offset); 76 : 0 : return -EINVAL; 77 : : case NFP_NET_CFG_TLV_TYPE_RESERVED: 78 : : break; 79 : 0 : case NFP_NET_CFG_TLV_TYPE_END: 80 [ # # ]: 0 : if (length == 0) 81 : : return 0; 82 : : 83 : 0 : PMD_DRV_LOG(ERR, "END TLV should be empty, has len: %u", length); 84 : 0 : return -EINVAL; 85 : 0 : case NFP_NET_CFG_TLV_TYPE_MBOX: 86 : 0 : caps->mbox_len = length; 87 : : 88 [ # # ]: 0 : if (length != 0) 89 : 0 : caps->mbox_off = data - net_hw->super.ctrl_bar; 90 : : else 91 : 0 : caps->mbox_off = 0; 92 : : break; 93 : 0 : case NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES: 94 [ # # ]: 0 : if (length != 0) 95 : 0 : caps->mbox_cmsg_types = rte_read32(data); 96 : : break; 97 : 0 : default: 98 [ # # ]: 0 : if (FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr) == 0) 99 : : break; 100 : : 101 : 0 : PMD_DRV_LOG(ERR, "Unknown TLV type: %u offset: %u len: %u", 102 : : tlv_type, offset, length); 103 : 0 : return -EINVAL; 104 : : } 105 : : } 106 : : 107 : : PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV"); 108 : : return -EINVAL; 109 : : }