mlxsw: core_linecards: Expose device FW version over device info

Extend MDDQ to obtain FW version of line card device and implement
device_info_get() op to fill up the info with that.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jiri Pirko 2022-04-25 06:44:30 +03:00 коммит произвёл David S. Miller
Родитель c38e9bf338
Коммит e932b4bdbd
2 изменённых файлов: 119 добавлений и 4 удалений

Просмотреть файл

@ -76,6 +76,21 @@ The ``mlxsw`` driver reports the following versions for line cards
- running
- Version of line card INI loaded
Line card device info versions
==============================
The ``mlxsw`` driver reports the following versions for line card devices
.. list-table:: devlink line card device info versions implemented
:widths: 5 5 90
* - Name
- Type
- Description
* - ``fw.version``
- running
- Three digit firmware version
Driver-specific Traps
=====================

Просмотреть файл

@ -87,13 +87,31 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard)
return linecard->name;
}
struct mlxsw_linecard_device_info {
u16 fw_major;
u16 fw_minor;
u16 fw_sub_minor;
};
struct mlxsw_linecard_device {
struct list_head list;
u8 index;
struct mlxsw_linecard *linecard;
struct devlink_linecard_device *devlink_device;
struct mlxsw_linecard_device_info info;
};
static struct mlxsw_linecard_device *
mlxsw_linecard_device_lookup(struct mlxsw_linecard *linecard, u8 index)
{
struct mlxsw_linecard_device *device;
list_for_each_entry(device, &linecard->device_list, list)
if (device->index == index)
return device;
return NULL;
}
static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core,
struct mlxsw_linecard *linecard,
u8 device_index, bool flash_owner)
@ -108,7 +126,7 @@ static int mlxsw_linecard_device_attach(struct mlxsw_core *mlxsw_core,
device->linecard = linecard;
device->devlink_device = devlink_linecard_device_create(linecard->devlink_linecard,
device_index, NULL);
device_index, device);
if (IS_ERR(device->devlink_device)) {
err = PTR_ERR(device->devlink_device);
goto err_devlink_linecard_device_attach;
@ -177,6 +195,77 @@ rollback:
return err;
}
static void mlxsw_linecard_device_update(struct mlxsw_linecard *linecard,
u8 device_index,
struct mlxsw_linecard_device_info *info)
{
struct mlxsw_linecard_device *device;
device = mlxsw_linecard_device_lookup(linecard, device_index);
if (!device)
return;
device->info = *info;
}
static int mlxsw_linecard_devices_update(struct mlxsw_linecard *linecard)
{
struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core;
u8 msg_seq = 0;
do {
struct mlxsw_linecard_device_info info;
char mddq_pl[MLXSW_REG_MDDQ_LEN];
bool data_valid;
u8 device_index;
int err;
mlxsw_reg_mddq_device_info_pack(mddq_pl, linecard->slot_index,
msg_seq);
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl);
if (err)
return err;
mlxsw_reg_mddq_device_info_unpack(mddq_pl, &msg_seq,
&data_valid, NULL,
&device_index,
&info.fw_major,
&info.fw_minor,
&info.fw_sub_minor);
if (!data_valid)
break;
mlxsw_linecard_device_update(linecard, device_index, &info);
} while (msg_seq);
return 0;
}
static int
mlxsw_linecard_device_info_get(struct devlink_linecard_device *devlink_linecard_device,
void *priv, struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
struct mlxsw_linecard_device *device = priv;
struct mlxsw_linecard_device_info *info;
struct mlxsw_linecard *linecard;
char buf[32];
linecard = device->linecard;
mutex_lock(&linecard->lock);
if (!linecard->active) {
mutex_unlock(&linecard->lock);
return 0;
}
info = &device->info;
sprintf(buf, "%u.%u.%u", info->fw_major, info->fw_minor,
info->fw_sub_minor);
mutex_unlock(&linecard->lock);
return devlink_info_version_running_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW,
buf);
}
static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard)
{
linecard->provisioned = false;
@ -390,11 +479,18 @@ static int mlxsw_linecard_ready_clear(struct mlxsw_linecard *linecard)
return 0;
}
static void mlxsw_linecard_active_set(struct mlxsw_linecard *linecard)
static int mlxsw_linecard_active_set(struct mlxsw_linecard *linecard)
{
int err;
err = mlxsw_linecard_devices_update(linecard);
if (err)
return err;
mlxsw_linecard_active_ops_call(linecard);
linecard->active = true;
devlink_linecard_activate(linecard->devlink_linecard);
return 0;
}
static void mlxsw_linecard_active_clear(struct mlxsw_linecard *linecard)
@ -443,8 +539,11 @@ static int mlxsw_linecard_status_process(struct mlxsw_linecards *linecards,
goto out;
}
if (active && linecard->active != active)
mlxsw_linecard_active_set(linecard);
if (active && linecard->active != active) {
err = mlxsw_linecard_active_set(linecard);
if (err)
goto out;
}
if (!active && linecard->active != active)
mlxsw_linecard_active_clear(linecard);
@ -872,6 +971,7 @@ static const struct devlink_linecard_ops mlxsw_linecard_ops = {
.types_count = mlxsw_linecard_types_count,
.types_get = mlxsw_linecard_types_get,
.info_get = mlxsw_linecard_info_get,
.device_info_get = mlxsw_linecard_device_info_get,
};
struct mlxsw_linecard_status_event {