Commit 5a6d7c9d authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-pf: Mailbox communication with AF

In the resource virtualization unit (RVU) each of the PF and AF
(admin function) share a 64KB of reserved memory region for
communication. This patch initializes PF <=> AF mailbox IRQs,
registers handlers for processing these communication messages.
Also adds support to process these messages in both directions
ie responses to PF initiated DOWN (PF => AF) messages and AF
initiated UP messages (AF => PF).

Mbox communication APIs and message formats are defined in AF driver
(drivers/net/ethernet/marvell/octeontx2/af), mbox.h from AF driver is
included here to avoid duplication.
Signed-off-by: default avatarGeetha sowjanya <gakula@marvell.com>
Signed-off-by: default avatarChristina Jacob <cjacob@marvell.com>
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarAleksey Makarov <amakarov@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16547577
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
obj-$(CONFIG_OCTEONTX2_PF) += octeontx2_nicpf.o obj-$(CONFIG_OCTEONTX2_PF) += octeontx2_nicpf.o
octeontx2_nicpf-y := otx2_pf.o octeontx2_nicpf-y := otx2_pf.o otx2_common.o
ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
// SPDX-License-Identifier: GPL-2.0
/* Marvell OcteonTx2 RVU Ethernet driver
*
* Copyright (C) 2020 Marvell International Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/interrupt.h>
#include <linux/pci.h>
#include "otx2_reg.h"
#include "otx2_common.h"
#define M(_name, _id, _fn_name, _req_type, _rsp_type) \
int __weak \
otx2_mbox_up_handler_ ## _fn_name(struct otx2_nic *pfvf, \
struct _req_type *req, \
struct _rsp_type *rsp) \
{ \
/* Nothing to do here */ \
return 0; \
} \
EXPORT_SYMBOL(otx2_mbox_up_handler_ ## _fn_name);
MBOX_UP_CGX_MESSAGES
#undef M
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <mbox.h>
#include "otx2_reg.h" #include "otx2_reg.h"
/* PCI device IDs */ /* PCI device IDs */
...@@ -20,12 +21,31 @@ ...@@ -20,12 +21,31 @@
/* PCI BAR nos */ /* PCI BAR nos */
#define PCI_CFG_REG_BAR_NUM 2 #define PCI_CFG_REG_BAR_NUM 2
#define PCI_MBOX_BAR_NUM 4
#define NAME_SIZE 32
struct mbox {
struct otx2_mbox mbox;
struct work_struct mbox_wrk;
struct otx2_mbox mbox_up;
struct work_struct mbox_up_wrk;
struct otx2_nic *pfvf;
void *bbuf_base; /* Bounce buffer for mbox memory */
struct mutex lock; /* serialize mailbox access */
int num_msgs; /* mbox number of messages */
int up_num_msgs; /* mbox_up number of messages */
};
struct otx2_hw { struct otx2_hw {
struct pci_dev *pdev; struct pci_dev *pdev;
u16 rx_queues; u16 rx_queues;
u16 tx_queues; u16 tx_queues;
u16 max_queues; u16 max_queues;
/* MSI-X */
char *irq_name;
cpumask_var_t *affinity_mask;
}; };
struct otx2_nic { struct otx2_nic {
...@@ -35,6 +55,12 @@ struct otx2_nic { ...@@ -35,6 +55,12 @@ struct otx2_nic {
struct otx2_hw hw; struct otx2_hw hw;
struct pci_dev *pdev; struct pci_dev *pdev;
struct device *dev; struct device *dev;
/* Mbox */
struct mbox mbox;
struct workqueue_struct *mbox_wq;
u16 pcifunc; /* RVU PF_FUNC */
}; };
/* Register read/write APIs */ /* Register read/write APIs */
...@@ -74,4 +100,144 @@ static inline u64 otx2_read64(struct otx2_nic *nic, u64 offset) ...@@ -74,4 +100,144 @@ static inline u64 otx2_read64(struct otx2_nic *nic, u64 offset)
return readq(addr); return readq(addr);
} }
/* Mbox bounce buffer APIs */
static inline int otx2_mbox_bbuf_init(struct mbox *mbox, struct pci_dev *pdev)
{
struct otx2_mbox *otx2_mbox;
struct otx2_mbox_dev *mdev;
mbox->bbuf_base = devm_kmalloc(&pdev->dev, MBOX_SIZE, GFP_KERNEL);
if (!mbox->bbuf_base)
return -ENOMEM;
/* Overwrite mbox mbase to point to bounce buffer, so that PF/VF
* prepare all mbox messages in bounce buffer instead of directly
* in hw mbox memory.
*/
otx2_mbox = &mbox->mbox;
mdev = &otx2_mbox->dev[0];
mdev->mbase = mbox->bbuf_base;
otx2_mbox = &mbox->mbox_up;
mdev = &otx2_mbox->dev[0];
mdev->mbase = mbox->bbuf_base;
return 0;
}
static inline void otx2_sync_mbox_bbuf(struct otx2_mbox *mbox, int devid)
{
u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
void *hw_mbase = mbox->hwbase + (devid * MBOX_SIZE);
struct otx2_mbox_dev *mdev = &mbox->dev[devid];
struct mbox_hdr *hdr;
u64 msg_size;
if (mdev->mbase == hw_mbase)
return;
hdr = hw_mbase + mbox->rx_start;
msg_size = hdr->msg_size;
if (msg_size > mbox->rx_size - msgs_offset)
msg_size = mbox->rx_size - msgs_offset;
/* Copy mbox messages from mbox memory to bounce buffer */
memcpy(mdev->mbase + mbox->rx_start,
hw_mbase + mbox->rx_start, msg_size + msgs_offset);
}
static inline void otx2_mbox_lock_init(struct mbox *mbox)
{
mutex_init(&mbox->lock);
}
static inline void otx2_mbox_lock(struct mbox *mbox)
{
mutex_lock(&mbox->lock);
}
static inline void otx2_mbox_unlock(struct mbox *mbox)
{
mutex_unlock(&mbox->lock);
}
/* Mbox APIs */
static inline int otx2_sync_mbox_msg(struct mbox *mbox)
{
int err;
if (!otx2_mbox_nonempty(&mbox->mbox, 0))
return 0;
otx2_mbox_msg_send(&mbox->mbox, 0);
err = otx2_mbox_wait_for_rsp(&mbox->mbox, 0);
if (err)
return err;
return otx2_mbox_check_rsp_msgs(&mbox->mbox, 0);
}
static inline int otx2_sync_mbox_up_msg(struct mbox *mbox, int devid)
{
int err;
if (!otx2_mbox_nonempty(&mbox->mbox_up, devid))
return 0;
otx2_mbox_msg_send(&mbox->mbox_up, devid);
err = otx2_mbox_wait_for_rsp(&mbox->mbox_up, devid);
if (err)
return err;
return otx2_mbox_check_rsp_msgs(&mbox->mbox_up, devid);
}
/* Use this API to send mbox msgs in atomic context
* where sleeping is not allowed
*/
static inline int otx2_sync_mbox_msg_busy_poll(struct mbox *mbox)
{
int err;
if (!otx2_mbox_nonempty(&mbox->mbox, 0))
return 0;
otx2_mbox_msg_send(&mbox->mbox, 0);
err = otx2_mbox_busy_poll_for_rsp(&mbox->mbox, 0);
if (err)
return err;
return otx2_mbox_check_rsp_msgs(&mbox->mbox, 0);
}
#define M(_name, _id, _fn_name, _req_type, _rsp_type) \
static struct _req_type __maybe_unused \
*otx2_mbox_alloc_msg_ ## _fn_name(struct mbox *mbox) \
{ \
struct _req_type *req; \
\
req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \
&mbox->mbox, 0, sizeof(struct _req_type), \
sizeof(struct _rsp_type)); \
if (!req) \
return NULL; \
req->hdr.sig = OTX2_MBOX_REQ_SIG; \
req->hdr.id = _id; \
return req; \
}
MBOX_MESSAGES
#undef M
#define M(_name, _id, _fn_name, _req_type, _rsp_type) \
int \
otx2_mbox_up_handler_ ## _fn_name(struct otx2_nic *pfvf, \
struct _req_type *req, \
struct _rsp_type *rsp); \
MBOX_UP_CGX_MESSAGES
#undef M
#define RVU_PFVF_PF_SHIFT 10
#define RVU_PFVF_PF_MASK 0x3F
#define RVU_PFVF_FUNC_SHIFT 0
#define RVU_PFVF_FUNC_MASK 0x3FF
#endif /* OTX2_COMMON_H */ #endif /* OTX2_COMMON_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment