Skip to content

Commit 7f66ee4

Browse files
committed
Merge branch 'devlink'
Jiri Pirko says: ==================== Introduce devlink interface and first drivers to use it There a is need for some userspace API that would allow to expose things that are not directly related to any device class like net_device of ib_device, but rather chip-wide/switch-ASIC-wide stuff. Use cases: 1) get/set of port type (Ethernet/InfiniBand) 2) setting up port splitters - split port into multiple ones and squash again, enables usage of splitter cable 3) setting up shared buffers - shared among multiple ports within one chip (work in progress) 4) configuration of switch wide properties - resources division etc - This will allow to pass configuration that is unacceptable to be passed as a module option. First patch of this set introduces a new generic Netlink based interface, called "devlink". It is similar to nl80211 model and it is heavily influenced by it, including the API definition. The devlink introduction patch implements use cases 1) and 2). Other 2 are in development atm and will be addressed by follow-ups. It is very convenient for drivers to use devlink, as you can see in other patches in this set. Counterpart for devlink is userspace tool for now called "dl". Command line interface and outputs are derived from "ip" tool so it should be easy for users to get used to it. It is available here as a standalone tool for now: https://github.com/jpirko/devlink After this is merge in kernel, I will include the "dl" or "devlink" tool into iproute2 toolset. Port type setting example: myhost:~$ dl help Usage: dl [ OPTIONS ] OBJECT { COMMAND | help } where OBJECT := { dev | port | monitor } OPTIONS := { -v/--verbose } myhost:~$ dl dev help Usage: dl dev show [DEV] myhost:~$ dl dev show pci/0000:01:00.0 myhost:~$ dl port help Usage: dl port show [DEV/PORT_INDEX] Usage: dl port set DEV/PORT_INDEX [ type { eth | ib | auto} ] Usage: dl port split DEV/PORT_INDEX count Usage: dl port unsplit DEV/PORT_INDEX myhost:~$ dl port show pci/0000:01:00.0/1: type ib ibdev mlx4_0 pci/0000:01:00.0/2: type ib ibdev mlx4_0 myhost:~$ sudo dl port set pci/0000:01:00.0/1 type eth myhost:~$ dl port show pci/0000:01:00.0/1: type eth netdev ens4 pci/0000:01:00.0/2: type ib ibdev mlx4_0 myhost:~$ sudo dl port set ens4 type auto myhost:~$ dl port show pci/0000:01:00.0/1: type eth(auto) netdev ens4 pci/0000:01:00.0/2: type ib ibdev mlx4_0 Port splitting example: myswitch:~$ sudo modprobe mlxsw_pci myswitch:~$ dl port pci/0000:03:00.0/1: type eth netdev eth0 pci/0000:03:00.0/3: type eth netdev eth1 pci/0000:03:00.0/5: type eth netdev eth2 ... pci/0000:03:00.0/63: type eth netdev eth31 myswitch:~$ sudo dl port split pci/0000:03:00.0/1 2 (or "sudo dl port split eth0 2") myswitch:~$ dl port pci/0000:03:00.0/3: type eth netdev eth1 pci/0000:03:00.0/5: type eth netdev eth2 ... pci/0000:03:00.0/63: type eth netdev eth31 pci/0000:03:00.0/1: type eth netdev eth0 split_group 16 pci/0000:03:00.0/2: type eth netdev eth32 split_group 16 myswitch:~$ sudo dl port unsplit pci/0000:03:00.0/1 myswitch:~$ dl port pci/0000:03:00.0/3: type eth netdev eth1 pci/0000:03:00.0/5: type eth netdev eth2 pci/0000:03:00.0/63: type eth netdev eth31 pci/0000:03:00.0/1: type eth netdev eth0 v2->v3: patch 1/9 -removed generated devlink index and name, use bus name and dev name as a handle for all userspace originated commands. Along with that, remove sysfs stub. Requested by Hannes Sowa. patch 2/9 -add dev param to devlink_register (api change) patch 4/9 -add dev param to devlink_register (api change) patch 9/9 -set port's speed according to width fix by Ido v1->v2: patch 1/9 -removed no longer used "devlink_dev" helper -fix couple of typos and misspells patch 4/9: -removed SET_NETDEV_DEV set to devlink dev ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents bd070e2 + 18f1e70 commit 7f66ee4

File tree

18 files changed

+1425
-59
lines changed

18 files changed

+1425
-59
lines changed

MAINTAINERS

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3499,6 +3499,14 @@ F: include/linux/device-mapper.h
34993499
F: include/linux/dm-*.h
35003500
F: include/uapi/linux/dm-*.h
35013501

3502+
DEVLINK
3503+
M: Jiri Pirko <jiri@mellanox.com>
3504+
L: netdev@vger.kernel.org
3505+
S: Supported
3506+
F: net/core/devlink.c
3507+
F: include/net/devlink.h
3508+
F: include/uapi/linux/devlink.h
3509+
35023510
DIALOG SEMICONDUCTOR DRIVERS
35033511
M: Support Opensource <support.opensource@diasemi.com>
35043512
W: http://www.dialog-semiconductor.com/products

drivers/infiniband/hw/mlx4/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/if_vlan.h>
4242
#include <net/ipv6.h>
4343
#include <net/addrconf.h>
44+
#include <net/devlink.h>
4445

4546
#include <rdma/ib_smi.h>
4647
#include <rdma/ib_user_verbs.h>
@@ -2519,6 +2520,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
25192520
}
25202521

25212522
ibdev->ib_active = true;
2523+
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
2524+
devlink_port_type_ib_set(mlx4_get_devlink_port(dev, i),
2525+
&ibdev->ib_dev);
25222526

25232527
if (mlx4_is_mfunc(ibdev->dev))
25242528
init_pkeys(ibdev);
@@ -2643,7 +2647,10 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
26432647
{
26442648
struct mlx4_ib_dev *ibdev = ibdev_ptr;
26452649
int p;
2650+
int i;
26462651

2652+
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
2653+
devlink_port_type_clear(mlx4_get_devlink_port(dev, i));
26472654
ibdev->ib_active = false;
26482655
flush_workqueue(wq);
26492656

drivers/net/ethernet/mellanox/mlx4/en_netdev.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <net/ip.h>
4141
#include <net/busy_poll.h>
4242
#include <net/vxlan.h>
43+
#include <net/devlink.h>
4344

4445
#include <linux/mlx4/driver.h>
4546
#include <linux/mlx4/device.h>
@@ -2033,8 +2034,11 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
20332034
en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
20342035

20352036
/* Unregister device - this will close the port if it was up */
2036-
if (priv->registered)
2037+
if (priv->registered) {
2038+
devlink_port_type_clear(mlx4_get_devlink_port(mdev->dev,
2039+
priv->port));
20372040
unregister_netdev(dev);
2041+
}
20382042

20392043
if (priv->allocated)
20402044
mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
@@ -3051,6 +3055,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
30513055
}
30523056

30533057
priv->registered = 1;
3058+
devlink_port_type_eth_set(mlx4_get_devlink_port(mdev->dev, priv->port),
3059+
dev);
30543060

30553061
return 0;
30563062

drivers/net/ethernet/mellanox/mlx4/intf.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/slab.h>
3535
#include <linux/export.h>
3636
#include <linux/errno.h>
37+
#include <net/devlink.h>
3738

3839
#include "mlx4.h"
3940

@@ -249,3 +250,11 @@ void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int
249250
return result;
250251
}
251252
EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev);
253+
254+
struct devlink_port *mlx4_get_devlink_port(struct mlx4_dev *dev, int port)
255+
{
256+
struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
257+
258+
return &info->devlink_port;
259+
}
260+
EXPORT_SYMBOL_GPL(mlx4_get_devlink_port);

drivers/net/ethernet/mellanox/mlx4/main.c

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <linux/io-mapping.h>
4343
#include <linux/delay.h>
4444
#include <linux/kmod.h>
45+
#include <net/devlink.h>
4546

4647
#include <linux/mlx4/device.h>
4748
#include <linux/mlx4/doorbell.h>
@@ -1081,36 +1082,20 @@ static ssize_t show_port_type(struct device *dev,
10811082
return strlen(buf);
10821083
}
10831084

