1908 lines · 52.2 KB · C
RawDownload
		if (err)			goto err_dl_port_unregister;	} 	err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);	if (err)		goto err_port_resource_unregister; 	nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port, perm_addr);	if (IS_ERR(nsim_dev_port->ns)) {		err = PTR_ERR(nsim_dev_port->ns);		goto err_port_debugfs_exit;	} 	if (nsim_dev_port_is_vf(nsim_dev_port)) {		err = devl_rate_leaf_create(&nsim_dev_port->devlink_port,					    nsim_dev_port, NULL);		if (err)			goto err_nsim_destroy;	} 	list_add(&nsim_dev_port->list, &nsim_dev->port_list); 	return 0; err_nsim_destroy:	nsim_destroy(nsim_dev_port->ns);err_port_debugfs_exit:	nsim_dev_port_debugfs_exit(nsim_dev_port);err_port_resource_unregister:	if (nsim_dev_port_is_pf(nsim_dev_port))		devl_port_resources_unregister(devlink_port);err_dl_port_unregister:	devl_port_unregister(devlink_port);err_port_free:	kfree(nsim_dev_port);	return err;} static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port){	struct devlink_port *devlink_port = &nsim_dev_port->devlink_port; 	list_del(&nsim_dev_port->list);	if (nsim_dev_port_is_vf(nsim_dev_port))		devl_rate_leaf_destroy(&nsim_dev_port->devlink_port);	nsim_destroy(nsim_dev_port->ns);	nsim_dev_port_debugfs_exit(nsim_dev_port);	if (nsim_dev_port_is_pf(nsim_dev_port))		devl_port_resources_unregister(devlink_port);	devl_port_unregister(devlink_port);	kfree(nsim_dev_port);} static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev){	struct nsim_dev_port *nsim_dev_port, *tmp; 	list_for_each_entry_safe(nsim_dev_port, tmp,				 &nsim_dev->port_list, list)		__nsim_dev_port_del(nsim_dev_port);} static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,				 unsigned int port_count){	int i, err; 	for (i = 0; i < port_count; i++) {		err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i, NULL);		if (err)			goto err_port_del_all;	}	return 0; err_port_del_all:	nsim_dev_port_del_all(nsim_dev);	return err;} static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,				  struct netlink_ext_ack *extack){	struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;	struct devlink *devlink;	int err; 	devlink = priv_to_devlink(nsim_dev);	nsim_dev = devlink_priv(devlink);	INIT_LIST_HEAD(&nsim_dev->port_list);	nsim_dev->fw_update_status = true;	nsim_dev->fw_update_overwrite_mask = 0; 	nsim_devlink_param_load_driverinit_values(devlink); 	err = nsim_dev_dummy_region_init(nsim_dev, devlink);	if (err)		return err; 	err = nsim_dev_traps_init(devlink);	if (err)		goto err_dummy_region_exit; 	nsim_dev->fib_data = nsim_fib_create(devlink, extack);	if (IS_ERR(nsim_dev->fib_data)) {		err = PTR_ERR(nsim_dev->fib_data);		goto err_traps_exit;	} 	err = nsim_dev_health_init(nsim_dev, devlink);	if (err)		goto err_fib_destroy; 	err = nsim_dev_psample_init(nsim_dev);	if (err)		goto err_health_exit; 	err = nsim_dev_hwstats_init(nsim_dev);	if (err)		goto err_psample_exit; 	err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);	if (err)		goto err_hwstats_exit; 	nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",						      0200,						      nsim_dev->ddir,						      nsim_dev,						&nsim_dev_take_snapshot_fops);	return 0; err_hwstats_exit:	nsim_dev_hwstats_exit(nsim_dev);err_psample_exit:	nsim_dev_psample_exit(nsim_dev);err_health_exit:	nsim_dev_health_exit(nsim_dev);err_fib_destroy:	nsim_fib_destroy(devlink, nsim_dev->fib_data);err_traps_exit:	nsim_dev_traps_exit(devlink);err_dummy_region_exit:	nsim_dev_dummy_region_exit(nsim_dev);	return err;} int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev){	struct nsim_dev *nsim_dev;	struct devlink *devlink;	int err; 	devlink = devlink_alloc_ns(&nsim_dev_devlink_ops, sizeof(*nsim_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);	get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);	INIT_LIST_HEAD(&nsim_dev->port_list);	nsim_dev->fw_update_status = true;	nsim_dev->fw_update_overwrite_mask = 0;	nsim_dev->fw_update_flash_chunk_time_ms = NSIM_DEV_FLASH_CHUNK_TIME_MS_DEFAULT;	nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;	nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;	nsim_dev->test2 = NSIM_DEV_TEST2_DEFAULT;	spin_lock_init(&nsim_dev->fa_cookie_lock);	mutex_init(&nsim_dev->progs_list_lock); 	dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); 	nsim_dev->vfconfigs = kzalloc_objs(struct nsim_vf_config,					   nsim_bus_dev->max_vfs,					   GFP_KERNEL | __GFP_NOWARN);	if (!nsim_dev->vfconfigs) {		err = -ENOMEM;		goto err_devlink_unlock;	} 	err = devl_register(devlink);	if (err)		goto err_vfc_free; 	err = nsim_dev_resources_register(devlink);	if (err)		goto err_dl_unregister; 	err = devl_params_register(devlink, nsim_devlink_params,				   ARRAY_SIZE(nsim_devlink_params));	if (err)		goto err_resource_unregister;	nsim_devlink_set_params_init_values(nsim_dev, devlink); 	err = nsim_dev_dummy_region_init(nsim_dev, devlink);	if (err)		goto err_params_unregister; 	err = nsim_dev_traps_init(devlink);	if (err)		goto err_dummy_region_exit; 	err = nsim_dev_debugfs_init(nsim_dev);	if (err)		goto err_traps_exit; 	nsim_dev->fib_data = nsim_fib_create(devlink, NULL);	if (IS_ERR(nsim_dev->fib_data)) {		err = PTR_ERR(nsim_dev->fib_data);		goto err_debugfs_exit;	} 	err = nsim_dev_health_init(nsim_dev, devlink);	if (err)		goto err_fib_destroy; 	err = nsim_bpf_dev_init(nsim_dev);	if (err)		goto err_health_exit; 	err = nsim_dev_psample_init(nsim_dev);	if (err)		goto err_bpf_dev_exit; 	err = nsim_dev_hwstats_init(nsim_dev);	if (err)		goto err_psample_exit; 	err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);	if (err)		goto err_hwstats_exit; 	nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY;	devl_unlock(devlink);	return 0; err_hwstats_exit:	nsim_dev_hwstats_exit(nsim_dev);err_psample_exit:	nsim_dev_psample_exit(nsim_dev);err_bpf_dev_exit:	nsim_bpf_dev_exit(nsim_dev);err_health_exit:	nsim_dev_health_exit(nsim_dev);err_fib_destroy:	nsim_fib_destroy(devlink, nsim_dev->fib_data);err_debugfs_exit:	nsim_dev_debugfs_exit(nsim_dev);err_traps_exit:	nsim_dev_traps_exit(devlink);err_dummy_region_exit:	nsim_dev_dummy_region_exit(nsim_dev);err_params_unregister:	devl_params_unregister(devlink, nsim_devlink_params,			       ARRAY_SIZE(nsim_devlink_params));err_resource_unregister:	devl_resources_unregister(devlink);err_dl_unregister:	devl_unregister(devlink);err_vfc_free:	kfree(nsim_dev->vfconfigs);err_devlink_unlock:	devl_unlock(devlink);	devlink_free(devlink);	dev_set_drvdata(&nsim_bus_dev->dev, NULL);	return err;} static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev){	struct devlink *devlink = priv_to_devlink(nsim_dev); 	if (devlink_is_reload_failed(devlink))		return;	debugfs_remove(nsim_dev->take_snapshot); 	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);	} 	nsim_dev_port_del_all(nsim_dev);	nsim_dev_hwstats_exit(nsim_dev);	nsim_dev_psample_exit(nsim_dev);	nsim_dev_health_exit(nsim_dev);	nsim_fib_destroy(devlink, nsim_dev->fib_data);	nsim_dev_traps_exit(devlink);	nsim_dev_dummy_region_exit(nsim_dev);} void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev){	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);	struct devlink *devlink = priv_to_devlink(nsim_dev); 	devl_lock(devlink);	nsim_dev_reload_destroy(nsim_dev); 	nsim_bpf_dev_exit(nsim_dev);	nsim_dev_debugfs_exit(nsim_dev);	devl_params_unregister(devlink, nsim_devlink_params,			       ARRAY_SIZE(nsim_devlink_params));	devl_resources_unregister(devlink);	devl_unregister(devlink);	kfree(nsim_dev->vfconfigs);	kfree(nsim_dev->fa_cookie);	mutex_destroy(&nsim_dev->progs_list_lock);	devl_unlock(devlink);	devlink_free(devlink);	dev_set_drvdata(&nsim_bus_dev->dev, NULL);} static struct nsim_dev_port *__nsim_dev_port_lookup(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type,		       unsigned int port_index){	struct nsim_dev_port *nsim_dev_port; 	port_index = nsim_dev_port_index(type, port_index);	list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)		if (nsim_dev_port->port_index == port_index)			return nsim_dev_port;	return NULL;} int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,		      unsigned int port_index, u8 perm_addr[ETH_ALEN]){	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);	int err; 	devl_lock(priv_to_devlink(nsim_dev));	if (__nsim_dev_port_lookup(nsim_dev, type, port_index))		err = -EEXIST;	else		err = __nsim_dev_port_add(nsim_dev, type, port_index, perm_addr);	devl_unlock(priv_to_devlink(nsim_dev));	return err;} int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,		      unsigned int port_index){	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);	struct nsim_dev_port *nsim_dev_port;	int err = 0; 	devl_lock(priv_to_devlink(nsim_dev));	nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, type, port_index);	if (!nsim_dev_port)		err = -ENOENT;	else		__nsim_dev_port_del(nsim_dev_port);	devl_unlock(priv_to_devlink(nsim_dev));	return err;} int nsim_drv_configure_vfs(struct nsim_bus_dev *nsim_bus_dev,			   unsigned int num_vfs){	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);	struct devlink *devlink = priv_to_devlink(nsim_dev);	int ret = 0; 	devl_lock(devlink);	if (nsim_bus_dev->num_vfs == num_vfs)		goto exit_unlock;	if (nsim_bus_dev->num_vfs && num_vfs) {		ret = -EBUSY;		goto exit_unlock;	}	if (nsim_bus_dev->max_vfs < num_vfs) {		ret = -ENOMEM;		goto exit_unlock;	} 	nsim_bus_dev_set_vfs(nsim_bus_dev, num_vfs);	if (nsim_esw_mode_is_switchdev(nsim_dev)) {		if (num_vfs) {			ret = nsim_esw_switchdev_enable(nsim_dev, NULL);			if (ret) {				nsim_bus_dev_set_vfs(nsim_bus_dev, 0);				goto exit_unlock;			}		} else {			nsim_esw_legacy_enable(nsim_dev, NULL);		}	} exit_unlock:	devl_unlock(devlink); 	return ret;} int nsim_dev_init(void){	nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);	return PTR_ERR_OR_ZERO(nsim_dev_ddir);} void nsim_dev_exit(void){	debugfs_remove_recursive(nsim_dev_ddir);}

Lines 1501–1908 of 1908. Previous lines