Commit f8909d3d authored by Sai Krishna's avatar Sai Krishna Committed by Jakub Kicinski
Browse files

octeontx2-af: CN20K mbox implementation for AF's VF



This patch implements the CN20k MBOX communication between AF and
AF's VFs. This implementation uses separate trigger interrupts
for request, response messages against using trigger message data in CN10K.

Signed-off-by: default avatarSai Krishna <saikrishnag@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Link: https://patch.msgid.link/1749639716-13868-6-git-send-email-sbhatta@marvell.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 370c2374
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
struct ng_rvu {
	struct mbox_ops         *rvu_mbox_ops;
	struct qmem             *pf_mbox_addr;
	struct qmem             *vf_mbox_addr;
};

/* Mbox related APIs */
@@ -21,8 +22,11 @@ int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
			       int num, int type, unsigned long *pf_bmap);
void cn20k_free_mbox_memory(struct rvu *rvu);
int cn20k_register_afpf_mbox_intr(struct rvu *rvu);
int cn20k_register_afvf_mbox_intr(struct rvu *rvu, int pf_vec_start);
void cn20k_rvu_enable_mbox_intr(struct rvu *rvu);
void cn20k_rvu_unregister_interrupts(struct rvu *rvu);
int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
		     void *reg_base, int direction, int ndevs);
void cn20k_rvu_enable_afvf_intr(struct rvu *rvu, int vfs);
void cn20k_rvu_disable_afvf_intr(struct rvu *rvu, int vfs);
#endif /* CN20K_API_H */
+160 −3
Original line number Diff line number Diff line
@@ -13,6 +13,91 @@
#include "reg.h"
#include "api.h"

static irqreturn_t cn20k_afvf_mbox_intr_handler(int irq, void *rvu_irq)
{
	struct rvu_irq_data *rvu_irq_data = rvu_irq;
	struct rvu *rvu = rvu_irq_data->rvu;
	u64 intr;

	/* Sync with mbox memory region */
	rmb();

	/* Clear interrupts */
	intr = rvupf_read64(rvu, rvu_irq_data->intr_status);
	rvupf_write64(rvu, rvu_irq_data->intr_status, intr);

	if (intr)
		trace_otx2_msg_interrupt(rvu->pdev, "VF(s) to AF", intr);

	rvu_irq_data->afvf_queue_work_hdlr(&rvu->afvf_wq_info, rvu_irq_data->start,
					   rvu_irq_data->mdevs, intr);

	return IRQ_HANDLED;
}

int cn20k_register_afvf_mbox_intr(struct rvu *rvu, int pf_vec_start)
{
	struct rvu_irq_data *irq_data;
	int intr_vec, offset, vec = 0;
	int err;

	/* irq data for 4 VFPF intr vectors */
	irq_data = devm_kcalloc(rvu->dev, 4,
				sizeof(struct rvu_irq_data), GFP_KERNEL);
	if (!irq_data)
		return -ENOMEM;

	for (intr_vec = RVU_MBOX_PF_INT_VEC_VFPF_MBOX0; intr_vec <=
					RVU_MBOX_PF_INT_VEC_VFPF1_MBOX1;
					intr_vec++, vec++) {
		switch (intr_vec) {
		case RVU_MBOX_PF_INT_VEC_VFPF_MBOX0:
			irq_data[vec].intr_status =
						RVU_MBOX_PF_VFPF_INTX(0);
			irq_data[vec].start = 0;
			irq_data[vec].mdevs = 64;
			break;
		case RVU_MBOX_PF_INT_VEC_VFPF_MBOX1:
			irq_data[vec].intr_status =
						RVU_MBOX_PF_VFPF_INTX(1);
			irq_data[vec].start = 64;
			irq_data[vec].mdevs = 64;
			break;
		case RVU_MBOX_PF_INT_VEC_VFPF1_MBOX0:
			irq_data[vec].intr_status =
						RVU_MBOX_PF_VFPF1_INTX(0);
			irq_data[vec].start = 0;
			irq_data[vec].mdevs = 64;
			break;
		case RVU_MBOX_PF_INT_VEC_VFPF1_MBOX1:
			irq_data[vec].intr_status = RVU_MBOX_PF_VFPF1_INTX(1);
			irq_data[vec].start = 64;
			irq_data[vec].mdevs = 64;
			break;
		}
		irq_data[vec].afvf_queue_work_hdlr =
						rvu_queue_work;
		offset = pf_vec_start + intr_vec;
		irq_data[vec].vec_num = offset;
		irq_data[vec].rvu = rvu;

		sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAF VFAF%d Mbox%d",
			vec / 2, vec % 2);
		err = request_irq(pci_irq_vector(rvu->pdev, offset),
				  rvu->ng_rvu->rvu_mbox_ops->afvf_intr_handler, 0,
				  &rvu->irq_name[offset * NAME_SIZE],
				  &irq_data[vec]);
		if (err) {
			dev_err(rvu->dev,
				"RVUAF: IRQ registration failed for AFVF mbox irq\n");
			return err;
		}
		rvu->irq_allocated[offset] = true;
	}

	return 0;
}