1084-
static ssize_t set_port_type(struct device *dev,
1085-
struct device_attribute *attr,
1086-
const char *buf, size_t count)
1085+
static int __set_port_type(struct mlx4_port_info *info,
1086+
enum mlx4_port_type port_type)
10871087
{
1088-
struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
1089-
port_attr);
10901088
struct mlx4_dev *mdev = info->dev;
10911089
struct mlx4_priv *priv = mlx4_priv(mdev);
10921090
enum mlx4_port_type types[MLX4_MAX_PORTS];
10931091
enum mlx4_port_type new_types[MLX4_MAX_PORTS];
1094-
static DEFINE_MUTEX(set_port_type_mutex);
10951092
int i;
10961093
int err = 0;
10971094

1098-
mutex_lock(&set_port_type_mutex);
1099-
1100-
if (!strcmp(buf, "ib\n"))
1101-
info->tmp_type = MLX4_PORT_TYPE_IB;
1102-
else if (!strcmp(buf, "eth\n"))
1103-
info->tmp_type = MLX4_PORT_TYPE_ETH;
1104-
else if (!strcmp(buf, "auto\n"))
1105-
info->tmp_type = MLX4_PORT_TYPE_AUTO;
1106-
else {
1107-
mlx4_err(mdev, "%s is not supported port type\n", buf);
1108-
err = -EINVAL;
1109-
goto err_out;
1110-
}
1111-
11121095
mlx4_stop_sense(mdev);
11131096
mutex_lock(&priv->port_mutex);
1097+
info->tmp_type = port_type;
1098+
11141099
/* Possible type is always the one that was delivered */
11151100
mdev->caps.possible_type[info->port] = info->tmp_type;
11161101

@@ -1152,6 +1137,37 @@ static ssize_t set_port_type(struct device *dev,
11521137
out:
11531138
mlx4_start_sense(mdev);
11541139
mutex_unlock(&priv->port_mutex);
1140+
1141+
return err;
1142+
}
1143+
1144+
static ssize_t set_port_type(struct device *dev,
1145+
struct device_attribute *attr,
1146+
const char *buf, size_t count)
1147+
{
1148+
struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
1149+
port_attr);
1150+
struct mlx4_dev *mdev = info->dev;
1151+
enum mlx4_port_type port_type;
1152+
static DEFINE_MUTEX(set_port_type_mutex);
1153+
int err;
1154+
1155+
mutex_lock(&set_port_type_mutex);
1156+
1157+
if (!strcmp(buf, "ib\n")) {
1158+
port_type = MLX4_PORT_TYPE_IB;
1159+
} else if (!strcmp(buf, "eth\n")) {
1160+
port_type = MLX4_PORT_TYPE_ETH;
1161+
} else if (!strcmp(buf, "auto\n")) {
1162+
port_type = MLX4_PORT_TYPE_AUTO;
1163+
} else {
1164+
mlx4_err(mdev, "%s is not supported port type\n", buf);
1165+
err = -EINVAL;
1166+
goto err_out;
1167+
}
1168+
1169+
err = __set_port_type(info, port_type);
1170+
11551171
err_out:
11561172
mutex_unlock(&set_port_type_mutex);
11571173

@@ -2881,8 +2897,13 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
28812897

28822898
static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
28832899
{
2900+
struct devlink *devlink = priv_to_devlink(mlx4_priv(dev));
28842901
struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
2885-
int err = 0;
2902+
int err;
2903+
2904+
err = devlink_port_register(devlink, &info->devlink_port, port);
2905+
if (err)
2906+
return err;
28862907

28872908
info->dev = dev;
28882909
info->port = port;
@@ -2907,6 +2928,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
29072928
err = device_create_file(&dev->persist->pdev->dev, &info->port_attr);
29082929
if (err) {
29092930
mlx4_err(dev, "Failed to create file for port %d\n", port);
2931+
devlink_port_unregister(&info->devlink_port);
29102932
info->port = -1;
29112933
}
29122934

@@ -3678,23 +3700,54 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data,
36783700
return err;
36793701
}
36803702

