net/virtio-user: fix status management
[dpdk.git] / drivers / net / virtio / virtio_user_ethdev.c
index f3b35d1..6003f6d 100644 (file)
@@ -68,6 +68,7 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
        int connectfd;
        struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
        struct virtio_hw *hw = eth_dev->data->dev_private;
+       uint64_t protocol_features;
 
        connectfd = accept(dev->listenfd, NULL, NULL);
        if (connectfd < 0)
@@ -81,6 +82,25 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
                return -1;
        }
 
+       if (dev->device_features &
+                       (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) {
+               if (dev->ops->send_request(dev,
+                                       VHOST_USER_GET_PROTOCOL_FEATURES,
+                                       &protocol_features))
+                       return -1;
+
+               dev->protocol_features &= protocol_features;
+
+               if (dev->ops->send_request(dev,
+                                       VHOST_USER_SET_PROTOCOL_FEATURES,
+                                       &dev->protocol_features))
+                       return -1;
+
+               if (!(dev->protocol_features &
+                               (1ULL << VHOST_USER_PROTOCOL_F_MQ)))
+                       dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
+       }
+
        dev->device_features |= dev->frontend_features;
 
        /* umask vhost-user unsupported features */
@@ -89,10 +109,12 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
        dev->features &= dev->device_features;
 
        /* For packed ring, resetting queues is required in reconnection. */
-       if (vtpci_packed_queue(hw))
+       if (vtpci_packed_queue(hw) &&
+          (vtpci_get_status(hw) & VIRTIO_CONFIG_STATUS_DRIVER_OK)) {
                PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped"
                                " when packed ring reconnecting.");
                virtio_user_reset_queues_packed(eth_dev);
+       }
 
        ret = virtio_user_start_device(dev);
        if (ret < 0)
@@ -183,7 +205,7 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
                        }
                        r = recv(dev->vhostfd, buf, 128, MSG_PEEK);
                        if (r == 0 || (r < 0 && errno != EAGAIN)) {
-                               dev->status &= (~VIRTIO_NET_S_LINK_UP);
+                               dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
                                PMD_DRV_LOG(ERR, "virtio-user port %u is down",
                                            hw->port_id);
 
@@ -195,7 +217,7 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
                                                  virtio_user_delayed_handler,
                                                  (void *)hw);
                        } else {
-                               dev->status |= VIRTIO_NET_S_LINK_UP;
+                               dev->net_status |= VIRTIO_NET_S_LINK_UP;
                        }
                        if (fcntl(dev->vhostfd, F_SETFL,
                                        flags & ~O_NONBLOCK) == -1) {
@@ -203,12 +225,12 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
                                return;
                        }
                } else if (dev->is_server) {
-                       dev->status &= (~VIRTIO_NET_S_LINK_UP);
+                       dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
                        if (virtio_user_server_reconnect(dev) >= 0)
-                               dev->status |= VIRTIO_NET_S_LINK_UP;
+                               dev->net_status |= VIRTIO_NET_S_LINK_UP;
                }
 
-               *(uint16_t *)dst = dev->status;
+               *(uint16_t *)dst = dev->net_status;
        }
 
        if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs))
@@ -449,6 +471,10 @@ static const char *valid_args[] = {
        VIRTIO_USER_ARG_IN_ORDER,
 #define VIRTIO_USER_ARG_PACKED_VQ      "packed_vq"
        VIRTIO_USER_ARG_PACKED_VQ,
+#define VIRTIO_USER_ARG_SPEED          "speed"
+       VIRTIO_USER_ARG_SPEED,
+#define VIRTIO_USER_ARG_VECTORIZED     "vectorized"
+       VIRTIO_USER_ARG_VECTORIZED,
        NULL
 };
 
@@ -476,12 +502,17 @@ static int
 get_integer_arg(const char *key __rte_unused,
                const char *value, void *extra_args)
 {
+       uint64_t integer = 0;
        if (!value || !extra_args)
                return -EINVAL;
-
-       *(uint64_t *)extra_args = strtoull(value, NULL, 0);
-
-       return 0;
+       errno = 0;
+       integer = strtoull(value, NULL, 0);
+       /* extra_args keeps default value, it should be replaced
+        * only in case of successful parsing of the 'value' arg
+        */
+       if (errno == 0)
+               *(uint64_t *)extra_args = integer;
+       return -errno;
 }
 
 static struct rte_eth_dev *
@@ -517,7 +548,8 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev)
         */
        hw->use_msix = 1;
        hw->modern   = 0;
-       hw->use_simple_rx = 0;
+       hw->use_vec_rx = 0;
+       hw->use_vec_tx = 0;
        hw->use_inorder_rx = 0;
        hw->use_inorder_tx = 0;
        hw->virtio_user_dev = dev;
@@ -551,6 +583,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
        uint64_t mrg_rxbuf = 1;
        uint64_t in_order = 1;
        uint64_t packed_vq = 0;
+       uint64_t vectorized = 0;
        char *path = NULL;
        char *ifname = NULL;
        char *mac_addr = NULL;
@@ -560,7 +593,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
                const char *name = rte_vdev_device_name(dev);
                eth_dev = rte_eth_dev_attach_secondary(name);
                if (!eth_dev) {
-                       RTE_LOG(ERR, PMD, "Failed to probe %s\n", name);
+                       PMD_INIT_LOG(ERR, "Failed to probe %s", name);
                        return -1;
                }
 
@@ -667,6 +700,15 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
                }
        }
 
+       if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_VECTORIZED) == 1) {
+               if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_VECTORIZED,
+                                      &get_integer_arg, &vectorized) < 0) {
+                       PMD_INIT_LOG(ERR, "error to parse %s",
+                                    VIRTIO_USER_ARG_VECTORIZED);
+                       goto end;
+               }
+       }
+
        if (queues > 1 && cq == 0) {
                PMD_INIT_LOG(ERR, "multi-q requires ctrl-q");
                goto end;
@@ -712,13 +754,27 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
                goto end;
        }
 
-       /* previously called by rte_pci_probe() for physical dev */
+       /* previously called by pci probing for physical dev */
        if (eth_virtio_dev_init(eth_dev) < 0) {
                PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails");
                virtio_user_eth_dev_free(eth_dev);
                goto end;
        }
 
+       if (vectorized) {
+               if (packed_vq) {
+#if defined(CC_AVX512_SUPPORT)
+                       hw->use_vec_rx = 1;
+                       hw->use_vec_tx = 1;
+#else
+                       PMD_INIT_LOG(INFO,
+                               "building environment do not support packed ring vectorized");
+#endif
+               } else {
+                       hw->use_vec_rx = 1;
+               }
+       }
+
        rte_eth_dev_probing_finish(eth_dev);
        ret = 0;
 
@@ -776,4 +832,6 @@ RTE_PMD_REGISTER_PARAM_STRING(net_virtio_user,
        "server=<0|1> "
        "mrg_rxbuf=<0|1> "
        "in_order=<0|1> "
-       "packed_vq=<0|1>");
+       "packed_vq=<0|1> "
+       "speed=<int> "
+       "vectorized=<0|1>");