Commit b473b0d2 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

devlink: create a special NDO for getting the devlink instance



Instead of iterating over all devlink ports add a NDO which
will return the devlink instance from the driver.

v2: add the netdev_to_devlink() helper (Michal)
v3: check that devlink has ops (Florian)
v4: hold devlink_mutex (Jiri)

Suggested-by: default avatarJiri Pirko <jiri@resnulli.us>
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f4b6bcc7
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -941,6 +941,8 @@ struct dev_ifalias {
	char ifalias[];
};

struct devlink;

/*
 * This structure defines the management hooks for network devices.
 * The following hooks can be defined; unless noted otherwise, they are
@@ -1249,6 +1251,10 @@ struct dev_ifalias {
 *	that got dropped are freed/returned via xdp_return_frame().
 *	Returns negative number, means general error invoking ndo, meaning
 *	no frames were xmit'ed and core-caller will free all frames.
 * struct devlink *(*ndo_get_devlink)(struct net_device *dev);
 *	Get devlink instance associated with a given netdev.
 *	Called with a reference on the netdevice and devlink locks only,
 *	rtnl_lock is not held.
 */
struct net_device_ops {
	int			(*ndo_init)(struct net_device *dev);
@@ -1447,6 +1453,7 @@ struct net_device_ops {
						u32 flags);
	int			(*ndo_xsk_async_xmit)(struct net_device *dev,
						      u32 queue_id);
	struct devlink *	(*ndo_get_devlink)(struct net_device *dev);
};

/**
+9 −0
Original line number Diff line number Diff line
@@ -538,6 +538,15 @@ static inline struct devlink *priv_to_devlink(void *priv)
	return container_of(priv, struct devlink, priv);
}

static inline struct devlink *netdev_to_devlink(struct net_device *dev)
{
#if IS_ENABLED(CONFIG_NET_DEVLINK)
	if (dev->netdev_ops->ndo_get_devlink)
		return dev->netdev_ops->ndo_get_devlink(dev);
#endif
	return NULL;
}

struct ib_device;

#if IS_ENABLED(CONFIG_NET_DEVLINK)
+17 −39
Original line number Diff line number Diff line
@@ -6397,9 +6397,6 @@ static void __devlink_compat_running_version(struct devlink *devlink,
	struct sk_buff *msg;
	int rem, err;

	if (!devlink->ops->info_get)
		return;

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return;
@@ -6431,55 +6428,36 @@ free_msg:
void devlink_compat_running_version(struct net_device *dev,
				    char *buf, size_t len)
{
	struct devlink_port *devlink_port;
	struct devlink *devlink;

	mutex_lock(&devlink_mutex);
	list_for_each_entry(devlink, &devlink_list, list) {
	devlink = netdev_to_devlink(dev);
	if (!devlink || !devlink->ops || !devlink->ops->info_get)
		goto unlock_list;

	mutex_lock(&devlink->lock);
		list_for_each_entry(devlink_port, &devlink->port_list, list) {
			if (devlink_port->type == DEVLINK_PORT_TYPE_ETH &&
			    devlink_port->type_dev == dev) {
				__devlink_compat_running_version(devlink,
								 buf, len);
	__devlink_compat_running_version(devlink, buf, len);
	mutex_unlock(&devlink->lock);
				goto out;
			}
		}
		mutex_unlock(&devlink->lock);
	}
out:
unlock_list:
	mutex_unlock(&devlink_mutex);
}

int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
{
	struct devlink_port *devlink_port;
	struct devlink *devlink;

	mutex_lock(&devlink_mutex);
	list_for_each_entry(devlink, &devlink_list, list) {
		mutex_lock(&devlink->lock);
		list_for_each_entry(devlink_port, &devlink->port_list, list) {
	int ret = -EOPNOTSUPP;

			if (devlink_port->type != DEVLINK_PORT_TYPE_ETH ||
			    devlink_port->type_dev != dev)
				continue;
	mutex_lock(&devlink_mutex);
	devlink = netdev_to_devlink(dev);
	if (!devlink || !devlink->ops || !devlink->ops->flash_update)
		goto unlock_list;

			mutex_unlock(&devlink_mutex);
			if (devlink->ops->flash_update)
				ret = devlink->ops->flash_update(devlink,
								 file_name,
								 NULL, NULL);
			mutex_unlock(&devlink->lock);
			return ret;
		}
	mutex_lock(&devlink->lock);
	ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
	mutex_unlock(&devlink->lock);
	}
unlock_list:
	mutex_unlock(&devlink_mutex);

	return -EOPNOTSUPP;
	return ret;
}

static int __init devlink_init(void)