Skip to content

Commit

Permalink
net/mlx5: SF, Add auxiliary device driver
Browse files Browse the repository at this point in the history
Add auxiliary device driver for mlx5 subfunction auxiliary device.

A mlx5 subfunction is similar to PCI PF and VF. For a subfunction
an auxiliary device is created.

As a result, when mlx5 SF auxiliary device binds to the driver,
its netdev and rdma device are created, they appear as

$ ls -l /sys/bus/auxiliary/devices/
mlx5_core.sf.4 -> ../../../devices/pci0000:00/0000:00:03.0/0000:06:00.0/mlx5_core.sf.4

$ ls -l /sys/class/net/eth1/device
/sys/class/net/eth1/device -> ../../../mlx5_core.sf.4

$ cat /sys/bus/auxiliary/devices/mlx5_core.sf.4/sfnum
88

$ devlink dev show
pci/0000:06:00.0
auxiliary/mlx5_core.sf.4

$ devlink port show auxiliary/mlx5_core.sf.4/1
auxiliary/mlx5_core.sf.4/1: type eth netdev p0sf88 flavour virtual port 0 splittable false

$ rdma link show mlx5_0/1
link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev p0sf88

$ rdma dev show
8: rocep6s0f1: node_type ca fw 16.29.0550 node_guid 248a:0703:00b3:d113 sys_image_guid 248a:0703:00b3:d112
13: mlx5_0: node_type ca fw 16.29.0550 node_guid 0000:00ff:fe00:8888 sys_image_guid 248a:0703:00b3:d112

In future, devlink device instance name will adapt to have sfnum
annotation using either an alias or as devlink instance name described
in RFC [1].

[1] https://lore.kernel.org/netdev/20200519092258.GF4655@nanopsycho/

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Vu Pham <vuhuong@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
  • Loading branch information
paravmellanox authored and Saeed Mahameed committed Jan 22, 2021
1 parent 90d010b commit 1958fc2
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 6 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@ mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/dr_domain.o steering/dr_table.o
#
# SF device
#
mlx5_core-$(CONFIG_MLX5_SF) += sf/vhca_event.o sf/dev/dev.o
mlx5_core-$(CONFIG_MLX5_SF) += sf/vhca_event.o sf/dev/dev.o sf/dev/driver.o
12 changes: 12 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "fw_reset.h"
#include "fs_core.h"
#include "eswitch.h"
#include "sf/dev/dev.h"

static int mlx5_devlink_flash_update(struct devlink *devlink,
struct devlink_flash_update_params *params,
Expand Down Expand Up @@ -127,6 +128,17 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
bool sf_dev_allocated;

sf_dev_allocated = mlx5_sf_dev_allocated(dev);
if (sf_dev_allocated) {
/* Reload results in deleting SF device which further results in
* unregistering devlink instance while holding devlink_mutext.
* Hence, do not support reload.
*/
NL_SET_ERR_MSG_MOD(extack, "reload is unsupported when SFs are allocated\n");
return -EOPNOTSUPP;
}

switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/eq.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev)
for (i = 0; i < MLX5_EVENT_TYPE_MAX; i++)
ATOMIC_INIT_NOTIFIER_HEAD(&eq_table->nh[i]);

eq_table->irq_table = dev->priv.irq_table;
eq_table->irq_table = mlx5_irq_table_get(dev);
return 0;
}

Expand Down
12 changes: 9 additions & 3 deletions drivers/net/ethernet/mellanox/mlx5/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ unsigned int mlx5_core_debug_mask;
module_param_named(debug_mask, mlx5_core_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "debug mask: 1 = dump cmd data, 2 = dump cmd exec time, 3 = both. Default=0");

#define MLX5_DEFAULT_PROF 2
static unsigned int prof_sel = MLX5_DEFAULT_PROF;
module_param_named(prof_sel, prof_sel, uint, 0444);
MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
Expand Down Expand Up @@ -1303,7 +1302,7 @@ void mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup)
mutex_unlock(&dev->intf_state_mutex);
}

static int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
{
struct mlx5_priv *priv = &dev->priv;
int err;
Expand Down Expand Up @@ -1353,7 +1352,7 @@ static int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
return err;
}

static void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;

Expand Down Expand Up @@ -1696,6 +1695,10 @@ static int __init init(void)
if (err)
goto err_debug;

err = mlx5_sf_driver_register();
if (err)
goto err_sf;

