From cde29af9e68e757824821d290842fbceeae11f88 Mon Sep 17 00:00:00 2001 From: Shinas Rasheed Date: Fri, 15 Dec 2023 10:14:22 -0800 Subject: [PATCH 1/4] octeon_ep: add PF-VF mailbox communication 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: Shinas Rasheed Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- .../net/ethernet/marvell/octeon_ep/Makefile | 2 +- .../marvell/octeon_ep/octep_cn9k_pf.c | 59 ++- .../marvell/octeon_ep/octep_cnxk_pf.c | 46 ++- .../marvell/octeon_ep/octep_ctrl_mbox.h | 4 +- .../ethernet/marvell/octeon_ep/octep_main.c | 83 ++++- .../ethernet/marvell/octeon_ep/octep_main.h | 45 ++- .../marvell/octeon_ep/octep_pfvf_mbox.c | 335 ++++++++++++++++++ .../marvell/octeon_ep/octep_pfvf_mbox.h | 142 ++++++++ .../marvell/octeon_ep/octep_regs_cn9k_pf.h | 9 + .../marvell/octeon_ep/octep_regs_cnxk_pf.h | 13 + .../net/ethernet/marvell/octeon_ep/octep_tx.h | 24 +- 11 files changed, 713 insertions(+), 49 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 02a4a21bc298..62162ed63f34 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/Makefile +++ b/drivers/net/ethernet/marvell/octeon_ep/Makefile @@ -7,4 +7,4 @@ 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_cnxk_pf.o + octep_pfvf_mbox.o octep_cnxk_pf.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 9209f1ec1b52..b5805969404f 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c @@ -362,16 +362,55 @@ 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); +} + +/* Poll for mailbox messages from VF */ +static void octep_poll_pfvf_mailbox(struct octep_device *oct) +{ + u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue; + u64 reg0, reg1; + + 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) { + 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 (vf_mbox_queue < 64) { + if (!(reg0 & (0x1UL << vf_mbox_queue))) + continue; + } else { + if (!(reg1 & (0x1UL << (vf_mbox_queue - 64)))) + 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); + } +} + +/* PF-VF mailbox interrupt handler */ +static irqreturn_t octep_pfvf_mbox_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct = (struct octep_device *)dev; + + octep_poll_pfvf_mailbox(oct); + return IRQ_HANDLED; } /* Poll OEI events like heartbeat */ @@ -403,6 +442,7 @@ static irqreturn_t octep_oei_intr_handler_cn93_pf(void *dev) */ static void octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct) { + octep_poll_pfvf_mailbox(oct); octep_poll_oei_cn93_pf(oct); } @@ -646,6 +686,8 @@ static void octep_enable_interrupts_cn93_pf(struct octep_device *oct) 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); octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL); octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL); @@ -672,6 +714,8 @@ static void octep_disable_interrupts_cn93_pf(struct octep_device *oct) octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1C(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_MBOX_RINT_ENA_W1C(1), -1ULL); octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL); octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL); @@ -807,6 +851,7 @@ void octep_device_setup_cn93_pf(struct octep_device *oct) oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cn93_pf; oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cn93_pf; + oct->hw_ops.mbox_intr_handler = octep_pfvf_mbox_intr_handler_cn93_pf; oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cn93_pf; oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cn93_pf; oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cn93_pf; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c index 098a0c5c4d1c..5de0b5ecbc5f 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c @@ -392,16 +392,44 @@ static void octep_setup_mbox_regs_cnxk_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 + CNXK_SDP_EPF_MBOX_RINT(0); - /* PF to VF DATA reg. PF writes into this reg */ - mbox->mbox_write_reg = oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_PF_VF_DATA(q_no); + mbox->pf_vf_data_reg = oct->mmio[0].hw_addr + CNXK_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 + CNXK_SDP_R_MBOX_VF_PF_DATA(q_no); + mbox->vf_pf_data_reg = oct->mmio[0].hw_addr + CNXK_SDP_MBOX_VF_PF_DATA(q_no); +} + +static void octep_poll_pfvf_mailbox_cnxk_pf(struct octep_device *oct) +{ + u32 vf, active_vfs, active_rings_per_vf, vf_mbox_queue; + u64 reg0; + + reg0 = octep_read_csr64(oct, CNXK_SDP_EPF_MBOX_RINT(0)); + if (reg0) { + 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, CNXK_SDP_EPF_MBOX_RINT(0), reg0); + } +} + +static irqreturn_t octep_pfvf_mbox_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct = (struct octep_device *)dev; + + octep_poll_pfvf_mailbox_cnxk_pf(oct); + return IRQ_HANDLED; } /* Poll OEI events like heartbeat */ @@ -435,6 +463,7 @@ static irqreturn_t octep_oei_intr_handler_cnxk_pf(void *dev) */ static void octep_poll_non_ioq_interrupts_cnxk_pf(struct octep_device *oct) { + octep_poll_pfvf_mailbox_cnxk_pf(oct); octep_poll_oei_cnxk_pf(oct); } @@ -682,6 +711,7 @@ static void octep_enable_interrupts_cnxk_pf(struct octep_device *oct) octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask); octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_MBOX_RINT_ENA_W1S(0), -1ULL); octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL); octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL); @@ -708,6 +738,7 @@ static void octep_disable_interrupts_cnxk_pf(struct octep_device *oct) octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask); octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_MBOX_RINT_ENA_W1C(0), -1ULL); octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL); octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL); @@ -843,6 +874,7 @@ void octep_device_setup_cnxk_pf(struct octep_device *oct) oct->hw_ops.setup_oq_regs = octep_setup_oq_regs_cnxk_pf; oct->hw_ops.setup_mbox_regs = octep_setup_mbox_regs_cnxk_pf; + oct->hw_ops.mbox_intr_handler = octep_pfvf_mbox_intr_handler_cnxk_pf; oct->hw_ops.oei_intr_handler = octep_oei_intr_handler_cnxk_pf; oct->hw_ops.ire_intr_handler = octep_ire_intr_handler_cnxk_pf; oct->hw_ops.ore_intr_handler = octep_ore_intr_handler_cnxk_pf; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h index 7f8135788efc..6da32d40f926 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h @@ -16,10 +16,12 @@ * |reserved (4 bytes) | * |-------------------------------------------| * |host version (8 bytes) | + * | low 32 bits | * |host status (8 bytes) | * |host reserved (104 bytes) | * |-------------------------------------------| - * |fw version (8 bytes) | + * |fw version's (8 bytes) | + * | min=high 32 bits, max=low 32 bits | * |fw status (8 bytes) | * |fw reserved (104 bytes) | * |===========================================| diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c index e56188f1d09b..7c9faa714a10 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c @@ -16,6 +16,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; @@ -159,6 +160,21 @@ static void octep_disable_msix(struct octep_device *oct) dev_info(&oct->pdev->dev, "Disabled MSI-X\n"); } +/** + * octep_mbox_intr_handler() - common handler for pfvf mbox interrupts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for pfvf mbox interrupts. + */ +static irqreturn_t octep_mbox_intr_handler(int irq, void *data) +{ + struct octep_device *oct = data; + + return oct->hw_ops.mbox_intr_handler(oct); +} + /** * octep_oei_intr_handler() - common handler for output endpoint interrupts. * @@ -362,8 +378,12 @@ static int octep_request_irqs(struct octep_device *oct) snprintf(irq_name, OCTEP_MSIX_NAME_SIZE, "%s-%s", netdev->name, non_ioq_msix_names[i]); - if (!strncmp(non_ioq_msix_names[i], "epf_oei_rint", - strlen("epf_oei_rint"))) { + if (!strncmp(non_ioq_msix_names[i], "epf_mbox_rint", strlen("epf_mbox_rint"))) { + ret = request_irq(msix_entry->vector, + octep_mbox_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_oei_rint", + strlen("epf_oei_rint"))) { ret = request_irq(msix_entry->vector, octep_oei_intr_handler, 0, irq_name, oct); @@ -1322,6 +1342,7 @@ static void octep_device_cleanup(struct octep_device *oct) oct->mbox[i] = NULL; } + octep_delete_pfvf_mbox(oct); octep_ctrl_net_uninit(oct); cancel_delayed_work_sync(&oct->hb_task); @@ -1419,6 +1440,12 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_octep_config; } + err = octep_setup_pfvf_mbox(octep_dev); + if (err) { + dev_err(&pdev->dev, "PF-VF mailbox setup failed\n"); + goto register_dev_err; + } + err = octep_ctrl_net_get_info(octep_dev, OCTEP_CTRL_NET_INVALID_VFID, &octep_dev->conf->fw_info); if (err) { @@ -1487,6 +1514,21 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } +static int octep_sriov_disable(struct octep_device *oct) +{ + struct pci_dev *pdev = oct->pdev; + + if (pci_vfs_assigned(oct->pdev)) { + dev_warn(&pdev->dev, "Can't disable SRIOV while VFs are assigned\n"); + return -EPERM; + } + + pci_disable_sriov(pdev); + CFG_GET_ACTIVE_VFS(oct->conf) = 0; + + return 0; +} + /** * octep_remove() - Remove Octeon PCI device from driver control. * @@ -1504,6 +1546,7 @@ static void octep_remove(struct pci_dev *pdev) return; netdev = oct->netdev; + octep_sriov_disable(oct); if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); @@ -1514,11 +1557,47 @@ static void octep_remove(struct pci_dev *pdev) pci_disable_device(pdev); } +static int octep_sriov_enable(struct octep_device *oct, int num_vfs) +{ + struct pci_dev *pdev = oct->pdev; + int err; + + CFG_GET_ACTIVE_VFS(oct->conf) = num_vfs; + err = pci_enable_sriov(pdev, num_vfs); + if (err) { + dev_warn(&pdev->dev, "Failed to enable SRIOV err=%d\n", err); + CFG_GET_ACTIVE_VFS(oct->conf) = 0; + return err; + } + + return num_vfs; +} + +static int octep_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + struct octep_device *oct = pci_get_drvdata(pdev); + int max_nvfs; + + if (num_vfs == 0) + return octep_sriov_disable(oct); + + max_nvfs = CFG_GET_MAX_VFS(oct->conf); + + if (num_vfs > max_nvfs) { + dev_err(&pdev->dev, "Invalid VF count Max supported VFs = %d\n", + max_nvfs); + return -EINVAL; + } + + return octep_sriov_enable(oct, num_vfs); +} + static struct pci_driver octep_driver = { .name = OCTEP_DRV_NAME, .id_table = octep_pci_id_tbl, .probe = octep_probe, .remove = octep_remove, + .sriov_configure = octep_sriov_configure, }; /** diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h index 2cb93d425744..3223bb6f95ea 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h @@ -80,6 +80,7 @@ struct octep_hw_ops { void (*setup_oq_regs)(struct octep_device *oct, int q); void (*setup_mbox_regs)(struct octep_device *oct, int mbox); + irqreturn_t (*mbox_intr_handler)(void *ioq_vector); irqreturn_t (*oei_intr_handler)(void *ioq_vector); irqreturn_t (*ire_intr_handler)(void *ioq_vector); irqreturn_t (*ore_intr_handler)(void *ioq_vector); @@ -118,28 +119,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. */ @@ -217,6 +217,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. */ @@ -282,6 +287,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..0557c138060f --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_PFVF_MBOX_VERSION_V1) + 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_get_mtu(struct octep_device *oct, u32 vf_id, + union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + int max_rx_pktlen = oct->netdev->max_mtu + (ETH_HLEN + ETH_FCS_LEN); + + rsp->s_set_mtu.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; + rsp->s_get_mtu.mtu = max_rx_pktlen; +} + +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; +} + +static void octep_pfvf_dev_remove(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_dev_remove(oct, vf_id); + if (err) { + rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; + dev_err(&oct->pdev->dev, "Failed to acknowledge fw of vf %d removal\n", + vf_id); + return; + } + rsp->s.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[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 -ENOMEM; +} + +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); + + mutex_destroy(&oct->mbox[ring]->lock); + 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; + case OCTEP_PFVF_MBOX_CMD_GET_MTU: + octep_pfvf_get_mtu(oct, vf_id, cmd, &rsp); + break; + case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE: + octep_pfvf_dev_remove(oct, 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..83c072d97512 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h @@ -0,0 +1,142 @@ +/* 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_ + +/* VF flags */ +#define OCTEON_PFVF_FLAG_MAC_SET_BY_PF BIT_ULL(0) /* PF has set VF MAC address */ +#define OCTEON_SDP_16K_HW_FRS 16380UL +#define OCTEON_SDP_64K_HW_FRS 65531UL + +enum octep_pfvf_mbox_version { + OCTEP_PFVF_MBOX_VERSION_V0, + OCTEP_PFVF_MBOX_VERSION_V1, +}; + +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_GET_MTU, + OCTEP_PFVF_MBOX_CMD_DEV_REMOVE, + OCTEP_PFVF_MBOX_CMD_MAX, +}; + +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_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 rsvd:6; + u64 mtu:48; + } s_get_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 2e20a39d89af..ca473502d7a0 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_regs_cnxk_pf.h b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h index ea677f760ef0..e637d7c8224d 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h @@ -183,6 +183,7 @@ #define CNXK_SDP_R_OUT_INT_MDRT_CTL1_START 0x103A0 #define CNXK_SDP_R_OUT_INT_MDRT_DBG_START 0x103C0 +#define CNXK_SDP_R_MBOX_ISM_START 0x10500 #define CNXK_SDP_R_OUT_CNTS_ISM_START 0x10510 #define CNXK_SDP_R_IN_CNTS_ISM_START 0x10520 @@ -204,6 +205,9 @@ #define CNXK_SDP_R_OUT_INT_MDRT_DBG(ring) \ (CNXK_SDP_R_OUT_INT_MDRT_DBG_START + ((ring) * CNXK_RING_OFFSET)) +#define CNXK_SDP_R_MBOX_ISM(ring) \ + (CNXK_SDP_R_MBOX_ISM_START + ((ring) * CNXK_RING_OFFSET)) + #define CNXK_SDP_R_OUT_CNTS_ISM(ring) \ (CNXK_SDP_R_OUT_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) @@ -222,6 +226,9 @@ #define CNXK_SDP_R_MBOX_PF_VF_INT_START 0x10220 #define CNXK_SDP_R_MBOX_VF_PF_DATA_START 0x10230 +#define CNXK_SDP_MBOX_VF_PF_DATA_START 0x24000 +#define CNXK_SDP_MBOX_PF_VF_DATA_START 0x22000 + #define CNXK_SDP_R_MBOX_PF_VF_DATA(ring) \ (CNXK_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CNXK_RING_OFFSET)) @@ -231,6 +238,12 @@ #define CNXK_SDP_R_MBOX_VF_PF_DATA(ring) \ (CNXK_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CNXK_RING_OFFSET)) +#define CNXK_SDP_MBOX_VF_PF_DATA(ring) \ + (CNXK_SDP_MBOX_VF_PF_DATA_START + ((ring) * CNXK_EPVF_RING_OFFSET)) + +#define CNXK_SDP_MBOX_PF_VF_DATA(ring) \ + (CNXK_SDP_MBOX_PF_VF_DATA_START + ((ring) * CNXK_EPVF_RING_OFFSET)) + /* ##################### Interrupt Registers ########################## */ #define CNXK_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 059fa921069f..875a2c34091f 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.h @@ -61,6 +61,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; @@ -77,12 +89,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; @@ -107,12 +113,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 */ From c130e589d50bbf43eb77d45b806b38cf95e2bad9 Mon Sep 17 00:00:00 2001 From: Shinas Rasheed Date: Fri, 15 Dec 2023 10:14:23 -0800 Subject: [PATCH 2/4] octeon_ep: PF-VF mailbox version support Add PF-VF mailbox initial version support Signed-off-by: Shinas Rasheed Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- .../net/ethernet/marvell/octeon_ep/octep_main.h | 1 + .../ethernet/marvell/octeon_ep/octep_pfvf_mbox.c | 15 ++++++++++++--- .../ethernet/marvell/octeon_ep/octep_pfvf_mbox.h | 4 ++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h index 3223bb6f95ea..fee59e0e0138 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h @@ -220,6 +220,7 @@ struct octep_iface_link_info { /* The Octeon VF device specific info data structure.*/ struct octep_pfvf_info { u8 mac_addr[ETH_ALEN]; + u32 mbox_version; }; /* The Octeon device specific private data structure. diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c index 0557c138060f..fb4da72e5193 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c @@ -27,10 +27,18 @@ static void octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id, { u32 vf_version = (u32)cmd.s_version.version; - if (vf_version <= OCTEP_PFVF_MBOX_VERSION_V1) - rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; + dev_dbg(&oct->pdev->dev, "VF id:%d VF version:%d PF version:%d\n", + vf_id, vf_version, OCTEP_PFVF_MBOX_VERSION_CURRENT); + if (vf_version < OCTEP_PFVF_MBOX_VERSION_CURRENT) + rsp->s_version.version = vf_version; else - rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; + rsp->s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT; + + oct->vf_info[vf_id].mbox_version = rsp->s_version.version; + dev_dbg(&oct->pdev->dev, "VF id:%d negotiated VF version:%d\n", + vf_id, oct->vf_info[vf_id].mbox_version); + + rsp->s_version.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; } static void octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id, @@ -166,6 +174,7 @@ int octep_setup_pfvf_mbox(struct octep_device *oct) goto free_mbox; memset(oct->mbox[ring], 0, sizeof(struct octep_mbox)); + memset(&oct->vf_info[i], 0, sizeof(struct octep_pfvf_info)); mutex_init(&oct->mbox[ring]->lock); INIT_WORK(&oct->mbox[ring]->wk.work, octep_pfvf_mbox_work); oct->mbox[ring]->wk.ctxptr = oct->mbox[ring]; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h index 83c072d97512..af4dcf5ef7f1 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h @@ -13,11 +13,15 @@ #define OCTEON_SDP_16K_HW_FRS 16380UL #define OCTEON_SDP_64K_HW_FRS 65531UL +/* When a new command is implemented,PF Mbox version should be bumped. + */ enum octep_pfvf_mbox_version { OCTEP_PFVF_MBOX_VERSION_V0, OCTEP_PFVF_MBOX_VERSION_V1, }; +#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V1 + enum octep_pfvf_mbox_opcode { OCTEP_PFVF_MBOX_CMD_VERSION, OCTEP_PFVF_MBOX_CMD_SET_MTU, From e28db8cbeba3a55dfaf43554d2c2ce05da6f4a04 Mon Sep 17 00:00:00 2001 From: Shinas Rasheed Date: Fri, 15 Dec 2023 10:14:24 -0800 Subject: [PATCH 3/4] octeon_ep: control net framework to support VF offloads Inquire firmware on supported offloads, as well as convey offloads enabled dynamically to firmware for the VFs. Implement control net API to support the same. Signed-off-by: Shinas Rasheed Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- .../marvell/octeon_ep/octep_pfvf_mbox.c | 47 +++++++++++++++++++ .../marvell/octeon_ep/octep_pfvf_mbox.h | 21 ++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c index fb4da72e5193..dbb5b8f4ef30 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c @@ -158,6 +158,47 @@ static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id, rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; } +static void octep_pfvf_get_fw_info(struct octep_device *oct, u32 vf_id, + union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + struct octep_fw_info fw_info; + int err; + + err = octep_ctrl_net_get_info(oct, vf_id, &fw_info); + if (err) { + rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; + dev_err(&oct->pdev->dev, "Get VF info failed via host control Mbox\n"); + return; + } + + rsp->s_fw_info.pkind = fw_info.pkind; + rsp->s_fw_info.fsz = fw_info.fsz; + rsp->s_fw_info.rx_ol_flags = fw_info.rx_ol_flags; + rsp->s_fw_info.tx_ol_flags = fw_info.tx_ol_flags; + + rsp->s_fw_info.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; +} + +static void octep_pfvf_set_offloads(struct octep_device *oct, u32 vf_id, + union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + struct octep_ctrl_net_offloads offloads = { + .rx_offloads = cmd.s_offloads.rx_ol_flags, + .tx_offloads = cmd.s_offloads.tx_ol_flags + }; + int err; + + err = octep_ctrl_net_set_offloads(oct, vf_id, &offloads, true); + if (err) { + rsp->s_offloads.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; + dev_err(&oct->pdev->dev, "Set VF offloads failed via host control Mbox\n"); + return; + } + rsp->s_offloads.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; @@ -334,6 +375,12 @@ void octep_pfvf_mbox_work(struct work_struct *work) case OCTEP_PFVF_MBOX_CMD_DEV_REMOVE: octep_pfvf_dev_remove(oct, vf_id, cmd, &rsp); break; + case OCTEP_PFVF_MBOX_CMD_GET_FW_INFO: + octep_pfvf_get_fw_info(oct, vf_id, cmd, &rsp); + break; + case OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS: + octep_pfvf_set_offloads(oct, 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; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h index af4dcf5ef7f1..c18a9f26fc31 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h @@ -18,9 +18,10 @@ enum octep_pfvf_mbox_version { OCTEP_PFVF_MBOX_VERSION_V0, OCTEP_PFVF_MBOX_VERSION_V1, + OCTEP_PFVF_MBOX_VERSION_V2, }; -#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V1 +#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V2 enum octep_pfvf_mbox_opcode { OCTEP_PFVF_MBOX_CMD_VERSION, @@ -34,6 +35,8 @@ enum octep_pfvf_mbox_opcode { OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS, OCTEP_PFVF_MBOX_CMD_GET_MTU, OCTEP_PFVF_MBOX_CMD_DEV_REMOVE, + OCTEP_PFVF_MBOX_CMD_GET_FW_INFO, + OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS, OCTEP_PFVF_MBOX_CMD_MAX, }; @@ -138,6 +141,22 @@ union octep_pfvf_mbox_word { u64 status:1; u64 rsvd:53; } s_link_status; + struct { + u64 opcode:8; + u64 type:2; + u64 pkind:8; + u64 fsz:8; + u64 rx_ol_flags:16; + u64 tx_ol_flags:16; + u64 rsvd:6; + } s_fw_info; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:22; + u64 rx_ol_flags:16; + u64 tx_ol_flags:16; + } s_offloads; } __packed; void octep_pfvf_mbox_work(struct work_struct *work); From 4ebb86a97ceb948b32cbeafb598617a6c8748376 Mon Sep 17 00:00:00 2001 From: Shinas Rasheed Date: Fri, 15 Dec 2023 10:14:25 -0800 Subject: [PATCH 4/4] octeon_ep: support firmware notifications for VFs Notifications from firmware to vf has to pass through PF control mbox and via PF-VF mailboxes. The notifications have to be parsed out from the control mbox and passed to the PF-VF mailbox in order to reach the corresponding VF. Version compatibility should also be checked before messages are passed to the mailboxes. Signed-off-by: Shinas Rasheed Reviewed-by: Simon Horman Signed-off-by: Paolo Abeni --- .../marvell/octeon_ep/octep_ctrl_net.c | 6 ++ .../marvell/octeon_ep/octep_pfvf_mbox.c | 58 +++++++++++++++++++ .../marvell/octeon_ep/octep_pfvf_mbox.h | 2 + 3 files changed, 66 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c index 9dff2166dbb7..01b7be154c38 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c @@ -13,6 +13,7 @@ #include "octep_config.h" #include "octep_main.h" #include "octep_ctrl_net.h" +#include "octep_pfvf_mbox.h" /* Control plane version */ #define OCTEP_CP_VERSION_CURRENT OCTEP_CP_VERSION(1, 0, 0) @@ -329,6 +330,11 @@ static int process_mbox_notify(struct octep_device *oct, octep_ctrl_net_f2h_cmd_versions[cmd] < OCTEP_CP_VERSION_CURRENT) return -EOPNOTSUPP; + if (msg->hdr.s.is_vf) { + octep_pfvf_notify(oct, msg); + return 0; + } + switch (cmd) { case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS: if (netif_running(netdev)) { diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c index dbb5b8f4ef30..2e2c3be8a0b4 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c @@ -21,6 +21,15 @@ #include "octep_pfvf_mbox.h" #include "octep_ctrl_net.h" +/* When a new command is implemented, the below table should be updated + * with new command and it's version info. + */ +static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = { + [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1, + [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] = + OCTEP_PFVF_MBOX_VERSION_V2 +}; + 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) @@ -87,6 +96,34 @@ static void octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id, rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; } +static int octep_send_notification(struct octep_device *oct, u32 vf_id, + union octep_pfvf_mbox_word cmd) +{ + u32 max_rings_per_vf, vf_mbox_queue; + struct octep_mbox *mbox; + + /* check if VF PF Mailbox is compatible for this notification */ + if (pfvf_cmd_versions[cmd.s.opcode] > oct->vf_info[vf_id].mbox_version) { + dev_dbg(&oct->pdev->dev, "VF Mbox doesn't support Notification:%d on VF ver:%d\n", + cmd.s.opcode, oct->vf_info[vf_id].mbox_version); + return -EOPNOTSUPP; + } + + max_rings_per_vf = CFG_GET_MAX_RPVF(oct->conf); + vf_mbox_queue = vf_id * max_rings_per_vf; + if (!oct->mbox[vf_mbox_queue]) { + dev_err(&oct->pdev->dev, "Notif obtained for bad mbox vf %d\n", vf_id); + return -EINVAL; + } + mbox = oct->mbox[vf_mbox_queue]; + + mutex_lock(&mbox->lock); + writeq(cmd.u64, mbox->pf_vf_data_reg); + mutex_unlock(&mbox->lock); + + return 0; +} + 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) @@ -326,6 +363,27 @@ static void octep_pfvf_pf_get_data(struct octep_device *oct, } } +void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg) +{ + union octep_pfvf_mbox_word notif = { 0 }; + struct octep_ctrl_net_f2h_req *req; + + req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg; + switch (req->hdr.s.cmd) { + case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS: + notif.s_link_status.opcode = OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS; + notif.s_link_status.status = req->link.state; + break; + default: + pr_info("Unknown mbox notif for vf: %u\n", + req->hdr.s.cmd); + return; + } + + notif.s.type = OCTEP_PFVF_MBOX_TYPE_CMD; + octep_send_notification(oct, msg->hdr.s.vf_idx, notif); +} + void octep_pfvf_mbox_work(struct work_struct *work) { struct octep_pfvf_mbox_wk *wk = container_of(work, struct octep_pfvf_mbox_wk, work); diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h index c18a9f26fc31..0dc6eead292a 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h @@ -37,6 +37,7 @@ enum octep_pfvf_mbox_opcode { OCTEP_PFVF_MBOX_CMD_DEV_REMOVE, OCTEP_PFVF_MBOX_CMD_GET_FW_INFO, OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS, + OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS, OCTEP_PFVF_MBOX_CMD_MAX, }; @@ -162,4 +163,5 @@ union octep_pfvf_mbox_word { 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); +void octep_pfvf_notify(struct octep_device *oct, struct octep_ctrl_mbox_msg *msg); #endif