/* CN20K mbox PFx => AF irq handler */
static irqreturn_t cn20k_mbox_pf_common_intr_handler(int irq, void *rvu_irq)
{
@@ -150,6 +235,21 @@ int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
	int region;
	u64 bar;

	if (type == TYPE_AFVF) {
		for (region = 0; region < num; region++) {
			if (!test_bit(region, pf_bmap))
				continue;

			bar = (u64)phys_to_virt((u64)rvu->ng_rvu->vf_mbox_addr->base);
			bar += region * MBOX_SIZE;
			mbox_addr[region] = (void *)bar;

			if (!mbox_addr[region])
				return -ENOMEM;
		}
		return 0;
	}

	for (region = 0; region < num; region++) {
		if (!test_bit(region, pf_bmap))
			continue;
@@ -180,6 +280,9 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,
	 *
	 * AF will access mbox memory using direct physical addresses
	 * and PFs will access the same shared memory from BAR2.
	 *
	 * PF <=> VF mbox memory also works in the same fashion.
	 * AFPF, PFVF requires IOVA to be used to maintain the mailbox msgs
	 */

	err = qmem_alloc(rvu->dev, &mbox_addr, ndevs, mbox_size);
@@ -196,6 +299,10 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,
			iova += mbox_size;
		}
		break;
	case TYPE_AFVF:
		rvu->ng_rvu->vf_mbox_addr = mbox_addr;
		rvupf_write64(rvu, RVU_PF_VF_MBOX_ADDR, (u64)mbox_addr->iova);
		break;
	default:
		return 0;
	}
@@ -205,6 +312,7 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,

static struct mbox_ops cn20k_mbox_ops = {
	.pf_intr_handler = cn20k_mbox_pf_common_intr_handler,
	.afvf_intr_handler = cn20k_afvf_mbox_intr_handler,
};

int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)
@@ -216,9 +324,13 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)

	rvu->ng_rvu->rvu_mbox_ops = &cn20k_mbox_ops;

	if (type == TYPE_AFVF) {
		rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_PF_VF_CFG, ilog2(MBOX_SIZE));
	} else {
		for (dev = 0; dev < ndevs; dev++)
			rvu_write64(rvu, BLKADDR_RVUM,
				    RVU_MBOX_AF_PFX_CFG(dev), ilog2(MBOX_SIZE));
	}

	return rvu_alloc_mbox_memory(rvu, type, ndevs, MBOX_SIZE);
}
@@ -229,6 +341,51 @@ void cn20k_free_mbox_memory(struct rvu *rvu)
		return;

	qmem_free(rvu->dev, rvu->ng_rvu->pf_mbox_addr);
	qmem_free(rvu->dev, rvu->ng_rvu->vf_mbox_addr);
}

void cn20k_rvu_disable_afvf_intr(struct rvu *rvu, int vfs)
{
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1CX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1CX(0), INTR_MASK(vfs));

	if (vfs <= 64)
		return;

	rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
}

void cn20k_rvu_enable_afvf_intr(struct rvu *rvu, int vfs)
{
	/* Clear any pending interrupts and enable AF VF interrupts for
	 * the first 64 VFs.
	 */
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INTX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1SX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INTX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(0), INTR_MASK(vfs));

	/* FLR */
	rvupf_write64(rvu, RVU_PF_VFFLR_INTX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(0), INTR_MASK(vfs));

	/* Same for remaining VFs, if any. */
	if (vfs <= 64)
		return;

	rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INTX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INTX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));

	rvupf_write64(rvu, RVU_PF_VFFLR_INTX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
	rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
}

int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
+37 −0
Original line number Diff line number Diff line
@@ -41,4 +41,41 @@
#define NIX_CINTX_INT_W1S(a)			(0xd30 | (a) << 12)
#define NIX_QINTX_CNT(a)			(0xc00 | (a) << 12)

