Commit 012ec02a authored by Jiri Pirko's avatar Jiri Pirko Committed by Jakub Kicinski
Browse files

netdevsim: convert driver to use unlocked devlink API during init/fini



Prepare for devlink reload being called with devlink->lock held and
convert the netdevsim driver to use unlocked devlink API during init and
fini flows. Take devl_lock() in reload_down() and reload_up() ops in the
meantime before reload cmd is converted to take the lock itself.

Signed-off-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent eb0e9fa2
Loading
Loading
Loading
Loading
+0 −19
Original line number Diff line number Diff line
@@ -72,16 +72,7 @@ new_port_store(struct device *dev, struct device_attribute *attr,
	if (ret)
		return ret;

	if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
		return -EBUSY;

	if (nsim_bus_dev->in_reload) {
		mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
		return -EBUSY;
	}

	ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
	mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
	return ret ? ret : count;
}

@@ -102,16 +93,7 @@ del_port_store(struct device *dev, struct device_attribute *attr,
	if (ret)
		return ret;

	if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
		return -EBUSY;

	if (nsim_bus_dev->in_reload) {
		mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
		return -EBUSY;
	}

	ret = nsim_drv_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
	mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
	return ret ? ret : count;
}

@@ -298,7 +280,6 @@ nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queu
	nsim_bus_dev->num_queues = num_queues;
	nsim_bus_dev->initial_net = current->nsproxy->net_ns;
	nsim_bus_dev->max_vfs = NSIM_BUS_DEV_MAX_VFS;
	mutex_init(&nsim_bus_dev->nsim_bus_reload_lock);
	/* Disallow using nsim_bus_dev */
	smp_store_release(&nsim_bus_dev->init, false);

