// SPDX-License-Identifier: GPL-2.0+
/* Copyright (c) 2021 Hisilicon Limited. */

#include <net/devlink.h>

#include "hclge_devlink.h"

static int hclge_devlink_scc_info_get(struct devlink *devlink,
				      struct devlink_info_req *req)
{
	struct hclge_devlink_priv *priv = devlink_priv(devlink);
	char scc_version[HCLGE_DEVLINK_FW_SCC_LEN];
	struct hclge_dev *hdev = priv->hdev;
	u32 scc_version_tmp;
	int ret;

	ret = hclge_query_scc_version(hdev, &scc_version_tmp);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"failed to get scc version, ret = %d\n", ret);
		return ret;
	}

	snprintf(scc_version, sizeof(scc_version), "%lu.%lu.%lu.%lu",
		 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE3_MASK,
				 HNAE3_FW_VERSION_BYTE3_SHIFT),
		 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE2_MASK,
				 HNAE3_FW_VERSION_BYTE2_SHIFT),
		 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE1_MASK,
				 HNAE3_FW_VERSION_BYTE1_SHIFT),
		 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE0_MASK,
				 HNAE3_FW_VERSION_BYTE0_SHIFT));
	return devlink_info_version_running_put(req, "fw.scc", scc_version);
}

static int hclge_devlink_info_get(struct devlink *devlink,
				  struct devlink_info_req *req,
				  struct netlink_ext_ack *extack)
{
#define	HCLGE_DEVLINK_FW_STRING_LEN	32
	struct hclge_devlink_priv *priv = devlink_priv(devlink);
	char version_str[HCLGE_DEVLINK_FW_STRING_LEN];
	struct hclge_dev *hdev = priv->hdev;
	int ret;

	snprintf(version_str, sizeof(version_str), "%lu.%lu.%lu.%lu",
		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE3_MASK,
				 HNAE3_FW_VERSION_BYTE3_SHIFT),
		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE2_MASK,
				 HNAE3_FW_VERSION_BYTE2_SHIFT),
		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE1_MASK,
				 HNAE3_FW_VERSION_BYTE1_SHIFT),
		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE0_MASK,
				 HNAE3_FW_VERSION_BYTE0_SHIFT));

	ret = devlink_info_version_running_put(req,
					       DEVLINK_INFO_VERSION_GENERIC_FW,
					       version_str);
	if (ret) {
		dev_err(&hdev->pdev->dev, "failed to set running version of fw\n");
		return ret;
	}

	if (hdev->pdev->revision > HNAE3_DEVICE_VERSION_V2)
		ret = hclge_devlink_scc_info_get(devlink, req);

	return ret;
}

static int hclge_devlink_reload_down(struct devlink *devlink, bool netns_change,
				     enum devlink_reload_action action,
				     enum devlink_reload_limit limit,
				     struct netlink_ext_ack *extack)
{
	struct hclge_devlink_priv *priv = devlink_priv(devlink);
	struct hclge_dev *hdev = priv->hdev;
	struct hnae3_handle *h = &hdev->vport->nic;
	struct pci_dev *pdev = hdev->pdev;
	int ret;

	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
		dev_err(&pdev->dev, "reset is handling\n");
		return -EBUSY;
	}

	switch (action) {
	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
		rtnl_lock();
		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_DOWN_CLIENT);
		if (ret) {
			rtnl_unlock();
			return ret;
		}

		ret = hdev->nic_client->ops->reset_notify(h,
							  HNAE3_UNINIT_CLIENT);
		rtnl_unlock();
		return ret;
	default:
		return -EOPNOTSUPP;
	}
}

static int hclge_devlink_reload_up(struct devlink *devlink,
				   enum devlink_reload_action action,
				   enum devlink_reload_limit limit,
				   u32 *actions_performed,
				   struct netlink_ext_ack *extack)
{
	struct hclge_devlink_priv *priv = devlink_priv(devlink);
	struct hclge_dev *hdev = priv->hdev;
	struct hnae3_handle *h = &hdev->vport->nic;
	int ret;

	*actions_performed = BIT(action);
	switch (action) {
	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
		rtnl_lock();
		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_INIT_CLIENT);
		if (ret) {
			rtnl_unlock();
			return ret;
		}

		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_UP_CLIENT);
		rtnl_unlock();
		return ret;
	default:
		return -EOPNOTSUPP;
	}
}

static const struct devlink_ops hclge_devlink_ops = {
	.info_get = hclge_devlink_info_get,
	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
	.reload_down = hclge_devlink_reload_down,
	.reload_up = hclge_devlink_reload_up,
};

int hclge_devlink_init(struct hclge_dev *hdev)
{
	struct pci_dev *pdev = hdev->pdev;
	struct hclge_devlink_priv *priv;
	struct devlink *devlink;

	devlink = devlink_alloc(&hclge_devlink_ops,
				sizeof(struct hclge_devlink_priv), &pdev->dev);
	if (!devlink)
		return -ENOMEM;

	priv = devlink_priv(devlink);
	priv->hdev = hdev;
	hdev->devlink = devlink;

	devlink_register(devlink);
	return 0;
}

void hclge_devlink_uninit(struct hclge_dev *hdev)
{
	struct devlink *devlink = hdev->devlink;

	devlink_unregister(devlink);

	devlink_free(devlink);
}
