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