diff options
Diffstat (limited to 'net/devlink/core.c')
| -rw-r--r-- | net/devlink/core.c | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/net/devlink/core.c b/net/devlink/core.c index d8e509a669bf..eeb6a71f5f56 100644 --- a/net/devlink/core.c +++ b/net/devlink/core.c @@ -248,6 +248,24 @@ struct device *devlink_to_dev(const struct devlink *devlink) } EXPORT_SYMBOL_GPL(devlink_to_dev); +const char *devlink_bus_name(const struct devlink *devlink) +{ + return devlink->dev ? devlink->dev->bus->name : DEVLINK_INDEX_BUS_NAME; +} +EXPORT_SYMBOL_GPL(devlink_bus_name); + +const char *devlink_dev_name(const struct devlink *devlink) +{ + return devlink->dev ? dev_name(devlink->dev) : devlink->dev_name_index; +} +EXPORT_SYMBOL_GPL(devlink_dev_name); + +const char *devlink_dev_driver_name(const struct devlink *devlink) +{ + return devlink->dev_driver->name; +} +EXPORT_SYMBOL_GPL(devlink_dev_driver_name); + struct net *devlink_net(const struct devlink *devlink) { return read_pnet(&devlink->_net); @@ -311,7 +329,10 @@ static void devlink_release(struct work_struct *work) mutex_destroy(&devlink->lock); lockdep_unregister_key(&devlink->lock_key); - put_device(devlink->dev); + if (devlink->dev) + put_device(devlink->dev); + else + kfree(devlink->dev_name_index); kvfree(devlink); } @@ -321,13 +342,15 @@ void devlink_put(struct devlink *devlink) queue_rcu_work(system_percpu_wq, &devlink->rwork); } -struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp) +static struct devlink *__devlinks_xa_find_get(struct net *net, + unsigned long *indexp, + unsigned long end) { struct devlink *devlink = NULL; rcu_read_lock(); retry: - devlink = xa_find(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED); + devlink = xa_find(&devlinks, indexp, end, DEVLINK_REGISTERED); if (!devlink) goto unlock; @@ -346,6 +369,16 @@ next: goto retry; } +struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp) +{ + return __devlinks_xa_find_get(net, indexp, ULONG_MAX); +} + +struct devlink *devlinks_xa_lookup_get(struct net *net, unsigned long index) +{ + return __devlinks_xa_find_get(net, &index, index); +} + /** * devl_register - Register devlink instance * @devlink: devlink @@ -394,27 +427,15 @@ void devlink_unregister(struct devlink *devlink) } EXPORT_SYMBOL_GPL(devlink_unregister); -/** - * devlink_alloc_ns - Allocate new devlink instance resources - * in specific namespace - * - * @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, - struct device *dev) +struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size, + struct net *net, struct device *dev, + const struct device_driver *dev_driver) { struct devlink *devlink; static u32 last_id; int ret; - WARN_ON(!ops || !dev); + WARN_ON(!ops || !dev_driver); if (!devlink_reload_actions_valid(ops)) return NULL; @@ -427,8 +448,16 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops, if (ret < 0) goto err_xa_alloc; - devlink->dev = get_device(dev); + if (dev) { + devlink->dev = get_device(dev); + } else { + devlink->dev_name_index = kasprintf(GFP_KERNEL, "%u", devlink->index); + if (!devlink->dev_name_index) + goto err_kasprintf; + } + devlink->ops = ops; + devlink->dev_driver = dev_driver; xa_init_flags(&devlink->ports, XA_FLAGS_ALLOC); xa_init_flags(&devlink->params, XA_FLAGS_ALLOC); xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC); @@ -452,10 +481,32 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops, return devlink; +err_kasprintf: + xa_erase(&devlinks, devlink->index); err_xa_alloc: kvfree(devlink); return NULL; } + +/** + * devlink_alloc_ns - Allocate new devlink instance resources + * in specific namespace + * + * @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, + struct device *dev) +{ + WARN_ON(!dev); + return __devlink_alloc(ops, priv_size, net, dev, dev->driver); +} EXPORT_SYMBOL_GPL(devlink_alloc_ns); /** |
