xref: /dpdk/drivers/net/hns3/hns3_common.c (revision ac72aae60f71b8716f65d1e2daf531a5ca38c998)
1a4c7152dSHuisong Li /* SPDX-License-Identifier: BSD-3-Clause
2a4c7152dSHuisong Li  * Copyright(C) 2021 HiSilicon Limited
3a4c7152dSHuisong Li  */
4a4c7152dSHuisong Li 
5a4c7152dSHuisong Li #include <rte_kvargs.h>
61f37cb2bSDavid Marchand #include <bus_pci_driver.h>
7247f0ce2SChengwen Feng #include <ethdev_pci.h>
8247f0ce2SChengwen Feng #include <rte_pci.h>
9a4c7152dSHuisong Li 
10247f0ce2SChengwen Feng #include "hns3_logs.h"
11247f0ce2SChengwen Feng #include "hns3_regs.h"
12247f0ce2SChengwen Feng #include "hns3_rxtx.h"
1352a4e960SHuisong Li #include "hns3_dcb.h"
141c757dd5SChengwen Feng #include "hns3_common.h"
15247f0ce2SChengwen Feng 
16247f0ce2SChengwen Feng int
17247f0ce2SChengwen Feng hns3_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
18247f0ce2SChengwen Feng 		    size_t fw_size)
19247f0ce2SChengwen Feng {
20247f0ce2SChengwen Feng 	struct hns3_adapter *hns = eth_dev->data->dev_private;
21247f0ce2SChengwen Feng 	struct hns3_hw *hw = &hns->hw;
22247f0ce2SChengwen Feng 	uint32_t version = hw->fw_version;
23247f0ce2SChengwen Feng 	int ret;
24247f0ce2SChengwen Feng 
25247f0ce2SChengwen Feng 	ret = snprintf(fw_version, fw_size, "%lu.%lu.%lu.%lu",
26247f0ce2SChengwen Feng 		       hns3_get_field(version, HNS3_FW_VERSION_BYTE3_M,
27247f0ce2SChengwen Feng 				      HNS3_FW_VERSION_BYTE3_S),
28247f0ce2SChengwen Feng 		       hns3_get_field(version, HNS3_FW_VERSION_BYTE2_M,
29247f0ce2SChengwen Feng 				      HNS3_FW_VERSION_BYTE2_S),
30247f0ce2SChengwen Feng 		       hns3_get_field(version, HNS3_FW_VERSION_BYTE1_M,
31247f0ce2SChengwen Feng 				      HNS3_FW_VERSION_BYTE1_S),
32247f0ce2SChengwen Feng 		       hns3_get_field(version, HNS3_FW_VERSION_BYTE0_M,
33247f0ce2SChengwen Feng 				      HNS3_FW_VERSION_BYTE0_S));
34247f0ce2SChengwen Feng 	if (ret < 0)
35247f0ce2SChengwen Feng 		return -EINVAL;
36247f0ce2SChengwen Feng 
37247f0ce2SChengwen Feng 	ret += 1; /* add the size of '\0' */
38247f0ce2SChengwen Feng 	if (fw_size < (size_t)ret)
39247f0ce2SChengwen Feng 		return ret;
40247f0ce2SChengwen Feng 	else
41247f0ce2SChengwen Feng 		return 0;
42247f0ce2SChengwen Feng }
43247f0ce2SChengwen Feng 
44247f0ce2SChengwen Feng int
45247f0ce2SChengwen Feng hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
46247f0ce2SChengwen Feng {
47247f0ce2SChengwen Feng 	struct hns3_adapter *hns = eth_dev->data->dev_private;
48247f0ce2SChengwen Feng 	struct hns3_hw *hw = &hns->hw;
49247f0ce2SChengwen Feng 	uint16_t queue_num = hw->tqps_num;
50247f0ce2SChengwen Feng 
51247f0ce2SChengwen Feng 	/*
52247f0ce2SChengwen Feng 	 * In interrupt mode, 'max_rx_queues' is set based on the number of
53247f0ce2SChengwen Feng 	 * MSI-X interrupt resources of the hardware.
54247f0ce2SChengwen Feng 	 */
55247f0ce2SChengwen Feng 	if (hw->data->dev_conf.intr_conf.rxq == 1)
56247f0ce2SChengwen Feng 		queue_num = hw->intr_tqps_num;
57247f0ce2SChengwen Feng 
58247f0ce2SChengwen Feng 	info->max_rx_queues = queue_num;
59247f0ce2SChengwen Feng 	info->max_tx_queues = hw->tqps_num;
60247f0ce2SChengwen Feng 	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
61247f0ce2SChengwen Feng 	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
62a276af95SHuisong Li 	info->max_rx_bufsize = HNS3_MAX_BD_BUF_SIZE;
63247f0ce2SChengwen Feng 	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
64247f0ce2SChengwen Feng 	info->max_lro_pkt_size = HNS3_MAX_LRO_SIZE;
65247f0ce2SChengwen Feng 	info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
66247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
67247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
68247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
69247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
70247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
71247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_SCATTER |
72247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
73247f0ce2SChengwen Feng 				 RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
74a4b2c681SHuisong Li 				 RTE_ETH_RX_OFFLOAD_RSS_HASH);
75247f0ce2SChengwen Feng 	info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
76247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
77247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
78247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
79247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
80247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
81247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_TCP_TSO |
82247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
83247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
84247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |
85247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
86247f0ce2SChengwen Feng 				 RTE_ETH_TX_OFFLOAD_VLAN_INSERT);
87247f0ce2SChengwen Feng 
88f6e79b8dSChengwen Feng 	if (!hns->is_vf && !hw->port_base_vlan_cfg.state)
89247f0ce2SChengwen Feng 		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_QINQ_INSERT;
90247f0ce2SChengwen Feng 
91247f0ce2SChengwen Feng 	if (hns3_dev_get_support(hw, OUTER_UDP_CKSUM))
92247f0ce2SChengwen Feng 		info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
93247f0ce2SChengwen Feng 
9427fd4652SChengwen Feng 	info->dev_capa = RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP |
9527fd4652SChengwen Feng 			 RTE_ETH_DEV_CAPA_FLOW_SHARED_OBJECT_KEEP;
96247f0ce2SChengwen Feng 	if (hns3_dev_get_support(hw, INDEP_TXRX))
9727fd4652SChengwen Feng 		info->dev_capa |= RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
98247f0ce2SChengwen Feng 				  RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
99247f0ce2SChengwen Feng 
100247f0ce2SChengwen Feng 	if (hns3_dev_get_support(hw, PTP))
101247f0ce2SChengwen Feng 		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
102a4b2c681SHuisong Li 	if (hns3_dev_get_support(hw, GRO))
103a4b2c681SHuisong Li 		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
104247f0ce2SChengwen Feng 
105247f0ce2SChengwen Feng 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
106247f0ce2SChengwen Feng 		.nb_max = HNS3_MAX_RING_DESC,
107247f0ce2SChengwen Feng 		.nb_min = HNS3_MIN_RING_DESC,
108247f0ce2SChengwen Feng 		.nb_align = HNS3_ALIGN_RING_DESC,
109247f0ce2SChengwen Feng 	};
110247f0ce2SChengwen Feng 
111247f0ce2SChengwen Feng 	info->tx_desc_lim = (struct rte_eth_desc_lim) {
112247f0ce2SChengwen Feng 		.nb_max = HNS3_MAX_RING_DESC,
113247f0ce2SChengwen Feng 		.nb_min = HNS3_MIN_RING_DESC,
114247f0ce2SChengwen Feng 		.nb_align = HNS3_ALIGN_RING_DESC,
115247f0ce2SChengwen Feng 		.nb_seg_max = HNS3_MAX_TSO_BD_PER_PKT,
116247f0ce2SChengwen Feng 		.nb_mtu_seg_max = hw->max_non_tso_bd_num,
117247f0ce2SChengwen Feng 	};
118247f0ce2SChengwen Feng 
119247f0ce2SChengwen Feng 	info->default_rxconf = (struct rte_eth_rxconf) {
120247f0ce2SChengwen Feng 		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
121247f0ce2SChengwen Feng 		/*
122247f0ce2SChengwen Feng 		 * If there are no available Rx buffer descriptors, incoming
123247f0ce2SChengwen Feng 		 * packets are always dropped by hardware based on hns3 network
124247f0ce2SChengwen Feng 		 * engine.
125247f0ce2SChengwen Feng 		 */
126247f0ce2SChengwen Feng 		.rx_drop_en = 1,
127247f0ce2SChengwen Feng 		.offloads = 0,
128247f0ce2SChengwen Feng 	};
129247f0ce2SChengwen Feng 	info->default_txconf = (struct rte_eth_txconf) {
130247f0ce2SChengwen Feng 		.tx_rs_thresh = HNS3_DEFAULT_TX_RS_THRESH,
131247f0ce2SChengwen Feng 		.offloads = 0,
132247f0ce2SChengwen Feng 	};
133247f0ce2SChengwen Feng 
134247f0ce2SChengwen Feng 	info->reta_size = hw->rss_ind_tbl_size;
1355172f9c4SHuisong Li 	info->hash_key_size = hw->rss_key_size;
136247f0ce2SChengwen Feng 	info->flow_type_rss_offloads = HNS3_ETH_RSS_SUPPORT;
13736b0b4fdSJie Hai 	info->rss_algo_capa = RTE_ETH_HASH_ALGO_CAPA_MASK(DEFAULT) |
13836b0b4fdSJie Hai 			      RTE_ETH_HASH_ALGO_CAPA_MASK(TOEPLITZ) |
13936b0b4fdSJie Hai 			      RTE_ETH_HASH_ALGO_CAPA_MASK(SIMPLE_XOR) |
14036b0b4fdSJie Hai 			      RTE_ETH_HASH_ALGO_CAPA_MASK(SYMMETRIC_TOEPLITZ);
141247f0ce2SChengwen Feng 
142247f0ce2SChengwen Feng 	info->default_rxportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
143247f0ce2SChengwen Feng 	info->default_txportconf.burst_size = HNS3_DEFAULT_PORT_CONF_BURST_SIZE;
144247f0ce2SChengwen Feng 	info->default_rxportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
145247f0ce2SChengwen Feng 	info->default_txportconf.nb_queues = HNS3_DEFAULT_PORT_CONF_QUEUES_NUM;
146247f0ce2SChengwen Feng 	info->default_rxportconf.ring_size = HNS3_DEFAULT_RING_DESC;
147247f0ce2SChengwen Feng 	info->default_txportconf.ring_size = HNS3_DEFAULT_RING_DESC;
148247f0ce2SChengwen Feng 
149247f0ce2SChengwen Feng 	/*
150247f0ce2SChengwen Feng 	 * Next is the PF/VF difference section.
151247f0ce2SChengwen Feng 	 */
152247f0ce2SChengwen Feng 	if (!hns->is_vf) {
153247f0ce2SChengwen Feng 		info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
154247f0ce2SChengwen Feng 		info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
155247f0ce2SChengwen Feng 		info->speed_capa = hns3_get_speed_capa(hw);
156247f0ce2SChengwen Feng 	} else {
157247f0ce2SChengwen Feng 		info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
158247f0ce2SChengwen Feng 	}
159247f0ce2SChengwen Feng 
16053688fc9SChengwen Feng 	info->err_handle_mode = RTE_ETH_ERROR_HANDLE_MODE_PROACTIVE;
16153688fc9SChengwen Feng 
162247f0ce2SChengwen Feng 	return 0;
163247f0ce2SChengwen Feng }
164a4c7152dSHuisong Li 
165a4c7152dSHuisong Li static int
166a4c7152dSHuisong Li hns3_parse_io_hint_func(const char *key, const char *value, void *extra_args)
167a4c7152dSHuisong Li {
168a4c7152dSHuisong Li 	uint32_t hint = HNS3_IO_FUNC_HINT_NONE;
169a4c7152dSHuisong Li 
170a4c7152dSHuisong Li 	RTE_SET_USED(key);
171a4c7152dSHuisong Li 
1728e9bd299SChengwen Feng 	if (value == NULL || extra_args == NULL)
1738e9bd299SChengwen Feng 		return 0;
1748e9bd299SChengwen Feng 
175a4c7152dSHuisong Li 	if (strcmp(value, "vec") == 0)
176a4c7152dSHuisong Li 		hint = HNS3_IO_FUNC_HINT_VEC;
177a4c7152dSHuisong Li 	else if (strcmp(value, "sve") == 0)
178a4c7152dSHuisong Li 		hint = HNS3_IO_FUNC_HINT_SVE;
179a4c7152dSHuisong Li 	else if (strcmp(value, "simple") == 0)
180a4c7152dSHuisong Li 		hint = HNS3_IO_FUNC_HINT_SIMPLE;
181a4c7152dSHuisong Li 	else if (strcmp(value, "common") == 0)
182a4c7152dSHuisong Li 		hint = HNS3_IO_FUNC_HINT_COMMON;
183a4c7152dSHuisong Li 
184a4c7152dSHuisong Li 	/* If the hint is valid then update output parameters */
185a4c7152dSHuisong Li 	if (hint != HNS3_IO_FUNC_HINT_NONE)
186a4c7152dSHuisong Li 		*(uint32_t *)extra_args = hint;
187a4c7152dSHuisong Li 
188a4c7152dSHuisong Li 	return 0;
189a4c7152dSHuisong Li }
190a4c7152dSHuisong Li 
191a4c7152dSHuisong Li static const char *
192a4c7152dSHuisong Li hns3_get_io_hint_func_name(uint32_t hint)
193a4c7152dSHuisong Li {
194a4c7152dSHuisong Li 	switch (hint) {
195a4c7152dSHuisong Li 	case HNS3_IO_FUNC_HINT_VEC:
196a4c7152dSHuisong Li 		return "vec";
197a4c7152dSHuisong Li 	case HNS3_IO_FUNC_HINT_SVE:
198a4c7152dSHuisong Li 		return "sve";
199a4c7152dSHuisong Li 	case HNS3_IO_FUNC_HINT_SIMPLE:
200a4c7152dSHuisong Li 		return "simple";
201a4c7152dSHuisong Li 	case HNS3_IO_FUNC_HINT_COMMON:
202a4c7152dSHuisong Li 		return "common";
203a4c7152dSHuisong Li 	default:
204a4c7152dSHuisong Li 		return "none";
205a4c7152dSHuisong Li 	}
206a4c7152dSHuisong Li }
207a4c7152dSHuisong Li 
208a4c7152dSHuisong Li static int
209a4c7152dSHuisong Li hns3_parse_dev_caps_mask(const char *key, const char *value, void *extra_args)
210a4c7152dSHuisong Li {
211a4c7152dSHuisong Li 	uint64_t val;
212a4c7152dSHuisong Li 
213a4c7152dSHuisong Li 	RTE_SET_USED(key);
214a4c7152dSHuisong Li 
2158e9bd299SChengwen Feng 	if (value == NULL || extra_args == NULL)
2168e9bd299SChengwen Feng 		return 0;
2178e9bd299SChengwen Feng 
218e6a27020SHuisong Li 	val = strtoull(value, NULL, HNS3_CONVERT_TO_HEXADECIMAL);
219a4c7152dSHuisong Li 	*(uint64_t *)extra_args = val;
220a4c7152dSHuisong Li 
221a4c7152dSHuisong Li 	return 0;
222a4c7152dSHuisong Li }
223a4c7152dSHuisong Li 
224a4c7152dSHuisong Li static int
225a4c7152dSHuisong Li hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
226a4c7152dSHuisong Li {
227d7a0698cSDengdui Huang 	uint64_t val;
228a4c7152dSHuisong Li 
229a4c7152dSHuisong Li 	RTE_SET_USED(key);
230a4c7152dSHuisong Li 
2318e9bd299SChengwen Feng 	if (value == NULL || extra_args == NULL)
2328e9bd299SChengwen Feng 		return 0;
2338e9bd299SChengwen Feng 
234e6a27020SHuisong Li 	val = strtoul(value, NULL, HNS3_CONVERT_TO_DECIMAL);
235247f0ce2SChengwen Feng 
236247f0ce2SChengwen Feng 	/*
237247f0ce2SChengwen Feng 	 * 500ms is empirical value in process of mailbox communication. If
238247f0ce2SChengwen Feng 	 * the delay value is set to one lower than the empirical value, mailbox
239247f0ce2SChengwen Feng 	 * communication may fail.
240247f0ce2SChengwen Feng 	 */
241a4c7152dSHuisong Li 	if (val > HNS3_MBX_DEF_TIME_LIMIT_MS && val <= UINT16_MAX)
242a4c7152dSHuisong Li 		*(uint16_t *)extra_args = val;
243a4c7152dSHuisong Li 
244a4c7152dSHuisong Li 	return 0;
245a4c7152dSHuisong Li }
246a4c7152dSHuisong Li 
24706b9ee34SHuisong Li static int
24806b9ee34SHuisong Li hns3_parse_vlan_match_mode(const char *key, const char *value, void *args)
24906b9ee34SHuisong Li {
25006b9ee34SHuisong Li 	uint8_t mode;
25106b9ee34SHuisong Li 
25206b9ee34SHuisong Li 	RTE_SET_USED(key);
25306b9ee34SHuisong Li 
25406b9ee34SHuisong Li 	if (value == NULL) {
25506b9ee34SHuisong Li 		PMD_INIT_LOG(WARNING, "no value for key:\"%s\"", key);
25606b9ee34SHuisong Li 		return -1;
25706b9ee34SHuisong Li 	}
25806b9ee34SHuisong Li 
25906b9ee34SHuisong Li 	if (strcmp(value, "strict") == 0) {
26006b9ee34SHuisong Li 		mode = HNS3_FDIR_VLAN_STRICT_MATCH;
26106b9ee34SHuisong Li 	} else if (strcmp(value, "nostrict") == 0) {
26206b9ee34SHuisong Li 		mode = HNS3_FDIR_VLAN_NOSTRICT_MATCH;
26306b9ee34SHuisong Li 	} else {
26406b9ee34SHuisong Li 		PMD_INIT_LOG(WARNING, "invalid value:\"%s\" for key:\"%s\", "
26506b9ee34SHuisong Li 			"value must be 'strict' or 'nostrict'",
26606b9ee34SHuisong Li 			value, key);
26706b9ee34SHuisong Li 		return -1;
26806b9ee34SHuisong Li 	}
26906b9ee34SHuisong Li 
27006b9ee34SHuisong Li 	*(uint8_t *)args = mode;
27106b9ee34SHuisong Li 
27206b9ee34SHuisong Li 	return 0;
27306b9ee34SHuisong Li }
27406b9ee34SHuisong Li 
275a4732847SChengwen Feng static int
276a4732847SChengwen Feng hns3_parse_fdir_tuple_config(const char *key, const char *value, void *args)
277a4732847SChengwen Feng {
278a4732847SChengwen Feng 	enum hns3_fdir_tuple_config tuple_cfg;
279a4732847SChengwen Feng 
280a4732847SChengwen Feng 	tuple_cfg = hns3_parse_tuple_config(value);
281a4732847SChengwen Feng 	if (tuple_cfg == HNS3_FDIR_TUPLE_CONFIG_DEFAULT ||
282a4732847SChengwen Feng 	    tuple_cfg == HNS3_FDIR_TUPLE_CONFIG_BUTT) {
283a4732847SChengwen Feng 		PMD_INIT_LOG(WARNING, "invalid value:\"%s\" for key:\"%s\"",
284a4732847SChengwen Feng 			     value, key);
285a4732847SChengwen Feng 		return -1;
286a4732847SChengwen Feng 	}
287a4732847SChengwen Feng 
288a4732847SChengwen Feng 	*(enum hns3_fdir_tuple_config *)args = tuple_cfg;
289a4732847SChengwen Feng 
290a4732847SChengwen Feng 	return 0;
291a4732847SChengwen Feng }
292a4732847SChengwen Feng 
293*ac72aae6SDengdui Huang static int
294*ac72aae6SDengdui Huang hns3_parse_fdir_index_config(const char *key, const char *value, void *args)
295*ac72aae6SDengdui Huang {
296*ac72aae6SDengdui Huang 	enum hns3_fdir_index_config cfg;
297*ac72aae6SDengdui Huang 
298*ac72aae6SDengdui Huang 	if (strcmp(value, "hash") == 0) {
299*ac72aae6SDengdui Huang 		cfg  = HNS3_FDIR_INDEX_CONFIG_HASH;
300*ac72aae6SDengdui Huang 	} else if (strcmp(value, "priority") == 0) {
301*ac72aae6SDengdui Huang 		cfg  = HNS3_FDIR_INDEX_CONFIG_PRIORITY;
302*ac72aae6SDengdui Huang 	} else {
303*ac72aae6SDengdui Huang 		PMD_INIT_LOG(WARNING, "invalid value:\"%s\" for key:\"%s\", "
304*ac72aae6SDengdui Huang 			"value must be 'hash' or 'priority'",
305*ac72aae6SDengdui Huang 			value, key);
306*ac72aae6SDengdui Huang 		return -1;
307*ac72aae6SDengdui Huang 	}
308*ac72aae6SDengdui Huang 
309*ac72aae6SDengdui Huang 	*(enum hns3_fdir_index_config *)args = cfg;
310*ac72aae6SDengdui Huang 
311*ac72aae6SDengdui Huang 	return 0;
312*ac72aae6SDengdui Huang }
313*ac72aae6SDengdui Huang 
314a4c7152dSHuisong Li void
315a4c7152dSHuisong Li hns3_parse_devargs(struct rte_eth_dev *dev)
316a4c7152dSHuisong Li {
317a4c7152dSHuisong Li 	uint16_t mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
318a4c7152dSHuisong Li 	struct hns3_adapter *hns = dev->data->dev_private;
319a4c7152dSHuisong Li 	uint32_t rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
320a4c7152dSHuisong Li 	uint32_t tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
321a4c7152dSHuisong Li 	struct hns3_hw *hw = &hns->hw;
322a4c7152dSHuisong Li 	uint64_t dev_caps_mask = 0;
323a4c7152dSHuisong Li 	struct rte_kvargs *kvlist;
3245a2b22b4SHuisong Li 
3255a2b22b4SHuisong Li 	/* Set default value of runtime config parameters. */
3265a2b22b4SHuisong Li 	hns->rx_func_hint = HNS3_IO_FUNC_HINT_NONE;
3275a2b22b4SHuisong Li 	hns->tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
3285a2b22b4SHuisong Li 	hns->dev_caps_mask = 0;
3295a2b22b4SHuisong Li 	hns->mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
33006b9ee34SHuisong Li 	if (!hns->is_vf)
33106b9ee34SHuisong Li 		hns->pf.fdir.vlan_match_mode = HNS3_FDIR_VLAN_STRICT_MATCH;
332a4c7152dSHuisong Li 
333a4c7152dSHuisong Li 	if (dev->device->devargs == NULL)
334a4c7152dSHuisong Li 		return;
335a4c7152dSHuisong Li 
336a4c7152dSHuisong Li 	kvlist = rte_kvargs_parse(dev->device->devargs->args, NULL);
337a4c7152dSHuisong Li 	if (!kvlist)
338a4c7152dSHuisong Li 		return;
339a4c7152dSHuisong Li 
340a4c7152dSHuisong Li 	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_RX_FUNC_HINT,
341a4c7152dSHuisong Li 			   &hns3_parse_io_hint_func, &rx_func_hint);
342a4c7152dSHuisong Li 	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_TX_FUNC_HINT,
343a4c7152dSHuisong Li 			   &hns3_parse_io_hint_func, &tx_func_hint);
344a4c7152dSHuisong Li 	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_DEV_CAPS_MASK,
345a4c7152dSHuisong Li 			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
346a4c7152dSHuisong Li 	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
347a4c7152dSHuisong Li 			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
348a4732847SChengwen Feng 	if (!hns->is_vf) {
34906b9ee34SHuisong Li 		(void)rte_kvargs_process(kvlist,
350bf16032eSChengwen Feng 					 HNS3_DEVARG_FDIR_VLAN_MATCH_MODE,
35106b9ee34SHuisong Li 					 &hns3_parse_vlan_match_mode,
35206b9ee34SHuisong Li 					 &hns->pf.fdir.vlan_match_mode);
353a4732847SChengwen Feng 		(void)rte_kvargs_process(kvlist,
354a4732847SChengwen Feng 					 HNS3_DEVARG_FDIR_TUPLE_CONFIG,
355a4732847SChengwen Feng 					 &hns3_parse_fdir_tuple_config,
356a4732847SChengwen Feng 					 &hns->pf.fdir.tuple_cfg);
357*ac72aae6SDengdui Huang 		(void)rte_kvargs_process(kvlist,
358*ac72aae6SDengdui Huang 					 HNS3_DEVARG_FDIR_INDEX_CONFIG,
359*ac72aae6SDengdui Huang 					 &hns3_parse_fdir_index_config,
360*ac72aae6SDengdui Huang 					 &hns->pf.fdir.index_cfg);
361a4732847SChengwen Feng 	}
362a4c7152dSHuisong Li 
363a4c7152dSHuisong Li 	rte_kvargs_free(kvlist);
364a4c7152dSHuisong Li 
365a4c7152dSHuisong Li 	if (rx_func_hint != HNS3_IO_FUNC_HINT_NONE)
366a4c7152dSHuisong Li 		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_RX_FUNC_HINT,
367a4c7152dSHuisong Li 			  hns3_get_io_hint_func_name(rx_func_hint));
368a4c7152dSHuisong Li 	hns->rx_func_hint = rx_func_hint;
369a4c7152dSHuisong Li 	if (tx_func_hint != HNS3_IO_FUNC_HINT_NONE)
370a4c7152dSHuisong Li 		hns3_warn(hw, "parsed %s = %s.", HNS3_DEVARG_TX_FUNC_HINT,
371a4c7152dSHuisong Li 			  hns3_get_io_hint_func_name(tx_func_hint));
372a4c7152dSHuisong Li 	hns->tx_func_hint = tx_func_hint;
373a4c7152dSHuisong Li 
374a4c7152dSHuisong Li 	if (dev_caps_mask != 0)
375a4c7152dSHuisong Li 		hns3_warn(hw, "parsed %s = 0x%" PRIx64 ".",
376a4c7152dSHuisong Li 			  HNS3_DEVARG_DEV_CAPS_MASK, dev_caps_mask);
377a4c7152dSHuisong Li 	hns->dev_caps_mask = dev_caps_mask;
378247f0ce2SChengwen Feng 
379247f0ce2SChengwen Feng 	if (mbx_time_limit_ms != HNS3_MBX_DEF_TIME_LIMIT_MS)
380247f0ce2SChengwen Feng 		hns3_warn(hw, "parsed %s = %u.", HNS3_DEVARG_MBX_TIME_LIMIT_MS,
381247f0ce2SChengwen Feng 				mbx_time_limit_ms);
382247f0ce2SChengwen Feng 	hns->mbx_time_limit_ms = mbx_time_limit_ms;
383a4c7152dSHuisong Li }
384a4c7152dSHuisong Li 
385a4c7152dSHuisong Li void
386a4c7152dSHuisong Li hns3_clock_gettime(struct timeval *tv)
387a4c7152dSHuisong Li {
388a4c7152dSHuisong Li #ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
389a4c7152dSHuisong Li #define CLOCK_TYPE CLOCK_MONOTONIC_RAW
390a4c7152dSHuisong Li #else
391a4c7152dSHuisong Li #define CLOCK_TYPE CLOCK_MONOTONIC
392a4c7152dSHuisong Li #endif
393a4c7152dSHuisong Li #define NSEC_TO_USEC_DIV 1000
394a4c7152dSHuisong Li 
395a4c7152dSHuisong Li 	struct timespec spec;
396a4c7152dSHuisong Li 	(void)clock_gettime(CLOCK_TYPE, &spec);
397a4c7152dSHuisong Li 
398a4c7152dSHuisong Li 	tv->tv_sec = spec.tv_sec;
399a4c7152dSHuisong Li 	tv->tv_usec = spec.tv_nsec / NSEC_TO_USEC_DIV;
400a4c7152dSHuisong Li }
401a4c7152dSHuisong Li 
402a4c7152dSHuisong Li uint64_t
403a4c7152dSHuisong Li hns3_clock_calctime_ms(struct timeval *tv)
404a4c7152dSHuisong Li {
405a4c7152dSHuisong Li 	return (uint64_t)tv->tv_sec * MSEC_PER_SEC +
406a4c7152dSHuisong Li 		tv->tv_usec / USEC_PER_MSEC;
407a4c7152dSHuisong Li }
408a4c7152dSHuisong Li 
409a4c7152dSHuisong Li uint64_t
410a4c7152dSHuisong Li hns3_clock_gettime_ms(void)
411a4c7152dSHuisong Li {
412a4c7152dSHuisong Li 	struct timeval tv;
413a4c7152dSHuisong Li 
414a4c7152dSHuisong Li 	hns3_clock_gettime(&tv);
415a4c7152dSHuisong Li 	return hns3_clock_calctime_ms(&tv);
416a4c7152dSHuisong Li }
417a4c7152dSHuisong Li 
418a4c7152dSHuisong Li void hns3_ether_format_addr(char *buf, uint16_t size,
419a4c7152dSHuisong Li 			    const struct rte_ether_addr *ether_addr)
420a4c7152dSHuisong Li {
421f2d91cfbSHuisong Li 	(void)snprintf(buf, size, "%02X:**:**:**:%02X:%02X",
422a4c7152dSHuisong Li 			ether_addr->addr_bytes[0],
423a4c7152dSHuisong Li 			ether_addr->addr_bytes[4],
424a4c7152dSHuisong Li 			ether_addr->addr_bytes[5]);
425a4c7152dSHuisong Li }
426a4c7152dSHuisong Li 
427a4c7152dSHuisong Li static int
428a4c7152dSHuisong Li hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
429a4c7152dSHuisong Li 			   struct rte_ether_addr *mc_addr_set,
430a4c7152dSHuisong Li 			   uint32_t nb_mc_addr)
431a4c7152dSHuisong Li {
432a4c7152dSHuisong Li 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
433a4c7152dSHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
434a4c7152dSHuisong Li 	struct rte_ether_addr *addr;
435a4c7152dSHuisong Li 	uint16_t mac_addrs_capa;
436a4c7152dSHuisong Li 	uint32_t i;
437a4c7152dSHuisong Li 	uint32_t j;
438a4c7152dSHuisong Li 
439a4c7152dSHuisong Li 	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
440a4c7152dSHuisong Li 		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%u) "
441a4c7152dSHuisong Li 			 "invalid. valid range: 0~%d",
442a4c7152dSHuisong Li 			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
443c8cd8853SDengdui Huang 		return -ENOSPC;
444a4c7152dSHuisong Li 	}
445a4c7152dSHuisong Li 
446a4c7152dSHuisong Li 	/* Check if input mac addresses are valid */
447a4c7152dSHuisong Li 	for (i = 0; i < nb_mc_addr; i++) {
448a4c7152dSHuisong Li 		addr = &mc_addr_set[i];
449a4c7152dSHuisong Li 		if (!rte_is_multicast_ether_addr(addr)) {
450a4c7152dSHuisong Li 			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
451a4c7152dSHuisong Li 					      addr);
452a4c7152dSHuisong Li 			hns3_err(hw,
453a4c7152dSHuisong Li 				 "failed to set mc mac addr, addr(%s) invalid.",
454a4c7152dSHuisong Li 				 mac_str);
455a4c7152dSHuisong Li 			return -EINVAL;
456a4c7152dSHuisong Li 		}
457a4c7152dSHuisong Li 
458a4c7152dSHuisong Li 		/* Check if there are duplicate addresses */
459a4c7152dSHuisong Li 		for (j = i + 1; j < nb_mc_addr; j++) {
460a4c7152dSHuisong Li 			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
461a4c7152dSHuisong Li 				hns3_ether_format_addr(mac_str,
462a4c7152dSHuisong Li 						      RTE_ETHER_ADDR_FMT_SIZE,
463a4c7152dSHuisong Li 						      addr);
464a4c7152dSHuisong Li 				hns3_err(hw, "failed to set mc mac addr, "
465a4c7152dSHuisong Li 					 "addrs invalid. two same addrs(%s).",
466a4c7152dSHuisong Li 					 mac_str);
467a4c7152dSHuisong Li 				return -EINVAL;
468a4c7152dSHuisong Li 			}
469a4c7152dSHuisong Li 		}
470a4c7152dSHuisong Li 
471a4c7152dSHuisong Li 		/*
472a4c7152dSHuisong Li 		 * Check if there are duplicate addresses between mac_addrs
473a4c7152dSHuisong Li 		 * and mc_addr_set
474a4c7152dSHuisong Li 		 */
475a4c7152dSHuisong Li 		mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
476a4c7152dSHuisong Li 					      HNS3_UC_MACADDR_NUM;
477a4c7152dSHuisong Li 		for (j = 0; j < mac_addrs_capa; j++) {
478a4c7152dSHuisong Li 			if (rte_is_same_ether_addr(addr,
479a4c7152dSHuisong Li 						   &hw->data->mac_addrs[j])) {
480a4c7152dSHuisong Li 				hns3_ether_format_addr(mac_str,
481a4c7152dSHuisong Li 						       RTE_ETHER_ADDR_FMT_SIZE,
482a4c7152dSHuisong Li 						       addr);
483a4c7152dSHuisong Li 				hns3_err(hw, "failed to set mc mac addr, "
484a4c7152dSHuisong Li 					 "addrs invalid. addrs(%s) has already "
485a4c7152dSHuisong Li 					 "configured in mac_addr add API",
486a4c7152dSHuisong Li 					 mac_str);
487a4c7152dSHuisong Li 				return -EINVAL;
488a4c7152dSHuisong Li 			}
489a4c7152dSHuisong Li 		}
490a4c7152dSHuisong Li 	}
491a4c7152dSHuisong Li 
492a4c7152dSHuisong Li 	return 0;
493a4c7152dSHuisong Li }
494a4c7152dSHuisong Li 
495a4c7152dSHuisong Li int
496a4c7152dSHuisong Li hns3_set_mc_mac_addr_list(struct rte_eth_dev *dev,
497a4c7152dSHuisong Li 			  struct rte_ether_addr *mc_addr_set,
498a4c7152dSHuisong Li 			  uint32_t nb_mc_addr)
499a4c7152dSHuisong Li {
500a4c7152dSHuisong Li 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
50149d1ab20SDengdui Huang 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
502a4c7152dSHuisong Li 	struct rte_ether_addr *addr;
503a4c7152dSHuisong Li 	int cur_addr_num;
504a4c7152dSHuisong Li 	int set_addr_num;
505a4c7152dSHuisong Li 	int num;
506a4c7152dSHuisong Li 	int ret;
507a4c7152dSHuisong Li 	int i;
508a4c7152dSHuisong Li 
50949d1ab20SDengdui Huang 	if (mc_addr_set == NULL || nb_mc_addr == 0) {
51049d1ab20SDengdui Huang 		rte_spinlock_lock(&hw->lock);
51149d1ab20SDengdui Huang 		ret = hns3_configure_all_mc_mac_addr(hns, true);
51249d1ab20SDengdui Huang 		if (ret == 0)
51349d1ab20SDengdui Huang 			hw->mc_addrs_num = 0;
51449d1ab20SDengdui Huang 		rte_spinlock_unlock(&hw->lock);
51549d1ab20SDengdui Huang 		return ret;
51649d1ab20SDengdui Huang 	}
51749d1ab20SDengdui Huang 
518a4c7152dSHuisong Li 	/* Check if input parameters are valid */
519a4c7152dSHuisong Li 	ret = hns3_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
520a4c7152dSHuisong Li 	if (ret)
521a4c7152dSHuisong Li 		return ret;
522a4c7152dSHuisong Li 
523a4c7152dSHuisong Li 	rte_spinlock_lock(&hw->lock);
524a4c7152dSHuisong Li 	cur_addr_num = hw->mc_addrs_num;
525a4c7152dSHuisong Li 	for (i = 0; i < cur_addr_num; i++) {
526a4c7152dSHuisong Li 		num = cur_addr_num - i - 1;
527a4c7152dSHuisong Li 		addr = &hw->mc_addrs[num];
528a4c7152dSHuisong Li 		ret = hw->ops.del_mc_mac_addr(hw, addr);
529a4c7152dSHuisong Li 		if (ret) {
530a4c7152dSHuisong Li 			rte_spinlock_unlock(&hw->lock);
531a4c7152dSHuisong Li 			return ret;
532a4c7152dSHuisong Li 		}
533a4c7152dSHuisong Li 
534a4c7152dSHuisong Li 		hw->mc_addrs_num--;
535a4c7152dSHuisong Li 	}
536a4c7152dSHuisong Li 
537a4c7152dSHuisong Li 	set_addr_num = (int)nb_mc_addr;
538a4c7152dSHuisong Li 	for (i = 0; i < set_addr_num; i++) {
539a4c7152dSHuisong Li 		addr = &mc_addr_set[i];
540a4c7152dSHuisong Li 		ret = hw->ops.add_mc_mac_addr(hw, addr);
541a4c7152dSHuisong Li 		if (ret) {
542a4c7152dSHuisong Li 			rte_spinlock_unlock(&hw->lock);
543a4c7152dSHuisong Li 			return ret;
544a4c7152dSHuisong Li 		}
545a4c7152dSHuisong Li 
546a4c7152dSHuisong Li 		rte_ether_addr_copy(addr, &hw->mc_addrs[hw->mc_addrs_num]);
547a4c7152dSHuisong Li 		hw->mc_addrs_num++;
548a4c7152dSHuisong Li 	}
549a4c7152dSHuisong Li 	rte_spinlock_unlock(&hw->lock);
550a4c7152dSHuisong Li 
551a4c7152dSHuisong Li 	return 0;
552a4c7152dSHuisong Li }
553a4c7152dSHuisong Li 
554a4c7152dSHuisong Li int
555a4c7152dSHuisong Li hns3_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
556a4c7152dSHuisong Li {
557a4c7152dSHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
558a4c7152dSHuisong Li 	struct hns3_hw *hw = &hns->hw;
559a4c7152dSHuisong Li 	struct rte_ether_addr *addr;
560a4c7152dSHuisong Li 	int ret = 0;
561a4c7152dSHuisong Li 	int i;
562a4c7152dSHuisong Li 
563a4c7152dSHuisong Li 	for (i = 0; i < hw->mc_addrs_num; i++) {
564a4c7152dSHuisong Li 		addr = &hw->mc_addrs[i];
565a4c7152dSHuisong Li 		if (!rte_is_multicast_ether_addr(addr))
566a4c7152dSHuisong Li 			continue;
567a4c7152dSHuisong Li 		if (del)
568a4c7152dSHuisong Li 			ret = hw->ops.del_mc_mac_addr(hw, addr);
569a4c7152dSHuisong Li 		else
570a4c7152dSHuisong Li 			ret = hw->ops.add_mc_mac_addr(hw, addr);
571a4c7152dSHuisong Li 		if (ret) {
572a4c7152dSHuisong Li 			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
573a4c7152dSHuisong Li 					      addr);
574a4c7152dSHuisong Li 			hns3_dbg(hw, "failed to %s mc mac addr: %s ret = %d",
575a4c7152dSHuisong Li 				 del ? "Remove" : "Restore", mac_str, ret);
576a4c7152dSHuisong Li 		}
577a4c7152dSHuisong Li 	}
578a4c7152dSHuisong Li 	return ret;
579a4c7152dSHuisong Li }
580a4c7152dSHuisong Li 
581a4c7152dSHuisong Li int
582a4c7152dSHuisong Li hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
583a4c7152dSHuisong Li {
584a4c7152dSHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
585a4c7152dSHuisong Li 	struct hns3_hw *hw = &hns->hw;
586a4c7152dSHuisong Li 	struct hns3_hw_ops *ops = &hw->ops;
587a4c7152dSHuisong Li 	struct rte_ether_addr *addr;
588a4c7152dSHuisong Li 	uint16_t mac_addrs_capa;
589a4c7152dSHuisong Li 	int ret = 0;
59067d01034SHuisong Li 	uint16_t i;
591a4c7152dSHuisong Li 
592a4c7152dSHuisong Li 	mac_addrs_capa =
593a4c7152dSHuisong Li 		hns->is_vf ? HNS3_VF_UC_MACADDR_NUM : HNS3_UC_MACADDR_NUM;
594a4c7152dSHuisong Li 	for (i = 0; i < mac_addrs_capa; i++) {
595a4c7152dSHuisong Li 		addr = &hw->data->mac_addrs[i];
596a4c7152dSHuisong Li 		if (rte_is_zero_ether_addr(addr))
597a4c7152dSHuisong Li 			continue;
598a4c7152dSHuisong Li 		if (rte_is_multicast_ether_addr(addr))
599a4c7152dSHuisong Li 			ret = del ? ops->del_mc_mac_addr(hw, addr) :
600a4c7152dSHuisong Li 			      ops->add_mc_mac_addr(hw, addr);
601a4c7152dSHuisong Li 		else
602a4c7152dSHuisong Li 			ret = del ? ops->del_uc_mac_addr(hw, addr) :
603a4c7152dSHuisong Li 			      ops->add_uc_mac_addr(hw, addr);
604a4c7152dSHuisong Li 
605a4c7152dSHuisong Li 		if (ret) {
606a4c7152dSHuisong Li 			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
607a4c7152dSHuisong Li 					       addr);
60882c2ca6dSMin Hu (Connor) 			hns3_err(hw, "failed to %s mac addr(%s) index:%u ret = %d.",
609a4c7152dSHuisong Li 				 del ? "remove" : "restore", mac_str, i, ret);
610a4c7152dSHuisong Li 		}
611a4c7152dSHuisong Li 	}
612a4c7152dSHuisong Li 
613a4c7152dSHuisong Li 	return ret;
614a4c7152dSHuisong Li }
615a4c7152dSHuisong Li 
616a4c7152dSHuisong Li static bool
617a4c7152dSHuisong Li hns3_find_duplicate_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mc_addr)
618a4c7152dSHuisong Li {
619a4c7152dSHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
620a4c7152dSHuisong Li 	struct rte_ether_addr *addr;
621a4c7152dSHuisong Li 	int i;
622a4c7152dSHuisong Li 
623a4c7152dSHuisong Li 	for (i = 0; i < hw->mc_addrs_num; i++) {
624a4c7152dSHuisong Li 		addr = &hw->mc_addrs[i];
625a4c7152dSHuisong Li 		/* Check if there are duplicate addresses in mc_addrs[] */
626a4c7152dSHuisong Li 		if (rte_is_same_ether_addr(addr, mc_addr)) {
627a4c7152dSHuisong Li 			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
628a4c7152dSHuisong Li 					       addr);
629a4c7152dSHuisong Li 			hns3_err(hw, "failed to add mc mac addr, same addrs"
630a4c7152dSHuisong Li 				 "(%s) is added by the set_mc_mac_addr_list "
631a4c7152dSHuisong Li 				 "API", mac_str);
632a4c7152dSHuisong Li 			return true;
633a4c7152dSHuisong Li 		}
634a4c7152dSHuisong Li 	}
635a4c7152dSHuisong Li 
636a4c7152dSHuisong Li 	return false;
637a4c7152dSHuisong Li }
638a4c7152dSHuisong Li 
639a4c7152dSHuisong Li int
640a4c7152dSHuisong Li hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
641a4c7152dSHuisong Li 		  __rte_unused uint32_t idx, __rte_unused uint32_t pool)
642a4c7152dSHuisong Li {
643a4c7152dSHuisong Li 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
644a4c7152dSHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
645a4c7152dSHuisong Li 	int ret;
646a4c7152dSHuisong Li 
647a4c7152dSHuisong Li 	rte_spinlock_lock(&hw->lock);
648a4c7152dSHuisong Li 
649a4c7152dSHuisong Li 	/*
650a4c7152dSHuisong Li 	 * In hns3 network engine adding UC and MC mac address with different
651a4c7152dSHuisong Li 	 * commands with firmware. We need to determine whether the input
652a4c7152dSHuisong Li 	 * address is a UC or a MC address to call different commands.
653a4c7152dSHuisong Li 	 * By the way, it is recommended calling the API function named
654a4c7152dSHuisong Li 	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
655a4c7152dSHuisong Li 	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
656a4c7152dSHuisong Li 	 * may affect the specifications of UC mac addresses.
657a4c7152dSHuisong Li 	 */
658a4c7152dSHuisong Li 	if (rte_is_multicast_ether_addr(mac_addr)) {
659a4c7152dSHuisong Li 		if (hns3_find_duplicate_mc_addr(hw, mac_addr)) {
660a4c7152dSHuisong Li 			rte_spinlock_unlock(&hw->lock);
661a4c7152dSHuisong Li 			return -EINVAL;
662a4c7152dSHuisong Li 		}
663a4c7152dSHuisong Li 		ret = hw->ops.add_mc_mac_addr(hw, mac_addr);
664a4c7152dSHuisong Li 	} else {
665a4c7152dSHuisong Li 		ret = hw->ops.add_uc_mac_addr(hw, mac_addr);
666a4c7152dSHuisong Li 	}
667a4c7152dSHuisong Li 	rte_spinlock_unlock(&hw->lock);
668a4c7152dSHuisong Li 	if (ret) {
669a4c7152dSHuisong Li 		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
670a4c7152dSHuisong Li 				      mac_addr);
671a4c7152dSHuisong Li 		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
672a4c7152dSHuisong Li 			 ret);
673a4c7152dSHuisong Li 	}
674a4c7152dSHuisong Li 
675a4c7152dSHuisong Li 	return ret;
676a4c7152dSHuisong Li }
677a4c7152dSHuisong Li 
678a4c7152dSHuisong Li void
679a4c7152dSHuisong Li hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
680a4c7152dSHuisong Li {
681a4c7152dSHuisong Li 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
682a4c7152dSHuisong Li 	/* index will be checked by upper level rte interface */
683a4c7152dSHuisong Li 	struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[idx];
684a4c7152dSHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
685a4c7152dSHuisong Li 	int ret;
686a4c7152dSHuisong Li 
687a4c7152dSHuisong Li 	rte_spinlock_lock(&hw->lock);
688a4c7152dSHuisong Li 
689a4c7152dSHuisong Li 	if (rte_is_multicast_ether_addr(mac_addr))
690a4c7152dSHuisong Li 		ret = hw->ops.del_mc_mac_addr(hw, mac_addr);
691a4c7152dSHuisong Li 	else
692a4c7152dSHuisong Li 		ret = hw->ops.del_uc_mac_addr(hw, mac_addr);
693a4c7152dSHuisong Li 	rte_spinlock_unlock(&hw->lock);
694a4c7152dSHuisong Li 	if (ret) {
695a4c7152dSHuisong Li 		hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
696a4c7152dSHuisong Li 				      mac_addr);
697a4c7152dSHuisong Li 		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
698a4c7152dSHuisong Li 			 ret);
699a4c7152dSHuisong Li 	}
700a4c7152dSHuisong Li }
701247f0ce2SChengwen Feng 
702247f0ce2SChengwen Feng int
7032665a920SHuisong Li hns3_init_mac_addrs(struct rte_eth_dev *dev)
7042665a920SHuisong Li {
7052665a920SHuisong Li 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
7062665a920SHuisong Li 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
7072665a920SHuisong Li 	const char *memory_name = hns->is_vf ? "hns3vf-mac" : "hns3-mac";
7082665a920SHuisong Li 	uint16_t mac_addrs_capa = hns->is_vf ? HNS3_VF_UC_MACADDR_NUM :
7092665a920SHuisong Li 						HNS3_UC_MACADDR_NUM;
7102665a920SHuisong Li 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
7112665a920SHuisong Li 	struct rte_ether_addr *eth_addr;
7122665a920SHuisong Li 
7132665a920SHuisong Li 	/* Allocate memory for storing MAC addresses */
7142665a920SHuisong Li 	dev->data->mac_addrs = rte_zmalloc(memory_name,
7152665a920SHuisong Li 				sizeof(struct rte_ether_addr) * mac_addrs_capa,
7162665a920SHuisong Li 				0);
7172665a920SHuisong Li 	if (dev->data->mac_addrs == NULL) {
7182665a920SHuisong Li 		hns3_err(hw, "failed to allocate %zx bytes needed to store MAC addresses",
7192665a920SHuisong Li 			 sizeof(struct rte_ether_addr) * mac_addrs_capa);
7202665a920SHuisong Li 		return -ENOMEM;
7212665a920SHuisong Li 	}
7222665a920SHuisong Li 
7232665a920SHuisong Li 	eth_addr = (struct rte_ether_addr *)hw->mac.mac_addr;
7242665a920SHuisong Li 	if (!hns->is_vf) {
7252665a920SHuisong Li 		if (!rte_is_valid_assigned_ether_addr(eth_addr)) {
7262665a920SHuisong Li 			rte_eth_random_addr(hw->mac.mac_addr);
7272665a920SHuisong Li 			hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
7282665a920SHuisong Li 				(struct rte_ether_addr *)hw->mac.mac_addr);
7292665a920SHuisong Li 			hns3_warn(hw, "default mac_addr from firmware is an invalid "
7302665a920SHuisong Li 				  "unicast address, using random MAC address %s",
7312665a920SHuisong Li 				  mac_str);
7322665a920SHuisong Li 		}
7332665a920SHuisong Li 	} else {
7342665a920SHuisong Li 		/*
7352665a920SHuisong Li 		 * The hns3 PF ethdev driver in kernel support setting VF MAC
7362665a920SHuisong Li 		 * address on the host by "ip link set ..." command. To avoid
7372665a920SHuisong Li 		 * some incorrect scenes, for example, hns3 VF PMD driver fails
7382665a920SHuisong Li 		 * to receive and send packets after user configure the MAC
7392665a920SHuisong Li 		 * address by using the "ip link set ..." command, hns3 VF PMD
7402665a920SHuisong Li 		 * driver keep the same MAC address strategy as the hns3 kernel
7412665a920SHuisong Li 		 * ethdev driver in the initialization. If user configure a MAC
7422665a920SHuisong Li 		 * address by the ip command for VF device, then hns3 VF PMD
7432665a920SHuisong Li 		 * driver will start with it, otherwise start with a random MAC
7442665a920SHuisong Li 		 * address in the initialization.
7452665a920SHuisong Li 		 */
7462665a920SHuisong Li 		if (rte_is_zero_ether_addr(eth_addr))
7472665a920SHuisong Li 			rte_eth_random_addr(hw->mac.mac_addr);
7482665a920SHuisong Li 	}
7492665a920SHuisong Li 
7502665a920SHuisong Li 	rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.mac_addr,
7512665a920SHuisong Li 			    &dev->data->mac_addrs[0]);
7522665a920SHuisong Li 
7532665a920SHuisong Li 	return 0;
7542665a920SHuisong Li }
7552665a920SHuisong Li 
7562665a920SHuisong Li int
757247f0ce2SChengwen Feng hns3_init_ring_with_vector(struct hns3_hw *hw)
758247f0ce2SChengwen Feng {
759247f0ce2SChengwen Feng 	uint16_t vec;
76067d01034SHuisong Li 	uint16_t i;
761247f0ce2SChengwen Feng 	int ret;
762247f0ce2SChengwen Feng 
763247f0ce2SChengwen Feng 	/*
764247f0ce2SChengwen Feng 	 * In hns3 network engine, vector 0 is always the misc interrupt of this
765247f0ce2SChengwen Feng 	 * function, vector 1~N can be used respectively for the queues of the
766247f0ce2SChengwen Feng 	 * function. Tx and Rx queues with the same number share the interrupt
767247f0ce2SChengwen Feng 	 * vector. In the initialization clearing the all hardware mapping
768247f0ce2SChengwen Feng 	 * relationship configurations between queues and interrupt vectors is
769247f0ce2SChengwen Feng 	 * needed, so some error caused by the residual configurations, such as
770247f0ce2SChengwen Feng 	 * the unexpected Tx interrupt, can be avoid.
771247f0ce2SChengwen Feng 	 */
772247f0ce2SChengwen Feng 	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
773247f0ce2SChengwen Feng 	if (hw->intr.mapping_mode == HNS3_INTR_MAPPING_VEC_RSV_ONE)
774247f0ce2SChengwen Feng 		vec = vec - 1; /* the last interrupt is reserved */
775247f0ce2SChengwen Feng 	hw->intr_tqps_num = RTE_MIN(vec, hw->tqps_num);
776247f0ce2SChengwen Feng 	for (i = 0; i < hw->intr_tqps_num; i++) {
777247f0ce2SChengwen Feng 		/*
7787be78d02SJosh Soref 		 * Set gap limiter/rate limiter/quantity limiter algorithm
779247f0ce2SChengwen Feng 		 * configuration for interrupt coalesce of queue's interrupt.
780247f0ce2SChengwen Feng 		 */
781247f0ce2SChengwen Feng 		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
782247f0ce2SChengwen Feng 				       HNS3_TQP_INTR_GL_DEFAULT);
783247f0ce2SChengwen Feng 		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
784247f0ce2SChengwen Feng 				       HNS3_TQP_INTR_GL_DEFAULT);
785247f0ce2SChengwen Feng 		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
786247f0ce2SChengwen Feng 		/*
787247f0ce2SChengwen Feng 		 * QL(quantity limiter) is not used currently, just set 0 to
788247f0ce2SChengwen Feng 		 * close it.
789247f0ce2SChengwen Feng 		 */
790247f0ce2SChengwen Feng 		hns3_set_queue_intr_ql(hw, i, HNS3_TQP_INTR_QL_DEFAULT);
791247f0ce2SChengwen Feng 
792247f0ce2SChengwen Feng 		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
793247f0ce2SChengwen Feng 						    HNS3_RING_TYPE_TX, i);
794247f0ce2SChengwen Feng 		if (ret) {
79582c2ca6dSMin Hu (Connor) 			PMD_INIT_LOG(ERR, "fail to unbind TX ring(%u) with vector: %u, ret=%d",
7965bddaf38SHuisong Li 				     i, vec, ret);
797247f0ce2SChengwen Feng 			return ret;
798247f0ce2SChengwen Feng 		}
799247f0ce2SChengwen Feng 
800247f0ce2SChengwen Feng 		ret = hw->ops.bind_ring_with_vector(hw, vec, false,
801247f0ce2SChengwen Feng 						    HNS3_RING_TYPE_RX, i);
802247f0ce2SChengwen Feng 		if (ret) {
8035bddaf38SHuisong Li 			PMD_INIT_LOG(ERR, "fail to unbind RX ring(%d) with vector: %u, ret=%d",
8045bddaf38SHuisong Li 				     i, vec, ret);
805247f0ce2SChengwen Feng 			return ret;
806247f0ce2SChengwen Feng 		}
807247f0ce2SChengwen Feng 	}
808247f0ce2SChengwen Feng 
809247f0ce2SChengwen Feng 	return 0;
810247f0ce2SChengwen Feng }
811247f0ce2SChengwen Feng 
812247f0ce2SChengwen Feng int
813247f0ce2SChengwen Feng hns3_map_rx_interrupt(struct rte_eth_dev *dev)
814247f0ce2SChengwen Feng {
815247f0ce2SChengwen Feng 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
816247f0ce2SChengwen Feng 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
817247f0ce2SChengwen Feng 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
818247f0ce2SChengwen Feng 	uint16_t base = RTE_INTR_VEC_ZERO_OFFSET;
819247f0ce2SChengwen Feng 	uint16_t vec = RTE_INTR_VEC_ZERO_OFFSET;
820247f0ce2SChengwen Feng 	uint32_t intr_vector;
821247f0ce2SChengwen Feng 	uint16_t q_id;
822247f0ce2SChengwen Feng 	int ret;
823247f0ce2SChengwen Feng 
824247f0ce2SChengwen Feng 	/*
825247f0ce2SChengwen Feng 	 * hns3 needs a separate interrupt to be used as event interrupt which
826247f0ce2SChengwen Feng 	 * could not be shared with task queue pair, so KERNEL drivers need
827247f0ce2SChengwen Feng 	 * support multiple interrupt vectors.
828247f0ce2SChengwen Feng 	 */
829247f0ce2SChengwen Feng 	if (dev->data->dev_conf.intr_conf.rxq == 0 ||
830247f0ce2SChengwen Feng 	    !rte_intr_cap_multiple(intr_handle))
831247f0ce2SChengwen Feng 		return 0;
832247f0ce2SChengwen Feng 
833247f0ce2SChengwen Feng 	rte_intr_disable(intr_handle);
834247f0ce2SChengwen Feng 	intr_vector = hw->used_rx_queues;
835247f0ce2SChengwen Feng 	/* creates event fd for each intr vector when MSIX is used */
836247f0ce2SChengwen Feng 	if (rte_intr_efd_enable(intr_handle, intr_vector))
837247f0ce2SChengwen Feng 		return -EINVAL;
838247f0ce2SChengwen Feng 
839247f0ce2SChengwen Feng 	/* Allocate vector list */
840247f0ce2SChengwen Feng 	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
841247f0ce2SChengwen Feng 				    hw->used_rx_queues)) {
842247f0ce2SChengwen Feng 		hns3_err(hw, "failed to allocate %u rx_queues intr_vec",
843247f0ce2SChengwen Feng 			 hw->used_rx_queues);
844247f0ce2SChengwen Feng 		ret = -ENOMEM;
845247f0ce2SChengwen Feng 		goto alloc_intr_vec_error;
846247f0ce2SChengwen Feng 	}
847247f0ce2SChengwen Feng 
848247f0ce2SChengwen Feng 	if (rte_intr_allow_others(intr_handle)) {
849247f0ce2SChengwen Feng 		vec = RTE_INTR_VEC_RXTX_OFFSET;
850247f0ce2SChengwen Feng 		base = RTE_INTR_VEC_RXTX_OFFSET;
851247f0ce2SChengwen Feng 	}
852247f0ce2SChengwen Feng 
853247f0ce2SChengwen Feng 	for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
854247f0ce2SChengwen Feng 		ret = hw->ops.bind_ring_with_vector(hw, vec, true,
855247f0ce2SChengwen Feng 						    HNS3_RING_TYPE_RX, q_id);
856247f0ce2SChengwen Feng 		if (ret)
857247f0ce2SChengwen Feng 			goto bind_vector_error;
858247f0ce2SChengwen Feng 
859247f0ce2SChengwen Feng 		if (rte_intr_vec_list_index_set(intr_handle, q_id, vec))
860247f0ce2SChengwen Feng 			goto bind_vector_error;
861247f0ce2SChengwen Feng 		/*
862247f0ce2SChengwen Feng 		 * If there are not enough efds (e.g. not enough interrupt),
863247f0ce2SChengwen Feng 		 * remaining queues will be bond to the last interrupt.
864247f0ce2SChengwen Feng 		 */
865247f0ce2SChengwen Feng 		if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
866247f0ce2SChengwen Feng 			vec++;
867247f0ce2SChengwen Feng 	}
868247f0ce2SChengwen Feng 	rte_intr_enable(intr_handle);
869247f0ce2SChengwen Feng 	return 0;
870247f0ce2SChengwen Feng 
871247f0ce2SChengwen Feng bind_vector_error:
872247f0ce2SChengwen Feng 	rte_intr_vec_list_free(intr_handle);
873247f0ce2SChengwen Feng alloc_intr_vec_error:
874247f0ce2SChengwen Feng 	rte_intr_efd_disable(intr_handle);
875247f0ce2SChengwen Feng 	return ret;
876247f0ce2SChengwen Feng }
877247f0ce2SChengwen Feng 
878247f0ce2SChengwen Feng void
879247f0ce2SChengwen Feng hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
880247f0ce2SChengwen Feng {
881247f0ce2SChengwen Feng 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
882247f0ce2SChengwen Feng 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
883247f0ce2SChengwen Feng 	struct hns3_adapter *hns = dev->data->dev_private;
884247f0ce2SChengwen Feng 	struct hns3_hw *hw = &hns->hw;
885247f0ce2SChengwen Feng 	uint8_t base = RTE_INTR_VEC_ZERO_OFFSET;
886247f0ce2SChengwen Feng 	uint8_t vec = RTE_INTR_VEC_ZERO_OFFSET;
887247f0ce2SChengwen Feng 	uint16_t q_id;
888247f0ce2SChengwen Feng 
889247f0ce2SChengwen Feng 	if (dev->data->dev_conf.intr_conf.rxq == 0)
890247f0ce2SChengwen Feng 		return;
891247f0ce2SChengwen Feng 
892247f0ce2SChengwen Feng 	/* unmap the ring with vector */
893247f0ce2SChengwen Feng 	if (rte_intr_allow_others(intr_handle)) {
894247f0ce2SChengwen Feng 		vec = RTE_INTR_VEC_RXTX_OFFSET;
895247f0ce2SChengwen Feng 		base = RTE_INTR_VEC_RXTX_OFFSET;
896247f0ce2SChengwen Feng 	}
897247f0ce2SChengwen Feng 	if (rte_intr_dp_is_en(intr_handle)) {
898247f0ce2SChengwen Feng 		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
899247f0ce2SChengwen Feng 			(void)hw->ops.bind_ring_with_vector(hw, vec, false,
900247f0ce2SChengwen Feng 							HNS3_RING_TYPE_RX,
901247f0ce2SChengwen Feng 							q_id);
902247f0ce2SChengwen Feng 			if (vec < base + rte_intr_nb_efd_get(intr_handle) - 1)
903247f0ce2SChengwen Feng 				vec++;
904247f0ce2SChengwen Feng 		}
905247f0ce2SChengwen Feng 	}
906247f0ce2SChengwen Feng 	/* Clean datapath event and queue/vec mapping */
907247f0ce2SChengwen Feng 	rte_intr_efd_disable(intr_handle);
908247f0ce2SChengwen Feng 	rte_intr_vec_list_free(intr_handle);
909247f0ce2SChengwen Feng }
910247f0ce2SChengwen Feng 
911247f0ce2SChengwen Feng int
912247f0ce2SChengwen Feng hns3_restore_rx_interrupt(struct hns3_hw *hw)
913247f0ce2SChengwen Feng {
914247f0ce2SChengwen Feng 	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
915247f0ce2SChengwen Feng 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
916247f0ce2SChengwen Feng 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
917247f0ce2SChengwen Feng 	uint16_t q_id;
918247f0ce2SChengwen Feng 	int ret;
919247f0ce2SChengwen Feng 
920247f0ce2SChengwen Feng 	if (dev->data->dev_conf.intr_conf.rxq == 0)
921247f0ce2SChengwen Feng 		return 0;
922247f0ce2SChengwen Feng 
923247f0ce2SChengwen Feng 	if (rte_intr_dp_is_en(intr_handle)) {
924247f0ce2SChengwen Feng 		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
925247f0ce2SChengwen Feng 			ret = hw->ops.bind_ring_with_vector(hw,
926247f0ce2SChengwen Feng 				rte_intr_vec_list_index_get(intr_handle,
927247f0ce2SChengwen Feng 								   q_id),
928247f0ce2SChengwen Feng 				true, HNS3_RING_TYPE_RX, q_id);
929247f0ce2SChengwen Feng 			if (ret)
930247f0ce2SChengwen Feng 				return ret;
931247f0ce2SChengwen Feng 		}
932247f0ce2SChengwen Feng 	}
933247f0ce2SChengwen Feng 
934247f0ce2SChengwen Feng 	return 0;
935247f0ce2SChengwen Feng }
936f5ed7d99SHuisong Li 
937f5ed7d99SHuisong Li int
938f5ed7d99SHuisong Li hns3_get_pci_revision_id(struct hns3_hw *hw, uint8_t *revision_id)
939f5ed7d99SHuisong Li {
940f5ed7d99SHuisong Li 	struct rte_pci_device *pci_dev;
941f5ed7d99SHuisong Li 	struct rte_eth_dev *eth_dev;
942f5ed7d99SHuisong Li 	uint8_t revision;
943f5ed7d99SHuisong Li 	int ret;
944f5ed7d99SHuisong Li 
945f5ed7d99SHuisong Li 	eth_dev = &rte_eth_devices[hw->data->port_id];
946f5ed7d99SHuisong Li 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
947f5ed7d99SHuisong Li 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
948f5ed7d99SHuisong Li 				  HNS3_PCI_REVISION_ID);
949f5ed7d99SHuisong Li 	if (ret != HNS3_PCI_REVISION_ID_LEN) {
950f5ed7d99SHuisong Li 		hns3_err(hw, "failed to read pci revision id, ret = %d", ret);
951f5ed7d99SHuisong Li 		return -EIO;
952f5ed7d99SHuisong Li 	}
953f5ed7d99SHuisong Li 
954f5ed7d99SHuisong Li 	*revision_id = revision;
955f5ed7d99SHuisong Li 
956f5ed7d99SHuisong Li 	return 0;
957f5ed7d99SHuisong Li }
95852a4e960SHuisong Li 
95952a4e960SHuisong Li void
96052a4e960SHuisong Li hns3_set_default_dev_specifications(struct hns3_hw *hw)
96152a4e960SHuisong Li {
96252a4e960SHuisong Li 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
96352a4e960SHuisong Li 
96452a4e960SHuisong Li 	hw->max_non_tso_bd_num = HNS3_MAX_NON_TSO_BD_PER_PKT;
96552a4e960SHuisong Li 	hw->rss_ind_tbl_size = HNS3_RSS_IND_TBL_SIZE;
96652a4e960SHuisong Li 	hw->rss_key_size = HNS3_RSS_KEY_SIZE;
96752a4e960SHuisong Li 	hw->intr.int_ql_max = HNS3_INTR_QL_NONE;
96852a4e960SHuisong Li 
96952a4e960SHuisong Li 	if (hns->is_vf)
97052a4e960SHuisong Li 		return;
97152a4e960SHuisong Li 
97252a4e960SHuisong Li 	hw->max_tm_rate = HNS3_ETHER_MAX_RATE;
97352a4e960SHuisong Li }
97452a4e960SHuisong Li 
97552a4e960SHuisong Li static void
97652a4e960SHuisong Li hns3_parse_dev_specifications(struct hns3_hw *hw, struct hns3_cmd_desc *desc)
97752a4e960SHuisong Li {
97852a4e960SHuisong Li 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
97952a4e960SHuisong Li 	struct hns3_dev_specs_0_cmd *req0;
98052a4e960SHuisong Li 	struct hns3_dev_specs_1_cmd *req1;
98152a4e960SHuisong Li 
98252a4e960SHuisong Li 	req0 = (struct hns3_dev_specs_0_cmd *)desc[0].data;
98352a4e960SHuisong Li 	req1 = (struct hns3_dev_specs_1_cmd *)desc[1].data;
98452a4e960SHuisong Li 
98552a4e960SHuisong Li 	hw->max_non_tso_bd_num = req0->max_non_tso_bd_num;
98652a4e960SHuisong Li 	hw->rss_ind_tbl_size = rte_le_to_cpu_16(req0->rss_ind_tbl_size);
98752a4e960SHuisong Li 	hw->rss_key_size = rte_le_to_cpu_16(req0->rss_key_size);
98852a4e960SHuisong Li 	hw->intr.int_ql_max = rte_le_to_cpu_16(req0->intr_ql_max);
98952a4e960SHuisong Li 	hw->min_tx_pkt_len = req1->min_tx_pkt_len;
99052a4e960SHuisong Li 
99152a4e960SHuisong Li 	if (hns->is_vf)
99252a4e960SHuisong Li 		return;
99352a4e960SHuisong Li 
99452a4e960SHuisong Li 	hw->max_tm_rate = rte_le_to_cpu_32(req0->max_tm_rate);
99552a4e960SHuisong Li }
99652a4e960SHuisong Li 
99752a4e960SHuisong Li static int
99852a4e960SHuisong Li hns3_check_dev_specifications(struct hns3_hw *hw)
99952a4e960SHuisong Li {
100052a4e960SHuisong Li 	if (hw->rss_ind_tbl_size == 0 ||
100152a4e960SHuisong Li 	    hw->rss_ind_tbl_size > HNS3_RSS_IND_TBL_SIZE_MAX) {
100252a4e960SHuisong Li 		hns3_err(hw, "the indirection table size obtained (%u) is invalid, and should not be zero or exceed the maximum(%u)",
100352a4e960SHuisong Li 			 hw->rss_ind_tbl_size, HNS3_RSS_IND_TBL_SIZE_MAX);
100452a4e960SHuisong Li 		return -EINVAL;
100552a4e960SHuisong Li 	}
100652a4e960SHuisong Li 
10075172f9c4SHuisong Li 	if (hw->rss_key_size == 0 || hw->rss_key_size > HNS3_RSS_KEY_SIZE_MAX) {
10085172f9c4SHuisong Li 		hns3_err(hw, "the RSS key size obtained (%u) is invalid, and should not be zero or exceed the maximum(%u)",
10095172f9c4SHuisong Li 			 hw->rss_key_size, HNS3_RSS_KEY_SIZE_MAX);
10105172f9c4SHuisong Li 		return -EINVAL;
10115172f9c4SHuisong Li 	}
10125172f9c4SHuisong Li 
10135172f9c4SHuisong Li 	if (hw->rss_key_size > HNS3_RSS_KEY_SIZE)
10145172f9c4SHuisong Li 		hns3_warn(hw, "the RSS key size obtained (%u) is greater than the default key size (%u)",
10155172f9c4SHuisong Li 			  hw->rss_key_size, HNS3_RSS_KEY_SIZE);
10165172f9c4SHuisong Li 
101752a4e960SHuisong Li 	return 0;
101852a4e960SHuisong Li }
101952a4e960SHuisong Li 
102052a4e960SHuisong Li int
102152a4e960SHuisong Li hns3_query_dev_specifications(struct hns3_hw *hw)
102252a4e960SHuisong Li {
102352a4e960SHuisong Li 	struct hns3_cmd_desc desc[HNS3_QUERY_DEV_SPECS_BD_NUM];
102452a4e960SHuisong Li 	int ret;
102552a4e960SHuisong Li 	int i;
102652a4e960SHuisong Li 
102752a4e960SHuisong Li 	for (i = 0; i < HNS3_QUERY_DEV_SPECS_BD_NUM - 1; i++) {
102852a4e960SHuisong Li 		hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_QUERY_DEV_SPECS,
102952a4e960SHuisong Li 					  true);
103052a4e960SHuisong Li 		desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
103152a4e960SHuisong Li 	}
103252a4e960SHuisong Li 	hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_QUERY_DEV_SPECS, true);
103352a4e960SHuisong Li 
103452a4e960SHuisong Li 	ret = hns3_cmd_send(hw, desc, HNS3_QUERY_DEV_SPECS_BD_NUM);
103552a4e960SHuisong Li 	if (ret)
103652a4e960SHuisong Li 		return ret;
103752a4e960SHuisong Li 
103852a4e960SHuisong Li 	hns3_parse_dev_specifications(hw, desc);
103952a4e960SHuisong Li 
104052a4e960SHuisong Li 	return hns3_check_dev_specifications(hw);
104152a4e960SHuisong Li }
1042