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_OUTER_UDP_CKSUM) 255 : : 256 : : #define ICE_TX_VECTOR_OFFLOAD ( \ 257 : : RTE_ETH_TX_OFFLOAD_VLAN_INSERT | \ 258 : : RTE_ETH_TX_OFFLOAD_QINQ_INSERT | \ 259 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | \ 260 : : RTE_ETH_TX_OFFLOAD_SCTP_CKSUM | \ 261 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM | \ 262 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM) 263 : : 264 : : #define ICE_RX_VECTOR_OFFLOAD ( \ 265 : : RTE_ETH_RX_OFFLOAD_CHECKSUM | \ 266 : : RTE_ETH_RX_OFFLOAD_SCTP_CKSUM | \ 267 : : RTE_ETH_RX_OFFLOAD_VLAN | \ 268 : : RTE_ETH_RX_OFFLOAD_RSS_HASH) 269 : : 270 : : #define ICE_VECTOR_PATH 0 271 : : #define ICE_VECTOR_OFFLOAD_PATH 1 272 : : 273 : : static inline int 274 : 0 : ice_rx_vec_queue_default(struct ice_rx_queue *rxq) 275 : : { 276 [ # # ]: 0 : if (!rxq) 277 : : return -1; 278 : : 279 [ # # ]: 0 : if (!rte_is_power_of_2(rxq->nb_rx_desc)) 280 : : return -1; 281 : : 282 [ # # ]: 0 : if (rxq->rx_free_thresh < ICE_VPMD_RX_BURST) 283 : : return -1; 284 : : 285 [ # # ]: 0 : if (rxq->nb_rx_desc % rxq->rx_free_thresh) 286 : : return -1; 287 : : 288 [ # # ]: 0 : if (rxq->proto_xtr != PROTO_XTR_NONE) 289 : : return -1; 290 : : 291 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) 292 : : return -1; 293 : : 294 [ # # ]: 0 : if (rxq->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) 295 : : return -1; 296 : : 297 [ # # ]: 0 : if (rxq->offloads & ICE_RX_VECTOR_OFFLOAD) 298 : 0 : return ICE_VECTOR_OFFLOAD_PATH; 299 : : 300 : : return ICE_VECTOR_PATH; 301 : : } 302 : : 303 : : static inline int 304 : : ice_tx_vec_queue_default(struct ice_tx_queue *txq) 305 : : { 306 : 0 : if (!txq) 307 : : return -1; 308 : : 309 [ # # ]: 0 : if (txq->tx_rs_thresh < ICE_VPMD_TX_BURST || 310 : : txq->tx_rs_thresh > ICE_TX_MAX_FREE_BUF_SZ) 311 : : return -1; 312 : : 313 [ # # ]: 0 : if (txq->offloads & ICE_TX_NO_VECTOR_FLAGS) 314 : : return -1; 315 : : 316 [ # # ]: 0 : if (txq->offloads & ICE_TX_VECTOR_OFFLOAD) 317 : : return ICE_VECTOR_OFFLOAD_PATH; 318 : : 319 : : return ICE_VECTOR_PATH; 320 : : } 321 : : 322 : : static inline int 323 : 0 : ice_rx_vec_dev_check_default(struct rte_eth_dev *dev) 324 : : { 325 : : int i; 326 : : struct ice_rx_queue *rxq; 327 : : int ret = 0; 328 : : int result = 0; 329 : : 330 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) { 331 : 0 : rxq = dev->data->rx_queues[i]; 332 : 0 : ret = (ice_rx_vec_queue_default(rxq)); 333 [ # # ]: 0 : if (ret < 0) 334 : : return -1; 335 [ # # ]: 0 : if (ret == ICE_VECTOR_OFFLOAD_PATH) 336 : : result = ret; 337 : : } 338 : : 339 : : return result; 340 : : } 341 : : 342 : : static inline int 343 : 0 : ice_tx_vec_dev_check_default(struct rte_eth_dev *dev) 344 : : { 345 : : int i; 346 : : struct ice_tx_queue *txq; 347 : : int ret = 0; 348 : : int result = 0; 349 : : 350 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) { 351 [ # # ]: 0 : txq = dev->data->tx_queues[i]; 352 : : ret = ice_tx_vec_queue_default(txq); 353 : : if (ret < 0) 354 : : return -1; 355 [ # # ]: 0 : if (ret == ICE_VECTOR_OFFLOAD_PATH) 356 : : result = ret; 357 : : } 358 : : 359 : : return result; 360 : : } 361 : : 362 : : static inline void 363 : 0 : ice_txd_enable_offload(struct rte_mbuf *tx_pkt, 364 : : uint64_t *txd_hi) 365 : : { 366 : 0 : uint64_t ol_flags = tx_pkt->ol_flags; 367 : : uint32_t td_cmd = 0; 368 : : uint32_t td_offset = 0; 369 : : 370 : : /* Tx Checksum Offload */ 371 : : /* SET MACLEN */ 372 : 0 : td_offset |= (tx_pkt->l2_len >> 1) << 373 : : ICE_TX_DESC_LEN_MACLEN_S; 374 : : 375 : : /* Enable L3 checksum offload */ 376 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) { 377 : : td_cmd |= ICE_TX_DESC_CMD_IIPT_IPV4_CSUM; 378 : 0 : td_offset |= (tx_pkt->l3_len >> 2) << 379 : : ICE_TX_DESC_LEN_IPLEN_S; 380 [ # # ]: 0 : } else if (ol_flags & RTE_MBUF_F_TX_IPV4) { 381 : : td_cmd |= ICE_TX_DESC_CMD_IIPT_IPV4; 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_IPV6) { 385 : : td_cmd |= ICE_TX_DESC_CMD_IIPT_IPV6; 386 : 0 : td_offset |= (tx_pkt->l3_len >> 2) << 387 : : ICE_TX_DESC_LEN_IPLEN_S; 388 : : } 389 : : 390 : : /* Enable L4 checksum offloads */ 391 [ # # # # ]: 0 : switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) { 392 : 0 : case RTE_MBUF_F_TX_TCP_CKSUM: 393 : 0 : td_cmd |= ICE_TX_DESC_CMD_L4T_EOFT_TCP; 394 : 0 : td_offset |= (sizeof(struct rte_tcp_hdr) >> 2) << 395 : : ICE_TX_DESC_LEN_L4_LEN_S; 396 : 0 : break; 397 : 0 : case RTE_MBUF_F_TX_SCTP_CKSUM: 398 : 0 : td_cmd |= ICE_TX_DESC_CMD_L4T_EOFT_SCTP; 399 : 0 : td_offset |= (sizeof(struct rte_sctp_hdr) >> 2) << 400 : : ICE_TX_DESC_LEN_L4_LEN_S; 401 : 0 : break; 402 : 0 : case RTE_MBUF_F_TX_UDP_CKSUM: 403 : 0 : td_cmd |= ICE_TX_DESC_CMD_L4T_EOFT_UDP; 404 : 0 : td_offset |= (sizeof(struct rte_udp_hdr) >> 2) << 405 : : ICE_TX_DESC_LEN_L4_LEN_S; 406 : 0 : break; 407 : : default: 408 : : break; 409 : : } 410 : : 411 : 0 : *txd_hi |= ((uint64_t)td_offset) << ICE_TXD_QW1_OFFSET_S; 412 : : 413 : : /* Tx VLAN/QINQ insertion Offload */ 414 [ # # ]: 0 : if (ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) { 415 : 0 : td_cmd |= ICE_TX_DESC_CMD_IL2TAG1; 416 : 0 : *txd_hi |= ((uint64_t)tx_pkt->vlan_tci << 417 : : ICE_TXD_QW1_L2TAG1_S); 418 : : } 419 : : 420 : 0 : *txd_hi |= ((uint64_t)td_cmd) << ICE_TXD_QW1_CMD_S; 421 : 0 : } 422 : : #endif