Implement mailbox communication between PF and VFs.
PF-VF mailbox is used for all control commands from VF to PF and
asynchronous notification messages from PF to VF.
Signed-off-by: Veerasenareddy Burru <[email protected]>
Signed-off-by: Sathesh Edara <[email protected]>
Signed-off-by: Abhijit Ayarekar <[email protected]>
---
v1 -> v2:
* reworked the patch for changes made to preceding patches.
* removed device status oct->status, as it is not required with the
modified implementation.
.../net/ethernet/marvell/octeon_ep/Makefile | 3 +-
.../marvell/octeon_ep/octep_cn9k_pf.c | 42 ++-
.../ethernet/marvell/octeon_ep/octep_main.c | 15 +-
.../ethernet/marvell/octeon_ep/octep_main.h | 44 +--
.../marvell/octeon_ep/octep_pfvf_mbox.c | 305 ++++++++++++++++++
.../marvell/octeon_ep/octep_pfvf_mbox.h | 126 ++++++++
.../marvell/octeon_ep/octep_regs_cn9k_pf.h | 9 +
.../net/ethernet/marvell/octeon_ep/octep_tx.h | 24 +-
8 files changed, 523 insertions(+), 45 deletions(-)
create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
diff --git a/drivers/net/ethernet/marvell/octeon_ep/Makefile b/drivers/net/ethernet/marvell/octeon_ep/Makefile
index 2026c8118158..6cfa7198fdbd 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/Makefile
+++ b/drivers/net/ethernet/marvell/octeon_ep/Makefile
@@ -6,4 +6,5 @@
obj-$(CONFIG_OCTEON_EP) += octeon_ep.o
octeon_ep-y := octep_main.o octep_cn9k_pf.o octep_tx.o octep_rx.o \
- octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o
+ octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o \
+ octep_pfvf_mbox.o
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
index e307bae62673..4840133477dc 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
@@ -354,26 +354,50 @@ static void octep_setup_mbox_regs_cn93_pf(struct octep_device *oct, int q_no)
{
struct octep_mbox *mbox = oct->mbox[q_no];
- mbox->q_no = q_no;
-
- /* PF mbox interrupt reg */
- mbox->mbox_int_reg = oct->mmio[0].hw_addr + CN93_SDP_EPF_MBOX_RINT(0);
-
/* PF to VF DATA reg. PF writes into this reg */
- mbox->mbox_write_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_PF_VF_DATA(q_no);
+ mbox->pf_vf_data_reg = oct->mmio[0].hw_addr + CN93_SDP_MBOX_PF_VF_DATA(q_no);
/* VF to PF DATA reg. PF reads from this reg */
- mbox->mbox_read_reg = oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_VF_PF_DATA(q_no);
+ mbox->vf_pf_data_reg = oct->mmio[0].hw_addr + CN93_SDP_MBOX_VF_PF_DATA(q_no);
}
/* Process non-ioq interrupts required to keep pf interface running.
* OEI_RINT is needed for control mailbox
+ * MBOX_RINT is needed for pfvf mailbox
*/
static int octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct)
{
- u64 reg0;
+ u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue;
+ u64 reg0, reg1;
int handled = 0;
+ reg0 = octep_read_csr64(oct, CN93_SDP_EPF_MBOX_RINT(0));
+ reg1 = octep_read_csr64(oct, CN93_SDP_EPF_MBOX_RINT(1));
+ if (reg0 || reg1) {
+ dev_info(&oct->pdev->dev,
+ "Received MBOX_RINT intr: reg0 0x%llx reg1 0x%llx\n",
+ reg0, reg1);
+
+ active_vfs = CFG_GET_ACTIVE_VFS(oct->conf);
+ active_rings_per_vf = CFG_GET_ACTIVE_RPVF(oct->conf);
+ for (vf = 0; vf < active_vfs; vf++) {
+ vf_mbox_queue = vf * active_rings_per_vf;
+ if (!(reg0 & (0x1UL << vf_mbox_queue)))
+ continue;
+
+ if (!oct->mbox[vf_mbox_queue]) {
+ dev_err(&oct->pdev->dev, "bad mbox vf %d\n", vf);
+ continue;
+ }
+ schedule_work(&oct->mbox[vf_mbox_queue]->wk.work);
+ }
+ if (reg0)
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT(0), reg0);
+ if (reg1)
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT(1), reg1);
+
+ handled = 1;
+ }
/* Check for OEI INTR */
reg0 = octep_read_csr64(oct, CN93_SDP_EPF_OEI_RINT);
if (reg0) {
@@ -562,6 +586,8 @@ static void octep_enable_interrupts_cn93_pf(struct octep_device *oct)
octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT_ENA_W1S, -1ULL);
octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask);
octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask);
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1S(0), -1ULL);
+ octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1S(1), -1ULL);
}
/* Disable all interrupts */
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index d43161d1e38a..cd0d77ceb868 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -17,6 +17,7 @@
#include "octep_config.h"
#include "octep_main.h"
#include "octep_ctrl_net.h"
+#include "octep_pfvf_mbox.h"
#define OCTEP_INTR_POLL_TIME_MSECS 100
struct workqueue_struct *octep_wq;
@@ -1001,11 +1002,7 @@ static void octep_device_cleanup(struct octep_device *oct)
dev_info(&oct->pdev->dev, "Cleaning up Octeon Device ...\n");
- for (i = 0; i < OCTEP_MAX_VF; i++) {
- vfree(oct->mbox[i]);
- oct->mbox[i] = NULL;
- }
-
+ octep_delete_pfvf_mbox(oct);
octep_ctrl_net_uninit(oct);
oct->hw_ops.soft_reset(oct);
@@ -1100,6 +1097,14 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_err(&pdev->dev, "Device setup failed\n");
goto err_octep_config;
}
+
+ err = octep_setup_pfvf_mbox(octep_dev);
+ if (err) {
+ dev_err(&pdev->dev, " pfvf mailbox setup failed\n");
+ octep_ctrl_net_uninit(octep_dev);
+ return err;
+ }
+
INIT_WORK(&octep_dev->tx_timeout_task, octep_tx_timeout_task);
INIT_WORK(&octep_dev->ctrl_mbox_task, octep_ctrl_mbox_task);
INIT_DELAYED_WORK(&octep_dev->intr_poll_task, octep_intr_poll_task);
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
index 70cc3e236cb4..ad6d324bd525 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
@@ -94,28 +94,27 @@ struct octep_mbox_data {
u64 *data;
};
+#define MAX_VF_PF_MBOX_DATA_SIZE 384
+/* wrappers around work structs */
+struct octep_pfvf_mbox_wk {
+ struct work_struct work;
+ void *ctxptr;
+ u64 ctxul;
+};
+
/* Octeon device mailbox */
struct octep_mbox {
- /* A spinlock to protect access to this q_mbox. */
- spinlock_t lock;
-
- u32 q_no;
- u32 state;
-
- /* SLI_MAC_PF_MBOX_INT for PF, SLI_PKT_MBOX_INT for VF. */
- u8 __iomem *mbox_int_reg;
-
- /* SLI_PKT_PF_VF_MBOX_SIG(0) for PF,
- * SLI_PKT_PF_VF_MBOX_SIG(1) for VF.
- */
- u8 __iomem *mbox_write_reg;
-
- /* SLI_PKT_PF_VF_MBOX_SIG(1) for PF,
- * SLI_PKT_PF_VF_MBOX_SIG(0) for VF.
- */
- u8 __iomem *mbox_read_reg;
-
+ /* A mutex to protect access to this q_mbox. */
+ struct mutex lock;
+ u32 vf_id;
+ u32 config_data_index;
+ u32 message_len;
+ u8 __iomem *pf_vf_data_reg;
+ u8 __iomem *vf_pf_data_reg;
+ struct octep_pfvf_mbox_wk wk;
+ struct octep_device *oct;
struct octep_mbox_data mbox_data;
+ u8 config_data[MAX_VF_PF_MBOX_DATA_SIZE];
};
/* Tx/Rx queue vector per interrupt. */
@@ -193,6 +192,11 @@ struct octep_iface_link_info {
u8 oper_up;
};
+/* The Octeon VF device specific info data structure.*/
+struct octep_pfvf_info {
+ u8 mac_addr[ETH_ALEN];
+};
+
/* The Octeon device specific private data structure.
* Each Octeon device has this structure to represent all its components.
*/
@@ -259,6 +263,8 @@ struct octep_device {
/* Mailbox to talk to VFs */
struct octep_mbox *mbox[OCTEP_MAX_VF];
+ /* VFs info */
+ struct octep_pfvf_info vf_info[OCTEP_MAX_VF];
/* Work entry to handle Tx timeout */
struct work_struct tx_timeout_task;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
new file mode 100644
index 000000000000..01ead735a2e8
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell Octeon EP (EndPoint) Ethernet Driver
+ *
+ * Copyright (C) 2020 Marvell.
+ *
+ */
+#include <linux/types.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+
+#include "octep_config.h"
+#include "octep_main.h"
+#include "octep_pfvf_mbox.h"
+#include "octep_ctrl_net.h"
+
+static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ u32 vf_version = (u32)cmd.s_version.version;
+
+ if (vf_version <= OCTEP_PF_MBOX_VERSION)
+ rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ else
+ rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+}
+
+static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int status;
+
+ status = octep_ctrl_net_get_link_status(oct, vf_id);
+ if (status < 0) {
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Get VF link status failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ rsp->s_link_status.status = status;
+}
+
+static void octep_pfvf_set_link_status(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true);
+ if (err) {
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF link status failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true);
+ if (err) {
+ rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF Rx link state failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_set_mtu(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_mtu(oct, vf_id, cmd.s_set_mtu.mtu, true);
+ if (err) {
+ rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF MTU failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_set_mac_addr(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true);
+ if (err) {
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Set VF MAC address failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int err;
+
+ err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr);
+ if (err) {
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ dev_err(&oct->pdev->dev, "Get VF MAC address failed via host control Mbox\n");
+ return;
+ }
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+}
+
+int octep_setup_pfvf_mbox(struct octep_device *oct)
+{
+ int i = 0, num_vfs = 0, rings_per_vf = 0;
+ int ring = 0;
+
+ num_vfs = oct->conf->sriov_cfg.active_vfs;
+ rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
+
+ for (i = 0; i < num_vfs; i++) {
+ ring = rings_per_vf * i;
+ oct->mbox[ring] = vzalloc(sizeof(*oct->mbox[ring]));
+
+ if (!oct->mbox[ring])
+ goto free_mbox;
+
+ memset(oct->mbox[ring], 0, sizeof(struct octep_mbox));
+ mutex_init(&oct->mbox[ring]->lock);
+ INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work);
+ oct->mbox[ring]->wk.ctxptr = oct->mbox[i];
+
+ if (!oct->mbox[i])
+ oct->mbox[ring]->wk.ctxptr = oct->mbox[ring];
+
+ oct->mbox[ring]->oct = oct;
+ oct->mbox[ring]->vf_id = i;
+ oct->hw_ops.setup_mbox_regs(oct, ring);
+ }
+ return 0;
+
+free_mbox:
+ while (i) {
+ i--;
+ ring = rings_per_vf * i;
+ cancel_work_sync(&oct->mbox[ring]->wk.work);
+ mutex_destroy(&oct->mbox[ring]->lock);
+ vfree(oct->mbox[ring]);
+ oct->mbox[ring] = NULL;
+ }
+ return 1;
+}
+
+void octep_delete_pfvf_mbox(struct octep_device *oct)
+{
+ int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf;
+ int num_vfs = oct->conf->sriov_cfg.active_vfs;
+ int i = 0, ring = 0, vf_srn = 0;
+
+ for (i = 0; i < num_vfs; i++) {
+ ring = vf_srn + rings_per_vf * i;
+ if (!oct->mbox[ring])
+ continue;
+
+ if (work_pending(&oct->mbox[ring]->wk.work))
+ cancel_work_sync(&oct->mbox[ring]->wk.work);
+ vfree(oct->mbox[ring]);
+ oct->mbox[ring] = NULL;
+ }
+}
+
+static void octep_pfvf_pf_get_data(struct octep_device *oct,
+ struct octep_mbox *mbox, int vf_id,
+ union octep_pfvf_mbox_word cmd,
+ union octep_pfvf_mbox_word *rsp)
+{
+ int length = 0;
+ int i = 0;
+ int err;
+ struct octep_iface_link_info link_info;
+ struct octep_iface_rx_stats rx_stats;
+ struct octep_iface_tx_stats tx_stats;
+
+ rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+
+ if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) {
+ mbox->config_data_index = 0;
+ memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE);
+ /* Based on the OPCODE CMD the PF driver
+ * specific API should be called to fetch
+ * the requested data
+ */
+ switch (cmd.s.opcode) {
+ case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
+ memset(&link_info, 0, sizeof(link_info));
+ err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info);
+ if (!err) {
+ mbox->message_len = sizeof(link_info);
+ *((int32_t *)rsp->s_data.data) = mbox->message_len;
+ memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info));
+ } else {
+ rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ return;
+ }
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_STATS:
+ memset(&rx_stats, 0, sizeof(rx_stats));
+ memset(&tx_stats, 0, sizeof(tx_stats));
+ err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats);
+ if (!err) {
+ mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats);
+ *((int32_t *)rsp->s_data.data) = mbox->message_len;
+ memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats));
+ memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats,
+ sizeof(tx_stats));
+
+ } else {
+ rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ return;
+ }
+ break;
+ }
+ *((int32_t *)rsp->s_data.data) = mbox->message_len;
+ return;
+ }
+
+ if (mbox->message_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE)
+ length = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;
+ else
+ length = mbox->message_len;
+
+ mbox->message_len -= length;
+
+ for (i = 0; i < length; i++) {
+ rsp->s_data.data[i] =
+ mbox->config_data[mbox->config_data_index];
+ mbox->config_data_index++;
+ }
+}
+
+void octep_pfvf_mbox_work(struct work_struct *work)
+{
+ struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work);
+ union octep_pfvf_mbox_word cmd = { 0 };
+ union octep_pfvf_mbox_word rsp = { 0 };
+ struct octep_mbox *mbox = NULL;
+ struct octep_device *oct = NULL;
+ int vf_id;
+
+ mbox = (struct octep_mbox *)wk->ctxptr;
+ oct = (struct octep_device *)mbox->oct;
+ vf_id = mbox->vf_id;
+
+ mutex_lock(&mbox->lock);
+ cmd.u64 = readq(mbox->vf_pf_data_reg);
+ rsp.u64 = 0;
+
+ switch (cmd.s.opcode) {
+ case OCTEP_PFVF_MBOX_CMD_VERSION:
+ octep_pfvf_validate_version(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS:
+ octep_pfvf_get_link_status(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS:
+ octep_pfvf_set_link_status(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_RX_STATE:
+ octep_pfvf_set_rx_state(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_MTU:
+ octep_pfvf_set_mtu(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR:
+ octep_pfvf_set_mac_addr(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR:
+ octep_pfvf_get_mac_addr(oct, vf_id, cmd, &rsp);
+ break;
+ case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
+ case OCTEP_PFVF_MBOX_CMD_GET_STATS:
+ octep_pfvf_pf_get_data(oct, mbox, vf_id, cmd, &rsp);
+ break;
+ default:
+ dev_err(&oct->pdev->dev, "PF-VF mailbox: invalid opcode %d\n", cmd.s.opcode);
+ rsp.s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ break;
+ }
+ writeq(rsp.u64, mbox->vf_pf_data_reg);
+ mutex_unlock(&mbox->lock);
+}
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
new file mode 100644
index 000000000000..d113f1310655
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell Octeon EP (EndPoint) Ethernet Driver
+ *
+ * Copyright (C) 2020 Marvell.
+ *
+ */
+#ifndef _OCTEP_PFVF_MBOX_H_
+#define _OCTEP_PFVF_MBOX_H_
+
+#define OCTEP_PF_MBOX_VERSION 1
+
+enum octep_pfvf_mbox_opcode {
+ OCTEP_PFVF_MBOX_CMD_VERSION,
+ OCTEP_PFVF_MBOX_CMD_SET_MTU,
+ OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR,
+ OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR,
+ OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO,
+ OCTEP_PFVF_MBOX_CMD_GET_STATS,
+ OCTEP_PFVF_MBOX_CMD_SET_RX_STATE,
+ OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS,
+ OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS,
+ OCTEP_PFVF_MBOX_CMD_LAST,
+};
+
+enum octep_pfvf_mbox_word_type {
+ OCTEP_PFVF_MBOX_TYPE_CMD,
+ OCTEP_PFVF_MBOX_TYPE_RSP_ACK,
+ OCTEP_PFVF_MBOX_TYPE_RSP_NACK,
+};
+
+enum octep_pfvf_mbox_cmd_status {
+ OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP = 1,
+ OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT = 2,
+ OCTEP_PFVF_MBOX_CMD_STATUS_NACK = 3,
+ OCTEP_PFVF_MBOX_CMD_STATUS_BUSY = 4
+};
+
+enum octep_pfvf_mbox_state {
+ OCTEP_PFVF_MBOX_STATE_IDLE = 0,
+ OCTEP_PFVF_MBOX_STATE_BUSY = 1,
+};
+
+enum octep_pfvf_link_status {
+ OCTEP_PFVF_LINK_STATUS_DOWN,
+ OCTEP_PFVF_LINK_STATUS_UP,
+};
+
+enum octep_pfvf_link_speed {
+ OCTEP_PFVF_LINK_SPEED_NONE,
+ OCTEP_PFVF_LINK_SPEED_1000,
+ OCTEP_PFVF_LINK_SPEED_10000,
+ OCTEP_PFVF_LINK_SPEED_25000,
+ OCTEP_PFVF_LINK_SPEED_40000,
+ OCTEP_PFVF_LINK_SPEED_50000,
+ OCTEP_PFVF_LINK_SPEED_100000,
+ OCTEP_PFVF_LINK_SPEED_LAST,
+};
+
+enum octep_pfvf_link_duplex {
+ OCTEP_PFVF_LINK_HALF_DUPLEX,
+ OCTEP_PFVF_LINK_FULL_DUPLEX,
+};
+
+enum octep_pfvf_link_autoneg {
+ OCTEP_PFVF_LINK_AUTONEG,
+ OCTEP_PFVF_LINK_FIXED,
+};
+
+#define OCTEP_PFVF_MBOX_TIMEOUT_MS 500
+#define OCTEP_PFVF_MBOX_MAX_RETRIES 2
+#define OCTEP_PFVF_MBOX_VERSION 0
+#define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6
+#define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1
+#define OCTEP_PFVF_MBOX_WRITE_WAIT_TIME msecs_to_jiffies(1)
+
+union octep_pfvf_mbox_word {
+ u64 u64;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 data:48;
+ } s;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 frag:1;
+ u64 rsvd:5;
+ u8 data[6];
+ } s_data;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 version:48;
+ } s_version;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u8 mac_addr[6];
+ } s_set_mac;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 rsvd:6;
+ u64 mtu:48;
+ } s_set_mtu;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 state:1;
+ u64 rsvd:53;
+ } s_link_state;
+ struct {
+ u64 opcode:8;
+ u64 type:2;
+ u64 status:1;
+ u64 rsvd:53;
+ } s_link_status;
+} __packed;
+
+void octep_pfvf_mbox_work(struct work_struct *work);
+int octep_setup_pfvf_mbox(struct octep_device *oct);
+void octep_delete_pfvf_mbox(struct octep_device *oct);
+#endif
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
index 0466fd9a002d..f29c4344fc41 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
@@ -208,6 +208,9 @@
#define CN93_SDP_R_MBOX_PF_VF_INT_START 0x10220
#define CN93_SDP_R_MBOX_VF_PF_DATA_START 0x10230
+#define CN93_SDP_MBOX_VF_PF_DATA_START 0x24000
+#define CN93_SDP_MBOX_PF_VF_DATA_START 0x22000
+
#define CN93_SDP_R_MBOX_PF_VF_DATA(ring) \
(CN93_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CN93_RING_OFFSET))
@@ -217,6 +220,12 @@
#define CN93_SDP_R_MBOX_VF_PF_DATA(ring) \
(CN93_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CN93_RING_OFFSET))
+#define CN93_SDP_MBOX_VF_PF_DATA(ring) \
+ (CN93_SDP_MBOX_VF_PF_DATA_START + ((ring) * CN93_EPVF_RING_OFFSET))
+
+#define CN93_SDP_MBOX_PF_VF_DATA(ring) \
+ (CN93_SDP_MBOX_PF_VF_DATA_START + ((ring) * CN93_EPVF_RING_OFFSET))
+
/* ##################### Interrupt Registers ########################## */
#define CN93_SDP_R_ERR_TYPE_START 0x10400
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
index 2ef57980eb47..05788bf2cf08 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
@@ -45,6 +45,18 @@ struct octep_tx_buffer {
/* Hardware interface Tx statistics */
struct octep_iface_tx_stats {
+ /* Total frames sent on the interface */
+ u64 pkts;
+
+ /* Total octets sent on the interface */
+ u64 octs;
+
+ /* Packets sent to a broadcast DMAC */
+ u64 bcst;
+
+ /* Packets sent to the multicast DMAC */
+ u64 mcst;
+
/* Packets dropped due to excessive collisions */
u64 xscol;
@@ -61,12 +73,6 @@ struct octep_iface_tx_stats {
*/
u64 scol;
- /* Total octets sent on the interface */
- u64 octs;
-
- /* Total frames sent on the interface */
- u64 pkts;
-
/* Packets sent with an octet count < 64 */
u64 hist_lt64;
@@ -91,12 +97,6 @@ struct octep_iface_tx_stats {
/* Packets sent with an octet count of > 1518 */
u64 hist_gt1518;
- /* Packets sent to a broadcast DMAC */
- u64 bcst;
-
- /* Packets sent to the multicast DMAC */
- u64 mcst;
-
/* Packets sent that experienced a transmit underflow and were
* truncated
*/
--
2.36.0
Hi Veerasenareddy,
url: https://github.com/intel-lab-lkp/linux/commits/Veerasenareddy-Burru/octeon_ep-Update-PF-mailbox-for-VF/20221130-110134
base: 7a168f560e3c3829b74a893d3655caab14a7aef8
patch link: https://lore.kernel.org/r/20221129130933.25231-9-vburru%40marvell.com
patch subject: [PATCH net-next v2 8/9] octeon_ep: add PF-VF mailbox communication
config: ia64-randconfig-m041-20221204
compiler: ia64-linux-gcc (GCC) 12.1.0
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Reported-by: Dan Carpenter <[email protected]>
New smatch warnings:
drivers/net/ethernet/marvell/octeon_ep/octep_main.c:1105 octep_probe() warn: missing unwind goto?
vim +1105 drivers/net/ethernet/marvell/octeon_ep/octep_main.c
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1046 static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1047 {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1048 struct octep_device *octep_dev = NULL;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1049 struct net_device *netdev;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1050 int err;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1051
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1052 err = pci_enable_device(pdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1053 if (err) {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1054 dev_err(&pdev->dev, "Failed to enable PCI device\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1055 return err;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1056 }
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1057
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1058 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1059 if (err) {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1060 dev_err(&pdev->dev, "Failed to set DMA mask !!\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1061 goto err_dma_mask;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1062 }
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1063
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1064 err = pci_request_mem_regions(pdev, OCTEP_DRV_NAME);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1065 if (err) {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1066 dev_err(&pdev->dev, "Failed to map PCI memory regions\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1067 goto err_pci_regions;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1068 }
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1069
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1070 pci_enable_pcie_error_reporting(pdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1071 pci_set_master(pdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1072
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1073 #define FW_STATUS_READY 1
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1074 if (get_fw_ready_status(pdev) != FW_STATUS_READY) {
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1075 dev_notice(&pdev->dev, "Firmware not ready; defer probe.\n");
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1076 err = -EPROBE_DEFER;
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1077 goto err_alloc_netdev;
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1078 }
a36869e03997c0 Veerasenareddy Burru 2022-11-29 1079
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1080 netdev = alloc_etherdev_mq(sizeof(struct octep_device),
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1081 OCTEP_MAX_QUEUES);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1082 if (!netdev) {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1083 dev_err(&pdev->dev, "Failed to allocate netdev\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1084 err = -ENOMEM;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1085 goto err_alloc_netdev;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1086 }
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1087 SET_NETDEV_DEV(netdev, &pdev->dev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1088
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1089 octep_dev = netdev_priv(netdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1090 octep_dev->netdev = netdev;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1091 octep_dev->pdev = pdev;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1092 octep_dev->dev = &pdev->dev;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1093 pci_set_drvdata(pdev, octep_dev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1094
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1095 err = octep_device_setup(octep_dev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1096 if (err) {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1097 dev_err(&pdev->dev, "Device setup failed\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1098 goto err_octep_config;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1099 }
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1100
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1101 err = octep_setup_pfvf_mbox(octep_dev);
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1102 if (err) {
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1103 dev_err(&pdev->dev, " pfvf mailbox setup failed\n");
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1104 octep_ctrl_net_uninit(octep_dev);
f13f1764c1708a Veerasenareddy Burru 2022-11-29 @1105 return err;
This doesn't call free_netdev(netdev); so it's a leak.
The octep_device_cleanup() function calls octep_ctrl_net_uninit() but
presumably calling octep_device_cleanup() if octep_setup_pfvf_mbox()
fails is a bug... Ideally there would be a function which could clean
up octep_device_setup() and a different function which could clean up
octep_setup_pfvf_mbox() but maybe that's impossible because of weird
ordering constraints.
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1106 }
f13f1764c1708a Veerasenareddy Burru 2022-11-29 1107
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1108 INIT_WORK(&octep_dev->tx_timeout_task, octep_tx_timeout_task);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1109 INIT_WORK(&octep_dev->ctrl_mbox_task, octep_ctrl_mbox_task);
c310a95e2434e5 Veerasenareddy Burru 2022-11-29 1110 INIT_DELAYED_WORK(&octep_dev->intr_poll_task, octep_intr_poll_task);
c310a95e2434e5 Veerasenareddy Burru 2022-11-29 1111 octep_dev->poll_non_ioq_intr = true;
c310a95e2434e5 Veerasenareddy Burru 2022-11-29 1112 queue_delayed_work(octep_wq, &octep_dev->intr_poll_task,
c310a95e2434e5 Veerasenareddy Burru 2022-11-29 1113 msecs_to_jiffies(OCTEP_INTR_POLL_TIME_MSECS));
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1114
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1115 netdev->netdev_ops = &octep_netdev_ops;
5cc256e79bff06 Veerasenareddy Burru 2022-04-12 1116 octep_set_ethtool_ops(netdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1117 netif_carrier_off(netdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1118
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1119 netdev->hw_features = NETIF_F_SG;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1120 netdev->features |= netdev->hw_features;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1121 netdev->min_mtu = OCTEP_MIN_MTU;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1122 netdev->max_mtu = OCTEP_MAX_MTU;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1123 netdev->mtu = OCTEP_DEFAULT_MTU;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1124
6494f39ec1f4be Veerasenareddy Burru 2022-11-29 1125 err = octep_ctrl_net_get_mac_addr(octep_dev, OCTEP_CTRL_NET_INVALID_VFID,
6494f39ec1f4be Veerasenareddy Burru 2022-11-29 1126 octep_dev->mac_addr);
848ffce2f0c93f Ziyang Xuan 2022-11-11 1127 if (err) {
848ffce2f0c93f Ziyang Xuan 2022-11-11 1128 dev_err(&pdev->dev, "Failed to get mac address\n");
848ffce2f0c93f Ziyang Xuan 2022-11-11 1129 goto register_dev_err;
848ffce2f0c93f Ziyang Xuan 2022-11-11 1130 }
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1131 eth_hw_addr_set(netdev, octep_dev->mac_addr);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1132
0a03f3c511f57d Yang Yingliang 2022-04-15 1133 err = register_netdev(netdev);
0a03f3c511f57d Yang Yingliang 2022-04-15 1134 if (err) {
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1135 dev_err(&pdev->dev, "Failed to register netdev\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1136 goto register_dev_err;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1137 }
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1138 dev_info(&pdev->dev, "Device probe successful\n");
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1139 return 0;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1140
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1141 register_dev_err:
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1142 octep_device_cleanup(octep_dev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1143 err_octep_config:
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1144 free_netdev(netdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1145 err_alloc_netdev:
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1146 pci_disable_pcie_error_reporting(pdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1147 pci_release_mem_regions(pdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1148 err_pci_regions:
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1149 err_dma_mask:
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1150 pci_disable_device(pdev);
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1151 return err;
862cd659a6fbac Veerasenareddy Burru 2022-04-12 1152 }
--
0-DAY CI Kernel Test Service
https://01.org/lkp