/*
 * Copyright (c) 2016-2017, 2021, The Linux Foundation. All rights reserved.
 *
 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * @defgroup
 * @{
 */
#include "sw.h"
#include "hppe_shaper_reg.h"
#include "hppe_shaper.h"
#include "adpt.h"
#include "adpt_hppe.h"
#ifdef APPE
#include "adpt_appe_shaper.h"
#endif

#define NR_ADPT_HPPE_SHAPER_METER_UNIT         2
#define NR_ADPT_HPPE_SHAPER_METER_TOKEN_UNIT         8
#define ADPT_HPPE_SHAPER_METER_UNIT_BYTE       0
#define ADPT_HPPE_SHAPER_METER_UNIT_FRAME      1
#define ADPT_HPPE_SHAPER_BURST_SIZE_UNIT      65536
#define ADPT_HPPE_SHAPER_REFRESH_BITS  18
#define ADPT_HPPE_SHAPER_BUCKET_SIZE_BITS  14
#define ADPT_HPPE_SHAPER_REFRESH_MAX  ((1 << ADPT_HPPE_SHAPER_REFRESH_BITS) - 1)
#define ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX  ((1 << ADPT_HPPE_SHAPER_BUCKET_SIZE_BITS) - 1)
#define ADPT_HPPE_PORT_SHAPER         0
#define ADPT_HPPE_FLOW_SHAPER         1
#define ADPT_HPPE_QUEUE_SHAPER        2
#define ADPT_HPPE_SHAPER_MAX          0x3ffff
#define BYTE_SHAPER_MAX_RATE          10000000
#define BYTE_SHAPER_MIN_RATE          64
#define FRAME_SHAPER_MAX_RATE         14881000
#define FRAME_SHAPER_MIN_RATE         6

#ifdef APPE
static a_uint32_t appe_flow_shaper_type[SW_MAX_NR_DEV][APPE_SHAPER_FLOW_ID_MAX + 1] = {0};
static a_uint32_t appe_queue_shaper_type[SW_MAX_NR_DEV][APPE_SHAPER_QUEUE_ID_MAX + 1] = {0};
#endif
static a_uint32_t hppe_shaper_token_unit[NR_ADPT_HPPE_SHAPER_METER_UNIT]
	[NR_ADPT_HPPE_SHAPER_METER_TOKEN_UNIT] = {{2048 * 8,
	512 * 8,128 * 8,32 * 8,8 * 8,2 * 8, 4, 1},
	{2097152,524288,131072,32768,8192,2048,512,128}};

typedef struct
{
    a_uint64_t rate_1bit;
    a_uint64_t rate_max;
} adpt_hppe_shaper_rate_t;

typedef struct
{
    a_uint64_t burst_size_1bit;
    a_uint64_t burst_size_max;
} adpt_hppe_shaper_burst_size_t;

static adpt_hppe_shaper_rate_t
hppe_port_shaper_rate[NR_ADPT_HPPE_SHAPER_METER_UNIT][NR_ADPT_HPPE_SHAPER_METER_TOKEN_UNIT] =
{
	/* byte based*/
	{
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},

	/*frame based */
	{
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},
};

static adpt_hppe_shaper_rate_t
hppe_flow_shaper_rate[NR_ADPT_HPPE_SHAPER_METER_UNIT][NR_ADPT_HPPE_SHAPER_METER_TOKEN_UNIT] =
{
	/* byte based*/
	{
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},

	/*frame based */
	{
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},
};

static adpt_hppe_shaper_rate_t
hppe_queue_shaper_rate[NR_ADPT_HPPE_SHAPER_METER_UNIT][NR_ADPT_HPPE_SHAPER_METER_TOKEN_UNIT] =
{
	/* byte based*/
	{
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},

	/*frame based */
	{
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},
};

