| 545 | } |
| 546 | |
| 547 | static inline void |
| 548 | virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie, |
| 549 | uint16_t needed, int use_indirect, int can_push, |
| 550 | int in_order) |
| 551 | { |
| 552 | struct virtio_tx_region *txr = txvq->hdr_mz->addr; |
| 553 | struct vq_desc_extra *dxp; |
| 554 | struct virtqueue *vq = virtnet_txq_to_vq(txvq); |
| 555 | struct vring_desc *start_dp; |
| 556 | uint16_t seg_num = cookie->nb_segs; |
| 557 | uint16_t head_idx, idx; |
| 558 | int16_t head_size = vq->hw->vtnet_hdr_size; |
| 559 | bool prepend_header = false; |
| 560 | struct virtio_net_hdr *hdr; |
| 561 | |
| 562 | head_idx = vq->vq_desc_head_idx; |
| 563 | idx = head_idx; |
| 564 | if (in_order) |
| 565 | dxp = &vq->vq_descx[vq->vq_avail_idx & (vq->vq_nentries - 1)]; |
| 566 | else |
| 567 | dxp = &vq->vq_descx[idx]; |
| 568 | dxp->cookie = (void *)cookie; |
| 569 | dxp->ndescs = needed; |
| 570 | |
| 571 | start_dp = vq->vq_split.ring.desc; |
| 572 | |
| 573 | if (can_push) { |
| 574 | /* prepend cannot fail, checked by caller */ |
| 575 | hdr = rte_pktmbuf_mtod_offset(cookie, struct virtio_net_hdr *, |
| 576 | -head_size); |
| 577 | prepend_header = true; |
| 578 | |
| 579 | /* if offload disabled, it is not zeroed below, do it now */ |
| 580 | if (!vq->hw->has_tx_offload) |
| 581 | virtqueue_clear_net_hdr(hdr); |
| 582 | } else if (use_indirect) { |
| 583 | /* setup tx ring slot to point to indirect |
| 584 | * descriptor list stored in reserved region. |
| 585 | * |
| 586 | * the first slot in indirect ring is already preset |
| 587 | * to point to the header in reserved region |
| 588 | */ |
| 589 | start_dp[idx].addr = txvq->hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_indir, txr); |
| 590 | start_dp[idx].len = (seg_num + 1) * sizeof(struct vring_desc); |
| 591 | start_dp[idx].flags = VRING_DESC_F_INDIRECT; |
| 592 | hdr = (struct virtio_net_hdr *)&txr[idx].tx_hdr; |
| 593 | |
| 594 | /* loop below will fill in rest of the indirect elements */ |
| 595 | start_dp = txr[idx].tx_indir; |
| 596 | idx = 1; |
| 597 | } else { |
| 598 | /* setup first tx ring slot to point to header |
| 599 | * stored in reserved region. |
| 600 | */ |
| 601 | start_dp[idx].addr = txvq->hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_hdr, txr); |
| 602 | start_dp[idx].len = vq->hw->vtnet_hdr_size; |
| 603 | start_dp[idx].flags = VRING_DESC_F_NEXT; |
| 604 | hdr = (struct virtio_net_hdr *)&txr[idx].tx_hdr; |
no test coverage detected