From: Long Li <lon...@microsoft.com>

If a device probe fails, the alarm is canceled and will no longer work for
previously probed devices.

Fix this by introducing a flag to track if alarm has been set. Because it's
possible that an alarm is triggered while probing is in progress that may
modify vdev_netvsc_ctx_list, introduce a lock to protect it.

Cc: sta...@dpdk.org
Signed-off-by: Long Li <lon...@microsoft.com>
---
 drivers/net/vdev_netvsc/vdev_netvsc.c | 41 +++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/net/vdev_netvsc/vdev_netvsc.c 
b/drivers/net/vdev_netvsc/vdev_netvsc.c
index be8f19c..bd7e308 100644
--- a/drivers/net/vdev_netvsc/vdev_netvsc.c
+++ b/drivers/net/vdev_netvsc/vdev_netvsc.c
@@ -76,6 +76,11 @@ struct vdev_netvsc_ctx {
 /** Context list is common to all driver instances. */
 static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
        LIST_HEAD_INITIALIZER(vdev_netvsc_ctx_list);
+/* Lock to protect concurrent accesses to vdev_netvsc_ctx_list */
+static rte_rwlock_t vdev_netvsc_ctx_list_lock;
+
+/* Flag to track if alarm has been set */
+static int vdev_netvsc_alarm_set;
 
 /** Number of entries in context list. */
 static unsigned int vdev_netvsc_ctx_count;
@@ -454,19 +459,26 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
        struct vdev_netvsc_ctx *ctx;
        int ret;
 
+       rte_rwlock_write_lock(&vdev_netvsc_ctx_list_lock);
        LIST_FOREACH(ctx, &vdev_netvsc_ctx_list, entry) {
                ret = vdev_netvsc_foreach_iface(vdev_netvsc_device_probe, 0,
                      ctx);
                if (ret < 0)
                        break;
        }
-       if (!vdev_netvsc_ctx_count)
+       rte_rwlock_write_unlock(&vdev_netvsc_ctx_list_lock);
+
+       if (!vdev_netvsc_ctx_count) {
+               vdev_netvsc_alarm_set = 0;
                return;
+       }
+
        ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
                                vdev_netvsc_alarm, NULL);
        if (ret < 0) {
                DRV_LOG(ERR, "unable to reschedule alarm callback: %s",
                        rte_strerror(-ret));
+               vdev_netvsc_alarm_set = 0;
        }
 }
 
@@ -698,34 +710,41 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
                        " device.");
                goto error;
        }
-       rte_eal_alarm_cancel(vdev_netvsc_alarm, NULL);
+
+       rte_rwlock_write_lock(&vdev_netvsc_ctx_list_lock);
        /* Gather interfaces. */
        ret = vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 1, name,
                                        kvargs, specified, &matched);
        if (ret < 0)
-               goto error;
+               goto error_unlock;
        if (specified && matched < specified) {
                if (!force) {
                        DRV_LOG(ERR, "Cannot find the specified netvsc device");
-                       goto error;
+                       goto error_unlock;
                }
                /* Try to force probing on non-netvsc specified device. */
                if (vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 0, name,
                                              kvargs, specified, &matched) < 0)
-                       goto error;
+                       goto error_unlock;
                if (matched < specified) {
                        DRV_LOG(ERR, "Cannot find the specified device");
-                       goto error;
+                       goto error_unlock;
                }
                DRV_LOG(WARNING, "non-netvsc device was probed as netvsc");
        }
-       ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
+       if (!vdev_netvsc_alarm_set) {
+               ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
                                vdev_netvsc_alarm, NULL);
-       if (ret < 0) {
-               DRV_LOG(ERR, "unable to schedule alarm callback: %s",
-                       rte_strerror(-ret));
-               goto error;
+               if (ret < 0)
+                       DRV_LOG(ERR, "unable to schedule alarm callback: %s",
+                               rte_strerror(-ret));
+               else
+                       vdev_netvsc_alarm_set = 1;
        }
+
+error_unlock:
+       rte_rwlock_write_unlock(&vdev_netvsc_ctx_list_lock);
+
 error:
        if (kvargs)
                rte_kvargs_free(kvargs);
-- 
1.8.3.1

Reply via email to