// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
// Copyright (c) 2020 Mellanox Technologies

#include <linux/jhash.h>
#include "mod_hdr.h"

#define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)

struct mod_hdr_key {
	int num_actions;
	void *actions;
};

struct mlx5e_mod_hdr_handle {
	/* a node of a hash table which keeps all the mod_hdr entries */
	struct hlist_node mod_hdr_hlist;

	struct mod_hdr_key key;

	struct mlx5_modify_hdr *modify_hdr;

	refcount_t refcnt;
	struct completion res_ready;
	int compl_result;
};

static u32 hash_mod_hdr_info(struct mod_hdr_key *key)
{
	return jhash(key->actions,
		     key->num_actions * MLX5_MH_ACT_SZ, 0);
}

static int cmp_mod_hdr_info(struct mod_hdr_key *a, struct mod_hdr_key *b)
{
	if (a->num_actions != b->num_actions)
		return 1;

	return memcmp(a->actions, b->actions,
		      a->num_actions * MLX5_MH_ACT_SZ);
}

void mlx5e_mod_hdr_tbl_init(struct mod_hdr_tbl *tbl)
{
	mutex_init(&tbl->lock);
	hash_init(tbl->hlist);
}

void mlx5e_mod_hdr_tbl_destroy(struct mod_hdr_tbl *tbl)
{
	WARN_ON(!hash_empty(tbl->hlist));
	mutex_destroy(&tbl->lock);
}

static struct mlx5e_mod_hdr_handle *mod_hdr_get(struct mod_hdr_tbl *tbl,
						struct mod_hdr_key *key,
						u32 hash_key)
{
	struct mlx5e_mod_hdr_handle *mh, *found = NULL;

	hash_for_each_possible(tbl->hlist, mh, mod_hdr_hlist, hash_key) {
		if (!cmp_mod_hdr_info(&mh->key, key)) {
			refcount_inc(&mh->refcnt);
			found = mh;
			break;
		}
	}

	return found;
}

struct mlx5e_mod_hdr_handle *
mlx5e_mod_hdr_attach(struct mlx5_core_dev *mdev,
		     struct mod_hdr_tbl *tbl,
		     enum mlx5_flow_namespace_type namespace,
		     struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts)
{
	int num_actions, actions_size, err;
	struct mlx5e_mod_hdr_handle *mh;
	struct mod_hdr_key key;
	u32 hash_key;

	num_actions  = mod_hdr_acts->num_actions;
	actions_size = MLX5_MH_ACT_SZ * num_actions;

	key.actions = mod_hdr_acts->actions;
	key.num_actions = num_actions;

	hash_key = hash_mod_hdr_info(&key);

	mutex_lock(&tbl->lock);
	mh = mod_hdr_get(tbl, &key, hash_key);
	if (mh) {
		mutex_unlock(&tbl->lock);
		wait_for_completion(&mh->res_ready);

		if (mh->compl_result < 0) {
			err = -EREMOTEIO;
			goto attach_header_err;
		}
		goto attach_header;
	}

	mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL);
	if (!mh) {
		mutex_unlock(&tbl->lock);
		return ERR_PTR(-ENOMEM);
	}

	mh->key.actions = (void *)mh + sizeof(*mh);
	memcpy(mh->key.actions, key.actions, actions_size);
	mh->key.num_actions = num_actions;
	refcount_set(&mh->refcnt, 1);
	init_completion(&mh->res_ready);

	hash_add(tbl->hlist, &mh->mod_hdr_hlist, hash_key);
	mutex_unlock(&tbl->lock);

	mh->modify_hdr = mlx5_modify_header_alloc(mdev, namespace,
						  mh->key.num_actions,
						  mh->key.actions);
	if (IS_ERR(mh->modify_hdr)) {
		err = PTR_ERR(mh->modify_hdr);
		mh->compl_result = err;
		goto alloc_header_err;
	}
	mh->compl_result = 1;
	complete_all(&mh->res_ready);

attach_header:
	return mh;

alloc_header_err:
	complete_all(&mh->res_ready);
attach_header_err:
	mlx5e_mod_hdr_detach(mdev, tbl, mh);
	return ERR_PTR(err);
}

void mlx5e_mod_hdr_detach(struct mlx5_core_dev *mdev,
			  struct mod_hdr_tbl *tbl,
			  struct mlx5e_mod_hdr_handle *mh)
{
	if (!refcount_dec_and_mutex_lock(&mh->refcnt, &tbl->lock))
		return;
	hash_del(&mh->mod_hdr_hlist);
	mutex_unlock(&tbl->lock);

	if (mh->compl_result > 0)
		mlx5_modify_header_dealloc(mdev, mh->modify_hdr);

	kfree(mh);
}

struct mlx5_modify_hdr *mlx5e_mod_hdr_get(struct mlx5e_mod_hdr_handle *mh)
{
	return mh->modify_hdr;
}

char *
mlx5e_mod_hdr_alloc(struct mlx5_core_dev *mdev, int namespace,
		    struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts)
{
	int new_num_actions, max_hw_actions;
	size_t new_sz, old_sz;
	void *ret;

	if (mod_hdr_acts->num_actions < mod_hdr_acts->max_actions)
		goto out;

	max_hw_actions = mlx5e_mod_hdr_max_actions(mdev, namespace);
	new_num_actions = min(max_hw_actions,
			      mod_hdr_acts->actions ?
			      mod_hdr_acts->max_actions * 2 : 1);
	if (mod_hdr_acts->max_actions == new_num_actions)
		return ERR_PTR(-ENOSPC);

	new_sz = MLX5_MH_ACT_SZ * new_num_actions;
	old_sz = mod_hdr_acts->max_actions * MLX5_MH_ACT_SZ;

	if (mod_hdr_acts->is_static) {
		ret = kzalloc(new_sz, GFP_KERNEL);
		if (ret) {
			memcpy(ret, mod_hdr_acts->actions, old_sz);
			mod_hdr_acts->is_static = false;
		}
	} else {
		ret = krealloc(mod_hdr_acts->actions, new_sz, GFP_KERNEL);
		if (ret)
			memset(ret + old_sz, 0, new_sz - old_sz);
	}
	if (!ret)
		return ERR_PTR(-ENOMEM);

	mod_hdr_acts->actions = ret;
	mod_hdr_acts->max_actions = new_num_actions;

out:
	return mod_hdr_acts->actions + (mod_hdr_acts->num_actions * MLX5_MH_ACT_SZ);
}

void
mlx5e_mod_hdr_dealloc(struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts)
{
	if (!mod_hdr_acts->is_static)
		kfree(mod_hdr_acts->actions);

	mod_hdr_acts->actions = NULL;
	mod_hdr_acts->num_actions = 0;
	mod_hdr_acts->max_actions = 0;
}

char *
mlx5e_mod_hdr_get_item(struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts, int pos)
{
	return mod_hdr_acts->actions + (pos * MLX5_MH_ACT_SZ);
}
