From mboxrd@z Thu Jan 1 00:00:00 1970 From: Maxime Coquelin Subject: Re: [PATCH v10 7/9] net/virtio: add virtio send command packed queue support Date: Wed, 28 Nov 2018 18:25:49 +0100 Message-ID: References: <20181102090749.17316-1-jfreimann@redhat.com> <20181102090749.17316-8-jfreimann@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Cc: tiwei.bie@intel.com, Gavin.Hu@arm.com To: Jens Freimann , dev@dpdk.org Return-path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by dpdk.org (Postfix) with ESMTP id 788E01B3BB for ; Wed, 28 Nov 2018 18:25:57 +0100 (CET) In-Reply-To: <20181102090749.17316-8-jfreimann@redhat.com> Content-Language: en-US List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" On 11/2/18 10:07 AM, Jens Freimann wrote: > Use packed virtqueue format when reading and writing descriptors > to/from the ring. > > Signed-off-by: Jens Freimann > --- > drivers/net/virtio/virtio_ethdev.c | 90 ++++++++++++++++++++++++++++++ > 1 file changed, 90 insertions(+) > > diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c > index ed3d5bd2c..4451dd49b 100644 > --- a/drivers/net/virtio/virtio_ethdev.c > +++ b/drivers/net/virtio/virtio_ethdev.c > @@ -141,6 +141,90 @@ static const struct rte_virtio_xstats_name_off rte_virtio_txq_stat_strings[] = { > > struct virtio_hw_internal virtio_hw_internal[RTE_MAX_ETHPORTS]; > > +static struct virtio_pmd_ctrl * > +virtio_pq_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, > + int *dlen, int pkt_num) > +{ > + struct virtqueue *vq = cvq->vq; > + int head; > + struct vring_desc_packed *desc = vq->ring_packed.desc_packed; > + struct virtio_pmd_ctrl *result; > + int wrap_counter; > + int sum = 0; > + int k; > + > + /* > + * Format is enforced in qemu code: > + * One TX packet for header; > + * At least one TX packet per argument; > + * One RX packet for ACK. > + */ > + head = vq->vq_avail_idx; > + wrap_counter = vq->avail_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); > + vq->vq_free_cnt--; > + if (++vq->vq_avail_idx >= vq->vq_nentries) { > + vq->vq_avail_idx -= vq->vq_nentries; > + vq->avail_wrap_counter ^= 1; > + } > + > + for (k = 0; k < pkt_num; k++) { > + desc[vq->vq_avail_idx].addr = cvq->virtio_net_hdr_mem > + + sizeof(struct virtio_net_ctrl_hdr) > + + sizeof(ctrl->status) + sizeof(uint8_t) * sum; > + desc[vq->vq_avail_idx].len = dlen[k]; > + desc[vq->vq_avail_idx].flags = VRING_DESC_F_NEXT; > + sum += dlen[k]; > + vq->vq_free_cnt--; > + _set_desc_avail(&desc[vq->vq_avail_idx], > + vq->avail_wrap_counter); > + rte_smp_wmb(); > + vq->vq_free_cnt--; > + if (++vq->vq_avail_idx >= vq->vq_nentries) { > + vq->vq_avail_idx -= vq->vq_nentries; > + vq->avail_wrap_counter ^= 1; > + } > + } > + > + > + desc[vq->vq_avail_idx].addr = cvq->virtio_net_hdr_mem > + + sizeof(struct virtio_net_ctrl_hdr); > + desc[vq->vq_avail_idx].len = sizeof(ctrl->status); > + desc[vq->vq_avail_idx].flags = VRING_DESC_F_WRITE; > + _set_desc_avail(&desc[vq->vq_avail_idx], > + vq->avail_wrap_counter); > + _set_desc_avail(&desc[head], wrap_counter); > + rte_smp_wmb(); > + > + vq->vq_free_cnt--; > + if (++vq->vq_avail_idx >= vq->vq_nentries) { > + vq->vq_avail_idx -= vq->vq_nentries; > + vq->avail_wrap_counter ^= 1; > + } > + > + virtqueue_notify(vq); > + > + /* wait for used descriptors in virtqueue */ > + do { > + rte_rmb(); > + usleep(100); > + } while (!desc_is_used(&desc[head], vq)); Maybe better to poll for !desc_is_used(&desc[vq->vq_used_cons_idx], vq)) to make it clear we're safe using used_wrap_counter? > + > + /* now get used descriptors */ > + while(desc_is_used(&desc[vq->vq_used_cons_idx], vq)) { > + vq->vq_free_cnt++; > + if (++vq->vq_used_cons_idx >= vq->vq_nentries) { > + vq->vq_used_cons_idx -= vq->vq_nentries; > + vq->used_wrap_counter ^= 1; > + } > + } > + > + result = cvq->virtio_net_hdr_mz->addr; > + return result; > +} > + > static int > virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, > int *dlen, int pkt_num) > @@ -174,6 +258,11 @@ virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, > memcpy(cvq->virtio_net_hdr_mz->addr, ctrl, > sizeof(struct virtio_pmd_ctrl)); > > + if (vtpci_packed_queue(vq->hw)) { > + result = virtio_pq_send_command(cvq, ctrl, dlen, pkt_num); > + goto out_unlock; > + } > + > /* > * Format is enforced in qemu code: > * One TX packet for header; > @@ -245,6 +334,7 @@ virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, > > result = cvq->virtio_net_hdr_mz->addr; > > +out_unlock: > rte_spinlock_unlock(&cvq->lock); > return result->status; > } >