static adpt_hppe_shaper_burst_size_t
hppe_shaper_burst_size[NR_ADPT_HPPE_SHAPER_METER_UNIT][NR_ADPT_HPPE_SHAPER_METER_TOKEN_UNIT] =
{
	{	{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},
	{	{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
		{0,0},
	},
};

static sw_error_t
__adpt_hppe_port_shaper_max_rate(a_uint32_t dev_id, a_uint32_t time_slot)
{
	a_uint32_t i = 0, j = 0;
	a_uint32_t time_cycle;
	a_uint64_t temp, temp1,temp2;
	a_uint32_t ppe_freq = adpt_chip_freq_get(dev_id);

	/* time_cycle is ns*/
	time_cycle = ( time_slot * 8);

	for (j = 0; j < 8; j++)
	{
		/*max rate unit is bps*/
		temp1 = (a_uint64_t)(ADPT_HPPE_SHAPER_REFRESH_MAX  * 1000 * 8) *
			(a_uint64_t)(ppe_freq * 1000);
		temp2 =  hppe_shaper_token_unit[i][j] * time_cycle;

		do_div(temp1, temp2);
		hppe_port_shaper_rate[i][j].rate_max = temp1;

		temp = temp1;
		do_div(temp, ADPT_HPPE_SHAPER_REFRESH_MAX);
		hppe_port_shaper_rate[i][j].rate_1bit = temp;

		//printk("port shaper hppe_max_rate generating =%llu\n", hppe_port_shaper_rate[i][j].rate_max);
		//printk("port shaper byte step rate =%llu\n", hppe_port_shaper_rate[i][j].rate_1bit);
	}

	i = i + 1;
	for (j = 0; j < 8; j++)
	{
		/* max rate unit  is 1/1000 pps*/
		temp1 = (a_uint64_t)(ADPT_HPPE_SHAPER_REFRESH_MAX * 1000) * 1000 *
			(a_uint64_t)(ppe_freq * 1000);
		temp2 = (a_uint64_t)hppe_shaper_token_unit[i][j] * time_cycle;

		do_div(temp1, temp2);
		hppe_port_shaper_rate[i][j].rate_max = temp1;

		temp = temp1;
		do_div(temp, ADPT_HPPE_SHAPER_REFRESH_MAX);
		hppe_port_shaper_rate[i][j].rate_1bit = temp;

		//printk("port shaper hppe_max_rate generating =%llu\n", hppe_port_shaper_rate[i][j].rate_max);
		//printk("port shaper frame step rate =%llu\n", hppe_port_shaper_rate[i][j].rate_1bit);
	}

	return SW_OK;
}

static sw_error_t
__adpt_hppe_flow_shaper_max_rate(a_uint32_t dev_id, a_uint32_t time_slot)
{
	a_uint32_t i = 0, j = 0;
	a_uint32_t time_cycle;
	a_uint64_t temp, temp1,temp2;
	a_uint32_t ppe_freq = adpt_chip_freq_get(dev_id);

	/* time_cycle is ns*/
	time_cycle = ( time_slot * 8);

	for (j = 0; j < 8; j++)
	{
		/*max rate unit is bps*/
		temp1 = (a_uint64_t)(ADPT_HPPE_SHAPER_REFRESH_MAX  * 1000 * 8) *
			(a_uint64_t)(ppe_freq * 1000);
		temp2 =  hppe_shaper_token_unit[i][j] * time_cycle;

		do_div(temp1, temp2);
		hppe_flow_shaper_rate[i][j].rate_max = temp1;

		temp = temp1;
		do_div(temp, ADPT_HPPE_SHAPER_REFRESH_MAX);
		hppe_flow_shaper_rate[i][j].rate_1bit = temp;

		//printk("flow shaper hppe_max_rate generating =%llu\n", hppe_flow_shaper_rate[i][j].rate_max);
		//printk("flow shaper byte step rate =%llu\n", hppe_flow_shaper_rate[i][j].rate_1bit);
	}

	i = i + 1;
	for (j = 0; j < 8; j++)
	{
		/* max rate unit  is 1/1000 pps*/
		temp1 = (a_uint64_t)(ADPT_HPPE_SHAPER_REFRESH_MAX * 1000) * 1000 *
			(a_uint64_t)(ppe_freq * 1000);
		temp2 = (a_uint64_t)hppe_shaper_token_unit[i][j] * time_cycle;

		do_div(temp1, temp2);
		hppe_flow_shaper_rate[i][j].rate_max = temp1;

		temp = temp1;
		do_div(temp, ADPT_HPPE_SHAPER_REFRESH_MAX);
		hppe_flow_shaper_rate[i][j].rate_1bit = temp;

		//printk("flow shaper hppe_max_rate generating =%llu\n", hppe_flow_shaper_rate[i][j].rate_max);
		//printk("flow shaper frame step rate =%llu\n", hppe_flow_shaper_rate[i][j].rate_1bit);
	}

	return SW_OK;
}

static sw_error_t
__adpt_hppe_queue_shaper_max_rate(a_uint32_t dev_id, a_uint32_t time_slot)
{
	a_uint32_t i = 0, j = 0;
	a_uint32_t time_cycle;
	a_uint64_t temp, temp1,temp2;
	a_uint32_t ppe_freq = adpt_chip_freq_get(dev_id);

	/* time_cycle is ns*/
	time_cycle = ( time_slot * 8) / ppe_freq;

	for (j = 0; j < 8; j++)
	{
		/*max rate unit is bps*/
		temp1 = (a_uint64_t)(ADPT_HPPE_SHAPER_REFRESH_MAX  * 1000 * 8) * 1000;
		temp2 =  hppe_shaper_token_unit[i][j] * time_cycle;

		do_div(temp1, temp2);
		hppe_queue_shaper_rate[i][j].rate_max = temp1;

		temp = temp1;
		do_div(temp, ADPT_HPPE_SHAPER_REFRESH_MAX);
		hppe_queue_shaper_rate[i][j].rate_1bit = temp;

		//printk("queue shaper hppe_max_rate generating =%llu\n", hppe_queue_shaper_rate[i][j].rate_max);
		//printk("queue shaper byte step rate =%llu\n", hppe_queue_shaper_rate[i][j].rate_1bit);
	}

	i = i + 1;
	for (j = 0; j < 8; j++)
	{
		/* max rate unit  is 1/1000 pps*/
		temp1 = (a_uint64_t)(ADPT_HPPE_SHAPER_REFRESH_MAX * 1000) * 1000 * 1000;
		temp2 = (a_uint64_t)hppe_shaper_token_unit[i][j] * time_cycle;

		do_div(temp1, temp2);
		hppe_queue_shaper_rate[i][j].rate_max = temp1;

		temp = temp1;
		do_div(temp, ADPT_HPPE_SHAPER_REFRESH_MAX);
		hppe_queue_shaper_rate[i][j].rate_1bit = temp;

		//printk("queue shaper hppe_max_rate generating =%llu\n", hppe_queue_shaper_rate[i][j].rate_max);
		//printk("queue shaper frame step rate =%llu\n", hppe_queue_shaper_rate[i][j].rate_1bit);
	}

	return SW_OK;
}

static sw_error_t
__adpt_hppe_shaper_max_burst_size(void)
{
	a_uint32_t i = 0, j = 0;
	a_uint64_t temp = 0, temp1 = 0;

	for (j = 0; j < 8; j++)
	{
		/*max size unit is 1/1000 byte based*/
		temp = (a_uint64_t)(ADPT_HPPE_SHAPER_BURST_SIZE_UNIT * ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX);
		do_div(temp, hppe_shaper_token_unit[i][j]);
		hppe_shaper_burst_size[i][j].burst_size_max = (a_uint64_t)(temp * 1000);

		temp1 = hppe_shaper_burst_size[i][j].burst_size_max;
		do_div(temp1, ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX);
		hppe_shaper_burst_size[i][j].burst_size_1bit = temp1;

		//printk("shpaer byte hppe_max_burst_size generating =%llu\n", hppe_shaper_burst_size[i][j].burst_size_max);
		//printk("shpaer byte hppe_max_burst_size step  =%llu\n", hppe_shaper_burst_size[i][j].burst_size_1bit);
	}

	i = i + 1;
	for (j = 0; j < 8; j++)
	{
		/* max size unit is 1/1000 frame based */
		temp = (a_uint64_t)(ADPT_HPPE_SHAPER_BURST_SIZE_UNIT * ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX);
		do_div(temp, hppe_shaper_token_unit[i][j]);
		hppe_shaper_burst_size[i][j].burst_size_max = (a_uint64_t)(temp * 1000);

		temp1 = hppe_shaper_burst_size[i][j].burst_size_max;
		do_div(temp1, ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX);
		hppe_shaper_burst_size[i][j].burst_size_1bit = temp1;

		//printk("shaper frame hppe_max_burst_size generating =%llu\n", hppe_shaper_burst_size[i][j].burst_size_max);
		//printk("shpaer frame hppe_max_burst_size step  =%llu\n", hppe_shaper_burst_size[i][j].burst_size_1bit);
	}

	return SW_OK;
}

static sw_error_t
__adpt_hppe_shaper_one_bucket_parameter_select(a_uint32_t shaper_type,
						a_uint64_t c_rate,
						a_uint64_t c_burst_size,
						a_uint32_t meter_unit,
						a_uint32_t *token_unit)
{
	a_uint32_t  temp_token_unit = 0;
	a_uint32_t  match = A_FALSE;
	a_uint64_t  max_rate =0;

	for (temp_token_unit = 0; temp_token_unit < 8; temp_token_unit++)
	{
		if (ADPT_HPPE_PORT_SHAPER == shaper_type)
			max_rate = hppe_port_shaper_rate[meter_unit][temp_token_unit].rate_max;

		if (ADPT_HPPE_FLOW_SHAPER == shaper_type)
			max_rate = hppe_flow_shaper_rate[meter_unit][temp_token_unit].rate_max;

		if (ADPT_HPPE_QUEUE_SHAPER == shaper_type)
			max_rate = hppe_queue_shaper_rate[meter_unit][temp_token_unit].rate_max;

		if (c_rate > max_rate)
		{
			continue;
		}
		else if (c_burst_size <= hppe_shaper_burst_size[meter_unit][temp_token_unit].burst_size_max)
		{
			*token_unit = temp_token_unit;
			match = A_TRUE;
			break;
		}
	}

	if (match == A_FALSE)
	{
		printk("Not match  shaper C token bucket parameter rate configuration\n");
		return SW_BAD_PARAM;
	}

	return SW_OK;
}

static sw_error_t
__adpt_hppe_shaper_two_bucket_parameter_select(a_uint32_t shaper_type,
						a_uint64_t c_rate,
						a_uint64_t c_burst_size,
						a_uint64_t e_rate,
						a_uint64_t e_burst_size,
						a_uint32_t meter_unit,
						a_uint32_t *token_unit)
{
	a_uint32_t  temp_token_unit;
	a_uint32_t  match = A_FALSE;
	a_uint64_t  max_rate = 0, temp_rate = 0, temp_burst_size = 0;

	if(c_rate > e_rate)
		temp_rate = c_rate;
	else
		temp_rate = e_rate;

	if(c_burst_size > e_burst_size)
		temp_burst_size = c_burst_size;
	else
		temp_burst_size = e_burst_size;

	for (temp_token_unit = 0; temp_token_unit < 8; temp_token_unit++)
	{
		if (ADPT_HPPE_PORT_SHAPER == shaper_type)
			max_rate = hppe_port_shaper_rate[meter_unit][temp_token_unit].rate_max;

		if (ADPT_HPPE_FLOW_SHAPER == shaper_type)
			max_rate = hppe_flow_shaper_rate[meter_unit][temp_token_unit].rate_max;

		if (ADPT_HPPE_QUEUE_SHAPER == shaper_type)
			max_rate = hppe_queue_shaper_rate[meter_unit][temp_token_unit].rate_max;

		 if (temp_rate > max_rate)
		 {
		 	continue;
		 }
		 else if(temp_burst_size <= hppe_shaper_burst_size[meter_unit][temp_token_unit].burst_size_max)
		{
			*token_unit = temp_token_unit;
			match = A_TRUE;
			break;
		}
	}

	if (match == A_FALSE)
	{
		printk("Not match shaper  C and E token bucket parameter rate configuration \n");
		return SW_BAD_PARAM;
	}

	return SW_OK;
}

static sw_error_t
__adpt_hppe_shaper_rate_to_refresh(a_uint32_t shaper_type,
							a_uint32_t rate,
							a_uint32_t *refresh,
							a_bool_t meter_unit,
							a_uint32_t  token_unit)
{
	a_uint32_t temp_refresh;
	a_uint64_t temp_rate, temp_rate_1bit;

	temp_rate_1bit = 0;

	if (ADPT_HPPE_PORT_SHAPER == shaper_type)
	{
		temp_rate_1bit = hppe_port_shaper_rate[meter_unit][token_unit].rate_1bit;
	}

	if (ADPT_HPPE_FLOW_SHAPER == shaper_type)
	{
		temp_rate_1bit = hppe_flow_shaper_rate[meter_unit][token_unit].rate_1bit;
	}

	if (ADPT_HPPE_QUEUE_SHAPER == shaper_type)
	{
		temp_rate_1bit = hppe_queue_shaper_rate[meter_unit][token_unit].rate_1bit;
	}

	if(temp_rate_1bit > 0)
	{
		temp_rate = ((a_uint64_t)rate) * 1000;
		do_div(temp_rate, temp_rate_1bit);
		temp_refresh = temp_rate;
	}
	else
	{
		return SW_BAD_PARAM;
	}

	if (temp_refresh > ADPT_HPPE_SHAPER_REFRESH_MAX)
	{
		temp_refresh = ADPT_HPPE_SHAPER_REFRESH_MAX;
	}

	*refresh = temp_refresh;

	return SW_OK;
}

static sw_error_t
__adpt_hppe_shaper_burst_size_to_bucket_size(a_uint32_t burst_size,
							a_uint32_t *bucket_size,
							a_bool_t meter_unit,
							a_uint32_t  token_unit)
{
	a_uint32_t temp_bucket_size;
	a_uint64_t temp_burst_size;

	if(hppe_shaper_burst_size[meter_unit][token_unit].burst_size_1bit > 0)
	{
		temp_burst_size = ((a_uint64_t)burst_size) * 1000;
		do_div(temp_burst_size, hppe_shaper_burst_size[meter_unit][token_unit].burst_size_1bit);
		temp_bucket_size = temp_burst_size;
	}
	else
	{
		return SW_BAD_PARAM;
	}

	if(temp_bucket_size > ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX)
	{
		temp_bucket_size = ADPT_HPPE_SHAPER_BUCKET_SIZE_MAX;
	}

	*bucket_size = temp_bucket_size;

	return SW_OK;
}

static sw_error_t
__adpt_hppe_shaper_refresh_to_rate(a_uint32_t shaper_type,
							a_uint32_t refresh,
							a_uint32_t *rate,
							a_bool_t meter_unit,
							a_uint32_t  token_unit)
{
	a_uint32_t temp_rate;
	a_uint64_t temp_refresh, temp_rate_1bit;

	temp_rate_1bit = 0;

	if (ADPT_HPPE_PORT_SHAPER == shaper_type)
	{
		temp_rate_1bit = hppe_port_shaper_rate[meter_unit][token_unit].rate_1bit;
	}

	if (ADPT_HPPE_FLOW_SHAPER == shaper_type)
	{
		temp_rate_1bit = hppe_flow_shaper_rate[meter_unit][token_unit].rate_1bit;
	}

	if (ADPT_HPPE_QUEUE_SHAPER == shaper_type)
	{
		temp_rate_1bit = hppe_queue_shaper_rate[meter_unit][token_unit].rate_1bit;
	}

	if(temp_rate_1bit > 0)
	{
		temp_refresh = ((a_uint64_t)refresh) * temp_rate_1bit;
		do_div(temp_refresh, 1000);
		temp_rate = temp_refresh;
	}
	else
	{
		return SW_BAD_PARAM;
	}

	*rate = temp_rate;

	return SW_OK;
}
static sw_error_t
__adpt_hppe_shaper_bucket_size_to_burst_size(a_uint32_t bucket_size,
							a_uint32_t *burst_size,
							a_bool_t meter_unit,
							a_uint32_t  token_unit)
{
	a_uint32_t temp_burst_size;
	a_uint64_t temp_bucket_size;

	if(hppe_shaper_burst_size[meter_unit][token_unit].burst_size_1bit > 0)
	{
		temp_bucket_size = ((a_uint64_t)bucket_size) * hppe_shaper_burst_size[meter_unit][token_unit].burst_size_1bit;
		do_div(temp_bucket_size, 1000);
		temp_burst_size = temp_bucket_size;
	}
	else
	{
		return SW_BAD_PARAM;
	}

	*burst_size = temp_burst_size;

	return SW_OK;
}

sw_error_t
adpt_hppe_queue_shaper_get(a_uint32_t dev_id, a_uint32_t queue_id,
		fal_shaper_config_t * shaper)
{
	sw_error_t rv = SW_OK;
	union l0_shp_cfg_tbl_u l0_shp_cfg_tbl;
	union l0_comp_cfg_tbl_u l0_comp_cfg_tbl;
	a_uint32_t hppe_cir =0, hppe_cbs = 0, hppe_eir = 0, hppe_ebs = 0;
#ifdef APPE
	a_uint32_t hppe_cir_max = 0, hppe_eir_max= 0;
#endif

	memset(&l0_shp_cfg_tbl, 0, sizeof(l0_shp_cfg_tbl));
	memset(&l0_comp_cfg_tbl, 0, sizeof(l0_comp_cfg_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(shaper);

	if ((queue_id < 0) || (queue_id > 299))
		return SW_BAD_PARAM;

	hppe_l0_comp_cfg_tbl_get(dev_id, queue_id, &l0_comp_cfg_tbl);


	rv = hppe_l0_shp_cfg_tbl_get(dev_id, queue_id, &l0_shp_cfg_tbl);

	if( rv != SW_OK )
		return rv;

	hppe_cir = l0_shp_cfg_tbl.bf.cir;
	hppe_cbs = l0_shp_cfg_tbl.bf.cbs;
	hppe_eir = l0_shp_cfg_tbl.bf.eir;
	hppe_ebs = l0_shp_cfg_tbl.bf.ebs;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		hppe_cir_max = (l0_shp_cfg_tbl.bf.cir_max_1 << 14) |
				l0_shp_cfg_tbl.bf.cir_max_0;
		hppe_eir_max = l0_shp_cfg_tbl.bf.eir_max;
	}
#endif
	__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_QUEUE_SHAPER,
				hppe_cir,
				&shaper->cir,
				l0_shp_cfg_tbl.bf.meter_unit,
				l0_shp_cfg_tbl.bf.token_unit);

	__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_QUEUE_SHAPER,
				hppe_eir,
				&shaper->eir,
				l0_shp_cfg_tbl.bf.meter_unit,
				l0_shp_cfg_tbl.bf.token_unit);
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_QUEUE_SHAPER,
				hppe_cir_max,
				&shaper->cir_max,
				l0_shp_cfg_tbl.bf.meter_unit,
				l0_shp_cfg_tbl.bf.token_unit);

		__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_QUEUE_SHAPER,
				hppe_eir_max,
				&shaper->eir_max,
				l0_shp_cfg_tbl.bf.meter_unit,
				l0_shp_cfg_tbl.bf.token_unit);
	}
