Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mlxsw: core_linecards: Introduce per line card auxiliary device
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
Showing
4 changed files
with
162 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters