162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Marvell RVU Ethernet driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2021 Marvell.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "cn10k.h"
962306a36Sopenharmony_ci#include "otx2_reg.h"
1062306a36Sopenharmony_ci#include "otx2_struct.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic struct dev_hw_ops	otx2_hw_ops = {
1362306a36Sopenharmony_ci	.sq_aq_init = otx2_sq_aq_init,
1462306a36Sopenharmony_ci	.sqe_flush = otx2_sqe_flush,
1562306a36Sopenharmony_ci	.aura_freeptr = otx2_aura_freeptr,
1662306a36Sopenharmony_ci	.refill_pool_ptrs = otx2_refill_pool_ptrs,
1762306a36Sopenharmony_ci};
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic struct dev_hw_ops cn10k_hw_ops = {
2062306a36Sopenharmony_ci	.sq_aq_init = cn10k_sq_aq_init,
2162306a36Sopenharmony_ci	.sqe_flush = cn10k_sqe_flush,
2262306a36Sopenharmony_ci	.aura_freeptr = cn10k_aura_freeptr,
2362306a36Sopenharmony_ci	.refill_pool_ptrs = cn10k_refill_pool_ptrs,
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciint cn10k_lmtst_init(struct otx2_nic *pfvf)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	struct lmtst_tbl_setup_req *req;
3062306a36Sopenharmony_ci	struct otx2_lmt_info *lmt_info;
3162306a36Sopenharmony_ci	int err, cpu;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (!test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
3462306a36Sopenharmony_ci		pfvf->hw_ops = &otx2_hw_ops;
3562306a36Sopenharmony_ci		return 0;
3662306a36Sopenharmony_ci	}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	pfvf->hw_ops = &cn10k_hw_ops;
3962306a36Sopenharmony_ci	/* Total LMTLINES = num_online_cpus() * 32 (For Burst flush).*/
4062306a36Sopenharmony_ci	pfvf->tot_lmt_lines = (num_online_cpus() * LMT_BURST_SIZE);
4162306a36Sopenharmony_ci	pfvf->hw.lmt_info = alloc_percpu(struct otx2_lmt_info);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	mutex_lock(&pfvf->mbox.lock);
4462306a36Sopenharmony_ci	req = otx2_mbox_alloc_msg_lmtst_tbl_setup(&pfvf->mbox);
4562306a36Sopenharmony_ci	if (!req) {
4662306a36Sopenharmony_ci		mutex_unlock(&pfvf->mbox.lock);
4762306a36Sopenharmony_ci		return -ENOMEM;
4862306a36Sopenharmony_ci	}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	req->use_local_lmt_region = true;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	err = qmem_alloc(pfvf->dev, &pfvf->dync_lmt, pfvf->tot_lmt_lines,
5362306a36Sopenharmony_ci			 LMT_LINE_SIZE);
5462306a36Sopenharmony_ci	if (err) {
5562306a36Sopenharmony_ci		mutex_unlock(&pfvf->mbox.lock);
5662306a36Sopenharmony_ci		return err;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci	pfvf->hw.lmt_base = (u64 *)pfvf->dync_lmt->base;
5962306a36Sopenharmony_ci	req->lmt_iova = (u64)pfvf->dync_lmt->iova;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	err = otx2_sync_mbox_msg(&pfvf->mbox);
6262306a36Sopenharmony_ci	mutex_unlock(&pfvf->mbox.lock);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	for_each_possible_cpu(cpu) {
6562306a36Sopenharmony_ci		lmt_info = per_cpu_ptr(pfvf->hw.lmt_info, cpu);
6662306a36Sopenharmony_ci		lmt_info->lmt_addr = ((u64)pfvf->hw.lmt_base +
6762306a36Sopenharmony_ci				      (cpu * LMT_BURST_SIZE * LMT_LINE_SIZE));
6862306a36Sopenharmony_ci		lmt_info->lmt_id = cpu * LMT_BURST_SIZE;
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	return 0;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ciEXPORT_SYMBOL(cn10k_lmtst_init);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciint cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct nix_cn10k_aq_enq_req *aq;
7862306a36Sopenharmony_ci	struct otx2_nic *pfvf = dev;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	/* Get memory to put this msg */
8162306a36Sopenharmony_ci	aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
8262306a36Sopenharmony_ci	if (!aq)
8362306a36Sopenharmony_ci		return -ENOMEM;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	aq->sq.cq = pfvf->hw.rx_queues + qidx;
8662306a36Sopenharmony_ci	aq->sq.max_sqe_size = NIX_MAXSQESZ_W16; /* 128 byte */
8762306a36Sopenharmony_ci	aq->sq.cq_ena = 1;
8862306a36Sopenharmony_ci	aq->sq.ena = 1;
8962306a36Sopenharmony_ci	aq->sq.smq = otx2_get_smq_idx(pfvf, qidx);
9062306a36Sopenharmony_ci	aq->sq.smq_rr_weight = mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
9162306a36Sopenharmony_ci	aq->sq.default_chan = pfvf->hw.tx_chan_base;
9262306a36Sopenharmony_ci	aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */
9362306a36Sopenharmony_ci	aq->sq.sqb_aura = sqb_aura;
9462306a36Sopenharmony_ci	aq->sq.sq_int_ena = NIX_SQINT_BITS;
9562306a36Sopenharmony_ci	aq->sq.qint_idx = 0;
9662306a36Sopenharmony_ci	/* Due pipelining impact minimum 2000 unused SQ CQE's
9762306a36Sopenharmony_ci	 * need to maintain to avoid CQ overflow.
9862306a36Sopenharmony_ci	 */
9962306a36Sopenharmony_ci	aq->sq.cq_limit = ((SEND_CQ_SKID * 256) / (pfvf->qset.sqe_cnt));
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	/* Fill AQ info */
10262306a36Sopenharmony_ci	aq->qidx = qidx;
10362306a36Sopenharmony_ci	aq->ctype = NIX_AQ_CTYPE_SQ;
10462306a36Sopenharmony_ci	aq->op = NIX_AQ_INSTOP_INIT;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return otx2_sync_mbox_msg(&pfvf->mbox);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define NPA_MAX_BURST 16
11062306a36Sopenharmony_ciint cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct otx2_nic *pfvf = dev;
11362306a36Sopenharmony_ci	int cnt = cq->pool_ptrs;
11462306a36Sopenharmony_ci	u64 ptrs[NPA_MAX_BURST];
11562306a36Sopenharmony_ci	dma_addr_t bufptr;
11662306a36Sopenharmony_ci	int num_ptrs = 1;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/* Refill pool with new buffers */
11962306a36Sopenharmony_ci	while (cq->pool_ptrs) {
12062306a36Sopenharmony_ci		if (otx2_alloc_buffer(pfvf, cq, &bufptr)) {
12162306a36Sopenharmony_ci			if (num_ptrs--)
12262306a36Sopenharmony_ci				__cn10k_aura_freeptr(pfvf, cq->cq_idx, ptrs,
12362306a36Sopenharmony_ci						     num_ptrs);
12462306a36Sopenharmony_ci			break;
12562306a36Sopenharmony_ci		}
12662306a36Sopenharmony_ci		cq->pool_ptrs--;
12762306a36Sopenharmony_ci		ptrs[num_ptrs] = (u64)bufptr + OTX2_HEAD_ROOM;
12862306a36Sopenharmony_ci		num_ptrs++;
12962306a36Sopenharmony_ci		if (num_ptrs == NPA_MAX_BURST || cq->pool_ptrs == 0) {
13062306a36Sopenharmony_ci			__cn10k_aura_freeptr(pfvf, cq->cq_idx, ptrs,
13162306a36Sopenharmony_ci					     num_ptrs);
13262306a36Sopenharmony_ci			num_ptrs = 1;
13362306a36Sopenharmony_ci		}
13462306a36Sopenharmony_ci	}
13562306a36Sopenharmony_ci	return cnt - cq->pool_ptrs;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_civoid cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	struct otx2_lmt_info *lmt_info;
14162306a36Sopenharmony_ci	struct otx2_nic *pfvf = dev;
14262306a36Sopenharmony_ci	u64 val = 0, tar_addr = 0;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	lmt_info = per_cpu_ptr(pfvf->hw.lmt_info, smp_processor_id());
14562306a36Sopenharmony_ci	/* FIXME: val[0:10] LMT_ID.
14662306a36Sopenharmony_ci	 * [12:15] no of LMTST - 1 in the burst.
14762306a36Sopenharmony_ci	 * [19:63] data size of each LMTST in the burst except first.
14862306a36Sopenharmony_ci	 */
14962306a36Sopenharmony_ci	val = (lmt_info->lmt_id & 0x7FF);
15062306a36Sopenharmony_ci	/* Target address for LMTST flush tells HW how many 128bit
15162306a36Sopenharmony_ci	 * words are present.
15262306a36Sopenharmony_ci	 * tar_addr[6:4] size of first LMTST - 1 in units of 128b.
15362306a36Sopenharmony_ci	 */
15462306a36Sopenharmony_ci	tar_addr |= sq->io_addr | (((size / 16) - 1) & 0x7) << 4;
15562306a36Sopenharmony_ci	dma_wmb();
15662306a36Sopenharmony_ci	memcpy((u64 *)lmt_info->lmt_addr, sq->sqe_base, size);
15762306a36Sopenharmony_ci	cn10k_lmt_flush(val, tar_addr);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	sq->head++;
16062306a36Sopenharmony_ci	sq->head &= (sq->sqe_cnt - 1);
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ciint cn10k_free_all_ipolicers(struct otx2_nic *pfvf)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct nix_bandprof_free_req *req;
16662306a36Sopenharmony_ci	int rc;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (is_dev_otx2(pfvf->pdev))
16962306a36Sopenharmony_ci		return 0;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	mutex_lock(&pfvf->mbox.lock);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	req = otx2_mbox_alloc_msg_nix_bandprof_free(&pfvf->mbox);
17462306a36Sopenharmony_ci	if (!req) {
17562306a36Sopenharmony_ci		rc =  -ENOMEM;
17662306a36Sopenharmony_ci		goto out;
17762306a36Sopenharmony_ci	}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	/* Free all bandwidth profiles allocated */
18062306a36Sopenharmony_ci	req->free_all = true;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	rc = otx2_sync_mbox_msg(&pfvf->mbox);
18362306a36Sopenharmony_ciout:
18462306a36Sopenharmony_ci	mutex_unlock(&pfvf->mbox.lock);
18562306a36Sopenharmony_ci	return rc;
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ciint cn10k_alloc_leaf_profile(struct otx2_nic *pfvf, u16 *leaf)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	struct nix_bandprof_alloc_req *req;
19162306a36Sopenharmony_ci	struct nix_bandprof_alloc_rsp *rsp;
19262306a36Sopenharmony_ci	int rc;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	req = otx2_mbox_alloc_msg_nix_bandprof_alloc(&pfvf->mbox);
19562306a36Sopenharmony_ci	if (!req)
19662306a36Sopenharmony_ci		return  -ENOMEM;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	req->prof_count[BAND_PROF_LEAF_LAYER] = 1;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	rc = otx2_sync_mbox_msg(&pfvf->mbox);
20162306a36Sopenharmony_ci	if (rc)
20262306a36Sopenharmony_ci		goto out;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	rsp = (struct  nix_bandprof_alloc_rsp *)
20562306a36Sopenharmony_ci	       otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
20662306a36Sopenharmony_ci	if (!rsp->prof_count[BAND_PROF_LEAF_LAYER]) {
20762306a36Sopenharmony_ci		rc = -EIO;
20862306a36Sopenharmony_ci		goto out;
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	*leaf = rsp->prof_idx[BAND_PROF_LEAF_LAYER][0];
21262306a36Sopenharmony_ciout:
21362306a36Sopenharmony_ci	if (rc) {
21462306a36Sopenharmony_ci		dev_warn(pfvf->dev,
21562306a36Sopenharmony_ci			 "Failed to allocate ingress bandwidth policer\n");
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return rc;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ciint cn10k_alloc_matchall_ipolicer(struct otx2_nic *pfvf)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	struct otx2_hw *hw = &pfvf->hw;
22462306a36Sopenharmony_ci	int ret;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	mutex_lock(&pfvf->mbox.lock);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	ret = cn10k_alloc_leaf_profile(pfvf, &hw->matchall_ipolicer);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	mutex_unlock(&pfvf->mbox.lock);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	return ret;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci#define POLICER_TIMESTAMP	  1  /* 1 second */
23662306a36Sopenharmony_ci#define MAX_RATE_EXP		  22 /* Valid rate exponent range: 0 - 22 */
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic void cn10k_get_ingress_burst_cfg(u32 burst, u32 *burst_exp,
23962306a36Sopenharmony_ci					u32 *burst_mantissa)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	int tmp;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* Burst is calculated as
24462306a36Sopenharmony_ci	 * (1+[BURST_MANTISSA]/256)*2^[BURST_EXPONENT]
24562306a36Sopenharmony_ci	 * This is the upper limit on number tokens (bytes) that
24662306a36Sopenharmony_ci	 * can be accumulated in the bucket.
24762306a36Sopenharmony_ci	 */
24862306a36Sopenharmony_ci	*burst_exp = ilog2(burst);
24962306a36Sopenharmony_ci	if (burst < 256) {
25062306a36Sopenharmony_ci		/* No float: can't express mantissa in this case */
25162306a36Sopenharmony_ci		*burst_mantissa = 0;
25262306a36Sopenharmony_ci		return;
25362306a36Sopenharmony_ci	}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (*burst_exp > MAX_RATE_EXP)
25662306a36Sopenharmony_ci		*burst_exp = MAX_RATE_EXP;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/* Calculate mantissa
25962306a36Sopenharmony_ci	 * Find remaining bytes 'burst - 2^burst_exp'
26062306a36Sopenharmony_ci	 * mantissa = (remaining bytes) / 2^ (burst_exp - 8)
26162306a36Sopenharmony_ci	 */
26262306a36Sopenharmony_ci	tmp = burst - rounddown_pow_of_two(burst);
26362306a36Sopenharmony_ci	*burst_mantissa = tmp / (1UL << (*burst_exp - 8));
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic void cn10k_get_ingress_rate_cfg(u64 rate, u32 *rate_exp,
26762306a36Sopenharmony_ci				       u32 *rate_mantissa, u32 *rdiv)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	u32 div = 0;
27062306a36Sopenharmony_ci	u32 exp = 0;
27162306a36Sopenharmony_ci	u64 tmp;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	/* Figure out mantissa, exponent and divider from given max pkt rate
27462306a36Sopenharmony_ci	 *
27562306a36Sopenharmony_ci	 * To achieve desired rate HW adds
27662306a36Sopenharmony_ci	 * (1+[RATE_MANTISSA]/256)*2^[RATE_EXPONENT] tokens (bytes) at every
27762306a36Sopenharmony_ci	 * policer timeunit * 2^rdiv ie 2 * 2^rdiv usecs, to the token bucket.
27862306a36Sopenharmony_ci	 * Here policer timeunit is 2 usecs and rate is in bits per sec.
27962306a36Sopenharmony_ci	 * Since floating point cannot be used below algorithm uses 1000000
28062306a36Sopenharmony_ci	 * scale factor to support rates upto 100Gbps.
28162306a36Sopenharmony_ci	 */
28262306a36Sopenharmony_ci	tmp = rate * 32 * 2;
28362306a36Sopenharmony_ci	if (tmp < 256000000) {
28462306a36Sopenharmony_ci		while (tmp < 256000000) {
28562306a36Sopenharmony_ci			tmp = tmp * 2;
28662306a36Sopenharmony_ci			div++;
28762306a36Sopenharmony_ci		}
28862306a36Sopenharmony_ci	} else {
28962306a36Sopenharmony_ci		for (exp = 0; tmp >= 512000000 && exp <= MAX_RATE_EXP; exp++)
29062306a36Sopenharmony_ci			tmp = tmp / 2;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		if (exp > MAX_RATE_EXP)
29362306a36Sopenharmony_ci			exp = MAX_RATE_EXP;
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	*rate_mantissa = (tmp - 256000000) / 1000000;
29762306a36Sopenharmony_ci	*rate_exp = exp;
29862306a36Sopenharmony_ci	*rdiv = div;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ciint cn10k_map_unmap_rq_policer(struct otx2_nic *pfvf, int rq_idx,
30262306a36Sopenharmony_ci			       u16 policer, bool map)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	struct nix_cn10k_aq_enq_req *aq;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
30762306a36Sopenharmony_ci	if (!aq)
30862306a36Sopenharmony_ci		return -ENOMEM;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* Enable policing and set the bandwidth profile (policer) index */
31162306a36Sopenharmony_ci	if (map)
31262306a36Sopenharmony_ci		aq->rq.policer_ena = 1;
31362306a36Sopenharmony_ci	else
31462306a36Sopenharmony_ci		aq->rq.policer_ena = 0;
31562306a36Sopenharmony_ci	aq->rq_mask.policer_ena = 1;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	aq->rq.band_prof_id = policer;
31862306a36Sopenharmony_ci	aq->rq_mask.band_prof_id = GENMASK(9, 0);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/* Fill AQ info */
32162306a36Sopenharmony_ci	aq->qidx = rq_idx;
32262306a36Sopenharmony_ci	aq->ctype = NIX_AQ_CTYPE_RQ;
32362306a36Sopenharmony_ci	aq->op = NIX_AQ_INSTOP_WRITE;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	return otx2_sync_mbox_msg(&pfvf->mbox);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ciint cn10k_free_leaf_profile(struct otx2_nic *pfvf, u16 leaf)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	struct nix_bandprof_free_req *req;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	req = otx2_mbox_alloc_msg_nix_bandprof_free(&pfvf->mbox);
33362306a36Sopenharmony_ci	if (!req)
33462306a36Sopenharmony_ci		return -ENOMEM;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	req->prof_count[BAND_PROF_LEAF_LAYER] = 1;
33762306a36Sopenharmony_ci	req->prof_idx[BAND_PROF_LEAF_LAYER][0] = leaf;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	return otx2_sync_mbox_msg(&pfvf->mbox);
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ciint cn10k_free_matchall_ipolicer(struct otx2_nic *pfvf)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	struct otx2_hw *hw = &pfvf->hw;
34562306a36Sopenharmony_ci	int qidx, rc;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	mutex_lock(&pfvf->mbox.lock);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	/* Remove RQ's policer mapping */
35062306a36Sopenharmony_ci	for (qidx = 0; qidx < hw->rx_queues; qidx++)
35162306a36Sopenharmony_ci		cn10k_map_unmap_rq_policer(pfvf, qidx,
35262306a36Sopenharmony_ci					   hw->matchall_ipolicer, false);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	rc = cn10k_free_leaf_profile(pfvf, hw->matchall_ipolicer);
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	mutex_unlock(&pfvf->mbox.lock);
35762306a36Sopenharmony_ci	return rc;
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ciint cn10k_set_ipolicer_rate(struct otx2_nic *pfvf, u16 profile,
36162306a36Sopenharmony_ci			    u32 burst, u64 rate, bool pps)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	struct nix_cn10k_aq_enq_req *aq;
36462306a36Sopenharmony_ci	u32 burst_exp, burst_mantissa;
36562306a36Sopenharmony_ci	u32 rate_exp, rate_mantissa;
36662306a36Sopenharmony_ci	u32 rdiv;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	/* Get exponent and mantissa values for the desired rate */
36962306a36Sopenharmony_ci	cn10k_get_ingress_burst_cfg(burst, &burst_exp, &burst_mantissa);
37062306a36Sopenharmony_ci	cn10k_get_ingress_rate_cfg(rate, &rate_exp, &rate_mantissa, &rdiv);
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	/* Init bandwidth profile */
37362306a36Sopenharmony_ci	aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
37462306a36Sopenharmony_ci	if (!aq)
37562306a36Sopenharmony_ci		return -ENOMEM;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* Set initial color mode to blind */
37862306a36Sopenharmony_ci	aq->prof.icolor = 0x03;
37962306a36Sopenharmony_ci	aq->prof_mask.icolor = 0x03;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	/* Set rate and burst values */
38262306a36Sopenharmony_ci	aq->prof.cir_exponent = rate_exp;
38362306a36Sopenharmony_ci	aq->prof_mask.cir_exponent = 0x1F;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	aq->prof.cir_mantissa = rate_mantissa;
38662306a36Sopenharmony_ci	aq->prof_mask.cir_mantissa = 0xFF;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	aq->prof.cbs_exponent = burst_exp;
38962306a36Sopenharmony_ci	aq->prof_mask.cbs_exponent = 0x1F;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	aq->prof.cbs_mantissa = burst_mantissa;
39262306a36Sopenharmony_ci	aq->prof_mask.cbs_mantissa = 0xFF;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	aq->prof.rdiv = rdiv;
39562306a36Sopenharmony_ci	aq->prof_mask.rdiv = 0xF;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	if (pps) {
39862306a36Sopenharmony_ci		/* The amount of decremented tokens is calculated according to
39962306a36Sopenharmony_ci		 * the following equation:
40062306a36Sopenharmony_ci		 * max([ LMODE ? 0 : (packet_length - LXPTR)] +
40162306a36Sopenharmony_ci		 *	     ([ADJUST_MANTISSA]/256 - 1) * 2^[ADJUST_EXPONENT],
40262306a36Sopenharmony_ci		 *	1/256)
40362306a36Sopenharmony_ci		 * if LMODE is 1 then rate limiting will be based on
40462306a36Sopenharmony_ci		 * PPS otherwise bps.
40562306a36Sopenharmony_ci		 * The aim of the ADJUST value is to specify a token cost per
40662306a36Sopenharmony_ci		 * packet in contrary to the packet length that specifies a
40762306a36Sopenharmony_ci		 * cost per byte. To rate limit based on PPS adjust mantissa
40862306a36Sopenharmony_ci		 * is set as 384 and exponent as 1 so that number of tokens
40962306a36Sopenharmony_ci		 * decremented becomes 1 i.e, 1 token per packeet.
41062306a36Sopenharmony_ci		 */
41162306a36Sopenharmony_ci		aq->prof.adjust_exponent = 1;
41262306a36Sopenharmony_ci		aq->prof_mask.adjust_exponent = 0x1F;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci		aq->prof.adjust_mantissa = 384;
41562306a36Sopenharmony_ci		aq->prof_mask.adjust_mantissa = 0x1FF;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci		aq->prof.lmode = 0x1;
41862306a36Sopenharmony_ci		aq->prof_mask.lmode = 0x1;
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	/* Two rate three color marker
42262306a36Sopenharmony_ci	 * With PEIR/EIR set to zero, color will be either green or red
42362306a36Sopenharmony_ci	 */
42462306a36Sopenharmony_ci	aq->prof.meter_algo = 2;
42562306a36Sopenharmony_ci	aq->prof_mask.meter_algo = 0x3;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	aq->prof.rc_action = NIX_RX_BAND_PROF_ACTIONRESULT_DROP;
42862306a36Sopenharmony_ci	aq->prof_mask.rc_action = 0x3;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	aq->prof.yc_action = NIX_RX_BAND_PROF_ACTIONRESULT_PASS;
43162306a36Sopenharmony_ci	aq->prof_mask.yc_action = 0x3;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	aq->prof.gc_action = NIX_RX_BAND_PROF_ACTIONRESULT_PASS;
43462306a36Sopenharmony_ci	aq->prof_mask.gc_action = 0x3;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	/* Setting exponent value as 24 and mantissa as 0 configures
43762306a36Sopenharmony_ci	 * the bucket with zero values making bucket unused. Peak
43862306a36Sopenharmony_ci	 * information rate and Excess information rate buckets are
43962306a36Sopenharmony_ci	 * unused here.
44062306a36Sopenharmony_ci	 */
44162306a36Sopenharmony_ci	aq->prof.peir_exponent = 24;
44262306a36Sopenharmony_ci	aq->prof_mask.peir_exponent = 0x1F;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	aq->prof.peir_mantissa = 0;
44562306a36Sopenharmony_ci	aq->prof_mask.peir_mantissa = 0xFF;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	aq->prof.pebs_exponent = 24;
44862306a36Sopenharmony_ci	aq->prof_mask.pebs_exponent = 0x1F;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	aq->prof.pebs_mantissa = 0;
45162306a36Sopenharmony_ci	aq->prof_mask.pebs_mantissa = 0xFF;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	aq->prof.hl_en = 0;
45462306a36Sopenharmony_ci	aq->prof_mask.hl_en = 1;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	/* Fill AQ info */
45762306a36Sopenharmony_ci	aq->qidx = profile;
45862306a36Sopenharmony_ci	aq->ctype = NIX_AQ_CTYPE_BANDPROF;
45962306a36Sopenharmony_ci	aq->op = NIX_AQ_INSTOP_WRITE;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	return otx2_sync_mbox_msg(&pfvf->mbox);
46262306a36Sopenharmony_ci}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ciint cn10k_set_matchall_ipolicer_rate(struct otx2_nic *pfvf,
46562306a36Sopenharmony_ci				     u32 burst, u64 rate)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	struct otx2_hw *hw = &pfvf->hw;
46862306a36Sopenharmony_ci	int qidx, rc;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	mutex_lock(&pfvf->mbox.lock);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	rc = cn10k_set_ipolicer_rate(pfvf, hw->matchall_ipolicer, burst,
47362306a36Sopenharmony_ci				     rate, false);
47462306a36Sopenharmony_ci	if (rc)
47562306a36Sopenharmony_ci		goto out;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	for (qidx = 0; qidx < hw->rx_queues; qidx++) {
47862306a36Sopenharmony_ci		rc = cn10k_map_unmap_rq_policer(pfvf, qidx,
47962306a36Sopenharmony_ci						hw->matchall_ipolicer, true);
48062306a36Sopenharmony_ci		if (rc)
48162306a36Sopenharmony_ci			break;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ciout:
48562306a36Sopenharmony_ci	mutex_unlock(&pfvf->mbox.lock);
48662306a36Sopenharmony_ci	return rc;
48762306a36Sopenharmony_ci}
488