X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_ethdev.c;h=0ee1fab4d8d9e38b6dc60fb88e70b915e221c4e4;hb=727411f50ae33c5e318f3c9579c9cdd56eb2a5be;hp=1f0e239f3d0c6050cfcb3dce8ccc9a692af353c0;hpb=1978a9dc57f0e9bd83c64c31ec99a8869ab5a133;p=dpdk.git diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 1f0e239f3d..0ee1fab4d8 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -81,6 +83,9 @@ static int virtio_dev_queue_stats_mapping_set( int virtio_logtype_init; int virtio_logtype_driver; +static void virtio_notify_peers(struct rte_eth_dev *dev); +static void virtio_ack_link_announce(struct rte_eth_dev *dev); + /* * The set of PCI devices this driver supports */ @@ -274,17 +279,6 @@ virtio_dev_queue_release(void *queue __rte_unused) /* do nothing */ } -static int -virtio_get_queue_type(struct virtio_hw *hw, uint16_t vtpci_queue_idx) -{ - if (vtpci_queue_idx == hw->max_queue_pairs * 2) - return VTNET_CQ; - else if (vtpci_queue_idx % 2 == 0) - return VTNET_RQ; - else - return VTNET_TQ; -} - static uint16_t virtio_get_nr_vq(struct virtio_hw *hw) { @@ -1275,9 +1269,46 @@ virtio_inject_pkts(struct rte_eth_dev *dev, struct rte_mbuf **tx_pkts, return ret; } +static void +virtio_notify_peers(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtnet_rx *rxvq = dev->data->rx_queues[0]; + struct rte_mbuf *rarp_mbuf; + + rarp_mbuf = rte_net_make_rarp_packet(rxvq->mpool, + (struct ether_addr *)hw->mac_addr); + if (rarp_mbuf == NULL) { + PMD_DRV_LOG(ERR, "failed to make RARP packet."); + return; + } + + /* If virtio port just stopped, no need to send RARP */ + if (virtio_dev_pause(dev) < 0) { + rte_pktmbuf_free(rarp_mbuf); + return; + } + + virtio_inject_pkts(dev, &rarp_mbuf, 1); + virtio_dev_resume(dev); +} + +static void +virtio_ack_link_announce(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtio_pmd_ctrl ctrl; + + ctrl.hdr.class = VIRTIO_NET_CTRL_ANNOUNCE; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_ANNOUNCE_ACK; + + virtio_send_command(hw->cvq, &ctrl, NULL, 0); +} + /* - * Process Virtio Config changed interrupt and call the callback - * if link state changed. + * Process virtio config changed interrupt. Call the callback + * if link state changed, generate gratuitous RARP packet if + * the status indicates an ANNOUNCE. */ void virtio_interrupt_handler(void *param) @@ -1300,6 +1331,10 @@ virtio_interrupt_handler(void *param) NULL); } + if (isr & VIRTIO_NET_S_ANNOUNCE) { + virtio_notify_peers(dev); + virtio_ack_link_announce(dev); + } } /* set rx and tx handlers according to what is supported */ @@ -1436,6 +1471,11 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features) /* Reset the device although not necessary at startup */ vtpci_reset(hw); + if (hw->vqs) { + virtio_dev_free_mbufs(eth_dev); + virtio_free_queues(hw); + } + /* Tell the host we've noticed this device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); @@ -1819,7 +1859,7 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->use_simple_rx = 1; hw->use_simple_tx = 1; -#if defined RTE_ARCH_ARM64 || defined CONFIG_RTE_ARCH_ARM +#if defined RTE_ARCH_ARM64 || defined RTE_ARCH_ARM if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) { hw->use_simple_rx = 0; hw->use_simple_tx = 0; @@ -1927,47 +1967,44 @@ virtio_dev_start(struct rte_eth_dev *dev) static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) { + struct virtio_hw *hw = dev->data->dev_private; + uint16_t nr_vq = virtio_get_nr_vq(hw); + const char *type __rte_unused; + unsigned int i, mbuf_num = 0; + struct virtqueue *vq; struct rte_mbuf *buf; - int i, mbuf_num = 0; - - for (i = 0; i < dev->data->nb_rx_queues; i++) { - struct virtnet_rx *rxvq = dev->data->rx_queues[i]; - - PMD_INIT_LOG(DEBUG, - "Before freeing rxq[%d] used and unused buf", i); - VIRTQUEUE_DUMP(rxvq->vq); - - PMD_INIT_LOG(DEBUG, "rx_queues[%d]=%p", i, rxvq); - while ((buf = virtqueue_detatch_unused(rxvq->vq)) != NULL) { - rte_pktmbuf_free(buf); - mbuf_num++; - } + int queue_type; - PMD_INIT_LOG(DEBUG, "free %d mbufs", mbuf_num); - PMD_INIT_LOG(DEBUG, - "After freeing rxq[%d] used and unused buf", i); - VIRTQUEUE_DUMP(rxvq->vq); - } + for (i = 0; i < nr_vq; i++) { + vq = hw->vqs[i]; + if (!vq) + continue; - for (i = 0; i < dev->data->nb_tx_queues; i++) { - struct virtnet_tx *txvq = dev->data->tx_queues[i]; + queue_type = virtio_get_queue_type(hw, i); + if (queue_type == VTNET_RQ) + type = "rxq"; + else if (queue_type == VTNET_TQ) + type = "txq"; + else + continue; PMD_INIT_LOG(DEBUG, - "Before freeing txq[%d] used and unused bufs", - i); - VIRTQUEUE_DUMP(txvq->vq); + "Before freeing %s[%d] used and unused buf", + type, i); + VIRTQUEUE_DUMP(vq); - mbuf_num = 0; - while ((buf = virtqueue_detatch_unused(txvq->vq)) != NULL) { + while ((buf = virtqueue_detach_unused(vq)) != NULL) { rte_pktmbuf_free(buf); mbuf_num++; } - PMD_INIT_LOG(DEBUG, "free %d mbufs", mbuf_num); PMD_INIT_LOG(DEBUG, - "After freeing txq[%d] used and unused buf", i); - VIRTQUEUE_DUMP(txvq->vq); + "After freeing %s[%d] used and unused buf", + type, i); + VIRTQUEUE_DUMP(vq); } + + PMD_INIT_LOG(DEBUG, "%d mbufs freed", mbuf_num); } /*