| 765 | } |
| 766 | |
| 767 | static __rte_always_inline int |
| 768 | fill_vec_buf_split(struct virtio_net *dev, struct vhost_virtqueue *vq, |
| 769 | uint32_t avail_idx, uint16_t *vec_idx, |
| 770 | struct buf_vector *buf_vec, uint16_t *desc_chain_head, |
| 771 | uint32_t *desc_chain_len, uint8_t perm) |
| 772 | __rte_shared_locks_required(&vq->iotlb_lock) |
| 773 | { |
| 774 | uint16_t idx = vq->avail->ring[avail_idx & (vq->size - 1)]; |
| 775 | uint16_t vec_id = *vec_idx; |
| 776 | uint32_t len = 0; |
| 777 | uint64_t dlen; |
| 778 | uint32_t nr_descs = vq->size; |
| 779 | uint32_t cnt = 0; |
| 780 | struct vring_desc *descs = vq->desc; |
| 781 | struct vring_desc *idesc = NULL; |
| 782 | |
| 783 | if (unlikely(idx >= vq->size)) |
| 784 | return -1; |
| 785 | |
| 786 | *desc_chain_head = idx; |
| 787 | |
| 788 | if (vq->desc[idx].flags & VRING_DESC_F_INDIRECT) { |
| 789 | dlen = vq->desc[idx].len; |
| 790 | nr_descs = dlen / sizeof(struct vring_desc); |
| 791 | if (unlikely(nr_descs > vq->size)) |
| 792 | return -1; |
| 793 | |
| 794 | descs = (struct vring_desc *)(uintptr_t) |
| 795 | vhost_iova_to_vva(dev, vq, vq->desc[idx].addr, |
| 796 | &dlen, |
| 797 | VHOST_ACCESS_RO); |
| 798 | if (unlikely(!descs)) |
| 799 | return -1; |
| 800 | |
| 801 | if (unlikely(dlen < vq->desc[idx].len)) { |
| 802 | /* |
| 803 | * The indirect desc table is not contiguous |
| 804 | * in process VA space, we have to copy it. |
| 805 | */ |
| 806 | idesc = vhost_alloc_copy_ind_table(dev, vq, |
| 807 | vq->desc[idx].addr, vq->desc[idx].len); |
| 808 | if (unlikely(!idesc)) |
| 809 | return -1; |
| 810 | |
| 811 | descs = idesc; |
| 812 | } |
| 813 | |
| 814 | idx = 0; |
| 815 | } |
| 816 | |
| 817 | while (1) { |
| 818 | if (unlikely(idx >= nr_descs || cnt++ >= nr_descs)) { |
| 819 | free_ind_table(idesc); |
| 820 | return -1; |
| 821 | } |
| 822 | |
| 823 | dlen = descs[idx].len; |
| 824 | len += dlen; |
no test coverage detected