| 617 | } |
| 618 | |
| 619 | static inline void |
| 620 | virtqueue_enqueue_xmit_packed(struct virtnet_tx *txvq, struct rte_mbuf *cookie, |
| 621 | uint16_t needed, int use_indirect, int can_push, |
| 622 | int in_order) |
| 623 | { |
| 624 | struct virtio_tx_region *txr = txvq->hdr_mz->addr; |
| 625 | struct vq_desc_extra *dxp; |
| 626 | struct virtqueue *vq = virtnet_txq_to_vq(txvq); |
| 627 | struct vring_packed_desc *start_dp, *head_dp; |
| 628 | uint16_t idx, id, head_idx, head_flags; |
| 629 | int16_t head_size = vq->hw->vtnet_hdr_size; |
| 630 | struct virtio_net_hdr *hdr; |
| 631 | uint16_t prev; |
| 632 | bool prepend_header = false; |
| 633 | uint16_t seg_num = cookie->nb_segs; |
| 634 | |
| 635 | id = in_order ? vq->vq_avail_idx : vq->vq_desc_head_idx; |
| 636 | |
| 637 | dxp = &vq->vq_descx[id]; |
| 638 | dxp->ndescs = needed; |
| 639 | dxp->cookie = cookie; |
| 640 | |
| 641 | head_idx = vq->vq_avail_idx; |
| 642 | idx = head_idx; |
| 643 | prev = head_idx; |
| 644 | start_dp = vq->vq_packed.ring.desc; |
| 645 | |
| 646 | head_dp = &vq->vq_packed.ring.desc[idx]; |
| 647 | head_flags = cookie->next ? VRING_DESC_F_NEXT : 0; |
| 648 | head_flags |= vq->vq_packed.cached_flags; |
| 649 | |
| 650 | if (can_push) { |
| 651 | /* prepend cannot fail, checked by caller */ |
| 652 | hdr = rte_pktmbuf_mtod_offset(cookie, struct virtio_net_hdr *, |
| 653 | -head_size); |
| 654 | prepend_header = true; |
| 655 | |
| 656 | /* if offload disabled, it is not zeroed below, do it now */ |
| 657 | if (!vq->hw->has_tx_offload) |
| 658 | virtqueue_clear_net_hdr(hdr); |
| 659 | } else if (use_indirect) { |
| 660 | /* setup tx ring slot to point to indirect |
| 661 | * descriptor list stored in reserved region. |
| 662 | * |
| 663 | * the first slot in indirect ring is already preset |
| 664 | * to point to the header in reserved region |
| 665 | */ |
| 666 | start_dp[idx].addr = txvq->hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_packed_indir, txr); |
| 667 | start_dp[idx].len = (seg_num + 1) * sizeof(struct vring_packed_desc); |
| 668 | /* Packed descriptor id needs to be restored when inorder. */ |
| 669 | if (in_order) |
| 670 | start_dp[idx].id = idx; |
| 671 | /* reset flags for indirect desc */ |
| 672 | head_flags = VRING_DESC_F_INDIRECT; |
| 673 | head_flags |= vq->vq_packed.cached_flags; |
| 674 | hdr = (struct virtio_net_hdr *)&txr[idx].tx_hdr; |
| 675 | |
| 676 | /* loop below will fill in rest of the indirect elements */ |
no test coverage detected