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

octeontx2-af: CN20k mbox to support AF REQ/ACK functionality



This implementation uses separate trigger interrupts for request,
response MBOX messages against using trigger message data in CN10K.
This patch adds support for basic mbox implementation for CN20K
from AF side.

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-4-git-send-email-sbhatta@marvell.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent e53ee4ac
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -20,4 +20,9 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int num);
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);
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);
#endif /* CN20K_API_H */
+172 −0
Original line number Diff line number Diff line
@@ -13,6 +13,137 @@
#include "reg.h"
#include "api.h"

/* CN20K mbox PFx => AF irq handler */
static irqreturn_t cn20k_mbox_pf_common_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;

	/* Clear interrupts */
	intr = rvu_read64(rvu, BLKADDR_RVUM, rvu_irq_data->intr_status);
	rvu_write64(rvu, BLKADDR_RVUM, rvu_irq_data->intr_status, intr);

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

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

	rvu_irq_data->rvu_queue_work_hdlr(&rvu->afpf_wq_info,
					  rvu_irq_data->start,
					  rvu_irq_data->mdevs, intr);

	return IRQ_HANDLED;
}

void cn20k_rvu_enable_mbox_intr(struct rvu *rvu)
{
	struct rvu_hwinfo *hw = rvu->hw;

	/* Clear spurious irqs, if any */
	rvu_write64(rvu, BLKADDR_RVUM,
		    RVU_MBOX_AF_PFAF_INT(0), INTR_MASK(hw->total_pfs));

	rvu_write64(rvu, BLKADDR_RVUM,
		    RVU_MBOX_AF_PFAF_INT(1), INTR_MASK(hw->total_pfs - 64));

	rvu_write64(rvu, BLKADDR_RVUM,
		    RVU_MBOX_AF_PFAF1_INT(0), INTR_MASK(hw->total_pfs));

	rvu_write64(rvu, BLKADDR_RVUM,
		    RVU_MBOX_AF_PFAF1_INT(1), INTR_MASK(hw->total_pfs - 64));

	/* Enable mailbox interrupt for all PFs except PF0 i.e AF itself */
	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF_INT_ENA_W1S(0),
		    INTR_MASK(hw->total_pfs) & ~1ULL);

	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF_INT_ENA_W1S(1),
		    INTR_MASK(hw->total_pfs - 64));

	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF1_INT_ENA_W1S(0),
		    INTR_MASK(hw->total_pfs) & ~1ULL);

	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF1_INT_ENA_W1S(1),
		    INTR_MASK(hw->total_pfs - 64));
}

void cn20k_rvu_unregister_interrupts(struct rvu *rvu)
{
	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF_INT_ENA_W1C(0),
		    INTR_MASK(rvu->hw->total_pfs) & ~1ULL);

	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF_INT_ENA_W1C(1),
		    INTR_MASK(rvu->hw->total_pfs - 64));

	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF1_INT_ENA_W1C(0),
		    INTR_MASK(rvu->hw->total_pfs) & ~1ULL);

	rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_AF_PFAF1_INT_ENA_W1C(1),
		    INTR_MASK(rvu->hw->total_pfs - 64));
}

int cn20k_register_afpf_mbox_intr(struct rvu *rvu)
{
	struct rvu_irq_data *irq_data;
	int intr_vec, ret, vec = 0;

	/* irq data for 4 PF 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_AF_CN20K_INT_VEC_PFAF_MBOX0; intr_vec <=
				RVU_AF_CN20K_INT_VEC_PFAF1_MBOX1; intr_vec++,
				vec++) {
		switch (intr_vec) {
		case RVU_AF_CN20K_INT_VEC_PFAF_MBOX0:
			irq_data[vec].intr_status =
						RVU_MBOX_AF_PFAF_INT(0);
			irq_data[vec].start = 0;
			irq_data[vec].mdevs = 64;
			break;
		case RVU_AF_CN20K_INT_VEC_PFAF_MBOX1:
			irq_data[vec].intr_status =
						RVU_MBOX_AF_PFAF_INT(1);
			irq_data[vec].start = 64;
			irq_data[vec].mdevs = 96;
			break;
		case RVU_AF_CN20K_INT_VEC_PFAF1_MBOX0:
			irq_data[vec].intr_status =
						RVU_MBOX_AF_PFAF1_INT(0);
			irq_data[vec].start = 0;
			irq_data[vec].mdevs = 64;
			break;
		case RVU_AF_CN20K_INT_VEC_PFAF1_MBOX1:
			irq_data[vec].intr_status =
						RVU_MBOX_AF_PFAF1_INT(1);
			irq_data[vec].start = 64;
			irq_data[vec].mdevs = 96;
			break;
		}
		irq_data[vec].rvu_queue_work_hdlr = rvu_queue_work;
		irq_data[vec].vec_num = intr_vec;
		irq_data[vec].rvu = rvu;

		/* Register mailbox interrupt handler */
		sprintf(&rvu->irq_name[intr_vec * NAME_SIZE],
			"RVUAF PFAF%d Mbox%d",
			vec / 2, vec % 2);
		ret = request_irq(pci_irq_vector(rvu->pdev, intr_vec),
				  rvu->ng_rvu->rvu_mbox_ops->pf_intr_handler, 0,
				  &rvu->irq_name[intr_vec * NAME_SIZE],
				  &irq_data[vec]);
		if (ret)
			return ret;

		rvu->irq_allocated[intr_vec] = true;
	}

	return 0;
}