#ifdef CONFIG_MLX5_CORE_EN
err = mlx5e_init();
if (err) {
Expand All @@ -1706,6 +1709,8 @@ static int __init init(void)

return 0;

err_sf:
pci_unregister_driver(&mlx5_core_driver);
err_debug:
mlx5_unregister_debugfs();
return err;
Expand All @@ -1716,6 +1721,7 @@ static void __exit cleanup(void)
#ifdef CONFIG_MLX5_CORE_EN
mlx5e_cleanup();
#endif
mlx5_sf_driver_unregister();
pci_unregister_driver(&mlx5_core_driver);
mlx5_unregister_debugfs();
}
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ enum mlx5_semaphore_space_address {
MLX5_SEMAPHORE_SW_RESET = 0x20,
};

#define MLX5_DEFAULT_PROF 2

int mlx5_query_hca_caps(struct mlx5_core_dev *dev);
int mlx5_query_board_id(struct mlx5_core_dev *dev);
int mlx5_cmd_init(struct mlx5_core_dev *dev);
Expand Down Expand Up @@ -176,6 +178,7 @@ struct cpumask *
mlx5_irq_get_affinity_mask(struct mlx5_irq_table *irq_table, int vecidx);
struct cpu_rmap *mlx5_irq_get_rmap(struct mlx5_irq_table *table);
int mlx5_irq_get_num_comp(struct mlx5_irq_table *table);
struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev);

int mlx5_events_init(struct mlx5_core_dev *dev);
void mlx5_events_cleanup(struct mlx5_core_dev *dev);
Expand Down Expand Up @@ -257,6 +260,13 @@ enum {
u8 mlx5_get_nic_state(struct mlx5_core_dev *dev);
void mlx5_set_nic_state(struct mlx5_core_dev *dev, u8 state);

static inline bool mlx5_core_is_sf(const struct mlx5_core_dev *dev)
{
return dev->coredev_type == MLX5_COREDEV_SF;
}

int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx);
void mlx5_mdev_uninit(struct mlx5_core_dev *dev);
void mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup);
int mlx5_load_one(struct mlx5_core_dev *dev, bool boot);

Expand Down
20 changes: 20 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev)
{
struct mlx5_irq_table *irq_table;

if (mlx5_core_is_sf(dev))
return 0;

irq_table = kvzalloc(sizeof(*irq_table), GFP_KERNEL);
if (!irq_table)
return -ENOMEM;
Expand All @@ -40,6 +43,9 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev)

void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev)
{
if (mlx5_core_is_sf(dev))
return;

kvfree(dev->priv.irq_table);
}

Expand Down Expand Up @@ -268,6 +274,9 @@ int mlx5_irq_table_create(struct mlx5_core_dev *dev)
int nvec;
int err;

if (mlx5_core_is_sf(dev))
return 0;

nvec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() +
MLX5_IRQ_VEC_COMP_BASE;
nvec = min_t(int, nvec, num_eqs);
Expand Down Expand Up @@ -319,6 +328,9 @@ void mlx5_irq_table_destroy(struct mlx5_core_dev *dev)
struct mlx5_irq_table *table = dev->priv.irq_table;
int i;

if (mlx5_core_is_sf(dev))
return;

/* free_irq requires that affinity and rmap will be cleared
* before calling it. This is why there is asymmetry with set_rmap
* which should be called after alloc_irq but before request_irq.
Expand All @@ -332,3 +344,11 @@ void mlx5_irq_table_destroy(struct mlx5_core_dev *dev)
kfree(table->irq);
}

struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev)
{
#ifdef CONFIG_MLX5_SF
if (mlx5_core_is_sf(dev))
return dev->priv.parent_mdev->priv.irq_table;
#endif
return dev->priv.irq_table;
}
10 changes: 10 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ static bool mlx5_sf_dev_supported(const struct mlx5_core_dev *dev)
return MLX5_CAP_GEN(dev, sf) && mlx5_vhca_event_supported(dev);
}

bool mlx5_sf_dev_allocated(const struct mlx5_core_dev *dev)
{
struct mlx5_sf_dev_table *table = dev->priv.sf_dev_table;

if (!mlx5_sf_dev_supported(dev))
return false;

return !xa_empty(&table->devices);
}

static ssize_t sfnum_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct auxiliary_device *adev = container_of(dev, struct auxiliary_device, dev);
Expand Down
20 changes: 20 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@
struct mlx5_sf_dev {
struct auxiliary_device adev;
struct mlx5_core_dev *parent_mdev;
struct mlx5_core_dev *mdev;
phys_addr_t bar_base_addr;
u32 sfnum;
};

void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev);
void mlx5_sf_dev_table_destroy(struct mlx5_core_dev *dev);

int mlx5_sf_driver_register(void);
void mlx5_sf_driver_unregister(void);

bool mlx5_sf_dev_allocated(const struct mlx5_core_dev *dev);

#else

static inline void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev)
Expand All @@ -30,6 +36,20 @@ static inline void mlx5_sf_dev_table_destroy(struct mlx5_core_dev *dev)
{
}

static inline int mlx5_sf_driver_register(void)
{
return 0;
}

static inline void mlx5_sf_driver_unregister(void)
{
}

static inline bool mlx5_sf_dev_allocated(const struct mlx5_core_dev *dev)
{
return 0;
}

#endif

#endif
101 changes: 101 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2020 Mellanox Technologies Ltd */

