162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* Copyright (C) 2020 Marvell. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "otx2_cpt_common.h"
562306a36Sopenharmony_ci#include "otx2_cptlf.h"
662306a36Sopenharmony_ci#include "rvu_reg.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define CPT_TIMER_HOLD 0x03F
962306a36Sopenharmony_ci#define CPT_COUNT_HOLD 32
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic void cptlf_do_set_done_time_wait(struct otx2_cptlf_info *lf,
1262306a36Sopenharmony_ci					int time_wait)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	union otx2_cptx_lf_done_wait done_wait;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
1762306a36Sopenharmony_ci				      lf->slot, OTX2_CPT_LF_DONE_WAIT);
1862306a36Sopenharmony_ci	done_wait.s.time_wait = time_wait;
1962306a36Sopenharmony_ci	otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
2062306a36Sopenharmony_ci			 OTX2_CPT_LF_DONE_WAIT, done_wait.u);
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic void cptlf_do_set_done_num_wait(struct otx2_cptlf_info *lf, int num_wait)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	union otx2_cptx_lf_done_wait done_wait;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
2862306a36Sopenharmony_ci				      lf->slot, OTX2_CPT_LF_DONE_WAIT);
2962306a36Sopenharmony_ci	done_wait.s.num_wait = num_wait;
3062306a36Sopenharmony_ci	otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
3162306a36Sopenharmony_ci			 OTX2_CPT_LF_DONE_WAIT, done_wait.u);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic void cptlf_set_done_time_wait(struct otx2_cptlfs_info *lfs,
3562306a36Sopenharmony_ci				     int time_wait)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	int slot;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++)
4062306a36Sopenharmony_ci		cptlf_do_set_done_time_wait(&lfs->lf[slot], time_wait);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic void cptlf_set_done_num_wait(struct otx2_cptlfs_info *lfs, int num_wait)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	int slot;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++)
4862306a36Sopenharmony_ci		cptlf_do_set_done_num_wait(&lfs->lf[slot], num_wait);
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic int cptlf_set_pri(struct otx2_cptlf_info *lf, int pri)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct otx2_cptlfs_info *lfs = lf->lfs;
5462306a36Sopenharmony_ci	union otx2_cptx_af_lf_ctrl lf_ctrl;
5562306a36Sopenharmony_ci	int ret;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	ret = otx2_cpt_read_af_reg(lfs->mbox, lfs->pdev,
5862306a36Sopenharmony_ci				   CPT_AF_LFX_CTL(lf->slot),
5962306a36Sopenharmony_ci				   &lf_ctrl.u, lfs->blkaddr);
6062306a36Sopenharmony_ci	if (ret)
6162306a36Sopenharmony_ci		return ret;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	lf_ctrl.s.pri = pri ? 1 : 0;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	ret = otx2_cpt_write_af_reg(lfs->mbox, lfs->pdev,
6662306a36Sopenharmony_ci				    CPT_AF_LFX_CTL(lf->slot),
6762306a36Sopenharmony_ci				    lf_ctrl.u, lfs->blkaddr);
6862306a36Sopenharmony_ci	return ret;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic int cptlf_set_eng_grps_mask(struct otx2_cptlf_info *lf,
7262306a36Sopenharmony_ci				   int eng_grps_mask)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	struct otx2_cptlfs_info *lfs = lf->lfs;
7562306a36Sopenharmony_ci	union otx2_cptx_af_lf_ctrl lf_ctrl;
7662306a36Sopenharmony_ci	int ret;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	ret = otx2_cpt_read_af_reg(lfs->mbox, lfs->pdev,
7962306a36Sopenharmony_ci				   CPT_AF_LFX_CTL(lf->slot),
8062306a36Sopenharmony_ci				   &lf_ctrl.u, lfs->blkaddr);
8162306a36Sopenharmony_ci	if (ret)
8262306a36Sopenharmony_ci		return ret;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	lf_ctrl.s.grp = eng_grps_mask;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	ret = otx2_cpt_write_af_reg(lfs->mbox, lfs->pdev,
8762306a36Sopenharmony_ci				    CPT_AF_LFX_CTL(lf->slot),
8862306a36Sopenharmony_ci				    lf_ctrl.u, lfs->blkaddr);
8962306a36Sopenharmony_ci	return ret;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic int cptlf_set_grp_and_pri(struct otx2_cptlfs_info *lfs,
9362306a36Sopenharmony_ci				 int eng_grp_mask, int pri)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	int slot, ret = 0;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++) {
9862306a36Sopenharmony_ci		ret = cptlf_set_pri(&lfs->lf[slot], pri);
9962306a36Sopenharmony_ci		if (ret)
10062306a36Sopenharmony_ci			return ret;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci		ret = cptlf_set_eng_grps_mask(&lfs->lf[slot], eng_grp_mask);
10362306a36Sopenharmony_ci		if (ret)
10462306a36Sopenharmony_ci			return ret;
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci	return ret;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic void cptlf_hw_init(struct otx2_cptlfs_info *lfs)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	/* Disable instruction queues */
11262306a36Sopenharmony_ci	otx2_cptlf_disable_iqueues(lfs);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	/* Set instruction queues base addresses */
11562306a36Sopenharmony_ci	otx2_cptlf_set_iqueues_base_addr(lfs);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	/* Set instruction queues sizes */
11862306a36Sopenharmony_ci	otx2_cptlf_set_iqueues_size(lfs);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	/* Set done interrupts time wait */
12162306a36Sopenharmony_ci	cptlf_set_done_time_wait(lfs, CPT_TIMER_HOLD);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	/* Set done interrupts num wait */
12462306a36Sopenharmony_ci	cptlf_set_done_num_wait(lfs, CPT_COUNT_HOLD);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* Enable instruction queues */
12762306a36Sopenharmony_ci	otx2_cptlf_enable_iqueues(lfs);
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic void cptlf_hw_cleanup(struct otx2_cptlfs_info *lfs)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	/* Disable instruction queues */
13362306a36Sopenharmony_ci	otx2_cptlf_disable_iqueues(lfs);
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic void cptlf_set_misc_intrs(struct otx2_cptlfs_info *lfs, u8 enable)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	union otx2_cptx_lf_misc_int_ena_w1s irq_misc = { .u = 0x0 };
13962306a36Sopenharmony_ci	u64 reg = enable ? OTX2_CPT_LF_MISC_INT_ENA_W1S :
14062306a36Sopenharmony_ci			   OTX2_CPT_LF_MISC_INT_ENA_W1C;
14162306a36Sopenharmony_ci	int slot;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	irq_misc.s.fault = 0x1;
14462306a36Sopenharmony_ci	irq_misc.s.hwerr = 0x1;
14562306a36Sopenharmony_ci	irq_misc.s.irde = 0x1;
14662306a36Sopenharmony_ci	irq_misc.s.nqerr = 0x1;
14762306a36Sopenharmony_ci	irq_misc.s.nwrp = 0x1;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++)
15062306a36Sopenharmony_ci		otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, reg,
15162306a36Sopenharmony_ci				 irq_misc.u);
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic void cptlf_enable_intrs(struct otx2_cptlfs_info *lfs)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	int slot;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	/* Enable done interrupts */
15962306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++)
16062306a36Sopenharmony_ci		otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot,
16162306a36Sopenharmony_ci				 OTX2_CPT_LF_DONE_INT_ENA_W1S, 0x1);
16262306a36Sopenharmony_ci	/* Enable Misc interrupts */
16362306a36Sopenharmony_ci	cptlf_set_misc_intrs(lfs, true);
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic void cptlf_disable_intrs(struct otx2_cptlfs_info *lfs)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	int slot;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++)
17162306a36Sopenharmony_ci		otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot,
17262306a36Sopenharmony_ci				 OTX2_CPT_LF_DONE_INT_ENA_W1C, 0x1);
17362306a36Sopenharmony_ci	cptlf_set_misc_intrs(lfs, false);
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic inline int cptlf_read_done_cnt(struct otx2_cptlf_info *lf)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	union otx2_cptx_lf_done irq_cnt;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
18162306a36Sopenharmony_ci				    OTX2_CPT_LF_DONE);
18262306a36Sopenharmony_ci	return irq_cnt.s.done;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	union otx2_cptx_lf_misc_int irq_misc, irq_misc_ack;
18862306a36Sopenharmony_ci	struct otx2_cptlf_info *lf = arg;
18962306a36Sopenharmony_ci	struct device *dev;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	dev = &lf->lfs->pdev->dev;
19262306a36Sopenharmony_ci	irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
19362306a36Sopenharmony_ci				     lf->slot, OTX2_CPT_LF_MISC_INT);
19462306a36Sopenharmony_ci	irq_misc_ack.u = 0x0;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (irq_misc.s.fault) {
19762306a36Sopenharmony_ci		dev_err(dev, "Memory error detected while executing CPT_INST_S, LF %d.\n",
19862306a36Sopenharmony_ci			lf->slot);
19962306a36Sopenharmony_ci		irq_misc_ack.s.fault = 0x1;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	} else if (irq_misc.s.hwerr) {
20262306a36Sopenharmony_ci		dev_err(dev, "HW error from an engine executing CPT_INST_S, LF %d.",
20362306a36Sopenharmony_ci			lf->slot);
20462306a36Sopenharmony_ci		irq_misc_ack.s.hwerr = 0x1;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	} else if (irq_misc.s.nwrp) {
20762306a36Sopenharmony_ci		dev_err(dev, "SMMU fault while writing CPT_RES_S to CPT_INST_S[RES_ADDR], LF %d.\n",
20862306a36Sopenharmony_ci			lf->slot);
20962306a36Sopenharmony_ci		irq_misc_ack.s.nwrp = 0x1;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	} else if (irq_misc.s.irde) {
21262306a36Sopenharmony_ci		dev_err(dev, "Memory error when accessing instruction memory queue CPT_LF_Q_BASE[ADDR].\n");
21362306a36Sopenharmony_ci		irq_misc_ack.s.irde = 0x1;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	} else if (irq_misc.s.nqerr) {
21662306a36Sopenharmony_ci		dev_err(dev, "Error enqueuing an instruction received at CPT_LF_NQ.\n");
21762306a36Sopenharmony_ci		irq_misc_ack.s.nqerr = 0x1;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	} else {
22062306a36Sopenharmony_ci		dev_err(dev, "Unhandled interrupt in CPT LF %d\n", lf->slot);
22162306a36Sopenharmony_ci		return IRQ_NONE;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/* Acknowledge interrupts */
22562306a36Sopenharmony_ci	otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
22662306a36Sopenharmony_ci			 OTX2_CPT_LF_MISC_INT, irq_misc_ack.u);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	return IRQ_HANDLED;
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic irqreturn_t cptlf_done_intr_handler(int irq, void *arg)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	union otx2_cptx_lf_done_wait done_wait;
23462306a36Sopenharmony_ci	struct otx2_cptlf_info *lf = arg;
23562306a36Sopenharmony_ci	int irq_cnt;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* Read the number of completed requests */
23862306a36Sopenharmony_ci	irq_cnt = cptlf_read_done_cnt(lf);
23962306a36Sopenharmony_ci	if (irq_cnt) {
24062306a36Sopenharmony_ci		done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr,
24162306a36Sopenharmony_ci					      lf->slot, OTX2_CPT_LF_DONE_WAIT);
24262306a36Sopenharmony_ci		/* Acknowledge the number of completed requests */
24362306a36Sopenharmony_ci		otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
24462306a36Sopenharmony_ci				 OTX2_CPT_LF_DONE_ACK, irq_cnt);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot,
24762306a36Sopenharmony_ci				 OTX2_CPT_LF_DONE_WAIT, done_wait.u);
24862306a36Sopenharmony_ci		if (unlikely(!lf->wqe)) {
24962306a36Sopenharmony_ci			dev_err(&lf->lfs->pdev->dev, "No work for LF %d\n",
25062306a36Sopenharmony_ci				lf->slot);
25162306a36Sopenharmony_ci			return IRQ_NONE;
25262306a36Sopenharmony_ci		}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		/* Schedule processing of completed requests */
25562306a36Sopenharmony_ci		tasklet_hi_schedule(&lf->wqe->work);
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci	return IRQ_HANDLED;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_civoid otx2_cptlf_unregister_interrupts(struct otx2_cptlfs_info *lfs)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	int i, offs, vector;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	for (i = 0; i < lfs->lfs_num; i++) {
26562306a36Sopenharmony_ci		for (offs = 0; offs < OTX2_CPT_LF_MSIX_VECTORS; offs++) {
26662306a36Sopenharmony_ci			if (!lfs->lf[i].is_irq_reg[offs])
26762306a36Sopenharmony_ci				continue;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci			vector = pci_irq_vector(lfs->pdev,
27062306a36Sopenharmony_ci						lfs->lf[i].msix_offset + offs);
27162306a36Sopenharmony_ci			free_irq(vector, &lfs->lf[i]);
27262306a36Sopenharmony_ci			lfs->lf[i].is_irq_reg[offs] = false;
27362306a36Sopenharmony_ci		}
27462306a36Sopenharmony_ci	}
27562306a36Sopenharmony_ci	cptlf_disable_intrs(lfs);
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(otx2_cptlf_unregister_interrupts,
27862306a36Sopenharmony_ci		     CRYPTO_DEV_OCTEONTX2_CPT);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic int cptlf_do_register_interrrupts(struct otx2_cptlfs_info *lfs,
28162306a36Sopenharmony_ci					 int lf_num, int irq_offset,
28262306a36Sopenharmony_ci					 irq_handler_t handler)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	int ret, vector;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	vector = pci_irq_vector(lfs->pdev, lfs->lf[lf_num].msix_offset +
28762306a36Sopenharmony_ci				irq_offset);
28862306a36Sopenharmony_ci	ret = request_irq(vector, handler, 0,
28962306a36Sopenharmony_ci			  lfs->lf[lf_num].irq_name[irq_offset],
29062306a36Sopenharmony_ci			  &lfs->lf[lf_num]);
29162306a36Sopenharmony_ci	if (ret)
29262306a36Sopenharmony_ci		return ret;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	lfs->lf[lf_num].is_irq_reg[irq_offset] = true;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return ret;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ciint otx2_cptlf_register_interrupts(struct otx2_cptlfs_info *lfs)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	int irq_offs, ret, i;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	for (i = 0; i < lfs->lfs_num; i++) {
30462306a36Sopenharmony_ci		irq_offs = OTX2_CPT_LF_INT_VEC_E_MISC;
30562306a36Sopenharmony_ci		snprintf(lfs->lf[i].irq_name[irq_offs], 32, "CPTLF Misc%d", i);
30662306a36Sopenharmony_ci		ret = cptlf_do_register_interrrupts(lfs, i, irq_offs,
30762306a36Sopenharmony_ci						    cptlf_misc_intr_handler);
30862306a36Sopenharmony_ci		if (ret)
30962306a36Sopenharmony_ci			goto free_irq;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci		irq_offs = OTX2_CPT_LF_INT_VEC_E_DONE;
31262306a36Sopenharmony_ci		snprintf(lfs->lf[i].irq_name[irq_offs], 32, "OTX2_CPTLF Done%d",
31362306a36Sopenharmony_ci			 i);
31462306a36Sopenharmony_ci		ret = cptlf_do_register_interrrupts(lfs, i, irq_offs,
31562306a36Sopenharmony_ci						    cptlf_done_intr_handler);
31662306a36Sopenharmony_ci		if (ret)
31762306a36Sopenharmony_ci			goto free_irq;
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci	cptlf_enable_intrs(lfs);
32062306a36Sopenharmony_ci	return 0;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cifree_irq:
32362306a36Sopenharmony_ci	otx2_cptlf_unregister_interrupts(lfs);
32462306a36Sopenharmony_ci	return ret;
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(otx2_cptlf_register_interrupts, CRYPTO_DEV_OCTEONTX2_CPT);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_civoid otx2_cptlf_free_irqs_affinity(struct otx2_cptlfs_info *lfs)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	int slot, offs;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++) {
33362306a36Sopenharmony_ci		for (offs = 0; offs < OTX2_CPT_LF_MSIX_VECTORS; offs++)
33462306a36Sopenharmony_ci			irq_set_affinity_hint(pci_irq_vector(lfs->pdev,
33562306a36Sopenharmony_ci					      lfs->lf[slot].msix_offset +
33662306a36Sopenharmony_ci					      offs), NULL);
33762306a36Sopenharmony_ci		free_cpumask_var(lfs->lf[slot].affinity_mask);
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(otx2_cptlf_free_irqs_affinity, CRYPTO_DEV_OCTEONTX2_CPT);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ciint otx2_cptlf_set_irqs_affinity(struct otx2_cptlfs_info *lfs)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	struct otx2_cptlf_info *lf = lfs->lf;
34562306a36Sopenharmony_ci	int slot, offs, ret;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++) {
34862306a36Sopenharmony_ci		if (!zalloc_cpumask_var(&lf[slot].affinity_mask, GFP_KERNEL)) {
34962306a36Sopenharmony_ci			dev_err(&lfs->pdev->dev,
35062306a36Sopenharmony_ci				"cpumask allocation failed for LF %d", slot);
35162306a36Sopenharmony_ci			ret = -ENOMEM;
35262306a36Sopenharmony_ci			goto free_affinity_mask;
35362306a36Sopenharmony_ci		}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		cpumask_set_cpu(cpumask_local_spread(slot,
35662306a36Sopenharmony_ci				dev_to_node(&lfs->pdev->dev)),
35762306a36Sopenharmony_ci				lf[slot].affinity_mask);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		for (offs = 0; offs < OTX2_CPT_LF_MSIX_VECTORS; offs++) {
36062306a36Sopenharmony_ci			ret = irq_set_affinity_hint(pci_irq_vector(lfs->pdev,
36162306a36Sopenharmony_ci						lf[slot].msix_offset + offs),
36262306a36Sopenharmony_ci						lf[slot].affinity_mask);
36362306a36Sopenharmony_ci			if (ret)
36462306a36Sopenharmony_ci				goto free_affinity_mask;
36562306a36Sopenharmony_ci		}
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci	return 0;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cifree_affinity_mask:
37062306a36Sopenharmony_ci	otx2_cptlf_free_irqs_affinity(lfs);
37162306a36Sopenharmony_ci	return ret;
37262306a36Sopenharmony_ci}
37362306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(otx2_cptlf_set_irqs_affinity, CRYPTO_DEV_OCTEONTX2_CPT);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ciint otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_mask, int pri,
37662306a36Sopenharmony_ci		    int lfs_num)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	int slot, ret;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	if (!lfs->pdev || !lfs->reg_base)
38162306a36Sopenharmony_ci		return -EINVAL;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	lfs->lfs_num = lfs_num;
38462306a36Sopenharmony_ci	for (slot = 0; slot < lfs->lfs_num; slot++) {
38562306a36Sopenharmony_ci		lfs->lf[slot].lfs = lfs;
38662306a36Sopenharmony_ci		lfs->lf[slot].slot = slot;
38762306a36Sopenharmony_ci		if (lfs->lmt_base)
38862306a36Sopenharmony_ci			lfs->lf[slot].lmtline = lfs->lmt_base +
38962306a36Sopenharmony_ci						(slot * LMTLINE_SIZE);
39062306a36Sopenharmony_ci		else
39162306a36Sopenharmony_ci			lfs->lf[slot].lmtline = lfs->reg_base +
39262306a36Sopenharmony_ci				OTX2_CPT_RVU_FUNC_ADDR_S(BLKADDR_LMT, slot,
39362306a36Sopenharmony_ci						 OTX2_CPT_LMT_LF_LMTLINEX(0));
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci		lfs->lf[slot].ioreg = lfs->reg_base +
39662306a36Sopenharmony_ci			OTX2_CPT_RVU_FUNC_ADDR_S(lfs->blkaddr, slot,
39762306a36Sopenharmony_ci						 OTX2_CPT_LF_NQX(0));
39862306a36Sopenharmony_ci	}
39962306a36Sopenharmony_ci	/* Send request to attach LFs */
40062306a36Sopenharmony_ci	ret = otx2_cpt_attach_rscrs_msg(lfs);
40162306a36Sopenharmony_ci	if (ret)
40262306a36Sopenharmony_ci		goto clear_lfs_num;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	ret = otx2_cpt_alloc_instruction_queues(lfs);
40562306a36Sopenharmony_ci	if (ret) {
40662306a36Sopenharmony_ci		dev_err(&lfs->pdev->dev,
40762306a36Sopenharmony_ci			"Allocating instruction queues failed\n");
40862306a36Sopenharmony_ci		goto detach_rsrcs;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci	cptlf_hw_init(lfs);
41162306a36Sopenharmony_ci	/*
41262306a36Sopenharmony_ci	 * Allow each LF to execute requests destined to any of 8 engine
41362306a36Sopenharmony_ci	 * groups and set queue priority of each LF to high
41462306a36Sopenharmony_ci	 */
41562306a36Sopenharmony_ci	ret = cptlf_set_grp_and_pri(lfs, eng_grp_mask, pri);
41662306a36Sopenharmony_ci	if (ret)
41762306a36Sopenharmony_ci		goto free_iq;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	return 0;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cifree_iq:
42262306a36Sopenharmony_ci	cptlf_hw_cleanup(lfs);
42362306a36Sopenharmony_ci	otx2_cpt_free_instruction_queues(lfs);
42462306a36Sopenharmony_cidetach_rsrcs:
42562306a36Sopenharmony_ci	otx2_cpt_detach_rsrcs_msg(lfs);
42662306a36Sopenharmony_ciclear_lfs_num:
42762306a36Sopenharmony_ci	lfs->lfs_num = 0;
42862306a36Sopenharmony_ci	return ret;
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(otx2_cptlf_init, CRYPTO_DEV_OCTEONTX2_CPT);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_civoid otx2_cptlf_shutdown(struct otx2_cptlfs_info *lfs)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	/* Cleanup LFs hardware side */
43562306a36Sopenharmony_ci	cptlf_hw_cleanup(lfs);
43662306a36Sopenharmony_ci	/* Free instruction queues */
43762306a36Sopenharmony_ci	otx2_cpt_free_instruction_queues(lfs);
43862306a36Sopenharmony_ci	/* Send request to detach LFs */
43962306a36Sopenharmony_ci	otx2_cpt_detach_rsrcs_msg(lfs);
44062306a36Sopenharmony_ci	lfs->lfs_num = 0;
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(otx2_cptlf_shutdown, CRYPTO_DEV_OCTEONTX2_CPT);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ciMODULE_AUTHOR("Marvell");
44562306a36Sopenharmony_ciMODULE_DESCRIPTION("Marvell RVU CPT Common module");
44662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
447