net/virtio: fix crash when device reconnecting
[dpdk.git] / drivers / net / virtio / virtio_user_ethdev.c
index f3b35d1..798f191 100644 (file)
@@ -89,10 +89,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)
@@ -449,6 +451,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 +482,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 +528,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 +563,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 +573,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 +680,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 +734,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 +812,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>");