diff options
author | Leon Romanovsky <leonro@nvidia.com> | 2021-08-08 21:57:43 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-08-09 10:21:40 +0100 |
commit | 919d13a7e455c2e7676042d7a5f94c164e859d8a (patch) | |
tree | 0b272b82900d1a7760b3cb2838390fa54cbd9a69 /net/core/devlink.c | |
parent | 94c0a6fbd5cfc34d3ce5fea5867123402cdc8794 (diff) |
devlink: Set device as early as possible
All kernel devlink implementations call to devlink_alloc() during
initialization routine for specific device which is used later as
a parent device for devlink_register().
Such late device assignment causes to the situation which requires us to
call to device_register() before setting other parameters, but that call
opens devlink to the world and makes accessible for the netlink users.
Any attempt to move devlink_register() to be the last call generates the
following error due to access to the devlink->dev pointer.
[ 8.758862] devlink_nl_param_fill+0x2e8/0xe50
[ 8.760305] devlink_param_notify+0x6d/0x180
[ 8.760435] __devlink_params_register+0x2f1/0x670
[ 8.760558] devlink_params_register+0x1e/0x20
The simple change of API to set devlink device in the devlink_alloc()
instead of devlink_register() fixes all this above and ensures that
prior to call to devlink_register() everything already set.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/devlink.c')
-rw-r--r-- | net/core/devlink.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/net/core/devlink.c b/net/core/devlink.c index ee95eee8d0ed..d3b16dd9f64e 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -8768,24 +8768,26 @@ static bool devlink_reload_actions_valid(const struct devlink_ops *ops) * @ops: ops * @priv_size: size of user private data * @net: net namespace + * @dev: parent device * * Allocate new devlink instance resources, including devlink index * and name. */ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops, - size_t priv_size, struct net *net) + size_t priv_size, struct net *net, + struct device *dev) { struct devlink *devlink; - if (WARN_ON(!ops)) - return NULL; - + WARN_ON(!ops || !dev); if (!devlink_reload_actions_valid(ops)) return NULL; devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); if (!devlink) return NULL; + + devlink->dev = dev; devlink->ops = ops; xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC); write_pnet(&devlink->_net, net); @@ -8810,12 +8812,9 @@ EXPORT_SYMBOL_GPL(devlink_alloc_ns); * devlink_register - Register devlink instance * * @devlink: devlink - * @dev: parent device */ -int devlink_register(struct devlink *devlink, struct device *dev) +int devlink_register(struct devlink *devlink) { - WARN_ON(devlink->dev); - devlink->dev = dev; mutex_lock(&devlink_mutex); list_add_tail(&devlink->list, &devlink_list); devlink_notify(devlink, DEVLINK_CMD_NEW); |