Skip to content

Commit

Permalink
mlxsw: core_linecards: Introduce per line card auxiliary device
Browse files Browse the repository at this point in the history
In order to be eventually able to expose line card gearbox version and
possibility to flash FW, model the line card as a separate device on
auxiliary bus.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
  • Loading branch information
Jiri Pirko committed Jun 2, 2022
1 parent 69c4b01 commit 2d0852c
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 2 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlxsw/Makefile
Expand Up @@ -2,7 +2,7 @@
obj-$(CONFIG_MLXSW_CORE) += mlxsw_core.o
mlxsw_core-objs := core.o core_acl_flex_keys.o \
core_acl_flex_actions.o core_env.o \
core_linecards.o
core_linecards.o core_linecard_dev.o
mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o
mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o
obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/core.h
Expand Up @@ -12,6 +12,7 @@
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/net_namespace.h>
#include <linux/auxiliary_bus.h>
#include <net/devlink.h>

#include "trap.h"
Expand Down Expand Up @@ -567,6 +568,8 @@ enum mlxsw_linecard_status_event_type {
MLXSW_LINECARD_STATUS_EVENT_TYPE_UNPROVISION,
};

struct mlxsw_linecard_dev;

struct mlxsw_linecard {
u8 slot_index;
struct mlxsw_linecards *linecards;
Expand All @@ -581,6 +584,7 @@ struct mlxsw_linecard {
active:1;
u16 hw_revision;
u16 ini_version;
struct mlxsw_linecard_dev *dev;
};

struct mlxsw_linecard_types_info;
Expand Down Expand Up @@ -620,4 +624,9 @@ void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core,
struct mlxsw_linecards_event_ops *ops,
void *priv);

int mlxsw_linecard_dev_add(struct mlxsw_linecard *linecard);
void mlxsw_linecard_dev_del(struct mlxsw_linecard *linecard);
int mlxsw_linecard_driver_register(void);
void mlxsw_linecard_driver_unregister(void);

#endif
144 changes: 144 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
@@ -0,0 +1,144 @@
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/* Copyright (c) 2022 NVIDIA Corporation and Mellanox Technologies. All rights reserved */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/auxiliary_bus.h>
#include <linux/idr.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <net/devlink.h>
#include "core.h"

#define MLXSW_LINECARD_DEV_ID_NAME "lc"

struct mlxsw_linecard_dev {
struct auxiliary_device adev;
struct mlxsw_linecard *linecard;
struct devlink *devlink;
};

static DEFINE_IDA(mlxsw_linecard_dev_ida);

int mlxsw_linecard_dev_id_alloc(void)
{
return ida_alloc(&mlxsw_linecard_dev_ida, GFP_KERNEL);
}

void mlxsw_linecard_dev_id_free(int id)
{
ida_free(&mlxsw_linecard_dev_ida, id);
}

static void mlxsw_linecard_dev_release(struct device *device)
{
struct auxiliary_device *adev = container_of(device, struct auxiliary_device, dev);
struct mlxsw_linecard_dev *linecard_dev = container_of(adev, struct mlxsw_linecard_dev, adev);

mlxsw_linecard_dev_id_free(adev->id);
kfree(linecard_dev);
}

int mlxsw_linecard_dev_add(struct mlxsw_linecard *linecard)
{
struct mlxsw_linecard_dev *linecard_dev;
int err;
int id;

id = mlxsw_linecard_dev_id_alloc();
if (id < 0) {
return id;
}

linecard_dev = kzalloc(sizeof(*linecard_dev), GFP_KERNEL);
if (!linecard_dev) {
mlxsw_linecard_dev_id_free(id);
return -ENOMEM;
}
linecard_dev->adev.id = id;
linecard_dev->adev.name = MLXSW_LINECARD_DEV_ID_NAME;
linecard_dev->adev.dev.release = mlxsw_linecard_dev_release;
linecard_dev->adev.dev.parent = linecard->linecards->bus_info->dev;
linecard_dev->linecard = linecard;

err = auxiliary_device_init(&linecard_dev->adev);
if (err) {
mlxsw_linecard_dev_id_free(id);
kfree(linecard_dev);
return err;
}

err = auxiliary_device_add(&linecard_dev->adev);
if (err) {
auxiliary_device_uninit(&linecard_dev->adev);
return err;
}

linecard->dev = linecard_dev;
return 0;
}

void mlxsw_linecard_dev_del(struct mlxsw_linecard *linecard)
{
struct mlxsw_linecard_dev *linecard_dev = linecard->dev;

auxiliary_device_delete(&linecard_dev->adev);
auxiliary_device_uninit(&linecard_dev->adev);
}

static const struct devlink_ops mlxsw_linecard_dev_devlink_ops = {

};


static int mlxsw_linecard_dev_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct mlxsw_linecard_dev *linecard_dev = container_of(adev, struct mlxsw_linecard_dev, adev);
struct devlink *devlink;

devlink = devlink_alloc(&mlxsw_linecard_dev_devlink_ops, 0, &adev->dev);
if (!devlink)
return -ENOMEM;

devlink_register(devlink);
linecard_dev->devlink = devlink;

return 0;
}

static void mlxsw_linecard_dev_remove(struct auxiliary_device *adev)
{
struct mlxsw_linecard_dev *linecard_dev = container_of(adev, struct mlxsw_linecard_dev, adev);
struct devlink *devlink = linecard_dev->devlink;

devlink_unregister(devlink);
devlink_free(devlink);
}

static const struct auxiliary_device_id mlxsw_linecard_dev_id_table[] = {
{ .name = KBUILD_MODNAME "." MLXSW_LINECARD_DEV_ID_NAME },
{},
};

MODULE_DEVICE_TABLE(auxiliary, mlxsw_linecard_dev_id_table);

static struct auxiliary_driver mlxsw_linecard_driver = {
.name = MLXSW_LINECARD_DEV_ID_NAME,
.probe = mlxsw_linecard_dev_probe,
.remove = mlxsw_linecard_dev_remove,
.id_table = mlxsw_linecard_dev_id_table,
};

int mlxsw_linecard_driver_register(void)
{
return auxiliary_driver_register(&mlxsw_linecard_driver);
}

void mlxsw_linecard_driver_unregister(void)
{
auxiliary_driver_unregister(&mlxsw_linecard_driver);
}
9 changes: 8 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
Expand Up @@ -270,10 +270,16 @@ static int mlxsw_linecard_ready_set(struct mlxsw_linecard *linecard)
char mddc_pl[MLXSW_REG_MDDC_LEN];
int err;

err = mlxsw_linecard_dev_add(linecard);
if (err)
return err;

mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, true);
err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl);
if (err)
if (err) {
mlxsw_linecard_dev_del(linecard);
return err;
}
linecard->ready = true;
return 0;
}
Expand All @@ -288,6 +294,7 @@ static int mlxsw_linecard_ready_clear(struct mlxsw_linecard *linecard)
err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl);
if (err)
return err;
mlxsw_linecard_dev_del(linecard);
linecard->ready = false;
return 0;
}
Expand Down

0 comments on commit 2d0852c

Please sign in to comment.