/*
 * Copyright 2022-2023 Arm Limited and/or its affiliates
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 * SPDX-License-Identifier: GPL-2.0-only
 */

/****************************************************************************
 * Includes
 ****************************************************************************/

#include "ethosu_network_info.h"

#include "ethosu_device.h"
#include "ethosu_network.h"
#include "ethosu_mailbox.h"
#include "uapi/ethosu.h"

#define NETWORK_INFO_RESP_TIMEOUT_MS 3000

static inline int ethosu_network_info_send(struct ethosu_network_info *info)
{
	/* Send network info request to firmware */
	return ethosu_mailbox_network_info_request(&info->edev->mailbox,
						   &info->msg,
						   info->net->buf,
						   info->net->index);
}

static void ethosu_network_info_fail(struct ethosu_mailbox_msg *msg)
{
	struct ethosu_network_info *info =
		container_of(msg, typeof(*info), msg);

	if (completion_done(&info->done))
		return;

	info->errno = -EFAULT;
	complete(&info->done);
}

int ethosu_network_info_request(struct ethosu_network *net,
				struct ethosu_uapi_network_info *uapi)
{
	struct ethosu_network_info *info;
	int ret;
	int timeout;

	info = devm_kzalloc(net->edev->dev, sizeof(*info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	info->edev = net->edev;
	info->net = net;
	info->uapi = uapi;
	init_completion(&info->done);
	info->msg.fail = ethosu_network_info_fail;

	ret = ethosu_mailbox_register(&info->edev->mailbox, &info->msg);
	if (ret < 0)
		goto kfree;

	/* Get reference to network */
	ethosu_network_get(info->net);

	ret = ethosu_network_info_send(info);
	if (ret)
		goto deregister;

	dev_info(info->edev->dev,
		 "Network info create. info=0x%pK, net=0x%pK, msg.id=0x%x\n",
		 info, info->net, info->msg.id);

	/* Unlock the device mutex and wait for completion */
	mutex_unlock(&info->edev->mutex);
	timeout = wait_for_completion_timeout(&info->done,
					      msecs_to_jiffies(
						      NETWORK_INFO_RESP_TIMEOUT_MS));
	mutex_lock(&info->edev->mutex);

	if (0 == timeout) {
		dev_warn(info->edev->dev, "Network info timed out. info=0x%pK",
			 info);

		ret = -ETIME;
		goto deregister;
	}

	ret = info->errno;

deregister:
	ethosu_mailbox_deregister(&info->edev->mailbox, &info->msg);
	ethosu_network_put(info->net);

kfree:
	dev_info(info->edev->dev,
		 "Network info destroy. info=0x%pK, msg.id=0x%x\n",
		 info, info->msg.id);
	devm_kfree(info->edev->dev, info);

	return ret;
}

void ethosu_network_info_rsp(struct ethosu_device *edev,
			     int msg_id,
			     struct ethosu_core_msg_network_info_rsp *rsp)
{
	int ret;
	struct ethosu_mailbox_msg *msg;
	struct ethosu_network_info *info;
	uint32_t i;

	msg = ethosu_mailbox_find(&edev->mailbox, msg_id);
	if (IS_ERR(msg)) {
		dev_warn(edev->dev,
			 "Id for network info msg not found. msg.id=0x%x\n",
			 msg_id);

		return;
	}

	info = container_of(msg, typeof(*info), msg);

	if (completion_done(&info->done))
		return;

	info->errno = 0;

	if (rsp->status != ETHOSU_CORE_STATUS_OK) {
		info->errno = -EBADF;
		goto signal_complete;
	}

	if (rsp->ifm_count > ETHOSU_FD_MAX || rsp->ofm_count > ETHOSU_FD_MAX) {
		info->errno = -ENFILE;
		goto signal_complete;
	}

	ret = strscpy(info->uapi->desc, rsp->desc, sizeof(info->uapi->desc));
	if (ret < 0) {
		info->errno = ret;
		goto signal_complete;
	}

	info->uapi->ifm_count = rsp->ifm_count;
	for (i = 0; i < rsp->ifm_count; i++)
		info->uapi->ifm_size[i] = rsp->ifm_size[i];

	info->uapi->ofm_count = rsp->ofm_count;
	for (i = 0; i < rsp->ofm_count; i++)
		info->uapi->ofm_size[i] = rsp->ofm_size[i];

signal_complete:
	complete(&info->done);
}
