X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_ethdev.c;h=12fcc23852f8bd10ce4d0c0b25be0e14a87fc80a;hb=921a72008f764826b0c2fbbc8d6c53a736205251;hp=b88f29759d98d824169c604e5a267930033af76b;hpb=abf4c84b25d114a32c7d2dfc77414964805a4ca5;p=dpdk.git diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index b88f29759d..12fcc23852 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -80,9 +80,6 @@ static int virtio_dev_link_update(struct rte_eth_dev *dev, static void virtio_set_hwaddr(struct virtio_hw *hw); static void virtio_get_hwaddr(struct virtio_hw *hw); -static void virtio_dev_rx_queue_release(__rte_unused void *rxq); -static void virtio_dev_tx_queue_release(__rte_unused void *txq); - static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); @@ -240,33 +237,45 @@ virtio_set_multiple_queues(struct rte_eth_dev *dev, uint16_t nb_queues) return 0; } +void +virtio_dev_queue_release(struct virtqueue *vq) { + struct virtio_hw *hw; + + if (vq) { + hw = vq->hw; + /* Select and deactivate the queue */ + VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->queue_id); + VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0); + + rte_free(vq); + vq = NULL; + } +} + int virtio_dev_queue_setup(struct rte_eth_dev *dev, int queue_type, uint16_t queue_idx, - uint16_t vtpci_queue_idx, + uint16_t vtpci_queue_idx, uint16_t nb_desc, unsigned int socket_id, struct virtqueue **pvq) { char vq_name[VIRTQUEUE_MAX_NAME_SZ]; const struct rte_memzone *mz; - uint16_t vq_size; - int size; + unsigned int vq_size, size; struct virtio_hw *hw = dev->data->dev_private; - struct virtqueue *vq = NULL; + struct virtqueue *vq = NULL; /* Write the virtqueue index to the Queue Select Field */ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vtpci_queue_idx); - PMD_INIT_LOG(DEBUG, "selecting queue: %d", vtpci_queue_idx); + PMD_INIT_LOG(DEBUG, "selecting queue: %u", vtpci_queue_idx); /* * Read the virtqueue size from the Queue Size field * Always power of 2 and if 0 virtqueue does not exist */ vq_size = VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM); - PMD_INIT_LOG(DEBUG, "vq_size: %d nb_desc:%d", vq_size, nb_desc); - if (nb_desc == 0) - nb_desc = vq_size; + PMD_INIT_LOG(DEBUG, "vq_size: %u nb_desc:%u", vq_size, nb_desc); if (vq_size == 0) { PMD_INIT_LOG(ERR, "%s: virtqueue does not exist", __func__); return -EINVAL; @@ -277,16 +286,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, return -EINVAL; } - if (nb_desc < vq_size) { - if (!rte_is_power_of_2(nb_desc)) { - PMD_INIT_LOG(ERR, - "nb_desc(%u) size is not powerof 2", - nb_desc); - return -EINVAL; - } - vq_size = nb_desc; - } - if (queue_type == VTNET_RQ) { snprintf(vq_name, sizeof(vq_name), "port%d_rvq%d", dev->data->port_id, queue_idx); @@ -314,7 +313,10 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, vq->queue_id = queue_idx; vq->vq_queue_index = vtpci_queue_idx; vq->vq_nentries = vq_size; - vq->vq_free_cnt = vq_size; + + if (nb_desc == 0 || nb_desc > vq_size) + nb_desc = vq_size; + vq->vq_free_cnt = nb_desc; /* * Reserve a memzone for vring elements @@ -411,13 +413,12 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, uint32_t socket_id) { struct virtqueue *vq; - uint16_t nb_desc = 0; int ret; struct virtio_hw *hw = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); ret = virtio_dev_queue_setup(dev, VTNET_CQ, VTNET_SQ_CQ_QUEUE_IDX, - vtpci_queue_idx, nb_desc, socket_id, &vq); + vtpci_queue_idx, 0, socket_id, &vq); if (ret < 0) { PMD_INIT_LOG(ERR, "control vq initialization failed"); return ret; @@ -427,6 +428,22 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, return 0; } +static void +virtio_free_queues(struct rte_eth_dev *dev) +{ + unsigned int i; + + for (i = 0; i < dev->data->nb_rx_queues; i++) + virtio_dev_rx_queue_release(dev->data->rx_queues[i]); + + dev->data->nb_rx_queues = 0; + + for (i = 0; i < dev->data->nb_tx_queues; i++) + virtio_dev_tx_queue_release(dev->data->tx_queues[i]); + + dev->data->nb_tx_queues = 0; +} + static void virtio_dev_close(struct rte_eth_dev *dev) { @@ -441,6 +458,7 @@ virtio_dev_close(struct rte_eth_dev *dev) vtpci_reset(hw); hw->started = 0; virtio_dev_free_mbufs(dev); + virtio_free_queues(dev); } static void @@ -553,10 +571,8 @@ static const struct eth_dev_ops virtio_eth_dev_ops = { .stats_reset = virtio_dev_stats_reset, .link_update = virtio_dev_link_update, .rx_queue_setup = virtio_dev_rx_queue_setup, - /* meaningfull only to multiple queue */ .rx_queue_release = virtio_dev_rx_queue_release, .tx_queue_setup = virtio_dev_tx_queue_setup, - /* meaningfull only to multiple queue */ .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, @@ -1146,7 +1162,6 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) struct virtio_hw *hw = eth_dev->data->dev_private; struct virtio_net_config *config; struct virtio_net_config local_config; - uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); @@ -1185,6 +1200,10 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); virtio_negotiate_features(hw); + /* If host does not support status then disable LSC */ + if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) + pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; + rx_func_get(eth_dev); /* Setting up rx_header size for the device */ @@ -1205,8 +1224,14 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) { config = &local_config; + vtpci_read_dev_config(hw, + offsetof(struct virtio_net_config, mac), + &config->mac, sizeof(config->mac)); + if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { - offset_conf += sizeof(config->status); + vtpci_read_dev_config(hw, + offsetof(struct virtio_net_config, status), + &config->status, sizeof(config->status)); } else { PMD_INIT_LOG(DEBUG, "VIRTIO_NET_F_STATUS is not supported"); @@ -1214,15 +1239,16 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) } if (vtpci_with_feature(hw, VIRTIO_NET_F_MQ)) { - offset_conf += sizeof(config->max_virtqueue_pairs); + vtpci_read_dev_config(hw, + offsetof(struct virtio_net_config, max_virtqueue_pairs), + &config->max_virtqueue_pairs, + sizeof(config->max_virtqueue_pairs)); } else { PMD_INIT_LOG(DEBUG, "VIRTIO_NET_F_MQ is not supported"); config->max_virtqueue_pairs = 1; } - vtpci_read_dev_config(hw, 0, (uint8_t *)config, offset_conf); - hw->max_rx_queues = (VIRTIO_MAX_RX_QUEUES < config->max_virtqueue_pairs) ? VIRTIO_MAX_RX_QUEUES : config->max_virtqueue_pairs; @@ -1287,8 +1313,7 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->tx_pkt_burst = NULL; eth_dev->rx_pkt_burst = NULL; - rte_free(hw->cvq); - hw->cvq = NULL; + virtio_dev_queue_release(hw->cvq); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; @@ -1334,19 +1359,6 @@ rte_virtio_pmd_init(const char *name __rte_unused, return 0; } -/* - * Only 1 queue is supported, no queue release related operation - */ -static void -virtio_dev_rx_queue_release(__rte_unused void *rxq) -{ -} - -static void -virtio_dev_tx_queue_release(__rte_unused void *txq) -{ -} - /* * Configure virtio device * It returns 0 on success. @@ -1392,9 +1404,8 @@ virtio_dev_start(struct rte_eth_dev *dev) struct rte_pci_device *pci_dev = dev->pci_dev; /* check if lsc interrupt feature is enabled */ - if ((dev->data->dev_conf.intr_conf.lsc) && - (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) { - if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { + if (dev->data->dev_conf.intr_conf.lsc) { + if (!(pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) { PMD_DRV_LOG(ERR, "link status not supported by host"); return -ENOTSUP; }