Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2019 Intel Corporation 3 : : */ 4 : : 5 : : #ifndef _ICE_RXTX_VEC_COMMON_H_ 6 : : #define _ICE_RXTX_VEC_COMMON_H_ 7 : : 8 : : #include "ice_rxtx.h" 9 : : 10 : : #ifndef __INTEL_COMPILER 11 : : #pragma GCC diagnostic ignored "-Wcast-qual" 12 : : #endif 13 : : 14 : : static inline uint16_t 15 : 0 : ice_rx_reassemble_packets(struct ice_rx_queue *rxq, struct rte_mbuf **rx_bufs, 16 : : uint16_t nb_bufs, uint8_t *split_flags) 17 : : { 18 : 0 : struct rte_mbuf *pkts[ICE_VPMD_RX_BURST] = {0}; /*finished pkts*/ 19 : 0 : struct rte_mbuf *start = rxq->pkt_first_seg; 20 : 0 : struct rte_mbuf *end = rxq->pkt_last_seg; 21 : : unsigned int pkt_idx, buf_idx; 22 : : 23 [ # # ]: 0 : for (buf_idx = 0, pkt_idx = 0; buf_idx < nb_bufs; buf_idx++) { 24 [ # # ]: 0 : if (end) { 25 : : /* processing a split packet */ 26 : 0 : end->next = rx_bufs[buf_idx]; 27 : 0 : rx_bufs[buf_idx]->data_len += rxq->crc_len; 28 : : 29 : 0 : start->nb_segs++; 30 : 0 : start->pkt_len += rx_bufs[buf_idx]->data_len; 31 : : end = end->next; 32 : : 33 [ # # ]: 0 : if (!split_flags[buf_idx]) { 34 : : /* it's the last packet of the set */ 35 : 0 : start->hash = end->hash; 36 : 0 : start->vlan_tci = end->vlan_tci; 37 : 0 : start->ol_flags = end->ol_flags; 38 : : /* we need to strip crc for the whole packet */ 39 : 0 : start->pkt_len -= rxq->crc_len; 40 [ # # ]: 0 : if (end->data_len > rxq->crc_len) { 41 : 0 : end->data_len -= rxq->crc_len; 42 : : } else { 43 : : /* free up last mbuf */ 44 : : struct rte_mbuf *secondlast = start; 45 : : 46 : 0 : start->nb_segs--; 47 [ # # ]: 0 : while (secondlast->next != end) 48 : : secondlast = secondlast->next; 49 : 0 : secondlast->data_len -= (rxq->crc_len - 50 : : end->data_len); 51 : 0 : secondlast->next = NULL; 52 : : rte_pktmbuf_free_seg(end); 53 : : } 54 : 0 : pkts[pkt_idx++] = start; 55 : : start = NULL; 56 : : end = NULL; 57 : : } 58 : : } else { 59 : : /* not processing a split packet */ 60 [ # # ]: 0 : if (!split_flags[buf_idx]) { 61 : : /* not a split packet, save and skip */ 62 : 0 : pkts[pkt_idx++] = rx_bufs[buf_idx]; 63 : 0 : continue; 64 : : } 65 : 0 : start = rx_bufs[buf_idx]; 66 : : end = start; 67 : 0 : rx_bufs[buf_idx]->data_len += rxq->crc_len; 68 : 0 : rx_bufs[buf_idx]->pkt_len += rxq->crc_len; 69 : : } 70 : : } 71 : : 72 : : /* save the partial packet for next time */ 73 : 0 : rxq->pkt_first_seg = start; 74 : 0 : rxq->pkt_last_seg = end; 75 : 0 : memcpy(rx_bufs, pkts, pkt_idx * (sizeof(*pkts))); 76 : 0 : return pkt_idx; 77 : : } 78 : : 79 : : static __rte_always_inline int 80 : : ice_tx_free_bufs_vec(struct ice_tx_queue *txq) 81 : : { 82 : : struct ice_tx_entry *txep; 83 : : uint32_t n; 84 : : uint32_t i; 85 : : int nb_free = 0; 86 : : struct rte_mbuf *m, *free[ICE_TX_MAX_FREE_BUF_SZ]; 87 : : 88 : : /* check DD bits on threshold descriptor */ 89 [ # # # # ]: 0 : if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz & 90 : : rte_cpu_to_le_64(ICE_TXD_QW1_DTYPE_M)) != 91 : : rte_cpu_to_le_64(ICE_TX_DESC_DTYPE_DESC_DONE)) 92 : : return 0; 93 : : 94 : 0 : n = txq->tx_rs_thresh; 95 : : 96 : : /* first buffer to free from S/W ring is at index 97 : : * tx_next_dd - (tx_rs_thresh-1) 98 : : */ 99 : 0 : txep = &txq->sw_ring[txq->tx_next_dd - (n - 1)]; 100 [ # # # # ]: 0 : m = rte_pktmbuf_prefree_seg(txep[0].mbuf); 101 [ # # # # ]: 0 : if (likely(m)) { 102 : 0 : free[0] = m; 103 : : nb_free = 1; 104 [ # # # # ]: 0 : for (i = 1; i < n; i++) { 105 [ # # # # ]: 0 : m = rte_pktmbuf_prefree_seg(txep[i].mbuf); 106 [ # # # # ]: 0 : if (likely(m)) { 107 [ # # # # ]: 0 : if (likely(m->pool == free[0]->pool)) { 108 : 0 : free[nb_free++] = m; 109 : : } else { 110 [ # # # # ]: 0 : rte_mempool_put_bulk(free[0]->pool, 111 : : (void *)free, 112 : : nb_free); 113 : 0 : free[0] = m; 114 : : nb_free = 1; 115 : : } 116 : : } 117 : : } 118 [ # # # # ]: 0 : rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); 119 : : } else { 120 [ # # # # ]: 0 : for (i = 1; i < n; i++) { 121 [ # # # # ]: 0 : m = rte_pktmbuf_prefree_seg(txep[i].mbuf); 122 [ # # # # ]: 0 : if (m) 123 [ # # # # ]: 0 : rte_mempool_put(m->pool, m); 124 : : } 125 : : } 126 : : 127 : : /* buffers were freed, update counters */ 128 : 0 : txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); 129 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); 130 [ # # # # ]: 0 : if (txq->tx_next_dd >= txq->nb_tx_desc) 131 : 0 : txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); 132 : : 133 : 0 : return txq->tx_rs_thresh; 134 : : } 135 : : 136 : : static __rte_always_inline void 137 : : ice_tx_backlog_entry(struct ice_tx_entry *txep, 138 : : struct rte_mbuf **tx_pkts, uint16_t nb_pkts) 139 : : { 140 : : int i; 141 : : 142 [ # # # # : 0 : for (i = 0; i < (int)nb_pkts; ++i) # # # # ] 143 : 0 : txep[i].mbuf = tx_pkts[i]; 144 : : } 145 : : 146 : : static inline void 147 : 0 : _ice_rx_queue_release_mbufs_vec(struct ice_rx_queue *rxq) 148 : : { 149 : 0 : const unsigned int mask = rxq->nb_rx_desc - 1; 150 : : unsigned int i; 151 : : 152 [ # # ]: 0 : if (unlikely(!rxq->sw_ring)) { 153 : 0 : PMD_DRV_LOG(DEBUG, "sw_ring is NULL"); 154 : 0 : return; 155 : : } 156 : : 157 [ # # ]: 0 : if (rxq->rxrearm_nb >= rxq->nb_rx_desc) 158 : : return; 159 : : 160 : : /* free all mbufs that are valid in the ring */ 161 [ # # ]: 0 : if (rxq->rxrearm_nb == 0) { 162 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) { 163 [ # # ]: 0 : if (rxq->sw_ring[i].mbuf) 164 : : rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); 165 : : } 166 : : } else { 167 : 0 : for (i = rxq->rx_tail; 168 [ # # ]: 0 : i != rxq->rxrearm_start; 169 : 0 : i = (i + 1) & mask) { 170 [ # # ]: 0 : if (rxq->sw_ring[i].mbuf) 171 : : rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); 172 : : } 173 : : } 174 : : 175 : 0 : rxq->rxrearm_nb = rxq->nb_rx_desc; 176 : : 177 : : /* set all entries to NULL */ 178 : 0 : memset(rxq->sw_ring, 0, sizeof(rxq->sw_ring[0]) * rxq->nb_rx_desc); 179 : : } 180 : : 181 : : static inline void 182 : 0 : _ice_tx_queue_release_mbufs_vec(struct ice_tx_queue *txq) 183 : : { 184 : : uint16_t i; 185 : : 186 [ # # # # ]: 0 : if (unlikely(!txq || !txq->sw_ring)) { 187 : 0 : PMD_DRV_LOG(DEBUG, "Pointer to rxq or sw_ring is NULL"); 188 : 0 : return; 189 : : } 190 : : 191 : : /** 192 : : * vPMD tx will not set sw_ring's mbuf to NULL after free, 193 : : * so need to free remains more carefully. 194 : : */ 195 : 0 : i = txq->tx_next_dd - txq->tx_rs_thresh + 1; 196 : : 197 : : #ifdef __AVX512VL__ 198 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[txq->vsi->adapter->pf.dev_data->port_id]; 199 : : 200 [ # # # # ]: 0 : if (dev->tx_pkt_burst == ice_xmit_pkts_vec_avx512 || 201 : : dev->tx_pkt_burst == ice_xmit_pkts_vec_avx512_offload) { 202 : : struct ice_vec_tx_entry *swr = (void *)txq->sw_ring; 203 : : 204 [ # # ]: 0 : if (txq->tx_tail < i) { 205 [ # # ]: 0 : for (; i < txq->nb_tx_desc; i++) { 206 [ # # ]: 0 : rte_pktmbuf_free_seg(swr[i].mbuf); 207 : 0 : swr[i].mbuf = NULL; 208 : : } 209 : : i = 0; 210 : : } 211 [ # # ]: 0 : for (; i < txq->tx_tail; i++) { 212 [ # # ]: 0 : rte_pktmbuf_free_seg(swr[i].mbuf); 213 : 0 : swr[i].mbuf = NULL; 214 : : } 215 : : } else 216 : : #endif 217 : : { 218 [ # # ]: 0 : if (txq->tx_tail < i) { 219 [ # # ]: 0 : for (; i < txq->nb_tx_desc; i++) { 220 [ # # ]: 0 : rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); 221 : 0 : txq->sw_ring[i].mbuf = NULL; 222 : : } 223 : : i = 0; 224 : : } 225 [ # # ]: 0 : for (; i < txq->tx_tail; i++) { 226 [ # # ]: 0 : rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); 227 : 0 : txq->sw_ring[i].mbuf = NULL; 228 : : } 229 : : } 230 : : } 231 : : 232 : : static inline int 233 : 0 : ice_rxq_vec_setup_default(struct ice_rx_queue *rxq) 234 : : { 235 : : uintptr_t p; 236 : 0 : struct rte_mbuf mb_def = { .buf_addr = 0 }; /* zeroed mbuf */ 237 : : 238 : 0 : mb_def.nb_segs = 1; 239 : 0 : mb_def.data_off = RTE_PKTMBUF_HEADROOM; 240 : 0 : mb_def.port = rxq->port_id; 241 : : rte_mbuf_refcnt_set(&mb_def, 1); 242 : : 243 : : /* prevent compiler reordering: rearm_data covers previous fields */ 244 : 0 : rte_compiler_barrier(); 245 : : p = (uintptr_t)&mb_def.rearm_data; 246 : 0 : rxq->mbuf_initializer = *(uint64_t *)p; 247 : 0 : return 0; 248 : : } 249 : : 250 : : #define ICE_TX_NO_VECTOR_FLAGS ( \ 251 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS | \ 252 : : RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM | \ 253 : : RTE_ETH_TX_OFFLOAD_TCP_TSO | \ 254 : : RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO | \ 255 : : RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO | \ 256 : : RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO | \ 257 : : RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO | \ 258 : : RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM) 259 : : 260 : : #define ICE_TX_VECTOR_OFFLOAD ( \ 261 : : RTE_ETH_TX_OFFLOAD_VLAN_INSERT | \ 262 : : RTE_ETH_TX_OFFLOAD_QINQ_INSERT | \ 263 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | \ 264 : : RTE_ETH_TX_OFFLOAD_SCTP_CKSUM | \ 265 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM | \ 266 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM) 267 : : 268 : : #define ICE_RX_VECTOR_OFFLOAD ( \ 269 : : RTE_ETH_RX_OFFLOAD_CHECKSUM | \ 270 : : RTE_ETH_RX_OFFLOAD_SCTP_CKSUM | \ 271 : : RTE_ETH_RX_OFFLOAD_VLAN | \ 272 : : RTE_ETH_RX_OFFLOAD_RSS_HASH) 273 : : 274 : : #define ICE_VECTOR_PATH 0 275 : : #define ICE_VECTOR_OFFLOAD_PATH 1 276 : : 277 : : static inline int 278 : 0 : ice_rx_vec_queue_default(struct ice_rx_queue *rxq) 279 : : { 280 [ # # ]: 0 : if (!rxq) 281 : : return -1; 282 : : 283 [ # # ]: 0 : if (!rte_is_power_of_2(rxq->nb_rx_desc)) 284 : : return -1; 285 : : 286 [ # # ]: 0 : if (rxq->rx_free_thresh < ICE_VPMD_RX_BURST) 287 : : return -1; 288 : : 289 [ # # ]: 0 : if (rxq->nb_rx_desc % rxq->rx_free_thresh) 290 : : return -1; 291 : : 292 [ # # ]: 0 : if (rxq->proto_xtr != PROTO_XTR_NONE) 293 : : return -1; 294 : : 295 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) 296 : : return -1; 297 : : 298 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) 299 : : return -1; 300 : : 301 [ # # ]: 0 : if (rxq->offloads & ICE_RX_VECTOR_OFFLOAD) 302 : 0 : return ICE_VECTOR_OFFLOAD_PATH; 303 : : 304 : : return ICE_VECTOR_PATH; 305 : : } 306 : : 307 : : static inline int 308 : : ice_tx_vec_queue_default(struct ice_tx_queue *txq) 309 : : { 310 : 0 : if (!txq) 311 : : return -1; 312 : : 313 [ # # ]: 0 : if (txq->tx_rs_thresh < ICE_VPMD_TX_BURST || 314 : : txq->tx_rs_thresh > ICE_TX_MAX_FREE_BUF_SZ) 315 : : return -1; 316 : : 317 [ # # ]: 0 : if (txq->offloads & ICE_TX_NO_VECTOR_FLAGS) 318 : : return -1; 319 : : 320 [ # # ]: 0 : if (txq->offloads & ICE_TX_VECTOR_OFFLOAD) 321 : : return ICE_VECTOR_OFFLOAD_PATH; 322 : : 323 : : return ICE_VECTOR_PATH; 324 : : } 325 : : 326 : : static inline int 327 : 0 : ice_rx_vec_dev_check_default(struct rte_eth_dev *dev) 328 : : { 329 : : int i; 330 : : struct ice_rx_queue *rxq; 331 : : int ret = 0; 332 : : int result = 0; 333 : : 334 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) { 335 : 0 : rxq = dev->data->rx_queues[i]; 336 : 0 : ret = (ice_rx_vec_queue_default(rxq)); 337 [ # # ]: 0 : if (ret < 0) 338 : : return -1; 339 [ # # ]: 0 : if (ret == ICE_VECTOR_OFFLOAD_PATH) 340 : : result = ret; 341 : : } 342 : : 343 : : return result; 344 : : } 345 : : 346 : : static inline int 347 : 0 : ice_tx_vec_dev_check_default(struct rte_eth_dev *dev) 348 : : { 349 : : int i; 350 : : struct ice_tx_queue *txq; 351 : : int ret = 0; 352 : : int result = 0; 353 : : 354 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) { 355 [ # # ]: 0 : txq = dev->data->tx_queues[i]; 356 : : ret = ice_tx_vec_queue_default(txq); 357 : : if (ret < 0) 358 : : return -1; 359 [ # # ]: 0 : if (ret == ICE_VECTOR_OFFLOAD_PATH) 360 : : result = ret; 361 : : } 362 : : 363 : : return result; 364 : : } 365 : : 366 : : static inline void 367 : 0 : ice_txd_enable_offload(struct rte_mbuf *tx_pkt, 368 : : uint64_t *txd_hi) 369 : : { 370 : 0 : uint64_t ol_flags = tx_pkt->ol_flags; 371 : : uint32_t td_cmd = 0; 372 : : uint32_t td_offset = 0; 373 : : 374 : : /* Tx Checksum Offload */ 375 : : /* SET MACLEN */ 376 : 0 : td_offset |= (tx_pkt->l2_len >> 1) << 377 : : ICE_TX_DESC_LEN_MACLEN_S; 378 : : 379 : : /* Enable L3 checksum offload */ 380 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) { 381 : : td_cmd |= ICE_TX_DESC_CMD_IIPT_IPV4_CSUM; 382 : 0 : td_offset |= (tx_pkt->l3_len >> 2) << 383 : : ICE_TX_DESC_LEN_IPLEN_S; 384 [ # # ]: 0 : } else if (ol_flags & RTE_MBUF_F_TX_IPV4) { 385 : : td_cmd |= ICE_TX_DESC_CMD_IIPT_IPV4; 386 : 0 : td_offset |= (tx_pkt->l3_len >> 2) << 387 : : ICE_TX_DESC_LEN_IPLEN_S; 388 [ # # ]: 0 : } else if (ol_flags & RTE_MBUF_F_TX_IPV6) { 389 : : td_cmd |= ICE_TX_DESC_CMD_IIPT_IPV6; 390 : 0 : td_offset |= (tx_pkt->l3_len >> 2) << 391 : : ICE_TX_DESC_LEN_IPLEN_S; 392 : : } 393 : : 394 : : /* Enable L4 checksum offloads */ 395 [ # # # # ]: 0 : switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) { 396 : 0 : case RTE_MBUF_F_TX_TCP_CKSUM: 397 : 0 : td_cmd |= ICE_TX_DESC_CMD_L4T_EOFT_TCP; 398 : 0 : td_offset |= (sizeof(struct rte_tcp_hdr) >> 2) << 399 : : ICE_TX_DESC_LEN_L4_LEN_S; 400 : 0 : break; 401 : 0 : case RTE_MBUF_F_TX_SCTP_CKSUM: 402 : 0 : td_cmd |= ICE_TX_DESC_CMD_L4T_EOFT_SCTP; 403 : 0 : td_offset |= (sizeof(struct rte_sctp_hdr) >> 2) << 404 : : ICE_TX_DESC_LEN_L4_LEN_S; 405 : 0 : break; 406 : 0 : case RTE_MBUF_F_TX_UDP_CKSUM: 407 : 0 : td_cmd |= ICE_TX_DESC_CMD_L4T_EOFT_UDP; 408 : 0 : td_offset |= (sizeof(struct rte_udp_hdr) >> 2) << 409 : : ICE_TX_DESC_LEN_L4_LEN_S; 410 : 0 : break; 411 : : default: 412 : : break; 413 : : } 414 : : 415 : 0 : *txd_hi |= ((uint64_t)td_offset) << ICE_TXD_QW1_OFFSET_S; 416 : : 417 : : /* Tx VLAN/QINQ insertion Offload */ 418 [ # # ]: 0 : if (ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) { 419 : 0 : td_cmd |= ICE_TX_DESC_CMD_IL2TAG1; 420 : 0 : *txd_hi |= ((uint64_t)tx_pkt->vlan_tci << 421 : : ICE_TXD_QW1_L2TAG1_S); 422 : : } 423 : : 424 : 0 : *txd_hi |= ((uint64_t)td_cmd) << ICE_TXD_QW1_CMD_S; 425 : 0 : } 426 : : #endif