#include <linux/mlx5/driver.h>
#include <linux/mlx5/device.h>
#include "mlx5_core.h"
#include "dev.h"
#include "devlink.h"

static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id)
{
struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
struct mlx5_core_dev *mdev;
struct devlink *devlink;
int err;

devlink = mlx5_devlink_alloc();
if (!devlink)
return -ENOMEM;

mdev = devlink_priv(devlink);
mdev->device = &adev->dev;
mdev->pdev = sf_dev->parent_mdev->pdev;
mdev->bar_addr = sf_dev->bar_base_addr;
mdev->iseg_base = sf_dev->bar_base_addr;
mdev->coredev_type = MLX5_COREDEV_SF;
mdev->priv.parent_mdev = sf_dev->parent_mdev;
mdev->priv.adev_idx = adev->id;
sf_dev->mdev = mdev;

err = mlx5_mdev_init(mdev, MLX5_DEFAULT_PROF);
if (err) {
mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err);
goto mdev_err;
}

mdev->iseg = ioremap(mdev->iseg_base, sizeof(*mdev->iseg));
if (!mdev->iseg) {
mlx5_core_warn(mdev, "remap error\n");
goto remap_err;
}

err = mlx5_load_one(mdev, true);
if (err) {
mlx5_core_warn(mdev, "mlx5_load_one err=%d\n", err);
goto load_one_err;
}
return 0;

load_one_err:
iounmap(mdev->iseg);
remap_err:
mlx5_mdev_uninit(mdev);
mdev_err:
mlx5_devlink_free(devlink);
return err;
}

static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
{
struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
struct devlink *devlink;

devlink = priv_to_devlink(sf_dev->mdev);
mlx5_unload_one(sf_dev->mdev, true);
iounmap(sf_dev->mdev->iseg);
mlx5_mdev_uninit(sf_dev->mdev);
mlx5_devlink_free(devlink);
}

static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev)
{
struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);

mlx5_unload_one(sf_dev->mdev, false);
}

static const struct auxiliary_device_id mlx5_sf_dev_id_table[] = {
{ .name = MLX5_ADEV_NAME "." MLX5_SF_DEV_ID_NAME, },
{ },
};

MODULE_DEVICE_TABLE(auxiliary, mlx5_sf_dev_id_table);

static struct auxiliary_driver mlx5_sf_driver = {
.name = MLX5_SF_DEV_ID_NAME,
.probe = mlx5_sf_dev_probe,
.remove = mlx5_sf_dev_remove,
.shutdown = mlx5_sf_dev_shutdown,
.id_table = mlx5_sf_dev_id_table,
};

int mlx5_sf_driver_register(void)
{
return auxiliary_driver_register(&mlx5_sf_driver);
}

void mlx5_sf_driver_unregister(void)
{
auxiliary_driver_unregister(&mlx5_sf_driver);
}
4 changes: 3 additions & 1 deletion include/linux/mlx5/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ enum port_state_policy {

enum mlx5_coredev_type {
MLX5_COREDEV_PF,
MLX5_COREDEV_VF
MLX5_COREDEV_VF,
MLX5_COREDEV_SF,
};

struct mlx5_field_desc {
Expand Down Expand Up @@ -608,6 +609,7 @@ struct mlx5_priv {
#ifdef CONFIG_MLX5_SF
struct mlx5_vhca_state_notifier *vhca_state_notifier;
struct mlx5_sf_dev_table *sf_dev_table;
struct mlx5_core_dev *parent_mdev;
#endif
};

Expand Down

0 comments on commit 1958fc2

Please sign in to comment.