+64 −70
Original line number Diff line number Diff line
@@ -436,7 +436,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
	int err;

	/* Resources for IPv4 */
	err = devlink_resource_register(devlink, "IPv4", (u64)-1,
	err = devl_resource_register(devlink, "IPv4", (u64)-1,
				     NSIM_RESOURCE_IPV4,
				     DEVLINK_RESOURCE_ID_PARENT_TOP,
				     &params);
@@ -445,7 +445,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
		goto out;
	}

	err = devlink_resource_register(devlink, "fib", (u64)-1,
	err = devl_resource_register(devlink, "fib", (u64)-1,
				     NSIM_RESOURCE_IPV4_FIB,
				     NSIM_RESOURCE_IPV4, &params);
	if (err) {
@@ -453,7 +453,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
		return err;
	}

	err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
	err = devl_resource_register(devlink, "fib-rules", (u64)-1,
				     NSIM_RESOURCE_IPV4_FIB_RULES,
				     NSIM_RESOURCE_IPV4, &params);
	if (err) {
@@ -462,7 +462,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
	}

	/* Resources for IPv6 */
	err = devlink_resource_register(devlink, "IPv6", (u64)-1,
	err = devl_resource_register(devlink, "IPv6", (u64)-1,
				     NSIM_RESOURCE_IPV6,
				     DEVLINK_RESOURCE_ID_PARENT_TOP,
				     &params);
@@ -471,7 +471,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
		goto out;
	}

	err = devlink_resource_register(devlink, "fib", (u64)-1,
	err = devl_resource_register(devlink, "fib", (u64)-1,
				     NSIM_RESOURCE_IPV6_FIB,
				     NSIM_RESOURCE_IPV6, &params);
	if (err) {
@@ -479,7 +479,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
		return err;
	}

	err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
	err = devl_resource_register(devlink, "fib-rules", (u64)-1,
				     NSIM_RESOURCE_IPV6_FIB_RULES,
				     NSIM_RESOURCE_IPV6, &params);
	if (err) {
@@ -488,7 +488,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
	}

	/* Resources for nexthops */
	err = devlink_resource_register(devlink, "nexthops", (u64)-1,
	err = devl_resource_register(devlink, "nexthops", (u64)-1,
				     NSIM_RESOURCE_NEXTHOPS,
				     DEVLINK_RESOURCE_ID_PARENT_TOP,
				     &params);
@@ -557,7 +557,7 @@ static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev,
				      struct devlink *devlink)
{
	nsim_dev->dummy_region =
		devlink_region_create(devlink, &dummy_region_ops,
		devl_region_create(devlink, &dummy_region_ops,
				   NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX,
				   NSIM_DEV_DUMMY_REGION_SIZE);
	return PTR_ERR_OR_ZERO(nsim_dev->dummy_region);
@@ -565,7 +565,7 @@ static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev,

static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev)
{
	devlink_region_destroy(nsim_dev->dummy_region);
	devl_region_destroy(nsim_dev->dummy_region);
}

static int
@@ -832,7 +832,11 @@ static void nsim_dev_trap_report_work(struct work_struct *work)
	/* For each running port and enabled packet trap, generate a UDP
	 * packet with a random 5-tuple and report it.
	 */
	devl_lock(priv_to_devlink(nsim_dev));
	if (!devl_trylock(priv_to_devlink(nsim_dev))) {
		schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0);
		return;
	}

	list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) {
		if (!netif_running(nsim_dev_port->ns->netdev))
			continue;
@@ -880,17 +884,17 @@ static int nsim_dev_traps_init(struct devlink *devlink)
	nsim_trap_data->nsim_dev = nsim_dev;
	nsim_dev->trap_data = nsim_trap_data;

	err = devlink_trap_policers_register(devlink, nsim_trap_policers_arr,
	err = devl_trap_policers_register(devlink, nsim_trap_policers_arr,
					  policers_count);
	if (err)
		goto err_trap_policers_cnt_free;

	err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr,
	err = devl_trap_groups_register(devlink, nsim_trap_groups_arr,
					ARRAY_SIZE(nsim_trap_groups_arr));
	if (err)
		goto err_trap_policers_unregister;

	err = devlink_traps_register(devlink, nsim_traps_arr,
	err = devl_traps_register(devlink, nsim_traps_arr,
				  ARRAY_SIZE(nsim_traps_arr), NULL);
	if (err)
		goto err_trap_groups_unregister;
@@ -903,10 +907,10 @@ static int nsim_dev_traps_init(struct devlink *devlink)
	return 0;

err_trap_groups_unregister:
	devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
	devl_trap_groups_unregister(devlink, nsim_trap_groups_arr,
				    ARRAY_SIZE(nsim_trap_groups_arr));
err_trap_policers_unregister:
	devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr,
	devl_trap_policers_unregister(devlink, nsim_trap_policers_arr,
				      ARRAY_SIZE(nsim_trap_policers_arr));
err_trap_policers_cnt_free:
	kfree(nsim_trap_data->trap_policers_cnt_arr);
@@ -923,11 +927,11 @@ static void nsim_dev_traps_exit(struct devlink *devlink)

	/* caution, trap work takes devlink lock */
	cancel_delayed_work_sync(&nsim_dev->trap_data->trap_report_dw);
	devlink_traps_unregister(devlink, nsim_traps_arr,
	devl_traps_unregister(devlink, nsim_traps_arr,
			      ARRAY_SIZE(nsim_traps_arr));
	devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
	devl_trap_groups_unregister(devlink, nsim_trap_groups_arr,
				    ARRAY_SIZE(nsim_trap_groups_arr));
	devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr,
	devl_trap_policers_unregister(devlink, nsim_trap_policers_arr,
				      ARRAY_SIZE(nsim_trap_policers_arr));
	kfree(nsim_dev->trap_data->trap_policers_cnt_arr);
	kfree(nsim_dev->trap_data->trap_items_arr);
@@ -943,24 +947,19 @@ static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
				struct netlink_ext_ack *extack)
{
	struct nsim_dev *nsim_dev = devlink_priv(devlink);
	struct nsim_bus_dev *nsim_bus_dev;

	nsim_bus_dev = nsim_dev->nsim_bus_dev;
	if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
		return -EOPNOTSUPP;

	devl_lock(devlink);
	if (nsim_dev->dont_allow_reload) {
		/* For testing purposes, user set debugfs dont_allow_reload
		 * value to true. So forbid it.
		 */
		NL_SET_ERR_MSG_MOD(extack, "User forbid the reload for testing purposes");
		mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
		devl_unlock(devlink);
		return -EOPNOTSUPP;
	}
	nsim_bus_dev->in_reload = true;

	nsim_dev_reload_destroy(nsim_dev);
	mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
	devl_unlock(devlink);
	return 0;
}

@@ -969,25 +968,21 @@ static int nsim_dev_reload_up(struct devlink *devlink, enum devlink_reload_actio
			      struct netlink_ext_ack *extack)
{
	struct nsim_dev *nsim_dev = devlink_priv(devlink);
	struct nsim_bus_dev *nsim_bus_dev;
	int ret;

	nsim_bus_dev = nsim_dev->nsim_bus_dev;
	mutex_lock(&nsim_bus_dev->nsim_bus_reload_lock);
	nsim_bus_dev->in_reload = false;

	devl_lock(devlink);
	if (nsim_dev->fail_reload) {
		/* For testing purposes, user set debugfs fail_reload
		 * value to true. Fail right away.
		 */
		NL_SET_ERR_MSG_MOD(extack, "User setup the reload to fail for testing purposes");
		mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
		devl_unlock(devlink);
		return -EINVAL;
	}

	*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
	ret = nsim_dev_reload_create(nsim_dev, extack);
	mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
	devl_unlock(devlink);
	return ret;
}

@@ -1434,11 +1429,9 @@ static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
{
	struct nsim_dev_port *nsim_dev_port, *tmp;

	devl_lock(priv_to_devlink(nsim_dev));
	list_for_each_entry_safe(nsim_dev_port, tmp,
				 &nsim_dev->port_list, list)
		__nsim_dev_port_del(nsim_dev_port);
	devl_unlock(priv_to_devlink(nsim_dev));
}

static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
@@ -1447,9 +1440,7 @@ static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
	int i, err;

	for (i = 0; i < port_count; i++) {
		devl_lock(priv_to_devlink(nsim_dev));
		err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i);
		devl_unlock(priv_to_devlink(nsim_dev));
		if (err)
			goto err_port_del_all;
	}
@@ -1537,6 +1528,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
				 nsim_bus_dev->initial_net, &nsim_bus_dev->dev);
	if (!devlink)
		return -ENOMEM;
	devl_lock(devlink);
	nsim_dev = devlink_priv(devlink);
	nsim_dev->nsim_bus_dev = nsim_bus_dev;
	nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
@@ -1555,7 +1547,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
				      GFP_KERNEL | __GFP_NOWARN);
	if (!nsim_dev->vfconfigs) {
		err = -ENOMEM;
		goto err_devlink_free;
		goto err_devlink_unlock;
	}

	err = nsim_dev_resources_register(devlink);
@@ -1608,6 +1600,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)

	nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY;
	devlink_set_features(devlink, DEVLINK_F_RELOAD);
	devl_unlock(devlink);
	devlink_register(devlink);
	return 0;

