From 47d9763a1dd3103d732da9eec350cfc1cd784717 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 8 Dec 2017 17:16:13 +0000 Subject: New upstream version 16.11.4 Change-Id: I733e0292d2e060161d148b3e114065d00b36d2ba Signed-off-by: Luca Boccassi --- drivers/net/virtio/virtio_ethdev.c | 15 +++++++++ drivers/net/virtio/virtio_ethdev.h | 6 ++++ drivers/net/virtio/virtio_rxtx.c | 48 +++++++++++++++++++++++------ drivers/net/virtio/virtio_rxtx_simple.c | 2 ++ drivers/net/virtio/virtio_user/vhost_user.c | 4 +++ drivers/net/virtio/virtqueue.c | 25 +++++++++++++++ drivers/net/virtio/virtqueue.h | 5 +++ 7 files changed, 95 insertions(+), 10 deletions(-) (limited to 'drivers/net/virtio') diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 67ebb1e5..8592485d 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1523,6 +1523,19 @@ virtio_dev_start(struct rte_eth_dev *dev) struct virtnet_rx *rxvq; struct virtnet_tx *txvq __rte_unused; struct virtio_hw *hw = dev->data->dev_private; + int ret; + + /* Finish the initialization of the queues */ + for (i = 0; i < dev->data->nb_rx_queues; i++) { + ret = virtio_dev_rx_queue_setup_finish(dev, i); + if (ret < 0) + return ret; + } + for (i = 0; i < dev->data->nb_tx_queues; i++) { + ret = virtio_dev_tx_queue_setup_finish(dev, i); + if (ret < 0) + return ret; + } /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc) { @@ -1551,6 +1564,8 @@ virtio_dev_start(struct rte_eth_dev *dev) for (i = 0; i < dev->data->nb_rx_queues; i++) { rxvq = dev->data->rx_queues[i]; + /* Flush the old packets */ + virtqueue_flush(rxvq->vq); virtqueue_notify(rxvq->vq); } diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index 4feccf93..c491ec1b 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -88,10 +88,16 @@ int virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); +int virtio_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, + uint16_t rx_queue_id); + int virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); +int virtio_dev_tx_queue_setup_finish(struct rte_eth_dev *dev, + uint16_t tx_queue_id); + uint16_t virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index a33ef1a8..43fac63b 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -72,7 +72,7 @@ #define VIRTIO_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ ETH_TXQ_FLAGS_NOOFFLOADS) -static void +void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) { struct vring_desc *dp, *dp_tail; @@ -291,6 +291,10 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie, /* prepend cannot fail, checked by caller */ hdr = (struct virtio_net_hdr *) rte_pktmbuf_prepend(cookie, head_size); + /* rte_pktmbuf_prepend() counts the hdr size to the pkt length, + * which is wrong. Below subtract restores correct pkt size. + */ + cookie->pkt_len -= head_size; /* if offload disabled, it is not zeroed below, do it now */ if (offload == 0) { ASSIGN_UNLESS_EQUAL(hdr->csum_start, 0); @@ -412,9 +416,6 @@ virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, struct virtio_hw *hw = dev->data->dev_private; struct virtqueue *vq = hw->vqs[vtpci_queue_idx]; struct virtnet_rx *rxvq; - int error, nbufs; - struct rte_mbuf *m; - uint16_t desc_idx; PMD_INIT_FUNC_TRACE(); @@ -431,10 +432,24 @@ virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, } dev->data->rx_queues[queue_idx] = rxvq; + return 0; +} + +int +virtio_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_idx) +{ + uint16_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_RQ_QUEUE_IDX; + struct virtio_hw *hw = dev->data->dev_private; + struct virtqueue *vq = hw->vqs[vtpci_queue_idx]; + struct virtnet_rx *rxvq = &vq->rxq; + struct rte_mbuf *m; + uint16_t desc_idx; + int error, nbufs; + + PMD_INIT_FUNC_TRACE(); /* Allocate blank mbufs for the each rx descriptor */ nbufs = 0; - error = ENOSPC; if (hw->use_simple_rxtx) { for (desc_idx = 0; desc_idx < vq->vq_nentries; @@ -525,7 +540,6 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, struct virtqueue *vq = hw->vqs[vtpci_queue_idx]; struct virtnet_tx *txvq; uint16_t tx_free_thresh; - uint16_t desc_idx; PMD_INIT_FUNC_TRACE(); @@ -554,9 +568,24 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, vq->vq_free_thresh = tx_free_thresh; - if (hw->use_simple_rxtx) { - uint16_t mid_idx = vq->vq_nentries >> 1; + dev->data->tx_queues[queue_idx] = txvq; + return 0; +} + +int +virtio_dev_tx_queue_setup_finish(struct rte_eth_dev *dev, + uint16_t queue_idx) +{ + uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; + struct virtio_hw *hw = dev->data->dev_private; + struct virtqueue *vq = hw->vqs[vtpci_queue_idx]; + uint16_t mid_idx = vq->vq_nentries >> 1; + struct virtnet_tx *txvq = &vq->txq; + uint16_t desc_idx; + PMD_INIT_FUNC_TRACE(); + + if (hw->use_simple_rxtx) { for (desc_idx = 0; desc_idx < mid_idx; desc_idx++) { vq->vq_ring.avail->ring[desc_idx] = desc_idx + mid_idx; @@ -578,7 +607,6 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, VIRTQUEUE_DUMP(vq); - dev->data->tx_queues[queue_idx] = txvq; return 0; } @@ -661,7 +689,7 @@ virtio_rx_offload(struct rte_mbuf *m, struct virtio_net_hdr *hdr) * In case of SCTP, this will be wrong since it's a CRC * but there's nothing we can do. */ - uint16_t csum, off; + uint16_t csum = 0, off; rte_raw_cksum_mbuf(m, hdr->csum_start, rte_pktmbuf_pkt_len(m) - hdr->csum_start, diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c index b651e53b..a6c0b34e 100644 --- a/drivers/net/virtio/virtio_rxtx_simple.c +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -65,6 +65,8 @@ virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, struct vring_desc *start_dp; uint16_t desc_idx; + cookie->port = vq->rxq.port_id; + desc_idx = vq->vq_avail_idx & (vq->vq_nentries - 1); dxp = &vq->vq_descx[desc_idx]; dxp->cookie = (void *)cookie; diff --git a/drivers/net/virtio/virtio_user/vhost_user.c b/drivers/net/virtio/virtio_user/vhost_user.c index 082e8217..6f4845b7 100644 --- a/drivers/net/virtio/virtio_user/vhost_user.c +++ b/drivers/net/virtio/virtio_user/vhost_user.c @@ -97,6 +97,10 @@ vhost_user_read(int fd, struct vhost_user_msg *msg) } sz_payload = msg->size; + + if ((size_t)sz_payload > sizeof(msg->payload)) + goto fail; + if (sz_payload) { ret = recv(fd, (void *)((char *)msg + sz_hdr), sz_payload, 0); if (ret < sz_payload) { diff --git a/drivers/net/virtio/virtqueue.c b/drivers/net/virtio/virtqueue.c index 7f60e3ef..4f8707ae 100644 --- a/drivers/net/virtio/virtqueue.c +++ b/drivers/net/virtio/virtqueue.c @@ -70,3 +70,28 @@ virtqueue_detatch_unused(struct virtqueue *vq) } return NULL; } + +/* Flush the elements in the used ring. */ +void +virtqueue_flush(struct virtqueue *vq) +{ + struct vring_used_elem *uep; + struct vq_desc_extra *dxp; + uint16_t used_idx, desc_idx; + uint16_t nb_used, i; + + nb_used = VIRTQUEUE_NUSED(vq); + + for (i = 0; i < nb_used; i++) { + used_idx = vq->vq_used_cons_idx & (vq->vq_nentries - 1); + uep = &vq->vq_ring.used->ring[used_idx]; + desc_idx = (uint16_t)uep->id; + dxp = &vq->vq_descx[desc_idx]; + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + vq->vq_used_cons_idx++; + vq_ring_free_chain(vq, desc_idx); + } +} diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 569c251c..ec967a5b 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -290,6 +290,9 @@ void virtqueue_dump(struct virtqueue *vq); */ struct rte_mbuf *virtqueue_detatch_unused(struct virtqueue *vq); +/* Flush the elements in the used ring. */ +void virtqueue_flush(struct virtqueue *vq); + static inline int virtqueue_full(const struct virtqueue *vq) { @@ -298,6 +301,8 @@ virtqueue_full(const struct virtqueue *vq) #define VIRTQUEUE_NUSED(vq) ((uint16_t)((vq)->vq_ring.used->idx - (vq)->vq_used_cons_idx)) +void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx); + static inline void vq_update_avail_idx(struct virtqueue *vq) { -- cgit 1.2.3-korg