/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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.
 */
#ifndef ID_POOL_H
#define ID_POOL_H

#include <linux/types.h>
#include "ka_compiler_pub.h"

#include "trs_pub_def.h"

#ifdef __cplusplus
extern "C" {
#endif

struct id_pool_inst {
    u32 phy_devid;
    u32 sub_id;
};

struct id_pool_attr {
    u32 node_tunable;   /* create vf need adjust rsv sqcq num */
    u32 id_start;
    u32 id_total_num;
};

int id_pool_get_total_num(struct id_pool_inst *inst, int type, u32 *id_total_num);

int id_pool_alloc(struct id_pool_inst *inst, int type, u32 *id, u32 num);
void id_pool_free(struct id_pool_inst *inst, int type, u32 *id, u32 num);

int id_pool_alloc_by_range(struct id_pool_inst *inst, int type, u32 start, u32 end, u32 *id, u32 num);

int id_pool_register(struct id_pool_inst *inst, int type, struct id_pool_attr *attr);
void id_pool_unregister(struct id_pool_inst *inst, int type, struct id_pool_attr *attr);

int id_pool_get_range(struct id_pool_inst *inst, int type, u32 *start, u32 *end);
int id_pool_get_total_num_by_range(struct id_pool_inst *inst, int type, u32 start, u32 end, u32 *total_num);
int id_pool_get_tunable_range_by_range(struct id_pool_inst *inst, int type, u32 *start, u32 *end);
int id_pool_get_avail_num(struct id_pool_inst *inst, int type, u32 *avail_num);

int id_pool_alloc_by_node_level(struct id_pool_inst *inst, int type, u32 node_level, u32 *id);
int id_pool_get_avail_num_by_node_level(struct id_pool_inst *inst, int type, u32 node_level, u32 *avail_num);
int id_pool_register_with_node_level(struct id_pool_inst *inst, int type, struct id_pool_attr *attr, u32 node_level);

static inline void id_pool_inst_pack(struct id_pool_inst *inst, u32 devid, u32 sub_id)
{
    inst->phy_devid = devid;
    inst->sub_id = sub_id;
}

static inline void id_pool_attr_pack(struct id_pool_attr *attr, bool tunable, u32 id_start, u32 id_total_num)
{
    attr->node_tunable = tunable;
    attr->id_start = id_start;
    attr->id_total_num = id_total_num;
}

int __ka_init init_id_pool(void);
void __ka_exit exit_id_pool(void);

int id_pool_setup_init(void);
void id_pool_setup_uninit(void);
#ifdef __cplusplus
}
#endif

#endif /* ID_POOL_H */