#define RVU_MBOX_AF_VFAF_INT(a)			(0x3000 | (a) << 6)
#define RVU_MBOX_AF_VFAF_INT_W1S(a)		(0x3008 | (a) << 6)
#define RVU_MBOX_AF_VFAF_INT_ENA_W1S(a)		(0x3010 | (a) << 6)
#define RVU_MBOX_AF_VFAF_INT_ENA_W1C(a)		(0x3018 | (a) << 6)
#define RVU_MBOX_AF_VFAF_INT_ENA_W1C(a)		(0x3018 | (a) << 6)
#define RVU_MBOX_AF_VFAF1_INT(a)		(0x3020 | (a) << 6)
#define RVU_MBOX_AF_VFAF1_INT_W1S(a)		(0x3028 | (a) << 6)
#define RVU_MBOX_AF_VFAF1_IN_ENA_W1S(a)		(0x3030 | (a) << 6)
#define RVU_MBOX_AF_VFAF1_IN_ENA_W1C(a)		(0x3038 | (a) << 6)

#define RVU_MBOX_AF_AFVFX_TRIG(a, b)		(0x10000 | (a) << 4 | (b) << 3)
#define RVU_MBOX_AF_VFX_ADDR(a)			(0x20000 | (a) << 4)
#define RVU_MBOX_AF_VFX_CFG(a)			(0x28000 | (a) << 4)

#define RVU_MBOX_PF_VFX_PFVF_TRIGX(a)		(0x2000 | (a) << 3)

#define RVU_MBOX_PF_VFPF_INTX(a)		(0x1000 | (a) << 3)
#define RVU_MBOX_PF_VFPF_INT_W1SX(a)		(0x1020 | (a) << 3)
#define RVU_MBOX_PF_VFPF_INT_ENA_W1SX(a)	(0x1040 | (a) << 3)
#define RVU_MBOX_PF_VFPF_INT_ENA_W1CX(a)	(0x1060 | (a) << 3)

#define RVU_MBOX_PF_VFPF1_INTX(a)		(0x1080 | (a) << 3)
#define RVU_MBOX_PF_VFPF1_INT_W1SX(a)		(0x10a0 | (a) << 3)
#define RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(a)	(0x10c0 | (a) << 3)
#define RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(a)	(0x10e0 | (a) << 3)

#define RVU_MBOX_PF_VF_ADDR			(0xC40)
#define RVU_MBOX_PF_LMTLINE_ADDR		(0xC48)
#define RVU_MBOX_PF_VF_CFG			(0xC60)

#define RVU_MBOX_VF_VFPF_TRIGX(a)		(0x3000 | (a) << 3)
#define RVU_MBOX_VF_INT				(0x20)
#define RVU_MBOX_VF_INT_W1S			(0x28)
#define RVU_MBOX_VF_INT_ENA_W1S			(0x30)
#define RVU_MBOX_VF_INT_ENA_W1C			(0x38)

