net/virtio: check head desc with correct wrap counter

In virtio_pq_send_command() we check for a used descriptor
and wait in an idle loop until it becomes used. We can't use
vq->used_wrap_counter here to check for the first descriptor
we made available because the ring could have wrapped. Let's use
the used_wrap_counter that matches the state of the head descriptor.

Fixes: ec194c2f18 ("net/virtio: support packed queue in send command")

Signed-off-by: Jens Freimann <jfreimann@redhat.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
This commit is contained in:
Jens Freimann 2019-01-11 10:39:28 +01:00 committed by Ferruh Yigit
parent 9230ab8d79
commit a4270ea4ff
2 changed files with 14 additions and 7 deletions

View File

@ -149,7 +149,7 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
int head;
struct vring_packed_desc *desc = vq->ring_packed.desc_packed;
struct virtio_pmd_ctrl *result;
int wrap_counter;
bool avail_wrap_counter, used_wrap_counter;
uint16_t flags;
int sum = 0;
int k;
@ -161,7 +161,8 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
* One RX packet for ACK.
*/
head = vq->vq_avail_idx;
wrap_counter = vq->avail_wrap_counter;
avail_wrap_counter = vq->avail_wrap_counter;
used_wrap_counter = vq->used_wrap_counter;
desc[head].flags = VRING_DESC_F_NEXT;
desc[head].addr = cvq->virtio_net_hdr_mem;
desc[head].len = sizeof(struct virtio_net_ctrl_hdr);
@ -199,8 +200,8 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
VRING_DESC_F_USED(!vq->avail_wrap_counter);
desc[vq->vq_avail_idx].flags = flags;
flags = VRING_DESC_F_NEXT;
flags |= VRING_DESC_F_AVAIL(wrap_counter) |
VRING_DESC_F_USED(!wrap_counter);
flags |= VRING_DESC_F_AVAIL(avail_wrap_counter) |
VRING_DESC_F_USED(!avail_wrap_counter);
desc[head].flags = flags;
rte_smp_wmb();
@ -216,7 +217,7 @@ virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
do {
rte_rmb();
usleep(100);
} while (!desc_is_used(&desc[head], vq));
} while (!__desc_is_used(&desc[head], used_wrap_counter));
/* now get used descriptors */
while (desc_is_used(&desc[vq->vq_used_cons_idx], vq)) {

View File

@ -281,7 +281,7 @@ struct virtio_tx_region {
};
static inline int
desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq)
__desc_is_used(struct vring_packed_desc *desc, bool wrap_counter)
{
uint16_t used, avail, flags;
@ -289,7 +289,13 @@ desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq)
used = !!(flags & VRING_DESC_F_USED(1));
avail = !!(flags & VRING_DESC_F_AVAIL(1));
return avail == used && used == vq->used_wrap_counter;
return avail == used && used == wrap_counter;
}
static inline int
desc_is_used(struct vring_packed_desc *desc, struct virtqueue *vq)
{
return __desc_is_used(desc, vq->used_wrap_counter);
}