1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. 4 * Copyright 2016-2018 NXP 5 * 6 */ 7 8 #include <time.h> 9 #include <net/if.h> 10 11 #include <rte_mbuf.h> 12 #include <rte_ethdev_driver.h> 13 #include <rte_malloc.h> 14 #include <rte_memcpy.h> 15 #include <rte_string_fns.h> 16 #include <rte_cycles.h> 17 #include <rte_kvargs.h> 18 #include <rte_dev.h> 19 20 #include <dpaa2_pmd_logs.h> 21 #include <dpaa2_hw_pvt.h> 22 #include <dpaa2_hw_mempool.h> 23 24 #include "../dpaa2_ethdev.h" 25 26 static int 27 dpaa2_distset_to_dpkg_profile_cfg( 28 uint64_t req_dist_set, 29 struct dpkg_profile_cfg *kg_cfg); 30 31 int 32 rte_pmd_dpaa2_set_custom_hash(uint16_t port_id, 33 uint16_t offset, 34 uint8_t size) 35 { 36 struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id]; 37 struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; 38 struct fsl_mc_io *dpni = priv->hw; 39 struct dpni_rx_tc_dist_cfg tc_cfg; 40 struct dpkg_profile_cfg kg_cfg; 41 void *p_params; 42 int ret, tc_index = 0; 43 44 p_params = rte_zmalloc( 45 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); 46 if (!p_params) { 47 DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); 48 return -ENOMEM; 49 } 50 51 kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA; 52 kg_cfg.extracts[0].extract.from_data.offset = offset; 53 kg_cfg.extracts[0].extract.from_data.size = size; 54 kg_cfg.num_extracts = 1; 55 56 ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); 57 if (ret) { 58 DPAA2_PMD_ERR("Unable to prepare extract parameters"); 59 rte_free(p_params); 60 return ret; 61 } 62 63 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); 64 tc_cfg.key_cfg_iova = (size_t)(DPAA2_VADDR_TO_IOVA(p_params)); 65 tc_cfg.dist_size = eth_dev->data->nb_rx_queues; 66 tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; 67 68 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, 69 &tc_cfg); 70 rte_free(p_params); 71 if (ret) { 72 DPAA2_PMD_ERR( 73 "Setting distribution for Rx failed with err: %d", 74 ret); 75 return ret; 76 } 77 78 return 0; 79 } 80 81 int 82 dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, 83 uint64_t req_dist_set) 84 { 85 struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; 86 struct fsl_mc_io *dpni = priv->hw; 87 struct dpni_rx_tc_dist_cfg tc_cfg; 88 struct dpkg_profile_cfg kg_cfg; 89 void *p_params; 90 int ret, tc_index = 0; 91 92 p_params = rte_malloc( 93 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); 94 if (!p_params) { 95 DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); 96 return -ENOMEM; 97 } 98 memset(p_params, 0, DIST_PARAM_IOVA_SIZE); 99 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); 100 101 ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg); 102 if (ret) { 103 DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported", 104 req_dist_set); 105 rte_free(p_params); 106 return ret; 107 } 108 tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params)); 109 tc_cfg.dist_size = eth_dev->data->nb_rx_queues; 110 tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; 111 112 ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); 113 if (ret) { 114 DPAA2_PMD_ERR("Unable to prepare extract parameters"); 115 rte_free(p_params); 116 return ret; 117 } 118 119 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, 120 &tc_cfg); 121 rte_free(p_params); 122 if (ret) { 123 DPAA2_PMD_ERR( 124 "Setting distribution for Rx failed with err: %d", 125 ret); 126 return ret; 127 } 128 129 return 0; 130 } 131 132 int dpaa2_remove_flow_dist( 133 struct rte_eth_dev *eth_dev, 134 uint8_t tc_index) 135 { 136 struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; 137 struct fsl_mc_io *dpni = priv->hw; 138 struct dpni_rx_tc_dist_cfg tc_cfg; 139 struct dpkg_profile_cfg kg_cfg; 140 void *p_params; 141 int ret; 142 143 p_params = rte_malloc( 144 NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); 145 if (!p_params) { 146 DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); 147 return -ENOMEM; 148 } 149 memset(p_params, 0, DIST_PARAM_IOVA_SIZE); 150 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); 151 kg_cfg.num_extracts = 0; 152 tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params)); 153 tc_cfg.dist_size = 0; 154 tc_cfg.dist_mode = DPNI_DIST_MODE_NONE; 155 156 ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); 157 if (ret) { 158 DPAA2_PMD_ERR("Unable to prepare extract parameters"); 159 rte_free(p_params); 160 return ret; 161 } 162 163 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, 164 &tc_cfg); 165 rte_free(p_params); 166 if (ret) 167 DPAA2_PMD_ERR( 168 "Setting distribution for Rx failed with err: %d", 169 ret); 170 return ret; 171 } 172 173 static int 174 dpaa2_distset_to_dpkg_profile_cfg( 175 uint64_t req_dist_set, 176 struct dpkg_profile_cfg *kg_cfg) 177 { 178 uint32_t loop = 0, i = 0, dist_field = 0; 179 int l2_configured = 0, l3_configured = 0; 180 int l4_configured = 0, sctp_configured = 0; 181 182 memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); 183 while (req_dist_set) { 184 if (req_dist_set % 2 != 0) { 185 dist_field = 1U << loop; 186 switch (dist_field) { 187 case ETH_RSS_L2_PAYLOAD: 188 189 if (l2_configured) 190 break; 191 l2_configured = 1; 192 193 kg_cfg->extracts[i].extract.from_hdr.prot = 194 NET_PROT_ETH; 195 kg_cfg->extracts[i].extract.from_hdr.field = 196 NH_FLD_ETH_TYPE; 197 kg_cfg->extracts[i].type = 198 DPKG_EXTRACT_FROM_HDR; 199 kg_cfg->extracts[i].extract.from_hdr.type = 200 DPKG_FULL_FIELD; 201 i++; 202 break; 203 204 case ETH_RSS_IPV4: 205 case ETH_RSS_FRAG_IPV4: 206 case ETH_RSS_NONFRAG_IPV4_OTHER: 207 case ETH_RSS_IPV6: 208 case ETH_RSS_FRAG_IPV6: 209 case ETH_RSS_NONFRAG_IPV6_OTHER: 210 case ETH_RSS_IPV6_EX: 211 212 if (l3_configured) 213 break; 214 l3_configured = 1; 215 216 kg_cfg->extracts[i].extract.from_hdr.prot = 217 NET_PROT_IP; 218 kg_cfg->extracts[i].extract.from_hdr.field = 219 NH_FLD_IP_SRC; 220 kg_cfg->extracts[i].type = 221 DPKG_EXTRACT_FROM_HDR; 222 kg_cfg->extracts[i].extract.from_hdr.type = 223 DPKG_FULL_FIELD; 224 i++; 225 226 kg_cfg->extracts[i].extract.from_hdr.prot = 227 NET_PROT_IP; 228 kg_cfg->extracts[i].extract.from_hdr.field = 229 NH_FLD_IP_DST; 230 kg_cfg->extracts[i].type = 231 DPKG_EXTRACT_FROM_HDR; 232 kg_cfg->extracts[i].extract.from_hdr.type = 233 DPKG_FULL_FIELD; 234 i++; 235 236 kg_cfg->extracts[i].extract.from_hdr.prot = 237 NET_PROT_IP; 238 kg_cfg->extracts[i].extract.from_hdr.field = 239 NH_FLD_IP_PROTO; 240 kg_cfg->extracts[i].type = 241 DPKG_EXTRACT_FROM_HDR; 242 kg_cfg->extracts[i].extract.from_hdr.type = 243 DPKG_FULL_FIELD; 244 kg_cfg->num_extracts++; 245 i++; 246 break; 247 248 case ETH_RSS_NONFRAG_IPV4_TCP: 249 case ETH_RSS_NONFRAG_IPV6_TCP: 250 case ETH_RSS_NONFRAG_IPV4_UDP: 251 case ETH_RSS_NONFRAG_IPV6_UDP: 252 case ETH_RSS_IPV6_TCP_EX: 253 case ETH_RSS_IPV6_UDP_EX: 254 255 if (l4_configured) 256 break; 257 l4_configured = 1; 258 259 kg_cfg->extracts[i].extract.from_hdr.prot = 260 NET_PROT_TCP; 261 kg_cfg->extracts[i].extract.from_hdr.field = 262 NH_FLD_TCP_PORT_SRC; 263 kg_cfg->extracts[i].type = 264 DPKG_EXTRACT_FROM_HDR; 265 kg_cfg->extracts[i].extract.from_hdr.type = 266 DPKG_FULL_FIELD; 267 i++; 268 269 kg_cfg->extracts[i].extract.from_hdr.prot = 270 NET_PROT_TCP; 271 kg_cfg->extracts[i].extract.from_hdr.field = 272 NH_FLD_TCP_PORT_SRC; 273 kg_cfg->extracts[i].type = 274 DPKG_EXTRACT_FROM_HDR; 275 kg_cfg->extracts[i].extract.from_hdr.type = 276 DPKG_FULL_FIELD; 277 i++; 278 break; 279 280 case ETH_RSS_NONFRAG_IPV4_SCTP: 281 case ETH_RSS_NONFRAG_IPV6_SCTP: 282 283 if (sctp_configured) 284 break; 285 sctp_configured = 1; 286 287 kg_cfg->extracts[i].extract.from_hdr.prot = 288 NET_PROT_SCTP; 289 kg_cfg->extracts[i].extract.from_hdr.field = 290 NH_FLD_SCTP_PORT_SRC; 291 kg_cfg->extracts[i].type = 292 DPKG_EXTRACT_FROM_HDR; 293 kg_cfg->extracts[i].extract.from_hdr.type = 294 DPKG_FULL_FIELD; 295 i++; 296 297 kg_cfg->extracts[i].extract.from_hdr.prot = 298 NET_PROT_SCTP; 299 kg_cfg->extracts[i].extract.from_hdr.field = 300 NH_FLD_SCTP_PORT_DST; 301 kg_cfg->extracts[i].type = 302 DPKG_EXTRACT_FROM_HDR; 303 kg_cfg->extracts[i].extract.from_hdr.type = 304 DPKG_FULL_FIELD; 305 i++; 306 break; 307 308 default: 309 DPAA2_PMD_WARN( 310 "Unsupported flow dist option %x", 311 dist_field); 312 return -EINVAL; 313 } 314 } 315 req_dist_set = req_dist_set >> 1; 316 loop++; 317 } 318 kg_cfg->num_extracts = i; 319 return 0; 320 } 321 322 int 323 dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, 324 void *blist) 325 { 326 /* Function to attach a DPNI with a buffer pool list. Buffer pool list 327 * handle is passed in blist. 328 */ 329 int32_t retcode; 330 struct fsl_mc_io *dpni = priv->hw; 331 struct dpni_pools_cfg bpool_cfg; 332 struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist; 333 struct dpni_buffer_layout layout; 334 int tot_size; 335 336 /* ... rx buffer layout . 337 * Check alignment for buffer layouts first 338 */ 339 340 /* ... rx buffer layout ... */ 341 tot_size = RTE_PKTMBUF_HEADROOM; 342 tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); 343 344 memset(&layout, 0, sizeof(struct dpni_buffer_layout)); 345 layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | 346 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | 347 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | 348 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | 349 DPNI_BUF_LAYOUT_OPT_TIMESTAMP | 350 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; 351 352 layout.pass_timestamp = true; 353 layout.pass_frame_status = 1; 354 layout.private_data_size = DPAA2_FD_PTA_SIZE; 355 layout.pass_parser_result = 1; 356 layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; 357 layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - 358 DPAA2_MBUF_HW_ANNOTATION; 359 retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, 360 DPNI_QUEUE_RX, &layout); 361 if (retcode) { 362 DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", 363 retcode); 364 return retcode; 365 } 366 367 /*Attach buffer pool to the network interface as described by the user*/ 368 bpool_cfg.num_dpbp = 1; 369 bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; 370 bpool_cfg.pools[0].backup_pool = 0; 371 bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, 372 DPAA2_PACKET_LAYOUT_ALIGN); 373 bpool_cfg.pools[0].priority_mask = 0; 374 375 retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); 376 if (retcode != 0) { 377 DPAA2_PMD_ERR("Error configuring buffer pool on interface." 378 " bpid = %d error code = %d", 379 bpool_cfg.pools[0].dpbp_id, retcode); 380 return retcode; 381 } 382 383 priv->bp_list = bp_list; 384 return 0; 385 } 386