@@ -1631,10 +1624,11 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
	devlink_params_unregister(devlink, nsim_devlink_params,
				  ARRAY_SIZE(nsim_devlink_params));
err_dl_unregister:
	devlink_resources_unregister(devlink);
	devl_resources_unregister(devlink);
err_vfc_free:
	kfree(nsim_dev->vfconfigs);
err_devlink_free:
err_devlink_unlock:
	devl_unlock(devlink);
	devlink_free(devlink);
	dev_set_drvdata(&nsim_bus_dev->dev, NULL);
	return err;
@@ -1648,13 +1642,11 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
		return;
	debugfs_remove(nsim_dev->take_snapshot);

	devl_lock(devlink);
	if (nsim_dev_get_vfs(nsim_dev)) {
		nsim_bus_dev_set_vfs(nsim_dev->nsim_bus_dev, 0);
		if (nsim_esw_mode_is_switchdev(nsim_dev))
			nsim_esw_legacy_enable(nsim_dev, NULL);
	}
	devl_unlock(devlink);

	nsim_dev_port_del_all(nsim_dev);
	nsim_dev_hwstats_exit(nsim_dev);
@@ -1671,14 +1663,16 @@ void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev)
	struct devlink *devlink = priv_to_devlink(nsim_dev);

	devlink_unregister(devlink);
	devl_lock(devlink);
	nsim_dev_reload_destroy(nsim_dev);

	nsim_bpf_dev_exit(nsim_dev);
	nsim_dev_debugfs_exit(nsim_dev);
	devlink_params_unregister(devlink, nsim_devlink_params,
				  ARRAY_SIZE(nsim_devlink_params));
	devlink_resources_unregister(devlink);
	devl_resources_unregister(devlink);
	kfree(nsim_dev->vfconfigs);
	devl_unlock(devlink);
	devlink_free(devlink);
	dev_set_drvdata(&nsim_bus_dev->dev, NULL);
}
+31 −31
Original line number Diff line number Diff line
@@ -1453,7 +1453,7 @@ static void nsim_fib_set_max_all(struct nsim_fib_data *data,
		int err;
		u64 val;

		err = devlink_resource_size_get(devlink, res_ids[i], &val);
		err = devl_resource_size_get(devlink, res_ids[i], &val);
		if (err)
			val = (u64) -1;
		nsim_fib_set_max(data, res_ids[i], val);
@@ -1562,23 +1562,23 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
		goto err_nexthop_nb_unregister;
	}

	devlink_resource_occ_get_register(devlink,
	devl_resource_occ_get_register(devlink,
				       NSIM_RESOURCE_IPV4_FIB,
				       nsim_fib_ipv4_resource_occ_get,
				       data);
	devlink_resource_occ_get_register(devlink,
	devl_resource_occ_get_register(devlink,
				       NSIM_RESOURCE_IPV4_FIB_RULES,
				       nsim_fib_ipv4_rules_res_occ_get,
				       data);
	devlink_resource_occ_get_register(devlink,
	devl_resource_occ_get_register(devlink,
				       NSIM_RESOURCE_IPV6_FIB,
				       nsim_fib_ipv6_resource_occ_get,
				       data);
	devlink_resource_occ_get_register(devlink,
	devl_resource_occ_get_register(devlink,
				       NSIM_RESOURCE_IPV6_FIB_RULES,
				       nsim_fib_ipv6_rules_res_occ_get,
				       data);
	devlink_resource_occ_get_register(devlink,
	devl_resource_occ_get_register(devlink,
				       NSIM_RESOURCE_NEXTHOPS,
				       nsim_fib_nexthops_res_occ_get,
				       data);
@@ -1604,15 +1604,15 @@ struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,

void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *data)
{
	devlink_resource_occ_get_unregister(devlink,
	devl_resource_occ_get_unregister(devlink,
					 NSIM_RESOURCE_NEXTHOPS);
	devlink_resource_occ_get_unregister(devlink,
	devl_resource_occ_get_unregister(devlink,
					 NSIM_RESOURCE_IPV6_FIB_RULES);
	devlink_resource_occ_get_unregister(devlink,
	devl_resource_occ_get_unregister(devlink,
					 NSIM_RESOURCE_IPV6_FIB);
	devlink_resource_occ_get_unregister(devlink,
	devl_resource_occ_get_unregister(devlink,
					 NSIM_RESOURCE_IPV4_FIB_RULES);
	devlink_resource_occ_get_unregister(devlink,
	devl_resource_occ_get_unregister(devlink,
					 NSIM_RESOURCE_IPV4_FIB);
	unregister_fib_notifier(devlink_net(devlink), &data->fib_nb);
	unregister_nexthop_notifier(devlink_net(devlink), &data->nexthop_nb);
+0 −3
Original line number Diff line number Diff line
@@ -376,9 +376,6 @@ struct nsim_bus_dev {
				  */
	unsigned int max_vfs;
	unsigned int num_vfs;
	/* Lock for devlink->reload_enabled in netdevsim module */
	struct mutex nsim_bus_reload_lock;
	bool in_reload;
	bool init;
};

+1 −0
Original line number Diff line number Diff line
@@ -1517,6 +1517,7 @@ struct device *devlink_to_dev(const struct devlink *devlink);

/* Devlink instance explicit locking */
void devl_lock(struct devlink *devlink);
int devl_trylock(struct devlink *devlink);
void devl_unlock(struct devlink *devlink);
void devl_assert_locked(struct devlink *devlink);
bool devl_lock_is_held(struct devlink *devlink);
Loading