#endif
	__adpt_hppe_shaper_bucket_size_to_burst_size(hppe_cbs,
				&shaper->cbs,
				l0_shp_cfg_tbl.bf.meter_unit,
				l0_shp_cfg_tbl.bf.token_unit);

	__adpt_hppe_shaper_bucket_size_to_burst_size(hppe_ebs,
				&shaper->ebs,
				l0_shp_cfg_tbl.bf.meter_unit,
				l0_shp_cfg_tbl.bf.token_unit);

	shaper->couple_en = l0_shp_cfg_tbl.bf.cf;
	shaper->meter_unit = l0_shp_cfg_tbl.bf.meter_unit;
	shaper->c_shaper_en = l0_shp_cfg_tbl.bf.c_shaper_enable;
	shaper->e_shaper_en = l0_shp_cfg_tbl.bf.e_shaper_enable;
	shaper->shaper_frame_mode = l0_comp_cfg_tbl.bf.shaper_meter_len;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		shaper->meter_type = appe_queue_shaper_type[dev_id][queue_id];
		shaper->next_ptr = l0_shp_cfg_tbl.bf.shp_refresh_nxt_ptr;
		shaper->grp_end = l0_shp_cfg_tbl.bf.grp_end;
		shaper->grp_couple_en = l0_shp_cfg_tbl.bf.grp_cf;
	}
#endif
	return SW_OK;
}