3703+
static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
3704+
enum devlink_port_type port_type)
3705+
{
3706+
struct mlx4_port_info *info = container_of(devlink_port,
3707+
struct mlx4_port_info,
3708+
devlink_port);
3709+
enum mlx4_port_type mlx4_port_type;
3710+
3711+
switch (port_type) {
3712+
case DEVLINK_PORT_TYPE_AUTO:
3713+
mlx4_port_type = MLX4_PORT_TYPE_AUTO;
3714+
break;
3715+
case DEVLINK_PORT_TYPE_ETH:
3716+
mlx4_port_type = MLX4_PORT_TYPE_ETH;
3717+
break;
3718+
case DEVLINK_PORT_TYPE_IB:
3719+
mlx4_port_type = MLX4_PORT_TYPE_IB;
3720+
break;
3721+
default:
3722+
return -EOPNOTSUPP;
3723+
}
3724+
3725+
return __set_port_type(info, mlx4_port_type);
3726+
}
3727+
3728+
static const struct devlink_ops mlx4_devlink_ops = {
3729+
.port_type_set = mlx4_devlink_port_type_set,
3730+
};
3731+
36813732
static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
36823733
{
3734+
struct devlink *devlink;
36833735
struct mlx4_priv *priv;
36843736
struct mlx4_dev *dev;
36853737
int ret;
36863738

36873739
printk_once(KERN_INFO "%s", mlx4_version);
36883740

3689-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
3690-
if (!priv)
3741+
devlink = devlink_alloc(&mlx4_devlink_ops, sizeof(*priv));
3742+
if (!devlink)
36913743
return -ENOMEM;
3744+
priv = devlink_priv(devlink);
36923745

36933746
dev = &priv->dev;
36943747
dev->persist = kzalloc(sizeof(*dev->persist), GFP_KERNEL);
36953748
if (!dev->persist) {
3696-
kfree(priv);
3697-
return -ENOMEM;
3749+
ret = -ENOMEM;
3750+
goto err_devlink_free;
36983751
}
36993752
dev->persist->pdev = pdev;
37003753
dev->persist->dev = dev;
@@ -3703,14 +3756,23 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
37033756
mutex_init(&dev->persist->device_state_mutex);
37043757
mutex_init(&dev->persist->interface_state_mutex);
37053758

3759+
ret = devlink_register(devlink, &pdev->dev);
3760+
if (ret)
3761+
goto err_persist_free;
3762+
37063763
ret = __mlx4_init_one(pdev, id->driver_data, priv);
3707-
if (ret) {
3708-
kfree(dev->persist);
3709-
kfree(priv);
3710-
} else {
3711-
pci_save_state(pdev);
3712-
}
3764+
if (ret)
3765+
goto err_devlink_unregister;
37133766

3767+
pci_save_state(pdev);
3768+
return 0;
3769+
3770+
err_devlink_unregister:
3771+
devlink_unregister(devlink);
3772+
err_persist_free:
3773+
kfree(dev->persist);
3774+
err_devlink_free:
3775+
devlink_free(devlink);
37143776
return ret;
37153777
}
37163778

@@ -3811,6 +3873,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
38113873
struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
38123874
struct mlx4_dev *dev = persist->dev;
38133875
struct mlx4_priv *priv = mlx4_priv(dev);
3876+
struct devlink *devlink = priv_to_devlink(priv);
38143877
int active_vfs = 0;
38153878

38163879
mutex_lock(&persist->interface_state_mutex);
@@ -3841,8 +3904,9 @@ static void mlx4_remove_one(struct pci_dev *pdev)
38413904

38423905
pci_release_regions(pdev);
38433906
pci_disable_device(pdev);
3907+
devlink_unregister(devlink);
38443908
kfree(dev->persist);
3845-
kfree(priv);
3909+
devlink_free(devlink);
38463910
pci_set_drvdata(pdev, NULL);
38473911
}
38483912

drivers/net/ethernet/mellanox/mlx4/mlx4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <linux/workqueue.h>
4646
#include <linux/interrupt.h>
4747
#include <linux/spinlock.h>
48+
#include <net/devlink.h>
4849

4950
#include <linux/mlx4/device.h>
5051
#include <linux/mlx4/driver.h>
@@ -828,6 +829,7 @@ struct mlx4_port_info {
828829
struct mlx4_roce_gid_table gid_table;
829830
int base_qpn;
830831
struct cpu_rmap *rmap;
832+
struct devlink_port devlink_port;
831833
};
832834

833835
struct mlx4_sense {

0 commit comments

Comments
 (0)