xref: /dpdk/drivers/net/nfp/nfp_net_ctrl.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
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