sw_error_t
adpt_hppe_queue_shaper_token_number_set(a_uint32_t dev_id,a_uint32_t queue_id,
		fal_shaper_token_number_t *token_number)
{
	union l0_shp_credit_tbl_u l0_shp_credit_tbl;

	memset(&l0_shp_credit_tbl, 0, sizeof(l0_shp_credit_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(token_number);

	if ((queue_id < 0) || (queue_id > 299))
		return SW_BAD_PARAM;

	hppe_l0_shp_credit_tbl_get(dev_id, queue_id, &l0_shp_credit_tbl);


	l0_shp_credit_tbl.bf.c_shaper_credit_neg = token_number->c_token_number_negative_en;
	l0_shp_credit_tbl.bf.c_shaper_credit = token_number->c_token_number;
	l0_shp_credit_tbl.bf.e_shaper_credit_neg = token_number->e_token_number_negative_en;
	l0_shp_credit_tbl.bf.e_shaper_credit_0 = token_number->e_token_number & 0x1;
	l0_shp_credit_tbl.bf.e_shaper_credit_1 = token_number->e_token_number >> 1;

	hppe_l0_shp_credit_tbl_set(dev_id, queue_id, &l0_shp_credit_tbl);

	return SW_OK;
}
#ifndef IN_SHAPER_MINI
sw_error_t
adpt_hppe_port_shaper_get(a_uint32_t dev_id, fal_port_t port_id,
		fal_shaper_config_t * shaper)
{
	union psch_shp_cfg_tbl_u psch_shp_cfg_tbl;
	union psch_comp_cfg_tbl_u psch_comp_cfg_tbl;
	a_uint32_t hppe_cir =0, hppe_cbs = 0;

	memset(&psch_shp_cfg_tbl, 0, sizeof(psch_shp_cfg_tbl));
	memset(&psch_comp_cfg_tbl, 0, sizeof(psch_comp_cfg_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(shaper);

	if (port_id < 0 || port_id > 7)
		return SW_BAD_PARAM;

	hppe_psch_shp_cfg_tbl_get(dev_id, port_id, &psch_shp_cfg_tbl);

	hppe_cir = psch_shp_cfg_tbl.bf.cir;
	hppe_cbs = psch_shp_cfg_tbl.bf.cbs;

	hppe_psch_comp_cfg_tbl_get(dev_id, port_id, &psch_comp_cfg_tbl);


	__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_PORT_SHAPER,
								hppe_cir,
								&shaper->cir,
								psch_shp_cfg_tbl.bf.meter_unit,
								psch_shp_cfg_tbl.bf.token_unit);


	__adpt_hppe_shaper_bucket_size_to_burst_size(hppe_cbs,
								&shaper->cbs,
								psch_shp_cfg_tbl.bf.meter_unit,
								psch_shp_cfg_tbl.bf.token_unit);

	shaper->meter_unit = psch_shp_cfg_tbl.bf.meter_unit;
	shaper->c_shaper_en = psch_shp_cfg_tbl.bf.shaper_enable;

	shaper->shaper_frame_mode = psch_comp_cfg_tbl.bf.shaper_meter_len;

	return SW_OK;
}

sw_error_t
adpt_hppe_flow_shaper_time_slot_get(a_uint32_t dev_id, a_uint32_t *time_slot)
{
	sw_error_t rv = SW_OK;
	union shp_slot_cfg_l1_u shp_slot_cfg_l1;

	memset(&shp_slot_cfg_l1, 0, sizeof(shp_slot_cfg_l1));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(time_slot);


	rv = hppe_shp_slot_cfg_l1_get(dev_id, &shp_slot_cfg_l1);

	if( rv != SW_OK )
		return rv;

	*time_slot = shp_slot_cfg_l1.bf.l1_shp_slot_time;

	return SW_OK;
}

sw_error_t
adpt_hppe_port_shaper_time_slot_get(a_uint32_t dev_id, a_uint32_t *time_slot)
{
	sw_error_t rv = SW_OK;
	union shp_slot_cfg_port_u shp_slot_cfg_port;

	memset(&shp_slot_cfg_port, 0, sizeof(shp_slot_cfg_port));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(time_slot);

	rv = hppe_shp_slot_cfg_port_get(dev_id, &shp_slot_cfg_port);

	if( rv != SW_OK )
		return rv;

	*time_slot = shp_slot_cfg_port.bf.port_shp_slot_time;

	return SW_OK;
}
#endif

sw_error_t
adpt_hppe_flow_shaper_time_slot_set(a_uint32_t dev_id, a_uint32_t time_slot)
{
	union shp_slot_cfg_l1_u shp_slot_cfg_l1;
	sw_error_t rv = SW_OK;

	memset(&shp_slot_cfg_l1, 0, sizeof(shp_slot_cfg_l1));
	ADPT_DEV_ID_CHECK(dev_id);

	if ((time_slot < 0x40) || (time_slot > 0xfff))
		return SW_BAD_PARAM;

	rv = hppe_shp_slot_cfg_l1_get(dev_id, &shp_slot_cfg_l1);

	if( rv != SW_OK )
		return rv;

	shp_slot_cfg_l1.bf.l1_shp_slot_time = time_slot;
	hppe_shp_slot_cfg_l1_set(dev_id, &shp_slot_cfg_l1);

	__adpt_hppe_flow_shaper_max_rate(dev_id, time_slot);

	return SW_OK;
}
sw_error_t
adpt_hppe_port_shaper_token_number_set(a_uint32_t dev_id, fal_port_t port_id,
		fal_shaper_token_number_t *token_number)
{
	union psch_shp_credit_tbl_u psch_shp_credit_tbl;
	union psch_shp_sign_tbl_u psch_shp_sign_tbl;

	memset(&psch_shp_credit_tbl, 0, sizeof(psch_shp_credit_tbl));
	memset(&psch_shp_sign_tbl, 0, sizeof(psch_shp_sign_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(token_number);

	if (port_id < 0 || port_id > 7)
		return SW_BAD_PARAM;

	hppe_psch_shp_credit_tbl_get(dev_id, port_id, &psch_shp_credit_tbl);
	hppe_psch_shp_sign_tbl_get(dev_id, port_id, &psch_shp_sign_tbl);


	psch_shp_sign_tbl.bf.shaper_credit_neg = token_number->c_token_number_negative_en;

	psch_shp_credit_tbl.bf.shaper_credit = token_number->c_token_number;

	hppe_psch_shp_credit_tbl_set(dev_id, port_id, &psch_shp_credit_tbl);

	hppe_psch_shp_sign_tbl_set(dev_id, port_id, &psch_shp_sign_tbl);

	return SW_OK;
}
#ifndef IN_SHAPER_MINI
sw_error_t
adpt_hppe_queue_shaper_token_number_get(a_uint32_t dev_id, a_uint32_t queue_id,
		fal_shaper_token_number_t *token_number)
{
	sw_error_t rv = SW_OK;
	union l0_shp_credit_tbl_u l0_shp_credit_tbl;

	memset(&l0_shp_credit_tbl, 0, sizeof(l0_shp_credit_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(token_number);

	if ((queue_id < 0) || (queue_id > 299))
		return SW_BAD_PARAM;

	rv = hppe_l0_shp_credit_tbl_get(dev_id, queue_id, &l0_shp_credit_tbl);

	if( rv != SW_OK )
		return rv;

	token_number->c_token_number_negative_en = l0_shp_credit_tbl.bf.c_shaper_credit_neg;
	token_number->c_token_number = l0_shp_credit_tbl.bf.c_shaper_credit;
	token_number->e_token_number_negative_en = l0_shp_credit_tbl.bf.e_shaper_credit_neg;
	token_number->e_token_number = l0_shp_credit_tbl.bf.e_shaper_credit_0 | (l0_shp_credit_tbl.bf.e_shaper_credit_1 << 1);


	return SW_OK;
}

sw_error_t
adpt_hppe_queue_shaper_time_slot_get(a_uint32_t dev_id, a_uint32_t *time_slot)
{
	sw_error_t rv = SW_OK;
	union shp_slot_cfg_l0_u shp_slot_cfg_l0;

	memset(&shp_slot_cfg_l0, 0, sizeof(shp_slot_cfg_l0));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(time_slot);


	rv = hppe_shp_slot_cfg_l0_get(dev_id, &shp_slot_cfg_l0);

	if( rv != SW_OK )
		return rv;

	*time_slot = shp_slot_cfg_l0.bf.l0_shp_slot_time;

	return SW_OK;
}

sw_error_t
adpt_hppe_port_shaper_token_number_get(a_uint32_t dev_id, fal_port_t port_id,
		fal_shaper_token_number_t *token_number)
{
	union psch_shp_credit_tbl_u psch_shp_credit_tbl;
	union psch_shp_sign_tbl_u psch_shp_sign_tbl;

	memset(&psch_shp_credit_tbl, 0, sizeof(psch_shp_credit_tbl));
	memset(&psch_shp_sign_tbl, 0, sizeof(psch_shp_sign_tbl));

	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(token_number);

	if (port_id < 0 || port_id > 7)
		return SW_BAD_PARAM;

	hppe_psch_shp_credit_tbl_get(dev_id, port_id, &psch_shp_credit_tbl);

	hppe_psch_shp_sign_tbl_get(dev_id, port_id, &psch_shp_sign_tbl);


	token_number->c_token_number_negative_en = psch_shp_sign_tbl.bf.shaper_credit_neg;
	token_number->c_token_number = psch_shp_credit_tbl.bf.shaper_credit;

	return SW_OK;
}
#endif

sw_error_t
adpt_hppe_flow_shaper_token_number_set(a_uint32_t dev_id, a_uint32_t flow_id,
		fal_shaper_token_number_t *token_number)
{
	union l1_shp_credit_tbl_u l1_shp_credit_tbl;

	memset(&l1_shp_credit_tbl, 0, sizeof(l1_shp_credit_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(token_number);

	if ((flow_id < 0) || (flow_id > 63))
		return SW_BAD_PARAM;


	l1_shp_credit_tbl.bf.c_shaper_credit_neg = token_number->c_token_number_negative_en;
	l1_shp_credit_tbl.bf.c_shaper_credit = token_number->c_token_number;
	l1_shp_credit_tbl.bf.e_shaper_credit_neg = token_number->e_token_number_negative_en;
	l1_shp_credit_tbl.bf.e_shaper_credit_0 = token_number->e_token_number & 0x1;
	l1_shp_credit_tbl.bf.e_shaper_credit_1 = token_number->e_token_number >> 1;

	hppe_l1_shp_credit_tbl_set(dev_id, flow_id, &l1_shp_credit_tbl);

	return SW_OK;
}
#ifndef IN_SHAPER_MINI
sw_error_t
adpt_hppe_flow_shaper_token_number_get(a_uint32_t dev_id, a_uint32_t flow_id,
		fal_shaper_token_number_t *token_number)
{
	sw_error_t rv = SW_OK;
	union l1_shp_credit_tbl_u l1_shp_credit_tbl;

	memset(&l1_shp_credit_tbl, 0, sizeof(l1_shp_credit_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(token_number);

	if ((flow_id < 0) || (flow_id > 63))
		return SW_BAD_PARAM;

	rv = hppe_l1_shp_credit_tbl_get(dev_id, flow_id, &l1_shp_credit_tbl);

	if( rv != SW_OK )
		return rv;

	token_number->c_token_number_negative_en = l1_shp_credit_tbl.bf.c_shaper_credit_neg;
	token_number->c_token_number = l1_shp_credit_tbl.bf.c_shaper_credit;
	token_number->e_token_number_negative_en = l1_shp_credit_tbl.bf.e_shaper_credit_neg;
	token_number->e_token_number = l1_shp_credit_tbl.bf.e_shaper_credit_0 |
		(l1_shp_credit_tbl.bf.e_shaper_credit_1 << 1);

	return SW_OK;
}
#endif

sw_error_t
adpt_hppe_flow_shaper_set(a_uint32_t dev_id, a_uint32_t flow_id,
		fal_shaper_config_t * shaper)
{
	sw_error_t rv = SW_OK;
	union l1_shp_cfg_tbl_u l1_shp_cfg_tbl;
	union l1_comp_cfg_tbl_u l1_comp_cfg_tbl;
	a_uint32_t hppe_cir = 0, hppe_cbs = 0, hppe_eir= 0, hppe_ebs = 0;
	a_uint64_t temp_cir = 0, temp_eir =0, temp_cbs =0, temp_ebs = 0;
	a_uint32_t token_unit = 0;
	fal_shaper_token_number_t token_number;
#ifdef APPE
	a_uint64_t temp_cir_max = 0, temp_eir_max =0;
	a_uint32_t hppe_cir_max = 0, hppe_eir_max= 0;
#endif

	memset(&l1_shp_cfg_tbl, 0, sizeof(l1_shp_cfg_tbl));
	memset(&l1_comp_cfg_tbl, 0, sizeof(l1_comp_cfg_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(shaper);

	if ((flow_id < 0) || (flow_id > 63))
		return SW_BAD_PARAM;

	if(ADPT_HPPE_SHAPER_METER_UNIT_BYTE == shaper->meter_unit)
	{
		if ((shaper->cir > BYTE_SHAPER_MAX_RATE) || (shaper->eir > BYTE_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir < BYTE_SHAPER_MIN_RATE) && (shaper->cir != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir < BYTE_SHAPER_MIN_RATE) && (shaper->eir != 0))
			return SW_BAD_PARAM;
#ifdef APPE
		if ((shaper->cir_max > BYTE_SHAPER_MAX_RATE) || (shaper->eir_max > BYTE_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir_max < BYTE_SHAPER_MIN_RATE) && (shaper->cir_max != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir_max < BYTE_SHAPER_MIN_RATE) && (shaper->eir_max != 0))
			return SW_BAD_PARAM;
#endif
	}
	if(ADPT_HPPE_SHAPER_METER_UNIT_FRAME == shaper->meter_unit)
	{
		if ((shaper->cir > FRAME_SHAPER_MAX_RATE) || (shaper->eir > FRAME_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir < FRAME_SHAPER_MIN_RATE) && (shaper->cir != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir < FRAME_SHAPER_MIN_RATE) && (shaper->eir != 0))
			return SW_BAD_PARAM;
#ifdef APPE
		if ((shaper->cir_max > FRAME_SHAPER_MAX_RATE) || (shaper->eir_max > FRAME_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir_max < FRAME_SHAPER_MIN_RATE) && (shaper->cir_max != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir_max < FRAME_SHAPER_MIN_RATE) && (shaper->eir_max != 0))
			return SW_BAD_PARAM;
#endif
	}

	hppe_l1_comp_cfg_tbl_get(dev_id, flow_id, &l1_comp_cfg_tbl);

	temp_cir = ((a_uint64_t)shaper->cir) * 1000;
	temp_cbs = ((a_uint64_t)shaper->cbs) * 1000;
	temp_eir = ((a_uint64_t)shaper->eir) * 1000;
	temp_ebs = ((a_uint64_t)shaper->ebs) * 1000;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
			if (shaper->meter_type == FAL_SHAPER_METER_MEF10_3) {
			temp_cir_max = ((a_uint64_t)shaper->cir_max) * 1000;
			temp_eir_max = ((a_uint64_t)shaper->eir_max) * 1000;

			if (temp_cir_max >= temp_cir) {
				temp_cir = temp_cir_max;
			}
			if (temp_eir_max >= temp_eir) {
				temp_eir = temp_eir_max;
			}
		}
	}
#endif
	rv = __adpt_hppe_shaper_two_bucket_parameter_select(ADPT_HPPE_FLOW_SHAPER,
				temp_cir,
				temp_cbs,
				temp_eir,
				temp_ebs,
				shaper->meter_unit,
				&token_unit);
	if( rv != SW_OK )
		return rv;
	SSDK_DEBUG("flow shaper meter unit is = %d\n", shaper->meter_unit);
	SSDK_DEBUG("flow shaper token unit is = %d\n", token_unit);

	__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_FLOW_SHAPER,
				shaper->cir,
				&hppe_cir,
				shaper->meter_unit,
				token_unit);

	__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_FLOW_SHAPER,
				shaper->eir,
				&hppe_eir,
				shaper->meter_unit,
				token_unit);
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		if (shaper->meter_type == FAL_SHAPER_METER_MEF10_3) {
			__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_FLOW_SHAPER,
				shaper->cir_max,
				&hppe_cir_max,
				shaper->meter_unit,
				token_unit);

			__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_FLOW_SHAPER,
				shaper->eir_max,
				&hppe_eir_max,
				shaper->meter_unit,
				token_unit);
		}
		if (shaper->meter_type == FAL_SHAPER_METER_RFC) {
			if (shaper->couple_en == A_FALSE) {
				hppe_cir_max = hppe_cir;
				hppe_eir_max = hppe_eir;
			} else {
				hppe_cir_max = hppe_cir;
				hppe_eir_max = ADPT_HPPE_SHAPER_MAX;
			}
		}
	}
#endif
	__adpt_hppe_shaper_burst_size_to_bucket_size(shaper->cbs,
				&hppe_cbs,
				shaper->meter_unit,
				token_unit);

	__adpt_hppe_shaper_burst_size_to_bucket_size(shaper->ebs,
				&hppe_ebs,
				shaper->meter_unit,
				token_unit);

	hppe_l1_shp_cfg_tbl_get(dev_id, flow_id, &l1_shp_cfg_tbl);
	SW_RTN_ON_ERROR (rv);

	l1_shp_cfg_tbl.bf.cf = shaper->couple_en;
	l1_shp_cfg_tbl.bf.meter_unit = shaper->meter_unit;
	l1_shp_cfg_tbl.bf.c_shaper_enable = shaper->c_shaper_en;
	l1_shp_cfg_tbl.bf.cbs = hppe_cbs;
	l1_shp_cfg_tbl.bf.cir = hppe_cir;
	l1_shp_cfg_tbl.bf.e_shaper_enable = shaper->e_shaper_en;
	l1_shp_cfg_tbl.bf.ebs = hppe_ebs;
	l1_shp_cfg_tbl.bf.eir = hppe_eir;
	l1_shp_cfg_tbl.bf.token_unit = token_unit;
	l1_comp_cfg_tbl.bf.shaper_meter_len = shaper->shaper_frame_mode;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		l1_shp_cfg_tbl.bf.cir_max_0 = hppe_cir_max & 0x1ffff;
		l1_shp_cfg_tbl.bf.cir_max_1 = hppe_cir_max >> 17;
		l1_shp_cfg_tbl.bf.eir_max = hppe_eir_max;
		if (shaper->meter_type == FAL_SHAPER_METER_MEF10_3) {
			l1_shp_cfg_tbl.bf.shp_refresh_nxt_ptr = shaper->next_ptr;
			l1_shp_cfg_tbl.bf.grp_end = shaper->grp_end;
			l1_shp_cfg_tbl.bf.grp_cf = shaper->grp_couple_en;
		} else {
			l1_shp_cfg_tbl.bf.grp_end = 0x1;
		}
		appe_flow_shaper_type[dev_id][flow_id] = shaper->meter_type;
	}
#endif
	hppe_l1_shp_cfg_tbl_set(dev_id, flow_id, &l1_shp_cfg_tbl);

	hppe_l1_comp_cfg_tbl_set(dev_id, flow_id, &l1_comp_cfg_tbl);

	if( A_FALSE == shaper->c_shaper_en)
	{
		token_number.c_token_number_negative_en = 0;
		token_number.c_token_number = 0;
		adpt_hppe_flow_shaper_token_number_set(dev_id, flow_id, &token_number);
	}
	if( A_FALSE == shaper->e_shaper_en)
	{
		token_number.e_token_number_negative_en = 0;
		token_number.e_token_number = 0;
		adpt_hppe_flow_shaper_token_number_set(dev_id, flow_id, &token_number);
	}

	return SW_OK;
}
sw_error_t
adpt_hppe_port_shaper_set(a_uint32_t dev_id, fal_port_t port_id,
		fal_shaper_config_t * shaper)
{
	sw_error_t rv = SW_OK;
	union psch_shp_cfg_tbl_u psch_shp_cfg_tbl;
	union psch_comp_cfg_tbl_u psch_comp_cfg_tbl;
	a_uint64_t temp_cir = 0,temp_cbs;
	a_uint32_t hppe_cir = 0, hppe_cbs = 0;
	a_uint32_t token_unit = 0;
	fal_shaper_token_number_t token_number;

	memset(&psch_shp_cfg_tbl, 0, sizeof(psch_shp_cfg_tbl));
	memset(&psch_comp_cfg_tbl, 0, sizeof(psch_comp_cfg_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(shaper);

	if (port_id < 0 || port_id > 7)
		return SW_BAD_PARAM;

	if(ADPT_HPPE_SHAPER_METER_UNIT_BYTE == shaper->meter_unit)
	{
		if (shaper->cir > BYTE_SHAPER_MAX_RATE)
			return SW_BAD_PARAM;
		if ((shaper->cir < BYTE_SHAPER_MIN_RATE) && (shaper->cir != 0))
			return SW_BAD_PARAM;
	}
	if(ADPT_HPPE_SHAPER_METER_UNIT_FRAME == shaper->meter_unit)
	{
		if (shaper->cir > FRAME_SHAPER_MAX_RATE)
			return SW_BAD_PARAM;
		if ((shaper->cir < FRAME_SHAPER_MIN_RATE) && (shaper->cir != 0))
			return SW_BAD_PARAM;
	}

	temp_cir = ((a_uint64_t)shaper->cir) * 1000;
	temp_cbs = ((a_uint64_t)shaper->cbs) * 1000;

	rv = __adpt_hppe_shaper_one_bucket_parameter_select(ADPT_HPPE_PORT_SHAPER,
								temp_cir,
								temp_cbs,
								shaper->meter_unit,
								&token_unit);
	if( rv != SW_OK )
		return rv;

	// printk("current shaper meter unit is = %d\n", shaper->meter_unit);
	// printk("current shaper token unit is = %d\n", token_unit);

	__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_PORT_SHAPER,
								shaper->cir,
								&hppe_cir,
								shaper->meter_unit,
								token_unit);

	__adpt_hppe_shaper_burst_size_to_bucket_size(shaper->cbs,
								&hppe_cbs,
								shaper->meter_unit,
								token_unit);

	psch_shp_cfg_tbl.bf.meter_unit = shaper->meter_unit;
	psch_shp_cfg_tbl.bf.shaper_enable = shaper->c_shaper_en;
	psch_shp_cfg_tbl.bf.cbs = hppe_cbs;
	psch_shp_cfg_tbl.bf.cir = hppe_cir;
	psch_shp_cfg_tbl.bf.token_unit = token_unit;

	psch_comp_cfg_tbl.bf.shaper_meter_len = shaper->shaper_frame_mode;

	hppe_psch_shp_cfg_tbl_set(dev_id, port_id, &psch_shp_cfg_tbl);

	hppe_psch_comp_cfg_tbl_set(dev_id, port_id, &psch_comp_cfg_tbl);

	if( A_FALSE == shaper->c_shaper_en)
	{
		token_number.c_token_number_negative_en = 0;
		token_number.c_token_number = 0;
		adpt_hppe_port_shaper_token_number_set(dev_id, port_id, &token_number);
	}

	return SW_OK;
}
sw_error_t
adpt_hppe_port_shaper_time_slot_set(a_uint32_t dev_id, a_uint32_t time_slot)
{
	sw_error_t rv = SW_OK;
	union shp_slot_cfg_port_u shp_slot_cfg_port;

	memset(&shp_slot_cfg_port, 0, sizeof(shp_slot_cfg_port));
	ADPT_DEV_ID_CHECK(dev_id);

	if ((time_slot < 0x8) || (time_slot > 0xfff))
		return SW_BAD_PARAM;

	rv = hppe_shp_slot_cfg_port_get(dev_id, &shp_slot_cfg_port);

	if( rv != SW_OK )
		return rv;

	shp_slot_cfg_port.bf.port_shp_slot_time = time_slot;
	hppe_shp_slot_cfg_port_set(dev_id, &shp_slot_cfg_port);

	__adpt_hppe_port_shaper_max_rate(dev_id, time_slot);

	__adpt_hppe_shaper_max_burst_size();

	return SW_OK;

}
#ifndef IN_SHAPER_MINI
sw_error_t
adpt_hppe_flow_shaper_get(a_uint32_t dev_id, a_uint32_t flow_id,
		fal_shaper_config_t * shaper)
{
	sw_error_t rv = SW_OK;
	union l1_shp_cfg_tbl_u l1_shp_cfg_tbl;
	union l1_comp_cfg_tbl_u l1_comp_cfg_tbl;
	a_uint32_t hppe_cir =0, hppe_cbs = 0, hppe_eir = 0, hppe_ebs = 0;
#ifdef APPE
	a_uint32_t hppe_cir_max = 0, hppe_eir_max= 0;
#endif

	memset(&l1_shp_cfg_tbl, 0, sizeof(l1_shp_cfg_tbl));
	memset(&l1_comp_cfg_tbl, 0, sizeof(l1_comp_cfg_tbl));

	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(shaper);

	if (flow_id < 0 || flow_id > 63)
		return SW_BAD_PARAM;

	hppe_l1_comp_cfg_tbl_get(dev_id, flow_id, &l1_comp_cfg_tbl);

	rv = hppe_l1_shp_cfg_tbl_get(dev_id, flow_id, &l1_shp_cfg_tbl);

	if( rv != SW_OK )
		return rv;

	hppe_cir = l1_shp_cfg_tbl.bf.cir;
	hppe_cbs = l1_shp_cfg_tbl.bf.cbs;
	hppe_eir = l1_shp_cfg_tbl.bf.eir;
	hppe_ebs= l1_shp_cfg_tbl.bf.ebs;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		hppe_cir_max = (l1_shp_cfg_tbl.bf.cir_max_1 << 17) |
				l1_shp_cfg_tbl.bf.cir_max_0;
		hppe_eir_max = l1_shp_cfg_tbl.bf.eir_max;
	}
#endif
	__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_FLOW_SHAPER,
				hppe_cir,
				&shaper->cir,
				l1_shp_cfg_tbl.bf.meter_unit,
				l1_shp_cfg_tbl.bf.token_unit);

	__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_FLOW_SHAPER,
				hppe_eir,
				&shaper->eir,
				l1_shp_cfg_tbl.bf.meter_unit,
				l1_shp_cfg_tbl.bf.token_unit);
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_FLOW_SHAPER,
				hppe_cir_max,
				&shaper->cir_max,
				l1_shp_cfg_tbl.bf.meter_unit,
				l1_shp_cfg_tbl.bf.token_unit);

		__adpt_hppe_shaper_refresh_to_rate(ADPT_HPPE_FLOW_SHAPER,
				hppe_eir_max,
				&shaper->eir_max,
				l1_shp_cfg_tbl.bf.meter_unit,
				l1_shp_cfg_tbl.bf.token_unit);
	}
#endif
	__adpt_hppe_shaper_bucket_size_to_burst_size(hppe_cbs,
				&shaper->cbs,
				l1_shp_cfg_tbl.bf.meter_unit,
				l1_shp_cfg_tbl.bf.token_unit);

	__adpt_hppe_shaper_bucket_size_to_burst_size(hppe_ebs,
				&shaper->ebs,
				l1_shp_cfg_tbl.bf.meter_unit,
				l1_shp_cfg_tbl.bf.token_unit);

	shaper->couple_en = l1_shp_cfg_tbl.bf.cf;
	shaper->meter_unit = l1_shp_cfg_tbl.bf.meter_unit;
	shaper->c_shaper_en = l1_shp_cfg_tbl.bf.c_shaper_enable;
	shaper->e_shaper_en = l1_shp_cfg_tbl.bf.e_shaper_enable;

	shaper->shaper_frame_mode = l1_comp_cfg_tbl.bf.shaper_meter_len;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		shaper->meter_type = appe_flow_shaper_type[dev_id][flow_id];
		shaper->next_ptr = l1_shp_cfg_tbl.bf.shp_refresh_nxt_ptr;
		shaper->grp_end = l1_shp_cfg_tbl.bf.grp_end;
		shaper->grp_couple_en = l1_shp_cfg_tbl.bf.grp_cf;
	}
#endif
	return SW_OK;
}
#endif

sw_error_t
adpt_hppe_queue_shaper_set(a_uint32_t dev_id,a_uint32_t queue_id,
		fal_shaper_config_t * shaper)
{
	sw_error_t rv = SW_OK;
	union l0_shp_cfg_tbl_u l0_shp_cfg_tbl;
	union l0_comp_cfg_tbl_u l0_comp_cfg_tbl;
	a_uint32_t hppe_cir = 0, hppe_cbs = 0, hppe_eir= 0, hppe_ebs = 0;
	a_uint32_t token_unit = 0;
	a_uint64_t temp_cir = 0, temp_eir =0, temp_cbs =0, temp_ebs = 0;
	fal_shaper_token_number_t token_number;
#ifdef APPE
	a_uint64_t temp_cir_max = 0, temp_eir_max =0;
	a_uint32_t hppe_cir_max = 0, hppe_eir_max= 0;
#endif

	memset(&l0_shp_cfg_tbl, 0, sizeof(l0_shp_cfg_tbl));
	memset(&l0_comp_cfg_tbl, 0, sizeof(l0_comp_cfg_tbl));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(shaper);

	if (queue_id < 0 || queue_id > 299)
		return SW_BAD_PARAM;

	if(ADPT_HPPE_SHAPER_METER_UNIT_BYTE == shaper->meter_unit)
	{
		if ((shaper->cir > BYTE_SHAPER_MAX_RATE) || (shaper->eir > BYTE_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir < BYTE_SHAPER_MIN_RATE) && (shaper->cir != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir < BYTE_SHAPER_MIN_RATE) && (shaper->eir != 0))
			return SW_BAD_PARAM;
#ifdef APPE
		if ((shaper->cir_max > BYTE_SHAPER_MAX_RATE) || (shaper->eir_max > BYTE_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir_max < BYTE_SHAPER_MIN_RATE) && (shaper->cir_max != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir_max < BYTE_SHAPER_MIN_RATE) && (shaper->eir_max != 0))
			return SW_BAD_PARAM;
#endif
	}
	if(ADPT_HPPE_SHAPER_METER_UNIT_FRAME == shaper->meter_unit)
	{
		if ((shaper->cir > FRAME_SHAPER_MAX_RATE) || (shaper->eir > FRAME_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir < FRAME_SHAPER_MIN_RATE) && (shaper->cir != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir < FRAME_SHAPER_MIN_RATE) && (shaper->eir != 0))
			return SW_BAD_PARAM;
#ifdef APPE
		if ((shaper->cir_max > FRAME_SHAPER_MAX_RATE) || (shaper->eir_max > FRAME_SHAPER_MAX_RATE))
			return SW_BAD_PARAM;
		if ((shaper->cir_max < FRAME_SHAPER_MIN_RATE) && (shaper->cir_max != 0))
			return SW_BAD_PARAM;
		if ((shaper->eir_max < FRAME_SHAPER_MIN_RATE) && (shaper->eir_max != 0))
			return SW_BAD_PARAM;
#endif
	}

	hppe_l0_comp_cfg_tbl_get(dev_id, queue_id, &l0_comp_cfg_tbl);

	temp_cir = ((a_uint64_t)shaper->cir) * 1000;
	temp_cbs = ((a_uint64_t)shaper->cbs) * 1000;
	temp_eir = ((a_uint64_t)shaper->eir) * 1000;
	temp_ebs = ((a_uint64_t)shaper->ebs) * 1000;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		if (shaper->meter_type == FAL_SHAPER_METER_MEF10_3) {
			temp_cir_max = ((a_uint64_t)shaper->cir_max) * 1000;
			temp_eir_max = ((a_uint64_t)shaper->eir_max) * 1000;
			if (temp_cir_max >= temp_cir) {
				temp_cir = temp_cir_max;
			}
			if (temp_eir_max >= temp_eir) {
				temp_eir = temp_eir_max;
			}
		}
	}
#endif
	rv = __adpt_hppe_shaper_two_bucket_parameter_select(ADPT_HPPE_QUEUE_SHAPER,
				temp_cir,
				temp_cbs,
				temp_eir,
				temp_ebs,
				shaper->meter_unit,
				&token_unit);
	if( rv != SW_OK )
		return rv;
	SSDK_DEBUG("queue shaper meter unit is = %d\n", shaper->meter_unit);
	SSDK_DEBUG("queue shaper token unit is = %d\n", token_unit);

	__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_QUEUE_SHAPER,
				shaper->cir,
				&hppe_cir,
				shaper->meter_unit,
				token_unit);

	__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_QUEUE_SHAPER,
				shaper->eir,
				&hppe_eir,
				shaper->meter_unit,
				token_unit);
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		if (shaper->meter_type == FAL_SHAPER_METER_MEF10_3) {
			__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_QUEUE_SHAPER,
				shaper->cir_max,
				&hppe_cir_max,
				shaper->meter_unit,
				token_unit);

			__adpt_hppe_shaper_rate_to_refresh(ADPT_HPPE_QUEUE_SHAPER,
				shaper->eir_max,
				&hppe_eir_max,
				shaper->meter_unit,
				token_unit);
		}
		if (shaper->meter_type == FAL_SHAPER_METER_RFC) {
			if (shaper->couple_en == A_FALSE) {
				hppe_cir_max = hppe_cir;
				hppe_eir_max = hppe_eir;
			} else {
				hppe_cir_max = hppe_cir;
				hppe_eir_max = ADPT_HPPE_SHAPER_MAX;
			}
		}
	}
#endif
	__adpt_hppe_shaper_burst_size_to_bucket_size(shaper->cbs,
				&hppe_cbs,
				shaper->meter_unit,
				token_unit);

	__adpt_hppe_shaper_burst_size_to_bucket_size(shaper->ebs,
				&hppe_ebs,
				shaper->meter_unit,
				token_unit);
	rv = hppe_l0_shp_cfg_tbl_get(dev_id, queue_id, &l0_shp_cfg_tbl);
	SW_RTN_ON_ERROR (rv);

	l0_shp_cfg_tbl.bf.cf = shaper->couple_en;
	l0_shp_cfg_tbl.bf.meter_unit = shaper->meter_unit;
	l0_shp_cfg_tbl.bf.c_shaper_enable = shaper->c_shaper_en;
	l0_shp_cfg_tbl.bf.cbs = hppe_cbs;
	l0_shp_cfg_tbl.bf.cir = hppe_cir;
	l0_shp_cfg_tbl.bf.e_shaper_enable = shaper->e_shaper_en;
	l0_shp_cfg_tbl.bf.ebs = hppe_ebs;
	l0_shp_cfg_tbl.bf.eir = hppe_eir;
	l0_shp_cfg_tbl.bf.token_unit = token_unit;
	l0_comp_cfg_tbl.bf.shaper_meter_len = shaper->shaper_frame_mode;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		l0_shp_cfg_tbl.bf.cir_max_0 = hppe_cir_max & 0x3fff;
		l0_shp_cfg_tbl.bf.cir_max_1 = hppe_cir_max >> 14;
		l0_shp_cfg_tbl.bf.eir_max = hppe_eir_max;
		if (shaper->meter_type == FAL_SHAPER_METER_MEF10_3) {
			l0_shp_cfg_tbl.bf.shp_refresh_nxt_ptr = shaper->next_ptr;
			l0_shp_cfg_tbl.bf.grp_end = shaper->grp_end;
			l0_shp_cfg_tbl.bf.grp_cf = shaper->grp_couple_en;
		} else {
			l0_shp_cfg_tbl.bf.grp_end = 0x1;
		}
		appe_queue_shaper_type[dev_id][queue_id] = shaper->meter_type;
	}
