// SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
/*
 * Copyright (C) 2018 Netronome Systems, Inc.
 *
 * This software is dual licensed under the GNU General License Version 2,
 * June 1991 as shown in the file COPYING in the top-level directory of this
 * source tree or the BSD 2-Clause License provided below.  You have the
 * option to license this software under the complete terms of either license.
 *
 * The BSD 2-Clause License:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      1. Redistributions of source code must retain the above
 *         copyright notice, this list of conditions and the following
 *         disclaimer.
 *
 *      2. Redistributions in binary form must reproduce the above
 *         copyright notice, this list of conditions and the following
 *         disclaimer in the documentation and/or other materials
 *         provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <linux/kernel.h>
#include <net/devlink.h>

#include "nfpcore/nfp_cpp.h"
#include "nfpcore/nfp_nffw.h"
#include "nfp_abi.h"
#include "nfp_app.h"
#include "nfp_main.h"

static u32 nfp_shared_buf_pool_unit(struct nfp_pf *pf, unsigned int sb)
{
	__le32 sb_id = cpu_to_le32(sb);
	unsigned int i;

	for (i = 0; i < pf->num_shared_bufs; i++)
		if (pf->shared_bufs[i].id == sb_id)
			return le32_to_cpu(pf->shared_bufs[i].pool_size_unit);

	WARN_ON_ONCE(1);
	return 0;
}

int nfp_shared_buf_pool_get(struct nfp_pf *pf, unsigned int sb, u16 pool_index,
			    struct devlink_sb_pool_info *pool_info)
{
	struct nfp_shared_buf_pool_info_get get_data;
	struct nfp_shared_buf_pool_id id = {
		.shared_buf	= cpu_to_le32(sb),
		.pool		= cpu_to_le32(pool_index),
	};
	unsigned int unit_size;
	int n;

	unit_size = nfp_shared_buf_pool_unit(pf, sb);
	if (!unit_size)
		return -EINVAL;

	n = nfp_mbox_cmd(pf, NFP_MBOX_POOL_GET, &id, sizeof(id),
			 &get_data, sizeof(get_data));
	if (n < 0)
		return n;
	if (n < sizeof(get_data))
		return -EIO;

	pool_info->pool_type = le32_to_cpu(get_data.pool_type);
	pool_info->threshold_type = le32_to_cpu(get_data.threshold_type);
	pool_info->size = le32_to_cpu(get_data.size) * unit_size;

	return 0;
}

int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb,
			    u16 pool_index, u32 size,
			    enum devlink_sb_threshold_type threshold_type)
{
	struct nfp_shared_buf_pool_info_set set_data = {
		.id = {
			.shared_buf	= cpu_to_le32(sb),
			.pool		= cpu_to_le32(pool_index),
		},
		.threshold_type	= cpu_to_le32(threshold_type),
	};
	unsigned int unit_size;

	unit_size = nfp_shared_buf_pool_unit(pf, sb);
	if (!unit_size || size % unit_size)
		return -EINVAL;
	set_data.size = cpu_to_le32(size / unit_size);

	return nfp_mbox_cmd(pf, NFP_MBOX_POOL_SET, &set_data, sizeof(set_data),
			    NULL, 0);
}

int nfp_shared_buf_register(struct nfp_pf *pf)
{
	struct devlink *devlink = priv_to_devlink(pf);
	unsigned int i, num_entries, entry_sz;
	struct nfp_cpp_area *sb_desc_area;
	u8 __iomem *sb_desc;
	int n, err;

	if (!pf->mbox)
		return 0;

	n = nfp_pf_rtsym_read_optional(pf, NFP_SHARED_BUF_COUNT_SYM_NAME, 0);
	if (n <= 0)
		return n;
	num_entries = n;

	sb_desc = nfp_pf_map_rtsym(pf, "sb_tbl", NFP_SHARED_BUF_TABLE_SYM_NAME,
				   num_entries * sizeof(pf->shared_bufs[0]),
				   &sb_desc_area);
	if (IS_ERR(sb_desc))
		return PTR_ERR(sb_desc);

	entry_sz = nfp_cpp_area_size(sb_desc_area) / num_entries;

	pf->shared_bufs = kmalloc_array(num_entries, sizeof(pf->shared_bufs[0]),
					GFP_KERNEL);
	if (!pf->shared_bufs) {
		err = -ENOMEM;
		goto err_release_area;
	}

	for (i = 0; i < num_entries; i++) {
		struct nfp_shared_buf *sb = &pf->shared_bufs[i];

		/* Entries may be larger in future FW */
		memcpy_fromio(sb, sb_desc + i * entry_sz, sizeof(*sb));

		err = devlink_sb_register(devlink,
					  le32_to_cpu(sb->id),
					  le32_to_cpu(sb->size),
					  le16_to_cpu(sb->ingress_pools_count),
					  le16_to_cpu(sb->egress_pools_count),
					  le16_to_cpu(sb->ingress_tc_count),
					  le16_to_cpu(sb->egress_tc_count));
		if (err)
			goto err_unreg_prev;
	}
	pf->num_shared_bufs = num_entries;

	nfp_cpp_area_release_free(sb_desc_area);

	return 0;

err_unreg_prev:
	while (i--)
		devlink_sb_unregister(devlink,
				      le32_to_cpu(pf->shared_bufs[i].id));
	kfree(pf->shared_bufs);
err_release_area:
	nfp_cpp_area_release_free(sb_desc_area);
	return err;
}

void nfp_shared_buf_unregister(struct nfp_pf *pf)
{
	struct devlink *devlink = priv_to_devlink(pf);
	unsigned int i;

	for (i = 0; i < pf->num_shared_bufs; i++)
		devlink_sb_unregister(devlink,
				      le32_to_cpu(pf->shared_bufs[i].id));
	kfree(pf->shared_bufs);
}