int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
			       int num, int type, unsigned long *pf_bmap)
{
@@ -72,6 +203,10 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,
	return 0;
}

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

int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)
{
	int dev;
@@ -79,6 +214,8 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)
	if (!is_cn20k(rvu->pdev))
		return 0;

	rvu->ng_rvu->rvu_mbox_ops = &cn20k_mbox_ops;

	for (dev = 0; dev < ndevs; dev++)
		rvu_write64(rvu, BLKADDR_RVUM,
			    RVU_MBOX_AF_PFX_CFG(dev), ilog2(MBOX_SIZE));
@@ -93,3 +230,38 @@ void cn20k_free_mbox_memory(struct rvu *rvu)

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

int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
			    int blkaddr, int nixlf)
{
	int qints, hwctx_size, err;
	u64 cfg, ctx_cfg;

	if (is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))
		return 0;

	ctx_cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST3);
	/* Alloc memory for CQINT's HW contexts */
	cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
	qints = (cfg >> 24) & 0xFFF;
	hwctx_size = 1UL << ((ctx_cfg >> 24) & 0xF);
	err = qmem_alloc(rvu->dev, &pfvf->cq_ints_ctx, qints, hwctx_size);
	if (err)
		return -ENOMEM;

	rvu_write64(rvu, blkaddr, NIX_AF_LFX_CINTS_BASE(nixlf),
		    (u64)pfvf->cq_ints_ctx->iova);

	/* Alloc memory for QINT's HW contexts */
	cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
	qints = (cfg >> 12) & 0xFFF;
	hwctx_size = 1UL << ((ctx_cfg >> 20) & 0xF);
	err = qmem_alloc(rvu->dev, &pfvf->nix_qints_ctx, qints, hwctx_size);
	if (err)
		return -ENOMEM;

	rvu_write64(rvu, blkaddr, NIX_AF_LFX_QINTS_BASE(nixlf),
		    (u64)pfvf->nix_qints_ctx->iova);

	return 0;
}
+17 −0
Original line number Diff line number Diff line
@@ -19,6 +19,23 @@
/* RVU AF BAR0 Mbox registers for AF => PFx */
#define RVU_MBOX_AF_PFX_ADDR(a)			(0x5000 | (a) << 4)
#define RVU_MBOX_AF_PFX_CFG(a)			(0x6000 | (a) << 4)
#define RVU_MBOX_AF_AFPFX_TRIGX(a)		(0x9000 | (a) << 3)
#define RVU_MBOX_AF_PFAF_INT(a)			(0x2980 | (a) << 6)
#define RVU_MBOX_AF_PFAF_INT_W1S(a)		(0x2988 | (a) << 6)
#define RVU_MBOX_AF_PFAF_INT_ENA_W1S(a)		(0x2990 | (a) << 6)
#define RVU_MBOX_AF_PFAF_INT_ENA_W1C(a)		(0x2998 | (a) << 6)
#define RVU_MBOX_AF_PFAF1_INT(a)		(0x29A0 | (a) << 6)
#define RVU_MBOX_AF_PFAF1_INT_W1S(a)		(0x29A8 | (a) << 6)
#define RVU_MBOX_AF_PFAF1_INT_ENA_W1S(a)	(0x29B0 | (a) << 6)
#define RVU_MBOX_AF_PFAF1_INT_ENA_W1C(a)	(0x29B8 | (a) << 6)

/* RVU PF => AF mbox registers */
#define RVU_MBOX_PF_PFAF_TRIGX(a)		(0xC00 | (a) << 3)
#define RVU_MBOX_PF_INT				(0xC20)
#define RVU_MBOX_PF_INT_W1S			(0xC28)
#define RVU_MBOX_PF_INT_ENA_W1S			(0xC30)
#define RVU_MBOX_PF_INT_ENA_W1C			(0xC38)

#define RVU_AF_BAR2_SEL				(0x9000000)
#define RVU_AF_BAR2_PFID			(0x16400)
#define NIX_CINTX_INT_W1S(a)			(0xd30 | (a) << 12)
+25 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell RVU Admin Function driver
 *
 * Copyright (C) 2024 Marvell.
 *
 */

#ifndef STRUCT_H
#define STRUCT_H