#endif
	hppe_l0_shp_cfg_tbl_set(dev_id, queue_id, &l0_shp_cfg_tbl);

	hppe_l0_comp_cfg_tbl_set(dev_id, queue_id, &l0_comp_cfg_tbl);

	if( A_FALSE == shaper->c_shaper_en)
	{
		token_number.c_token_number_negative_en = 0;
		token_number.c_token_number = 0;
		adpt_hppe_queue_shaper_token_number_set(dev_id, queue_id, &token_number);
	}
	if( A_FALSE == shaper->e_shaper_en)
	{
		token_number.e_token_number_negative_en = 0;
		token_number.e_token_number = 0;
		adpt_hppe_queue_shaper_token_number_set(dev_id, queue_id, &token_number);
	}

	return SW_OK;

}
sw_error_t
adpt_hppe_queue_shaper_time_slot_set(a_uint32_t dev_id, a_uint32_t time_slot)
{
	union shp_slot_cfg_l0_u shp_slot_cfg_l0;
	sw_error_t rv = SW_OK;

	memset(&shp_slot_cfg_l0, 0, sizeof(shp_slot_cfg_l0));
	ADPT_DEV_ID_CHECK(dev_id);

	if ((time_slot < 0x12c) || (time_slot > 0xfff))
		return SW_BAD_PARAM;

	rv = hppe_shp_slot_cfg_l0_get(dev_id, &shp_slot_cfg_l0);

	if( rv != SW_OK )
		return rv;

	shp_slot_cfg_l0.bf.l0_shp_slot_time = time_slot;
	hppe_shp_slot_cfg_l0_set(dev_id, &shp_slot_cfg_l0);

	__adpt_hppe_queue_shaper_max_rate(dev_id, time_slot);

	return SW_OK;
}