#define RVU_MBOX_VF_VFAF_TRIGX(a)		(0x2000 | (a) << 3)
#endif /* RVU_MBOX_REG_H */
+20 −0
Original line number Diff line number Diff line
@@ -63,24 +63,28 @@ int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
{
	switch (direction) {
	case MBOX_DIR_AFPF:
	case MBOX_DIR_PFVF:
		mbox->tx_start = MBOX_DOWN_TX_START;
		mbox->rx_start = MBOX_DOWN_RX_START;
		mbox->tx_size  = MBOX_DOWN_TX_SIZE;
		mbox->rx_size  = MBOX_DOWN_RX_SIZE;
		break;
	case MBOX_DIR_PFAF:
	case MBOX_DIR_VFPF:
		mbox->tx_start = MBOX_DOWN_RX_START;
		mbox->rx_start = MBOX_DOWN_TX_START;
		mbox->tx_size  = MBOX_DOWN_RX_SIZE;
		mbox->rx_size  = MBOX_DOWN_TX_SIZE;
		break;
	case MBOX_DIR_AFPF_UP:
	case MBOX_DIR_PFVF_UP:
		mbox->tx_start = MBOX_UP_TX_START;
		mbox->rx_start = MBOX_UP_RX_START;
		mbox->tx_size  = MBOX_UP_TX_SIZE;
		mbox->rx_size  = MBOX_UP_RX_SIZE;
		break;
	case MBOX_DIR_PFAF_UP:
	case MBOX_DIR_VFPF_UP:
		mbox->tx_start = MBOX_UP_RX_START;
		mbox->rx_start = MBOX_UP_TX_START;
		mbox->tx_size  = MBOX_UP_RX_SIZE;
@@ -107,6 +111,22 @@ int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
		mbox->trigger = RVU_MBOX_PF_PFAF_TRIGX(1);
		mbox->tr_shift = 0;
		break;
	case MBOX_DIR_PFVF:
		mbox->trigger = RVU_MBOX_PF_VFX_PFVF_TRIGX(1);
		mbox->tr_shift = 4;
		break;
	case MBOX_DIR_PFVF_UP:
		mbox->trigger = RVU_MBOX_PF_VFX_PFVF_TRIGX(0);
		mbox->tr_shift = 4;
		break;
	case MBOX_DIR_VFPF:
		mbox->trigger = RVU_MBOX_VF_VFPF_TRIGX(0);
		mbox->tr_shift = 0;
		break;
	case MBOX_DIR_VFPF_UP:
		mbox->trigger = RVU_MBOX_VF_VFPF_TRIGX(1);
		mbox->tr_shift = 0;
		break;
	default:
		return -ENODEV;
	}
+42 −25
Original line number Diff line number Diff line
@@ -2450,6 +2450,7 @@ static int rvu_get_mbox_regions(struct rvu *rvu, void __iomem **mbox_addr,

static struct mbox_ops rvu_mbox_ops = {
	.pf_intr_handler = rvu_mbox_pf_intr_handler,
	.afvf_intr_handler = rvu_mbox_intr_handler,
};

static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
@@ -2999,6 +3000,10 @@ static int rvu_afvf_msix_vectors_num_ok(struct rvu *rvu)
	 * VF interrupts can be handled. Offset equal to zero means
	 * that PF vectors are not configured and overlapping AF vectors.
	 */
	if (is_cn20k(rvu->pdev))
		return (pfvf->msix.max >= RVU_AF_CN20K_INT_VEC_CNT +
			RVU_MBOX_PF_INT_VEC_CNT) && offset;

	return (pfvf->msix.max >= RVU_AF_INT_VEC_CNT + RVU_PF_INT_VEC_CNT) &&
	       offset;
}
@@ -3107,12 +3112,12 @@ static int rvu_register_interrupts(struct rvu *rvu)
	/* Get PF MSIX vectors offset. */
	pf_vec_start = rvu_read64(rvu, BLKADDR_RVUM,
				  RVU_PRIV_PFX_INT_CFG(0)) & 0x3ff;

	if (!is_cn20k(rvu->pdev)) {
		/* Register MBOX0 interrupt. */
		offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX0;
		sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox0");
		ret = request_irq(pci_irq_vector(rvu->pdev, offset),
			  rvu_mbox_intr_handler, 0,
				  rvu->ng_rvu->rvu_mbox_ops->afvf_intr_handler, 0,
				  &rvu->irq_name[offset * NAME_SIZE],
				  rvu);
		if (ret)
@@ -3127,7 +3132,7 @@ static int rvu_register_interrupts(struct rvu *rvu)
		offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX1;
		sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox1");
		ret = request_irq(pci_irq_vector(rvu->pdev, offset),
			  rvu_mbox_intr_handler, 0,
				  rvu->ng_rvu->rvu_mbox_ops->afvf_intr_handler, 0,
				  &rvu->irq_name[offset * NAME_SIZE],
				  rvu);
		if (ret)
@@ -3135,6 +3140,12 @@ static int rvu_register_interrupts(struct rvu *rvu)
				"RVUAF: IRQ registration failed for Mbox1\n");

		rvu->irq_allocated[offset] = true;
	} else {
		ret = cn20k_register_afvf_mbox_intr(rvu, pf_vec_start);
		if (ret)
			dev_err(rvu->dev,
				"RVUAF: IRQ registration failed for Mbox\n");
	}

	/* Register FLR interrupt handler for AF's VFs */
	offset = pf_vec_start + RVU_PF_INT_VEC_VFFLR0;
@@ -3245,6 +3256,9 @@ static void rvu_disable_afvf_intr(struct rvu *rvu)
{
	int vfs = rvu->vfs;

	if (is_cn20k(rvu->pdev))
		return cn20k_rvu_disable_afvf_intr(rvu, vfs);

	rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(0), INTR_MASK(vfs));
	rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1CX(0), INTR_MASK(vfs));
@@ -3261,6 +3275,9 @@ static void rvu_enable_afvf_intr(struct rvu *rvu)
{
	int vfs = rvu->vfs;

	if (is_cn20k(rvu->pdev))
		return cn20k_rvu_enable_afvf_intr(rvu, vfs);

	/* Clear any pending interrupts and enable AF VF interrupts for
	 * the first 64 VFs.
	 */
Loading