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