sw_error_t
adpt_hppe_shaper_ipg_preamble_length_set(a_uint32_t dev_id, a_uint32_t ipg_pre_length)
{
	union ipg_pre_len_cfg_u ipg_pre_len_cfg;

	memset(&ipg_pre_len_cfg, 0, sizeof(ipg_pre_len_cfg));
	ADPT_DEV_ID_CHECK(dev_id);

	if (ipg_pre_length > 0x1f)
		return SW_BAD_PARAM;

	hppe_ipg_pre_len_cfg_get(dev_id, &ipg_pre_len_cfg);
	ipg_pre_len_cfg.bf.ipg_pre_len = ipg_pre_length;

	hppe_ipg_pre_len_cfg_set(dev_id, &ipg_pre_len_cfg);

	return SW_OK;
}

#ifndef IN_SHAPER_MINI
sw_error_t
adpt_hppe_shaper_ipg_preamble_length_get(a_uint32_t dev_id, a_uint32_t *ipg_pre_length)
{
	sw_error_t rv = SW_OK;
	union ipg_pre_len_cfg_u ipg_pre_len_cfg;

	memset(&ipg_pre_len_cfg, 0, sizeof(ipg_pre_len_cfg));
	ADPT_DEV_ID_CHECK(dev_id);
	ADPT_NULL_POINT_CHECK(ipg_pre_length);

	rv = hppe_ipg_pre_len_cfg_get(dev_id, &ipg_pre_len_cfg);

	if( rv != SW_OK )
		return rv;

	*ipg_pre_length = ipg_pre_len_cfg.bf.ipg_pre_len;

	return SW_OK;
}
#endif

