| 321 | } |
| 322 | |
| 323 | int |
| 324 | ionic_tx_tso(struct ionic_tx_qcq *txq, struct rte_mbuf *txm) |
| 325 | { |
| 326 | struct ionic_queue *q = &txq->qcq.q; |
| 327 | struct ionic_tx_stats *stats = &txq->stats; |
| 328 | struct ionic_txq_desc *desc; |
| 329 | struct ionic_txq_sg_elem *elem; |
| 330 | struct rte_mbuf *txm_seg; |
| 331 | rte_iova_t data_iova; |
| 332 | uint64_t desc_addr = 0, next_addr; |
| 333 | uint16_t desc_len = 0; |
| 334 | uint8_t desc_nsge = 0; |
| 335 | uint32_t hdrlen; |
| 336 | uint32_t mss = txm->tso_segsz; |
| 337 | uint32_t frag_left = 0; |
| 338 | uint32_t left; |
| 339 | uint32_t seglen; |
| 340 | uint32_t len; |
| 341 | uint32_t offset = 0; |
| 342 | bool start, done; |
| 343 | bool encap; |
| 344 | bool has_vlan = !!(txm->ol_flags & RTE_MBUF_F_TX_VLAN); |
| 345 | bool use_sgl = !!(txq->flags & IONIC_QCQ_F_SG); |
| 346 | uint16_t vlan_tci = txm->vlan_tci; |
| 347 | uint64_t ol_flags = txm->ol_flags; |
| 348 | |
| 349 | encap = ((ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM) || |
| 350 | (ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM)) && |
| 351 | ((ol_flags & RTE_MBUF_F_TX_OUTER_IPV4) || |
| 352 | (ol_flags & RTE_MBUF_F_TX_OUTER_IPV6)); |
| 353 | |
| 354 | /* Preload inner-most TCP csum field with IP pseudo hdr |
| 355 | * calculated with IP length set to zero. HW will later |
| 356 | * add in length to each TCP segment resulting from the TSO. |
| 357 | */ |
| 358 | |
| 359 | if (encap) { |
| 360 | ionic_tx_tcp_inner_pseudo_csum(txm); |
| 361 | hdrlen = txm->outer_l2_len + txm->outer_l3_len + |
| 362 | txm->l2_len + txm->l3_len + txm->l4_len; |
| 363 | } else { |
| 364 | ionic_tx_tcp_pseudo_csum(txm); |
| 365 | hdrlen = txm->l2_len + txm->l3_len + txm->l4_len; |
| 366 | } |
| 367 | |
| 368 | desc = ionic_tx_tso_next(txq, &elem); |
| 369 | txm_seg = txm; |
| 370 | start = true; |
| 371 | seglen = hdrlen + mss; |
| 372 | |
| 373 | /* Walk the chain of mbufs */ |
| 374 | while (txm_seg != NULL) { |
| 375 | offset = 0; |
| 376 | data_iova = rte_mbuf_data_iova(txm_seg); |
| 377 | left = txm_seg->data_len; |
| 378 | |
| 379 | /* Split the mbuf data up into multiple descriptors */ |
| 380 | while (left > 0) { |
no test coverage detected