X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_ethdev.c;h=76bd40a3e4aed62c627951b73a993a48f658bc18;hb=13b3137f3b7c8f866947a9b34e06a8aec0d084f7;hp=46d2e4ac60ec2fc89722a33dac51005eda23ee4d;hpb=3484c8d859b48f41c8958614736cc64f0e203f4c;p=dpdk.git diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 46d2e4ac60..76bd40a3e4 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -35,16 +35,17 @@ #include "virtio_logs.h" #include "virtqueue.h" #include "virtio_rxtx.h" +#include "virtio_user/virtio_user_dev.h" static int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev); static int virtio_dev_configure(struct rte_eth_dev *dev); static int virtio_dev_start(struct rte_eth_dev *dev); static void virtio_dev_stop(struct rte_eth_dev *dev); -static void virtio_dev_promiscuous_enable(struct rte_eth_dev *dev); -static void virtio_dev_promiscuous_disable(struct rte_eth_dev *dev); -static void virtio_dev_allmulticast_enable(struct rte_eth_dev *dev); -static void virtio_dev_allmulticast_disable(struct rte_eth_dev *dev); -static void virtio_dev_info_get(struct rte_eth_dev *dev, +static int virtio_dev_promiscuous_enable(struct rte_eth_dev *dev); +static int virtio_dev_promiscuous_disable(struct rte_eth_dev *dev); +static int virtio_dev_allmulticast_enable(struct rte_eth_dev *dev); +static int virtio_dev_allmulticast_disable(struct rte_eth_dev *dev); +static int virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int virtio_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); @@ -60,7 +61,7 @@ static int virtio_dev_xstats_get(struct rte_eth_dev *dev, static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); -static void virtio_dev_stats_reset(struct rte_eth_dev *dev); +static int virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); @@ -120,7 +121,6 @@ static const struct rte_virtio_xstats_name_off rte_virtio_rxq_stat_strings[] = { static const struct rte_virtio_xstats_name_off rte_virtio_txq_stat_strings[] = { {"good_packets", offsetof(struct virtnet_tx, stats.packets)}, {"good_bytes", offsetof(struct virtnet_tx, stats.bytes)}, - {"errors", offsetof(struct virtnet_tx, stats.errors)}, {"multicast_packets", offsetof(struct virtnet_tx, stats.multicast)}, {"broadcast_packets", offsetof(struct virtnet_tx, stats.broadcast)}, {"undersize_packets", offsetof(struct virtnet_tx, stats.size_bins[0])}, @@ -733,9 +733,20 @@ virtio_dev_close(struct rte_eth_dev *dev) vtpci_reset(hw); virtio_dev_free_mbufs(dev); virtio_free_queues(hw); + +#ifdef RTE_VIRTIO_USER + if (hw->virtio_user_dev) + virtio_user_dev_uninit(hw->virtio_user_dev); + else +#endif + if (dev->device) { + rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(dev)); + if (!hw->modern) + rte_pci_ioport_unmap(VTPCI_IO(hw)); + } } -static void +static int virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; @@ -745,7 +756,7 @@ virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control"); - return; + return -ENOTSUP; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; @@ -754,11 +765,15 @@ virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); - if (ret) + if (ret) { PMD_INIT_LOG(ERR, "Failed to enable promisc"); + return -EAGAIN; + } + + return 0; } -static void +static int virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; @@ -768,7 +783,7 @@ virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control"); - return; + return -ENOTSUP; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; @@ -777,11 +792,15 @@ virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); - if (ret) + if (ret) { PMD_INIT_LOG(ERR, "Failed to disable promisc"); + return -EAGAIN; + } + + return 0; } -static void +static int virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; @@ -791,7 +810,7 @@ virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control"); - return; + return -ENOTSUP; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; @@ -800,11 +819,15 @@ virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); - if (ret) + if (ret) { PMD_INIT_LOG(ERR, "Failed to enable allmulticast"); + return -EAGAIN; + } + + return 0; } -static void +static int virtio_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; @@ -814,7 +837,7 @@ virtio_dev_allmulticast_disable(struct rte_eth_dev *dev) if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control"); - return; + return -ENOTSUP; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; @@ -823,8 +846,12 @@ virtio_dev_allmulticast_disable(struct rte_eth_dev *dev) dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); - if (ret) + if (ret) { PMD_INIT_LOG(ERR, "Failed to disable allmulticast"); + return -EAGAIN; + } + + return 0; } #define VLAN_TAG_LEN 4 /* 802.3ac tag (not DMA'd) */ @@ -932,7 +959,6 @@ virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats) stats->opackets += txvq->stats.packets; stats->obytes += txvq->stats.bytes; - stats->oerrors += txvq->stats.errors; if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) { stats->q_opackets[i] = txvq->stats.packets; @@ -1058,7 +1084,7 @@ virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) return 0; } -static void +static int virtio_dev_stats_reset(struct rte_eth_dev *dev) { unsigned int i; @@ -1070,7 +1096,6 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev) txvq->stats.packets = 0; txvq->stats.bytes = 0; - txvq->stats.errors = 0; txvq->stats.multicast = 0; txvq->stats.broadcast = 0; memset(txvq->stats.size_bins, 0, @@ -1090,6 +1115,8 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev) memset(rxvq->stats.size_bins, 0, sizeof(rxvq->stats.size_bins[0]) * 8); } + + return 0; } static void @@ -1252,6 +1279,20 @@ virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return virtio_send_command(hw->cvq, &ctrl, &len, 1); } +static int +virtio_intr_unmask(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + if (rte_intr_ack(dev->intr_handle) < 0) + return -1; + + if (!hw->virtio_user_dev) + hw->use_msix = vtpci_msix_detect(RTE_ETH_DEV_TO_PCI(dev)); + + return 0; +} + static int virtio_intr_enable(struct rte_eth_dev *dev) { @@ -1445,7 +1486,7 @@ virtio_interrupt_handler(void *param) isr = vtpci_isr(hw); PMD_DRV_LOG(INFO, "interrupt status = %#x", isr); - if (virtio_intr_enable(dev) < 0) + if (virtio_intr_unmask(dev) < 0) PMD_DRV_LOG(ERR, "interrupt enable failed"); if (isr & VIRTIO_PCI_ISR_CONFIG) { @@ -1473,6 +1514,7 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev) { struct virtio_hw *hw = eth_dev->data->dev_private; + eth_dev->tx_pkt_prepare = virtio_xmit_pkts_prepare; if (vtpci_packed_queue(hw)) { PMD_INIT_LOG(INFO, "virtio: using packed ring %s Tx path on port %u", @@ -1645,10 +1687,8 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features) hw->weak_barriers = !vtpci_with_feature(hw, VIRTIO_F_ORDER_PLATFORM); - if (!hw->virtio_user_dev) { + if (!hw->virtio_user_dev) pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); - rte_eth_copy_pci_info(eth_dev, pci_dev); - } /* If host does not support both status and MSI-X then disable LSC */ if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS) && @@ -1823,7 +1863,14 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) struct virtio_hw *hw = eth_dev->data->dev_private; int ret; - RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr_mrg_rxbuf)); + if (sizeof(struct virtio_net_hdr_mrg_rxbuf) > RTE_PKTMBUF_HEADROOM) { + PMD_INIT_LOG(ERR, + "Not sufficient headroom required = %d, avail = %d", + (int)sizeof(struct virtio_net_hdr_mrg_rxbuf), + RTE_PKTMBUF_HEADROOM); + + return -1; + } eth_dev->dev_ops = &virtio_eth_dev_ops; @@ -1840,6 +1887,12 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) return 0; } + /* + * Pass the information to the rte_eth_dev_close() that it should also + * release the private port resources. + */ + eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; + /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("virtio", VIRTIO_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN, 0); @@ -1865,6 +1918,8 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) if (ret < 0) goto err_virtio_init; + hw->opened = true; + return 0; err_virtio_init: @@ -1882,8 +1937,6 @@ err_vtpci_init: static int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) { - struct virtio_hw *hw = eth_dev->data->dev_private; - PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() == RTE_PROC_SECONDARY) @@ -1896,12 +1949,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->tx_pkt_burst = NULL; eth_dev->rx_pkt_burst = NULL; - if (eth_dev->device) { - rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(eth_dev)); - if (!hw->modern) - rte_pci_ioport_unmap(VTPCI_IO(hw)); - } - PMD_INIT_LOG(DEBUG, "dev_uninit completed"); return 0; @@ -1948,11 +1995,6 @@ exit: static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev) { - if (rte_eal_iopl_init() != 0) { - PMD_INIT_LOG(ERR, "IOPL call failed - cannot use virtio PMD"); - return 1; - } - /* virtio pmd skips probe if device needs to work in vdpa mode */ if (vdpa_mode_selected(pci_dev->device.devargs)) return 1; @@ -1963,7 +2005,13 @@ static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev) { - return rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_dev_uninit); + int ret; + + ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_dev_uninit); + /* Port has already been released by close. */ + if (ret == -ENODEV) + ret = 0; + return ret; } static struct rte_pci_driver rte_virtio_pmd = { @@ -2018,6 +2066,13 @@ virtio_dev_configure(struct rte_eth_dev *dev) PMD_INIT_LOG(DEBUG, "configure"); req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES; + if (rxmode->mq_mode != ETH_MQ_RX_NONE) { + PMD_DRV_LOG(ERR, + "Unsupported Rx multi queue mode %d", + rxmode->mq_mode); + return -EINVAL; + } + if (dev->data->dev_conf.intr_conf.rxq) { ret = virtio_init_device(dev, hw->req_guest_features); if (ret < 0) @@ -2123,8 +2178,6 @@ virtio_dev_configure(struct rte_eth_dev *dev) DEV_RX_OFFLOAD_VLAN_STRIP)) hw->use_simple_rx = 0; - hw->opened = true; - return 0; } @@ -2361,7 +2414,7 @@ virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) return 0; } -static void +static int virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { uint64_t tso_mask, host_features; @@ -2403,6 +2456,8 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) (1ULL << VIRTIO_NET_F_HOST_TSO6); if ((host_features & tso_mask) == tso_mask) dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO; + + return 0; } /*