sw_error_t adpt_hppe_shaper_init(a_uint32_t dev_id)
{
	adpt_api_t *p_adpt_api = NULL;

	p_adpt_api = adpt_api_ptr_get(dev_id);

	if(p_adpt_api == NULL)
		return SW_FAIL;

#ifndef IN_SHAPER_MINI
	p_adpt_api->adpt_port_shaper_get = adpt_hppe_port_shaper_get;
	p_adpt_api->adpt_flow_shaper_time_slot_get = adpt_hppe_flow_shaper_time_slot_get;
	p_adpt_api->adpt_port_shaper_time_slot_get = adpt_hppe_port_shaper_time_slot_get;
	p_adpt_api->adpt_queue_shaper_token_number_get =
		adpt_hppe_queue_shaper_token_number_get;
	p_adpt_api->adpt_queue_shaper_time_slot_get = adpt_hppe_queue_shaper_time_slot_get;
	p_adpt_api->adpt_port_shaper_token_number_get =
		adpt_hppe_port_shaper_token_number_get;
	p_adpt_api->adpt_flow_shaper_token_number_get =
		adpt_hppe_flow_shaper_token_number_get;
	p_adpt_api->adpt_flow_shaper_get = adpt_hppe_flow_shaper_get;
	p_adpt_api->adpt_shaper_ipg_preamble_length_get =
		adpt_hppe_shaper_ipg_preamble_length_get;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		p_adpt_api->adpt_queue_shaper_ctrl_get = adpt_appe_queue_shaper_ctrl_get;
		p_adpt_api->adpt_flow_shaper_ctrl_get = adpt_appe_flow_shaper_ctrl_get;
	}
#endif
#endif
	p_adpt_api->adpt_flow_shaper_set = adpt_hppe_flow_shaper_set;
	p_adpt_api->adpt_queue_shaper_set = adpt_hppe_queue_shaper_set;
	p_adpt_api->adpt_queue_shaper_get = adpt_hppe_queue_shaper_get;
	p_adpt_api->adpt_port_shaper_set = adpt_hppe_port_shaper_set;
	p_adpt_api->adpt_shaper_ipg_preamble_length_set =
		adpt_hppe_shaper_ipg_preamble_length_set;
	p_adpt_api->adpt_queue_shaper_token_number_set =
		adpt_hppe_queue_shaper_token_number_set;
	p_adpt_api->adpt_port_shaper_token_number_set =
		adpt_hppe_port_shaper_token_number_set;
	p_adpt_api->adpt_flow_shaper_token_number_set =
		adpt_hppe_flow_shaper_token_number_set;
	p_adpt_api->adpt_port_shaper_time_slot_set = adpt_hppe_port_shaper_time_slot_set;
	p_adpt_api->adpt_flow_shaper_time_slot_set = adpt_hppe_flow_shaper_time_slot_set;
	p_adpt_api->adpt_queue_shaper_time_slot_set = adpt_hppe_queue_shaper_time_slot_set;
#ifdef APPE
	if (adpt_chip_type_get(dev_id) == CHIP_APPE) {
		p_adpt_api->adpt_queue_shaper_ctrl_set = adpt_appe_queue_shaper_ctrl_set;
		p_adpt_api->adpt_flow_shaper_ctrl_set = adpt_appe_flow_shaper_ctrl_set;
	}
#endif
	return SW_OK;
}

/**
 * @}
 */