/* RVU Admin function Interrupt Vector Enumeration */
enum rvu_af_cn20k_int_vec_e {
	RVU_AF_CN20K_INT_VEC_POISON		= 0x0,
	RVU_AF_CN20K_INT_VEC_PFFLR0		= 0x1,
	RVU_AF_CN20K_INT_VEC_PFFLR1		= 0x2,
	RVU_AF_CN20K_INT_VEC_PFME0		= 0x3,
	RVU_AF_CN20K_INT_VEC_PFME1		= 0x4,
	RVU_AF_CN20K_INT_VEC_GEN		= 0x5,
	RVU_AF_CN20K_INT_VEC_PFAF_MBOX0		= 0x6,
	RVU_AF_CN20K_INT_VEC_PFAF_MBOX1		= 0x7,
	RVU_AF_CN20K_INT_VEC_PFAF1_MBOX0	= 0x8,
	RVU_AF_CN20K_INT_VEC_PFAF1_MBOX1	= 0x9,
	RVU_AF_CN20K_INT_VEC_CNT		= 0xa,
};
#endif
+81 −2
Original line number Diff line number Diff line
@@ -31,8 +31,10 @@ void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
	mdev->rsp_size = 0;
	tx_hdr->num_msgs = 0;
	tx_hdr->msg_size = 0;
	tx_hdr->sig = 0;
	rx_hdr->num_msgs = 0;
	rx_hdr->msg_size = 0;
	rx_hdr->sig = 0;
}
EXPORT_SYMBOL(__otx2_mbox_reset);

@@ -56,9 +58,78 @@ void otx2_mbox_destroy(struct otx2_mbox *mbox)
}
EXPORT_SYMBOL(otx2_mbox_destroy);

int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
		     void *reg_base, int direction, int ndevs)
{
	switch (direction) {
	case MBOX_DIR_AFPF:
		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:
		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:
		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:
		mbox->tx_start = MBOX_UP_RX_START;
		mbox->rx_start = MBOX_UP_TX_START;
		mbox->tx_size  = MBOX_UP_RX_SIZE;
		mbox->rx_size  = MBOX_UP_TX_SIZE;
		break;
	default:
		return -ENODEV;
	}

	switch (direction) {
	case MBOX_DIR_AFPF:
		mbox->trigger = RVU_MBOX_AF_AFPFX_TRIGX(1);
		mbox->tr_shift = 4;
		break;
	case MBOX_DIR_AFPF_UP:
		mbox->trigger = RVU_MBOX_AF_AFPFX_TRIGX(0);
		mbox->tr_shift = 4;
		break;
	case MBOX_DIR_PFAF:
		mbox->trigger = RVU_MBOX_PF_PFAF_TRIGX(0);
		mbox->tr_shift = 0;
		break;
	case MBOX_DIR_PFAF_UP:
		mbox->trigger = RVU_MBOX_PF_PFAF_TRIGX(1);
		mbox->tr_shift = 0;
		break;
	default:
		return -ENODEV;
	}
	mbox->reg_base = reg_base;
	mbox->pdev = pdev;

	mbox->dev = kcalloc(ndevs, sizeof(struct otx2_mbox_dev), GFP_KERNEL);
	if (!mbox->dev) {
		otx2_mbox_destroy(mbox);
		return -ENOMEM;
	}
	mbox->ndevs = ndevs;

	return 0;
}

static int otx2_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
			   void *reg_base, int direction, int ndevs)
{
	if (is_cn20k(pdev))
		return cn20k_mbox_setup(mbox, pdev, reg_base,
							direction, ndevs);

	switch (direction) {
	case MBOX_DIR_AFPF:
	case MBOX_DIR_PFVF:
@@ -237,7 +308,10 @@ static void otx2_mbox_msg_send_data(struct otx2_mbox *mbox, int devid, u64 data)

	spin_lock(&mdev->mbox_lock);

	if (!tx_hdr->sig) {
		tx_hdr->msg_size = mdev->msg_size;
		tx_hdr->num_msgs = mdev->num_msgs;
	}

	/* Reset header for next messages */
	mdev->msg_size = 0;
@@ -251,7 +325,6 @@ static void otx2_mbox_msg_send_data(struct otx2_mbox *mbox, int devid, u64 data)
	 * messages.  So this should be written after writing all the messages
	 * to the shared memory.
	 */
	tx_hdr->num_msgs = mdev->num_msgs;
	rx_hdr->num_msgs = 0;

	msg = (struct mbox_msghdr *)(hw_mbase + mbox->tx_start + msgs_offset);
@@ -312,6 +385,7 @@ struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
{
	struct otx2_mbox_dev *mdev = &mbox->dev[devid];
	struct mbox_msghdr *msghdr = NULL;
	struct mbox_hdr *mboxhdr = NULL;

	spin_lock(&mdev->mbox_lock);
	size = ALIGN(size, MBOX_MSG_ALIGN);
@@ -335,6 +409,11 @@ struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
	mdev->msg_size += size;
	mdev->rsp_size += size_rsp;
	msghdr->next_msgoff = mdev->msg_size + msgs_offset;

	mboxhdr = mdev->mbase + mbox->tx_start;
	/* Clear the msg header region */
	memset(mboxhdr, 0, msgs_offset);

exit:
	spin_unlock(&mdev->mbox_lock);

Loading