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_cptpf.h"
662306a36Sopenharmony_ci#include "rvu_reg.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/* Fastpath ipsec opcode with inplace processing */
962306a36Sopenharmony_ci#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6))
1062306a36Sopenharmony_ci#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6))
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define cpt_inline_rx_opcode(pdev)                      \
1362306a36Sopenharmony_ci({                                                      \
1462306a36Sopenharmony_ci	u8 opcode;                                      \
1562306a36Sopenharmony_ci	if (is_dev_otx2(pdev))                          \
1662306a36Sopenharmony_ci		opcode = CPT_INLINE_RX_OPCODE;          \
1762306a36Sopenharmony_ci	else                                            \
1862306a36Sopenharmony_ci		opcode = CN10K_CPT_INLINE_RX_OPCODE;    \
1962306a36Sopenharmony_ci	(opcode);                                       \
2062306a36Sopenharmony_ci})
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/*
2362306a36Sopenharmony_ci * CPT PF driver version, It will be incremented by 1 for every feature
2462306a36Sopenharmony_ci * addition in CPT mailbox messages.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci#define OTX2_CPT_PF_DRV_VERSION 0x1
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int forward_to_af(struct otx2_cptpf_dev *cptpf,
2962306a36Sopenharmony_ci			 struct otx2_cptvf_info *vf,
3062306a36Sopenharmony_ci			 struct mbox_msghdr *req, int size)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct mbox_msghdr *msg;
3362306a36Sopenharmony_ci	int ret;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	mutex_lock(&cptpf->lock);
3662306a36Sopenharmony_ci	msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);
3762306a36Sopenharmony_ci	if (msg == NULL) {
3862306a36Sopenharmony_ci		mutex_unlock(&cptpf->lock);
3962306a36Sopenharmony_ci		return -ENOMEM;
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),
4362306a36Sopenharmony_ci	       (uint8_t *)req + sizeof(struct mbox_msghdr), size);
4462306a36Sopenharmony_ci	msg->id = req->id;
4562306a36Sopenharmony_ci	msg->pcifunc = req->pcifunc;
4662306a36Sopenharmony_ci	msg->sig = req->sig;
4762306a36Sopenharmony_ci	msg->ver = req->ver;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);
5062306a36Sopenharmony_ci	/* Error code -EIO indicate there is a communication failure
5162306a36Sopenharmony_ci	 * to the AF. Rest of the error codes indicate that AF processed
5262306a36Sopenharmony_ci	 * VF messages and set the error codes in response messages
5362306a36Sopenharmony_ci	 * (if any) so simply forward responses to VF.
5462306a36Sopenharmony_ci	 */
5562306a36Sopenharmony_ci	if (ret == -EIO) {
5662306a36Sopenharmony_ci		dev_warn(&cptpf->pdev->dev,
5762306a36Sopenharmony_ci			 "AF not responding to VF%d messages\n", vf->vf_id);
5862306a36Sopenharmony_ci		mutex_unlock(&cptpf->lock);
5962306a36Sopenharmony_ci		return ret;
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci	mutex_unlock(&cptpf->lock);
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,
6662306a36Sopenharmony_ci			       struct otx2_cptvf_info *vf,
6762306a36Sopenharmony_ci			       struct mbox_msghdr *req)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	struct otx2_cpt_caps_rsp *rsp;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	rsp = (struct otx2_cpt_caps_rsp *)
7262306a36Sopenharmony_ci	      otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,
7362306a36Sopenharmony_ci				  sizeof(*rsp));
7462306a36Sopenharmony_ci	if (!rsp)
7562306a36Sopenharmony_ci		return -ENOMEM;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	rsp->hdr.id = MBOX_MSG_GET_CAPS;
7862306a36Sopenharmony_ci	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
7962306a36Sopenharmony_ci	rsp->hdr.pcifunc = req->pcifunc;
8062306a36Sopenharmony_ci	rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;
8162306a36Sopenharmony_ci	rsp->cpt_revision = cptpf->pdev->revision;
8262306a36Sopenharmony_ci	memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	return 0;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,
8862306a36Sopenharmony_ci				      struct otx2_cptvf_info *vf,
8962306a36Sopenharmony_ci				      struct mbox_msghdr *req)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	struct otx2_cpt_egrp_num_msg *grp_req;
9262306a36Sopenharmony_ci	struct otx2_cpt_egrp_num_rsp *rsp;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	grp_req = (struct otx2_cpt_egrp_num_msg *)req;
9562306a36Sopenharmony_ci	rsp = (struct otx2_cpt_egrp_num_rsp *)
9662306a36Sopenharmony_ci	       otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
9762306a36Sopenharmony_ci	if (!rsp)
9862306a36Sopenharmony_ci		return -ENOMEM;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;
10162306a36Sopenharmony_ci	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
10262306a36Sopenharmony_ci	rsp->hdr.pcifunc = req->pcifunc;
10362306a36Sopenharmony_ci	rsp->eng_type = grp_req->eng_type;
10462306a36Sopenharmony_ci	rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,
10562306a36Sopenharmony_ci						grp_req->eng_type);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	return 0;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,
11162306a36Sopenharmony_ci				 struct otx2_cptvf_info *vf,
11262306a36Sopenharmony_ci				 struct mbox_msghdr *req)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	struct otx2_cpt_kvf_limits_rsp *rsp;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	rsp = (struct otx2_cpt_kvf_limits_rsp *)
11762306a36Sopenharmony_ci	      otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
11862306a36Sopenharmony_ci	if (!rsp)
11962306a36Sopenharmony_ci		return -ENOMEM;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;
12262306a36Sopenharmony_ci	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
12362306a36Sopenharmony_ci	rsp->hdr.pcifunc = req->pcifunc;
12462306a36Sopenharmony_ci	rsp->kvf_limits = cptpf->kvf_limits;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	return 0;
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf,
13062306a36Sopenharmony_ci					 int sso_pf_func, u8 slot)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct cpt_inline_ipsec_cfg_msg *req;
13362306a36Sopenharmony_ci	struct pci_dev *pdev = cptpf->pdev;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	req = (struct cpt_inline_ipsec_cfg_msg *)
13662306a36Sopenharmony_ci	      otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,
13762306a36Sopenharmony_ci				      sizeof(*req), sizeof(struct msg_rsp));
13862306a36Sopenharmony_ci	if (req == NULL) {
13962306a36Sopenharmony_ci		dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
14062306a36Sopenharmony_ci		return -EFAULT;
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci	memset(req, 0, sizeof(*req));
14362306a36Sopenharmony_ci	req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG;
14462306a36Sopenharmony_ci	req->hdr.sig = OTX2_MBOX_REQ_SIG;
14562306a36Sopenharmony_ci	req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0);
14662306a36Sopenharmony_ci	req->dir = CPT_INLINE_INBOUND;
14762306a36Sopenharmony_ci	req->slot = slot;
14862306a36Sopenharmony_ci	req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd;
14962306a36Sopenharmony_ci	req->sso_pf_func = sso_pf_func;
15062306a36Sopenharmony_ci	req->enable = 1;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp,
15662306a36Sopenharmony_ci				  struct otx2_cpt_rx_inline_lf_cfg *req)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	struct nix_inline_ipsec_cfg *nix_req;
15962306a36Sopenharmony_ci	struct pci_dev *pdev = cptpf->pdev;
16062306a36Sopenharmony_ci	int ret;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	nix_req = (struct nix_inline_ipsec_cfg *)
16362306a36Sopenharmony_ci		   otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,
16462306a36Sopenharmony_ci					   sizeof(*nix_req),
16562306a36Sopenharmony_ci					   sizeof(struct msg_rsp));
16662306a36Sopenharmony_ci	if (nix_req == NULL) {
16762306a36Sopenharmony_ci		dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
16862306a36Sopenharmony_ci		return -EFAULT;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	memset(nix_req, 0, sizeof(*nix_req));
17162306a36Sopenharmony_ci	nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG;
17262306a36Sopenharmony_ci	nix_req->hdr.sig = OTX2_MBOX_REQ_SIG;
17362306a36Sopenharmony_ci	nix_req->enable = 1;
17462306a36Sopenharmony_ci	if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS)
17562306a36Sopenharmony_ci		nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1;
17662306a36Sopenharmony_ci	else
17762306a36Sopenharmony_ci		nix_req->cpt_credit = req->credit - 1;
17862306a36Sopenharmony_ci	nix_req->gen_cfg.egrp = egrp;
17962306a36Sopenharmony_ci	if (req->opcode)
18062306a36Sopenharmony_ci		nix_req->gen_cfg.opcode = req->opcode;
18162306a36Sopenharmony_ci	else
18262306a36Sopenharmony_ci		nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev);
18362306a36Sopenharmony_ci	nix_req->gen_cfg.param1 = req->param1;
18462306a36Sopenharmony_ci	nix_req->gen_cfg.param2 = req->param2;
18562306a36Sopenharmony_ci	nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0);
18662306a36Sopenharmony_ci	nix_req->inst_qsel.cpt_slot = 0;
18762306a36Sopenharmony_ci	ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);
18862306a36Sopenharmony_ci	if (ret)
18962306a36Sopenharmony_ci		return ret;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if (cptpf->has_cpt1) {
19262306a36Sopenharmony_ci		ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1);
19362306a36Sopenharmony_ci		if (ret)
19462306a36Sopenharmony_ci			return ret;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0);
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,
20162306a36Sopenharmony_ci					     struct mbox_msghdr *req)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	struct otx2_cpt_rx_inline_lf_cfg *cfg_req;
20462306a36Sopenharmony_ci	u8 egrp;
20562306a36Sopenharmony_ci	int ret;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req;
20862306a36Sopenharmony_ci	if (cptpf->lfs.lfs_num) {
20962306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
21062306a36Sopenharmony_ci			"LF is already configured for RX inline ipsec.\n");
21162306a36Sopenharmony_ci		return -EEXIST;
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci	/*
21462306a36Sopenharmony_ci	 * Allow LFs to execute requests destined to only grp IE_TYPES and
21562306a36Sopenharmony_ci	 * set queue priority of each LF to high
21662306a36Sopenharmony_ci	 */
21762306a36Sopenharmony_ci	egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES);
21862306a36Sopenharmony_ci	if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {
21962306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
22062306a36Sopenharmony_ci			"Engine group for inline ipsec is not available\n");
22162306a36Sopenharmony_ci		return -ENOENT;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base,
22562306a36Sopenharmony_ci				&cptpf->afpf_mbox, BLKADDR_CPT0);
22662306a36Sopenharmony_ci	ret = otx2_cptlf_init(&cptpf->lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO,
22762306a36Sopenharmony_ci			      1);
22862306a36Sopenharmony_ci	if (ret) {
22962306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
23062306a36Sopenharmony_ci			"LF configuration failed for RX inline ipsec.\n");
23162306a36Sopenharmony_ci		return ret;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	if (cptpf->has_cpt1) {
23562306a36Sopenharmony_ci		cptpf->rsrc_req_blkaddr = BLKADDR_CPT1;
23662306a36Sopenharmony_ci		otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev,
23762306a36Sopenharmony_ci					cptpf->reg_base, &cptpf->afpf_mbox,
23862306a36Sopenharmony_ci					BLKADDR_CPT1);
23962306a36Sopenharmony_ci		ret = otx2_cptlf_init(&cptpf->cpt1_lfs, 1 << egrp,
24062306a36Sopenharmony_ci				      OTX2_CPT_QUEUE_HI_PRIO, 1);
24162306a36Sopenharmony_ci		if (ret) {
24262306a36Sopenharmony_ci			dev_err(&cptpf->pdev->dev,
24362306a36Sopenharmony_ci				"LF configuration failed for RX inline ipsec.\n");
24462306a36Sopenharmony_ci			goto lf_cleanup;
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci		cptpf->rsrc_req_blkaddr = 0;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req);
25062306a36Sopenharmony_ci	if (ret)
25162306a36Sopenharmony_ci		goto lf1_cleanup;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	return 0;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cilf1_cleanup:
25662306a36Sopenharmony_ci	otx2_cptlf_shutdown(&cptpf->cpt1_lfs);
25762306a36Sopenharmony_cilf_cleanup:
25862306a36Sopenharmony_ci	otx2_cptlf_shutdown(&cptpf->lfs);
25962306a36Sopenharmony_ci	return ret;
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
26362306a36Sopenharmony_ci			       struct otx2_cptvf_info *vf,
26462306a36Sopenharmony_ci			       struct mbox_msghdr *req, int size)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	int err = 0;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	/* Check if msg is valid, if not reply with an invalid msg */
26962306a36Sopenharmony_ci	if (req->sig != OTX2_MBOX_REQ_SIG)
27062306a36Sopenharmony_ci		goto inval_msg;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	switch (req->id) {
27362306a36Sopenharmony_ci	case MBOX_MSG_GET_ENG_GRP_NUM:
27462306a36Sopenharmony_ci		err = handle_msg_get_eng_grp_num(cptpf, vf, req);
27562306a36Sopenharmony_ci		break;
27662306a36Sopenharmony_ci	case MBOX_MSG_GET_CAPS:
27762306a36Sopenharmony_ci		err = handle_msg_get_caps(cptpf, vf, req);
27862306a36Sopenharmony_ci		break;
27962306a36Sopenharmony_ci	case MBOX_MSG_GET_KVF_LIMITS:
28062306a36Sopenharmony_ci		err = handle_msg_kvf_limits(cptpf, vf, req);
28162306a36Sopenharmony_ci		break;
28262306a36Sopenharmony_ci	case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG:
28362306a36Sopenharmony_ci		err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req);
28462306a36Sopenharmony_ci		break;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	default:
28762306a36Sopenharmony_ci		err = forward_to_af(cptpf, vf, req, size);
28862306a36Sopenharmony_ci		break;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci	return err;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ciinval_msg:
29362306a36Sopenharmony_ci	otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);
29462306a36Sopenharmony_ci	otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);
29562306a36Sopenharmony_ci	return err;
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ciirqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	struct otx2_cptpf_dev *cptpf = arg;
30162306a36Sopenharmony_ci	struct otx2_cptvf_info *vf;
30262306a36Sopenharmony_ci	int i, vf_idx;
30362306a36Sopenharmony_ci	u64 intr;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	/*
30662306a36Sopenharmony_ci	 * Check which VF has raised an interrupt and schedule
30762306a36Sopenharmony_ci	 * corresponding work queue to process the messages
30862306a36Sopenharmony_ci	 */
30962306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
31062306a36Sopenharmony_ci		/* Read the interrupt bits */
31162306a36Sopenharmony_ci		intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,
31262306a36Sopenharmony_ci				       RVU_PF_VFPF_MBOX_INTX(i));
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {
31562306a36Sopenharmony_ci			vf = &cptpf->vf[vf_idx];
31662306a36Sopenharmony_ci			if (intr & (1ULL << vf->intr_idx)) {
31762306a36Sopenharmony_ci				queue_work(cptpf->vfpf_mbox_wq,
31862306a36Sopenharmony_ci					   &vf->vfpf_mbox_work);
31962306a36Sopenharmony_ci				/* Clear the interrupt */
32062306a36Sopenharmony_ci				otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,
32162306a36Sopenharmony_ci						 0, RVU_PF_VFPF_MBOX_INTX(i),
32262306a36Sopenharmony_ci						 BIT_ULL(vf->intr_idx));
32362306a36Sopenharmony_ci			}
32462306a36Sopenharmony_ci		}
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci	return IRQ_HANDLED;
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_civoid otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	struct otx2_cptpf_dev *cptpf;
33262306a36Sopenharmony_ci	struct otx2_cptvf_info *vf;
33362306a36Sopenharmony_ci	struct otx2_mbox_dev *mdev;
33462306a36Sopenharmony_ci	struct mbox_hdr *req_hdr;
33562306a36Sopenharmony_ci	struct mbox_msghdr *msg;
33662306a36Sopenharmony_ci	struct otx2_mbox *mbox;
33762306a36Sopenharmony_ci	int offset, i, err;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);
34062306a36Sopenharmony_ci	cptpf = vf->cptpf;
34162306a36Sopenharmony_ci	mbox = &cptpf->vfpf_mbox;
34262306a36Sopenharmony_ci	/* sync with mbox memory region */
34362306a36Sopenharmony_ci	smp_rmb();
34462306a36Sopenharmony_ci	mdev = &mbox->dev[vf->vf_id];
34562306a36Sopenharmony_ci	/* Process received mbox messages */
34662306a36Sopenharmony_ci	req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
34762306a36Sopenharmony_ci	offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	for (i = 0; i < req_hdr->num_msgs; i++) {
35062306a36Sopenharmony_ci		msg = (struct mbox_msghdr *)(mdev->mbase + offset);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci		/* Set which VF sent this message based on mbox IRQ */
35362306a36Sopenharmony_ci		msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) |
35462306a36Sopenharmony_ci				((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK);
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci		err = cptpf_handle_vf_req(cptpf, vf, msg,
35762306a36Sopenharmony_ci					  msg->next_msgoff - offset);
35862306a36Sopenharmony_ci		/*
35962306a36Sopenharmony_ci		 * Behave as the AF, drop the msg if there is
36062306a36Sopenharmony_ci		 * no memory, timeout handling also goes here
36162306a36Sopenharmony_ci		 */
36262306a36Sopenharmony_ci		if (err == -ENOMEM || err == -EIO)
36362306a36Sopenharmony_ci			break;
36462306a36Sopenharmony_ci		offset = msg->next_msgoff;
36562306a36Sopenharmony_ci		/* Write barrier required for VF responses which are handled by
36662306a36Sopenharmony_ci		 * PF driver and not forwarded to AF.
36762306a36Sopenharmony_ci		 */
36862306a36Sopenharmony_ci		smp_wmb();
36962306a36Sopenharmony_ci	}
37062306a36Sopenharmony_ci	/* Send mbox responses to VF */
37162306a36Sopenharmony_ci	if (mdev->num_msgs)
37262306a36Sopenharmony_ci		otx2_mbox_msg_send(mbox, vf->vf_id);
37362306a36Sopenharmony_ci}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ciirqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	struct otx2_cptpf_dev *cptpf = arg;
37862306a36Sopenharmony_ci	struct otx2_mbox_dev *mdev;
37962306a36Sopenharmony_ci	struct otx2_mbox *mbox;
38062306a36Sopenharmony_ci	struct mbox_hdr *hdr;
38162306a36Sopenharmony_ci	u64 intr;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/* Read the interrupt bits */
38462306a36Sopenharmony_ci	intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (intr & 0x1ULL) {
38762306a36Sopenharmony_ci		mbox = &cptpf->afpf_mbox;
38862306a36Sopenharmony_ci		mdev = &mbox->dev[0];
38962306a36Sopenharmony_ci		hdr = mdev->mbase + mbox->rx_start;
39062306a36Sopenharmony_ci		if (hdr->num_msgs)
39162306a36Sopenharmony_ci			/* Schedule work queue function to process the MBOX request */
39262306a36Sopenharmony_ci			queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci		mbox = &cptpf->afpf_mbox_up;
39562306a36Sopenharmony_ci		mdev = &mbox->dev[0];
39662306a36Sopenharmony_ci		hdr = mdev->mbase + mbox->rx_start;
39762306a36Sopenharmony_ci		if (hdr->num_msgs)
39862306a36Sopenharmony_ci			/* Schedule work queue function to process the MBOX request */
39962306a36Sopenharmony_ci			queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work);
40062306a36Sopenharmony_ci		/* Clear and ack the interrupt */
40162306a36Sopenharmony_ci		otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,
40262306a36Sopenharmony_ci				 0x1ULL);
40362306a36Sopenharmony_ci	}
40462306a36Sopenharmony_ci	return IRQ_HANDLED;
40562306a36Sopenharmony_ci}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_cistatic void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
40862306a36Sopenharmony_ci				  struct mbox_msghdr *msg)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct otx2_cptlfs_info *lfs = &cptpf->lfs;
41162306a36Sopenharmony_ci	struct device *dev = &cptpf->pdev->dev;
41262306a36Sopenharmony_ci	struct cpt_rd_wr_reg_msg *rsp_rd_wr;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	if (msg->id >= MBOX_MSG_MAX) {
41562306a36Sopenharmony_ci		dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);
41662306a36Sopenharmony_ci		return;
41762306a36Sopenharmony_ci	}
41862306a36Sopenharmony_ci	if (msg->sig != OTX2_MBOX_RSP_SIG) {
41962306a36Sopenharmony_ci		dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",
42062306a36Sopenharmony_ci			msg->sig, msg->id);
42162306a36Sopenharmony_ci		return;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci	if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1)
42462306a36Sopenharmony_ci		lfs = &cptpf->cpt1_lfs;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	switch (msg->id) {
42762306a36Sopenharmony_ci	case MBOX_MSG_READY:
42862306a36Sopenharmony_ci		cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) &
42962306a36Sopenharmony_ci				RVU_PFVF_PF_MASK;
43062306a36Sopenharmony_ci		break;
43162306a36Sopenharmony_ci	case MBOX_MSG_CPT_RD_WR_REGISTER:
43262306a36Sopenharmony_ci		rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;
43362306a36Sopenharmony_ci		if (msg->rc) {
43462306a36Sopenharmony_ci			dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",
43562306a36Sopenharmony_ci				rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,
43662306a36Sopenharmony_ci				msg->rc);
43762306a36Sopenharmony_ci			return;
43862306a36Sopenharmony_ci		}
43962306a36Sopenharmony_ci		if (!rsp_rd_wr->is_write)
44062306a36Sopenharmony_ci			*rsp_rd_wr->ret_val = rsp_rd_wr->val;
44162306a36Sopenharmony_ci		break;
44262306a36Sopenharmony_ci	case MBOX_MSG_ATTACH_RESOURCES:
44362306a36Sopenharmony_ci		if (!msg->rc)
44462306a36Sopenharmony_ci			lfs->are_lfs_attached = 1;
44562306a36Sopenharmony_ci		break;
44662306a36Sopenharmony_ci	case MBOX_MSG_DETACH_RESOURCES:
44762306a36Sopenharmony_ci		if (!msg->rc)
44862306a36Sopenharmony_ci			lfs->are_lfs_attached = 0;
44962306a36Sopenharmony_ci		break;
45062306a36Sopenharmony_ci	case MBOX_MSG_CPT_INLINE_IPSEC_CFG:
45162306a36Sopenharmony_ci	case MBOX_MSG_NIX_INLINE_IPSEC_CFG:
45262306a36Sopenharmony_ci		break;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	default:
45562306a36Sopenharmony_ci		dev_err(dev,
45662306a36Sopenharmony_ci			"Unsupported msg %d received.\n", msg->id);
45762306a36Sopenharmony_ci		break;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,
46262306a36Sopenharmony_ci			  int vf_id, int size)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	struct otx2_mbox *vfpf_mbox;
46562306a36Sopenharmony_ci	struct mbox_msghdr *fwd;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	if (msg->id >= MBOX_MSG_MAX) {
46862306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
46962306a36Sopenharmony_ci			"MBOX msg with unknown ID %d\n", msg->id);
47062306a36Sopenharmony_ci		return;
47162306a36Sopenharmony_ci	}
47262306a36Sopenharmony_ci	if (msg->sig != OTX2_MBOX_RSP_SIG) {
47362306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
47462306a36Sopenharmony_ci			"MBOX msg with wrong signature %x, ID %d\n",
47562306a36Sopenharmony_ci			msg->sig, msg->id);
47662306a36Sopenharmony_ci		return;
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci	vfpf_mbox = &cptpf->vfpf_mbox;
47962306a36Sopenharmony_ci	vf_id--;
48062306a36Sopenharmony_ci	if (vf_id >= cptpf->enabled_vfs) {
48162306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
48262306a36Sopenharmony_ci			"MBOX msg to unknown VF: %d >= %d\n",
48362306a36Sopenharmony_ci			vf_id, cptpf->enabled_vfs);
48462306a36Sopenharmony_ci		return;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci	if (msg->id == MBOX_MSG_VF_FLR)
48762306a36Sopenharmony_ci		return;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);
49062306a36Sopenharmony_ci	if (!fwd) {
49162306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
49262306a36Sopenharmony_ci			"Forwarding to VF%d failed.\n", vf_id);
49362306a36Sopenharmony_ci		return;
49462306a36Sopenharmony_ci	}
49562306a36Sopenharmony_ci	memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),
49662306a36Sopenharmony_ci		(uint8_t *)msg + sizeof(struct mbox_msghdr), size);
49762306a36Sopenharmony_ci	fwd->id = msg->id;
49862306a36Sopenharmony_ci	fwd->pcifunc = msg->pcifunc;
49962306a36Sopenharmony_ci	fwd->sig = msg->sig;
50062306a36Sopenharmony_ci	fwd->ver = msg->ver;
50162306a36Sopenharmony_ci	fwd->rc = msg->rc;
50262306a36Sopenharmony_ci}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci/* Handle mailbox messages received from AF */
50562306a36Sopenharmony_civoid otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	struct otx2_cptpf_dev *cptpf;
50862306a36Sopenharmony_ci	struct otx2_mbox *afpf_mbox;
50962306a36Sopenharmony_ci	struct otx2_mbox_dev *mdev;
51062306a36Sopenharmony_ci	struct mbox_hdr *rsp_hdr;
51162306a36Sopenharmony_ci	struct mbox_msghdr *msg;
51262306a36Sopenharmony_ci	int offset, vf_id, i;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);
51562306a36Sopenharmony_ci	afpf_mbox = &cptpf->afpf_mbox;
51662306a36Sopenharmony_ci	mdev = &afpf_mbox->dev[0];
51762306a36Sopenharmony_ci	/* Sync mbox data into memory */
51862306a36Sopenharmony_ci	smp_wmb();
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);
52162306a36Sopenharmony_ci	offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	for (i = 0; i < rsp_hdr->num_msgs; i++) {
52462306a36Sopenharmony_ci		msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +
52562306a36Sopenharmony_ci					     offset);
52662306a36Sopenharmony_ci		vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &
52762306a36Sopenharmony_ci			 RVU_PFVF_FUNC_MASK;
52862306a36Sopenharmony_ci		if (vf_id > 0)
52962306a36Sopenharmony_ci			forward_to_vf(cptpf, msg, vf_id,
53062306a36Sopenharmony_ci				      msg->next_msgoff - offset);
53162306a36Sopenharmony_ci		else
53262306a36Sopenharmony_ci			process_afpf_mbox_msg(cptpf, msg);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci		offset = msg->next_msgoff;
53562306a36Sopenharmony_ci		/* Sync VF response ready to be sent */
53662306a36Sopenharmony_ci		smp_wmb();
53762306a36Sopenharmony_ci		mdev->msgs_acked++;
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci	otx2_mbox_reset(afpf_mbox, 0);
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_cistatic void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf,
54362306a36Sopenharmony_ci				      struct mbox_msghdr *msg)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg;
54662306a36Sopenharmony_ci	struct otx2_cptlfs_info *lfs = &cptpf->lfs;
54762306a36Sopenharmony_ci	struct msg_rsp *rsp;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	if (cptpf->lfs.lfs_num)
55062306a36Sopenharmony_ci		lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1,
55162306a36Sopenharmony_ci				   &lfs->lf[0]);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0,
55462306a36Sopenharmony_ci						    sizeof(*rsp));
55562306a36Sopenharmony_ci	if (!rsp)
55662306a36Sopenharmony_ci		return;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	rsp->hdr.id = msg->id;
55962306a36Sopenharmony_ci	rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
56062306a36Sopenharmony_ci	rsp->hdr.pcifunc = 0;
56162306a36Sopenharmony_ci	rsp->hdr.rc = 0;
56262306a36Sopenharmony_ci}
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_cistatic void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf,
56562306a36Sopenharmony_ci				     struct mbox_msghdr *msg)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	if (msg->id >= MBOX_MSG_MAX) {
56862306a36Sopenharmony_ci		dev_err(&cptpf->pdev->dev,
56962306a36Sopenharmony_ci			"MBOX msg with unknown ID %d\n", msg->id);
57062306a36Sopenharmony_ci		return;
57162306a36Sopenharmony_ci	}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	switch (msg->id) {
57462306a36Sopenharmony_ci	case MBOX_MSG_CPT_INST_LMTST:
57562306a36Sopenharmony_ci		handle_msg_cpt_inst_lmtst(cptpf, msg);
57662306a36Sopenharmony_ci		break;
57762306a36Sopenharmony_ci	default:
57862306a36Sopenharmony_ci		otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id);
57962306a36Sopenharmony_ci	}
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_civoid otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	struct otx2_cptpf_dev *cptpf;
58562306a36Sopenharmony_ci	struct otx2_mbox_dev *mdev;
58662306a36Sopenharmony_ci	struct mbox_hdr *rsp_hdr;
58762306a36Sopenharmony_ci	struct mbox_msghdr *msg;
58862306a36Sopenharmony_ci	struct otx2_mbox *mbox;
58962306a36Sopenharmony_ci	int offset, i;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work);
59262306a36Sopenharmony_ci	mbox = &cptpf->afpf_mbox_up;
59362306a36Sopenharmony_ci	mdev = &mbox->dev[0];
59462306a36Sopenharmony_ci	/* Sync mbox data into memory */
59562306a36Sopenharmony_ci	smp_wmb();
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
59862306a36Sopenharmony_ci	offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	for (i = 0; i < rsp_hdr->num_msgs; i++) {
60162306a36Sopenharmony_ci		msg = (struct mbox_msghdr *)(mdev->mbase + offset);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci		process_afpf_mbox_up_msg(cptpf, msg);
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci		offset = mbox->rx_start + msg->next_msgoff;
60662306a36Sopenharmony_ci	}
60762306a36Sopenharmony_ci	otx2_mbox_msg_send(mbox, 0);
60862306a36Sopenharmony_ci}
609