162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/module.h>
562306a36Sopenharmony_ci#include <linux/netdevice.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "ionic.h"
862306a36Sopenharmony_ci#include "ionic_bus.h"
962306a36Sopenharmony_ci#include "ionic_lif.h"
1062306a36Sopenharmony_ci#include "ionic_devlink.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic int ionic_dl_flash_update(struct devlink *dl,
1362306a36Sopenharmony_ci				 struct devlink_flash_update_params *params,
1462306a36Sopenharmony_ci				 struct netlink_ext_ack *extack)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	struct ionic *ionic = devlink_priv(dl);
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	return ionic_firmware_update(ionic->lif, params->fw, extack);
1962306a36Sopenharmony_ci}
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int ionic_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
2262306a36Sopenharmony_ci			     struct netlink_ext_ack *extack)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	struct ionic *ionic = devlink_priv(dl);
2562306a36Sopenharmony_ci	struct ionic_dev *idev = &ionic->idev;
2662306a36Sopenharmony_ci	char buf[16];
2762306a36Sopenharmony_ci	int err = 0;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	err = devlink_info_version_running_put(req,
3062306a36Sopenharmony_ci					       DEVLINK_INFO_VERSION_GENERIC_FW,
3162306a36Sopenharmony_ci					       idev->dev_info.fw_version);
3262306a36Sopenharmony_ci	if (err)
3362306a36Sopenharmony_ci		return err;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	snprintf(buf, sizeof(buf), "0x%x", idev->dev_info.asic_type);
3662306a36Sopenharmony_ci	err = devlink_info_version_fixed_put(req,
3762306a36Sopenharmony_ci					     DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,
3862306a36Sopenharmony_ci					     buf);
3962306a36Sopenharmony_ci	if (err)
4062306a36Sopenharmony_ci		return err;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	snprintf(buf, sizeof(buf), "0x%x", idev->dev_info.asic_rev);
4362306a36Sopenharmony_ci	err = devlink_info_version_fixed_put(req,
4462306a36Sopenharmony_ci					     DEVLINK_INFO_VERSION_GENERIC_ASIC_REV,
4562306a36Sopenharmony_ci					     buf);
4662306a36Sopenharmony_ci	if (err)
4762306a36Sopenharmony_ci		return err;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	err = devlink_info_serial_number_put(req, idev->dev_info.serial_num);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	return err;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic const struct devlink_ops ionic_dl_ops = {
5562306a36Sopenharmony_ci	.info_get	= ionic_dl_info_get,
5662306a36Sopenharmony_ci	.flash_update	= ionic_dl_flash_update,
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct ionic *ionic_devlink_alloc(struct device *dev)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	struct devlink *dl;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	dl = devlink_alloc(&ionic_dl_ops, sizeof(struct ionic), dev);
6462306a36Sopenharmony_ci	if (!dl)
6562306a36Sopenharmony_ci		return NULL;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return devlink_priv(dl);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_civoid ionic_devlink_free(struct ionic *ionic)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	struct devlink *dl = priv_to_devlink(ionic);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	devlink_free(dl);
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciint ionic_devlink_register(struct ionic *ionic)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	struct devlink *dl = priv_to_devlink(ionic);
8062306a36Sopenharmony_ci	struct devlink_port_attrs attrs = {};
8162306a36Sopenharmony_ci	int err;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
8462306a36Sopenharmony_ci	devlink_port_attrs_set(&ionic->dl_port, &attrs);
8562306a36Sopenharmony_ci	err = devlink_port_register(dl, &ionic->dl_port, 0);
8662306a36Sopenharmony_ci	if (err) {
8762306a36Sopenharmony_ci		dev_err(ionic->dev, "devlink_port_register failed: %d\n", err);
8862306a36Sopenharmony_ci		return err;
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	SET_NETDEV_DEVLINK_PORT(ionic->lif->netdev, &ionic->dl_port);
9262306a36Sopenharmony_ci	devlink_register(dl);
9362306a36Sopenharmony_ci	return 0;
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_civoid ionic_devlink_unregister(struct ionic *ionic)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct devlink *dl = priv_to_devlink(ionic);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	devlink_unregister(dl);
10162306a36Sopenharmony_ci	devlink_port_unregister(&ionic->dl_port);
10262306a36Sopenharmony_ci}
103