| 108 | } |
| 109 | |
| 110 | static struct virtio_pmd_ctrl * |
| 111 | virtio_send_command_split(struct virtnet_ctl *cvq, |
| 112 | struct virtio_pmd_ctrl *ctrl, |
| 113 | int *dlen, int pkt_num) |
| 114 | { |
| 115 | struct virtio_pmd_ctrl *result; |
| 116 | struct virtqueue *vq = virtnet_cq_to_vq(cvq); |
| 117 | uint32_t head, i; |
| 118 | int k, sum = 0; |
| 119 | |
| 120 | head = vq->vq_desc_head_idx; |
| 121 | |
| 122 | /* |
| 123 | * Format is enforced in qemu code: |
| 124 | * One TX packet for header; |
| 125 | * At least one TX packet per argument; |
| 126 | * One RX packet for ACK. |
| 127 | */ |
| 128 | vq->vq_split.ring.desc[head].flags = VRING_DESC_F_NEXT; |
| 129 | vq->vq_split.ring.desc[head].addr = cvq->hdr_mem; |
| 130 | vq->vq_split.ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr); |
| 131 | vq->vq_free_cnt--; |
| 132 | i = vq->vq_split.ring.desc[head].next; |
| 133 | |
| 134 | for (k = 0; k < pkt_num; k++) { |
| 135 | vq->vq_split.ring.desc[i].flags = VRING_DESC_F_NEXT; |
| 136 | vq->vq_split.ring.desc[i].addr = cvq->hdr_mem |
| 137 | + sizeof(struct virtio_net_ctrl_hdr) |
| 138 | + sizeof(ctrl->status) + sizeof(uint8_t) * sum; |
| 139 | vq->vq_split.ring.desc[i].len = dlen[k]; |
| 140 | sum += dlen[k]; |
| 141 | vq->vq_free_cnt--; |
| 142 | i = vq->vq_split.ring.desc[i].next; |
| 143 | } |
| 144 | |
| 145 | vq->vq_split.ring.desc[i].flags = VRING_DESC_F_WRITE; |
| 146 | vq->vq_split.ring.desc[i].addr = cvq->hdr_mem |
| 147 | + sizeof(struct virtio_net_ctrl_hdr); |
| 148 | vq->vq_split.ring.desc[i].len = sizeof(ctrl->status); |
| 149 | vq->vq_free_cnt--; |
| 150 | |
| 151 | vq->vq_desc_head_idx = vq->vq_split.ring.desc[i].next; |
| 152 | |
| 153 | vq_update_avail_ring(vq, head); |
| 154 | vq_update_avail_idx(vq); |
| 155 | |
| 156 | PMD_INIT_LOG(DEBUG, "vq->vq_queue_index = %d", vq->vq_queue_index); |
| 157 | |
| 158 | cvq->notify_queue(vq, cvq->notify_cookie); |
| 159 | |
| 160 | while (virtqueue_nused(vq) == 0) |
| 161 | usleep(100); |
| 162 | |
| 163 | while (virtqueue_nused(vq)) { |
| 164 | uint32_t idx, desc_idx, used_idx; |
| 165 | struct vring_used_elem *uep; |
| 166 | |
| 167 | used_idx = (uint32_t)(vq->vq_used_cons_idx |
no test coverage detected