lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Wed, 9 Feb 2022 14:50:10 -0800 From: Radha Mohan Chintakuntla <radhac@...vell.com> To: <linux-arm-kernel@...ts.infradead.org>, <arnd@...db.de>, <linus.walleij@...aro.org> CC: <linux-kernel@...r.kernel.org>, <sburla@...vell.com>, "Radha Mohan Chintakuntla" <radhac@...vell.com> Subject: [PATCH] soc: octeontx2-dpi: Add DPI DMA PF driver DPI DMA block in the Octeon TX2 SoC provides support for DMA between memory to memory transfers and also transfers between a host and Octeon Tx2 when it is in PCIe endpoint mode. Signed-off-by: Radha Mohan Chintakuntla <radhac@...vell.com> --- MAINTAINERS | 7 + drivers/soc/marvell/Kconfig | 10 + drivers/soc/marvell/Makefile | 1 + drivers/soc/marvell/octeontx2-dpi/Makefile | 8 + drivers/soc/marvell/octeontx2-dpi/dpi.c | 563 +++++++++++++++++++++ drivers/soc/marvell/octeontx2-dpi/dpi.h | 335 ++++++++++++ 6 files changed, 924 insertions(+) create mode 100644 drivers/soc/marvell/octeontx2-dpi/Makefile create mode 100644 drivers/soc/marvell/octeontx2-dpi/dpi.c create mode 100644 drivers/soc/marvell/octeontx2-dpi/dpi.h diff --git a/MAINTAINERS b/MAINTAINERS index fb48e0317d34..f39f64f0bc1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11463,6 +11463,13 @@ S: Maintained F: drivers/crypto/marvell/ F: include/linux/soc/marvell/octeontx2/ +MARVELL OCTEONTX2 DPI DMA PHYISCAL FUNCTION DRIVER +M: Radha Mohan Chintakuntla <radhac@...vell.com> +M: Veerasenareddy Burry <vburru@...vell.com> +L: linux-arm-kernel@...ts.infradead.org +S: Supported +F: drivers/soc/marvell/octeontx2-dpi/ + MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner <mlindner@...vell.com> M: Stephen Hemminger <stephen@...workplumber.org> diff --git a/drivers/soc/marvell/Kconfig b/drivers/soc/marvell/Kconfig index 4e8f8a60b3df..6e185e98a02c 100644 --- a/drivers/soc/marvell/Kconfig +++ b/drivers/soc/marvell/Kconfig @@ -4,6 +4,16 @@ menu "Marvell SoC drivers" +config OCTEONTX2_DPI_PF + tristate "OcteonTX2 DPI-DMA PF driver" + depends on ARM64 && PCI + default m + help + Select this option to enable DPI PF driver support. + DPI (DMA packet interface) provides DMA support for MAC. + This driver intializes DPI PF device and enables VFs for supporting + different types of DMA transfers. + config OCTEONTX2_SDP_PF tristate "OcteonTX2 SDP PF driver" depends on ARM64 && PCI && OCTEONTX2_AF && OCTEONTX2_MBOX diff --git a/drivers/soc/marvell/Makefile b/drivers/soc/marvell/Makefile index 9a9a4435d64d..a1835a44a22c 100644 --- a/drivers/soc/marvell/Makefile +++ b/drivers/soc/marvell/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 +obj-y += octeontx2-dpi/ obj-y += octeontx2-sdp/ diff --git a/drivers/soc/marvell/octeontx2-dpi/Makefile b/drivers/soc/marvell/octeontx2-dpi/Makefile new file mode 100644 index 000000000000..73640517593c --- /dev/null +++ b/drivers/soc/marvell/octeontx2-dpi/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for Marvell's OcteonTX2 DPI PF driver +# + +obj-$(CONFIG_OCTEONTX2_DPI_PF) += octeontx2_dpi.o + +octeontx2_dpi-y := dpi.o diff --git a/drivers/soc/marvell/octeontx2-dpi/dpi.c b/drivers/soc/marvell/octeontx2-dpi/dpi.c new file mode 100644 index 000000000000..9dd7167e930c --- /dev/null +++ b/drivers/soc/marvell/octeontx2-dpi/dpi.c @@ -0,0 +1,563 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell OcteonTx2 DPI PF driver + * + * Copyright (C) 2022 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/module.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/sysfs.h> + +#include "dpi.h" + +#define DPI_DRV_NAME "octeontx2-dpi" +#define DPI_DRV_STRING "Marvell OcteonTX2 DPI-DMA Driver" +#define DPI_DRV_VERSION "1.0" + +static int mps = 128; +module_param(mps, int, 0644); +MODULE_PARM_DESC(mps, "Maximum payload size, Supported sizes are 128, 256, 512 and 1024 bytes"); + +static int mrrs = 128; +module_param(mrrs, int, 0644); +MODULE_PARM_DESC(mrrs, "Maximum read request size, Supported sizes are 128, 256, 512 and 1024 bytes"); + +static inline bool is_otx3_dpi(struct dpipf *dpi) +{ + if (dpi->pdev->subsystem_device >= PCI_SUBDEVID_OCTEONTX3_DPI_PF) + return 1; + + return 0; +} + +static void dpi_reg_write(struct dpipf *dpi, u64 offset, u64 val) +{ + writeq(val, dpi->reg_base + offset); +} + +static u64 dpi_reg_read(struct dpipf *dpi, u64 offset) +{ + return readq(dpi->reg_base + offset); +} + +static int dpi_dma_engine_get_num(void) +{ + return DPI_MAX_ENGINES; +} + +static int dpi_queue_init(struct dpipf *dpi, struct dpipf_vf *dpivf, u8 vf) +{ + int engine = 0; + int queue = vf; + u64 reg = 0ULL; + u32 aura = dpivf->vf_config.aura; + u16 buf_size = dpivf->vf_config.csize; + u16 sso_pf_func = dpivf->vf_config.sso_pf_func; + u16 npa_pf_func = dpivf->vf_config.npa_pf_func; + + reg = DPI_DMA_IBUFF_CSIZE_CSIZE((u64)(buf_size / 8)); + if (is_otx3_dpi(dpi)) + reg |= DPI_DMA_IBUFF_CSIZE_NPA_FREE; + dpi_reg_write(dpi, DPI_DMAX_IBUFF_CSIZE(queue), reg); + + if (!is_otx3_dpi(dpi)) { + /* IDs are already configured while creating the domains. + * No need to configure here. + */ + for (engine = 0; engine < dpi_dma_engine_get_num(); engine++) { + /* Don't configure the queues for PKT engines */ + if (engine >= 4) + break; + + reg = 0; + reg = dpi_reg_read(dpi, DPI_DMA_ENGX_EN(engine)); + reg |= DPI_DMA_ENG_EN_QEN(0x1 << queue); + dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), reg); + } + } + + reg = dpi_reg_read(dpi, DPI_DMAX_IDS2(queue)); + reg |= DPI_DMA_IDS2_INST_AURA(aura); + dpi_reg_write(dpi, DPI_DMAX_IDS2(queue), reg); + + reg = dpi_reg_read(dpi, DPI_DMAX_IDS(queue)); + reg |= DPI_DMA_IDS_DMA_NPA_PF_FUNC(npa_pf_func); + reg |= DPI_DMA_IDS_DMA_SSO_PF_FUNC(sso_pf_func); + reg |= DPI_DMA_IDS_DMA_STRM(vf + 1); + reg |= DPI_DMA_IDS_INST_STRM(vf + 1); + dpi_reg_write(dpi, DPI_DMAX_IDS(queue), reg); + + return 0; +} + +static int dpi_queue_fini(struct dpipf *dpi, struct dpipf_vf *dpivf, u8 vf) +{ + u64 reg = 0ULL; + int engine = 0; + int queue = vf; + u16 buf_size = dpivf->vf_config.csize; + + for (engine = 0; engine < dpi_dma_engine_get_num(); engine++) { + /* Don't configure the queues for PKT engines */ + if (engine >= 4) + break; + + reg = 0; + reg = dpi_reg_read(dpi, DPI_DMA_ENGX_EN(engine)); + reg &= DPI_DMA_ENG_EN_QEN((~(1 << queue))); + dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), reg); + } + + dpi_reg_write(dpi, DPI_DMAX_QRST(queue), 0x1ULL); + /* TBD: below code required ? */ + dpi_reg_write(dpi, DPI_DMAX_IBUFF_CSIZE(queue), + DPI_DMA_IBUFF_CSIZE_CSIZE((u64)(buf_size))); + + /* Reset IDS and IDS2 registers */ + dpi_reg_write(dpi, DPI_DMAX_IDS2(queue), 0ULL); + dpi_reg_write(dpi, DPI_DMAX_IDS(queue), 0ULL); + + return 0; +} + +/** + * Global initialization of DPI + * + * @dpi: DPI device context structure + * @return Zero on success, negative on failure + */ +static int dpi_init(struct dpipf *dpi) +{ + int engine = 0, port = 0; + u8 mrrs_val, mps_val; + u64 reg = 0ULL; + + for (engine = 0; engine < dpi_dma_engine_get_num(); engine++) { + if (engine == 4 || engine == 5) + reg = DPI_ENG_BUF_BLKS(16); + else + reg = DPI_ENG_BUF_BLKS(8); + + dpi_reg_write(dpi, DPI_ENGX_BUF(engine), reg); + + /* Here qmap for the engines are set to 0. + * No dpi queues are mapped to engines. + * When a VF is initialised corresponding bit + * in the qmap will be set for all engines. + */ + if (!is_otx3_dpi(dpi)) + dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), 0x0ULL); + } + + reg = 0ULL; + reg = (DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_PKT_EN | + DPI_DMA_CONTROL_LDWB | DPI_DMA_CONTROL_O_MODE); + + if (is_otx3_dpi(dpi)) + reg |= DPI_DMA_CONTROL_DMA_ENB(0x3fULL); + else + reg |= DPI_DMA_CONTROL_DMA_ENB(0xfULL); + + dpi_reg_write(dpi, DPI_DMA_CONTROL, reg); + dpi_reg_write(dpi, DPI_CTL, DPI_CTL_EN); + + /* Configure MPS and MRRS for DPI */ + if (mrrs < DPI_EBUS_MRRS_MIN || mrrs > DPI_EBUS_MRRS_MAX || + !is_power_of_2(mrrs)) { + dev_info(&dpi->pdev->dev, + "Invalid MRRS size:%d, Using default size(128 bytes)\n" + , mrrs); + mrrs = 128; + } + mrrs_val = fls(mrrs) - 8; + + if (mps < DPI_EBUS_MPS_MIN || mps > DPI_EBUS_MPS_MAX + || !is_power_of_2(mps)) { + dev_info(&dpi->pdev->dev, + "Invalid MPS size:%d, Using default size(128 bytes)\n" + , mps); + mps = 128; + } + mps_val = fls(mps) - 8; + + for (port = 0; port < DPI_EBUS_MAX_PORTS; port++) { + reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(port)); + reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(0x7) | + DPI_EBUS_PORTX_CFG_MPS(0x7)); + reg |= (DPI_EBUS_PORTX_CFG_MPS(mps_val) | + DPI_EBUS_PORTX_CFG_MRRS(mrrs_val)); + dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(port), reg); + } + + /* Set the write control FIFO threshold as per HW recommendation */ + if (is_otx3_dpi(dpi)) + dpi_reg_write(dpi, DPI_WCTL_FIF_THR, 0x30); + + return 0; +} + +static int dpi_fini(struct dpipf *dpi) +{ + int engine = 0, port; + u64 reg = 0ULL; + + for (engine = 0; engine < dpi_dma_engine_get_num(); engine++) { + + dpi_reg_write(dpi, DPI_ENGX_BUF(engine), reg); + if (!is_otx3_dpi(dpi)) + dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), 0x0ULL); + } + + reg = 0ULL; + dpi_reg_write(dpi, DPI_DMA_CONTROL, reg); + dpi_reg_write(dpi, DPI_CTL, ~DPI_CTL_EN); + + for (port = 0; port < DPI_EBUS_MAX_PORTS; port++) { + reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(port)); + reg &= ~DPI_EBUS_PORTX_CFG_MRRS(0x7); + reg &= ~DPI_EBUS_PORTX_CFG_MPS(0x7); + dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(port), reg); + } + return 0; +} + +static int dpi_queue_reset(struct dpipf *dpi, u16 queue) +{ + /* Nothing to do yet */ + return 0; +} + +static irqreturn_t dpi_pf_intr_handler (int irq, void *dpi_irq) +{ + u64 reg_val = 0; + int i = 0; + struct dpipf *dpi = (struct dpipf *)dpi_irq; + + dev_err(&dpi->pdev->dev, "intr received: %d\n", irq); + + /* extract MSIX vector number from irq number. */ + while (irq != pci_irq_vector(dpi->pdev, i)) { + i++; + if (i > dpi->num_vec) + break; + } + if (i < DPI_REQQX_INT_IDX) { + reg_val = dpi_reg_read(dpi, DPI_DMA_CCX_INT(i)); + dev_err(&dpi->pdev->dev, "DPI_CC%d_INT raised: 0x%016llx\n", + i, reg_val); + dpi_reg_write(dpi, DPI_DMA_CCX_INT(i), 0x1ULL); + } else if (i < DPI_SDP_FLR_RING_LINTX_IDX) { + reg_val = dpi_reg_read( + dpi, DPI_REQQX_INT(i - DPI_REQQX_INT_IDX)); + dev_err(&dpi->pdev->dev, + "DPI_REQQ_INT raised for q:%d: 0x%016llx\n", + (i - 0x40), reg_val); + + dpi_reg_write( + dpi, DPI_REQQX_INT(i - DPI_REQQX_INT_IDX), reg_val); + + if (reg_val & (0x71ULL)) + dpi_queue_reset(dpi, (i - DPI_REQQX_INT_IDX)); + } else if (i < DPI_SDP_IRE_LINTX_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_SDP_FLR_RING_LINTX raised\n"); + + } else if (i < DPI_SDP_ORE_LINTX_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_SDP_IRE_LINTX raised\n"); + + } else if (i < DPI_SDP_ORD_LINTX_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_SDP_ORE_LINTX raised\n"); + + } else if (i < DPI_EPFX_PP_VF_LINTX_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_SDP_ORD_LINTX raised\n"); + + } else if (i < DPI_EPFX_DMA_VF_LINTX_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_EPFX_PP_VF_LINTX raised\n"); + + } else if (i < DPI_EPFX_MISC_LINTX_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_EPFX_DMA_VF_LINTX raised\n"); + + } else if (i < DPI_PF_RAS_IDX) { + /* TODO: handle interrupt */ + dev_err(&dpi->pdev->dev, "DPI_EPFX_MISC_LINTX raised\n"); + + } else if (i == DPI_PF_RAS_IDX) { + reg_val = dpi_reg_read(dpi, DPI_PF_RAS); + dev_err(&dpi->pdev->dev, "DPI_PF_RAS raised: 0x%016llx\n", + reg_val); + dpi_reg_write(dpi, DPI_PF_RAS, reg_val); + } + return IRQ_HANDLED; +} + +static int dpi_irq_init(struct dpipf *dpi) +{ + int i, irq = 0; + int ret = 0; + + /* Clear All Interrupts */ + dpi_reg_write(dpi, DPI_PF_RAS, DPI_PF_RAS_INT); + + /* Clear All Enables */ + dpi_reg_write(dpi, DPI_PF_RAS_ENA_W1C, DPI_PF_RAS_INT); + + for (i = 0; i < DPI_MAX_REQQ_INT; i++) { + dpi_reg_write(dpi, DPI_REQQX_INT(i), DPI_REQQ_INT); + dpi_reg_write(dpi, DPI_REQQX_INT_ENA_W1C(i), DPI_REQQ_INT); + } + + for (i = 0; i < DPI_MAX_CC_INT; i++) { + dpi_reg_write(dpi, DPI_DMA_CCX_INT(i), DPI_DMA_CC_INT); + dpi_reg_write(dpi, DPI_DMA_CCX_INT_ENA_W1C(i), DPI_DMA_CC_INT); + } + + dpi->num_vec = pci_msix_vec_count(dpi->pdev); + /* Enable MSI-X */ + ret = pci_alloc_irq_vectors(dpi->pdev, dpi->num_vec, + dpi->num_vec, PCI_IRQ_MSIX); + if (ret < 0) { + dev_err(&dpi->pdev->dev, + "DPIPF: Request for %d msix vectors failed, ret %d\n", + dpi->num_vec, ret); + goto alloc_fail; + } + + for (irq = 0; irq < dpi->num_vec; irq++) { + ret = request_irq(pci_irq_vector(dpi->pdev, irq), + dpi_pf_intr_handler, 0, "DPIPF", dpi); + if (ret) { + dev_err(&dpi->pdev->dev, + "DPIPF: IRQ(%d) registration failed for DPIPF\n", + irq); + goto fail; + } + } + +#define ENABLE_DPI_INTERRUPTS 0 +#if ENABLE_DPI_INTERRUPTS + /*Enable All Interrupts */ + for (i = 0; i < DPI_MAX_REQQ_INT; i++) + dpi_reg_write(dpi, DPI_REQQX_INT_ENA_W1S(i), DPI_REQQ_INT); + + dpi_reg_write(dpi, DPI_PF_RAS_ENA_W1S, DPI_PF_RAS_INT); +#endif + return 0; +fail: + if (irq) { + for (i = 0; i <= irq; i++) + free_irq(pci_irq_vector(dpi->pdev, i), dpi); + } + pci_free_irq_vectors(dpi->pdev); +alloc_fail: + dpi->num_vec = 0; + return ret; +} + +static void dpi_irq_free(struct dpipf *dpi) +{ + int i = 0; + + /* Clear All Enables */ + dpi_reg_write(dpi, DPI_PF_RAS_ENA_W1C, DPI_PF_RAS_INT); + + for (i = 0; i < DPI_MAX_REQQ_INT; i++) { + dpi_reg_write(dpi, DPI_REQQX_INT(i), DPI_REQQ_INT); + dpi_reg_write(dpi, DPI_REQQX_INT_ENA_W1C(i), DPI_REQQ_INT); + } + + for (i = 0; i < DPI_MAX_CC_INT; i++) { + dpi_reg_write(dpi, DPI_DMA_CCX_INT(i), DPI_DMA_CC_INT); + dpi_reg_write(dpi, DPI_DMA_CCX_INT_ENA_W1C(i), DPI_DMA_CC_INT); + } + + for (i = 0; i < dpi->num_vec; i++) + free_irq(pci_irq_vector(dpi->pdev, i), dpi); + + pci_free_irq_vectors(dpi->pdev); + dpi->num_vec = 0; +} + +static int dpi_sriov_configure(struct pci_dev *pdev, int numvfs) +{ + struct dpipf *dpi = pci_get_drvdata(pdev); + int ret = 0; + + if (numvfs == 0) { + pci_disable_sriov(pdev); + dpi->total_vfs = 0; + } else { + ret = pci_enable_sriov(pdev, numvfs); + if (ret == 0) { + dpi->total_vfs = numvfs; + ret = numvfs; + } + } + + return ret; +} + +static int queue_config(struct dpipf *dpi, struct dpipf_vf *dpivf, + union dpi_mbox_message_t *msg) +{ + switch (msg->s.cmd) { + case DPI_QUEUE_OPEN: + dpivf->vf_config.aura = msg->s.aura; + dpivf->vf_config.csize = msg->s.csize; + dpivf->vf_config.sso_pf_func = msg->s.sso_pf_func; + dpivf->vf_config.npa_pf_func = msg->s.npa_pf_func; + dpi_queue_init(dpi, dpivf, msg->s.vfid); + dpivf->setup_done = true; + break; + case DPI_QUEUE_CLOSE: + dpivf->vf_config.aura = 0; + dpivf->vf_config.csize = 0; + dpivf->vf_config.sso_pf_func = 0; + dpivf->vf_config.npa_pf_func = 0; + dpi_queue_fini(dpi, dpivf, msg->s.vfid); + dpivf->setup_done = false; + break; + default: + return -1; + } + return 0; +} + +static int dpi_queue_config(struct pci_dev *pfdev, + union dpi_mbox_message_t *msg) +{ + struct device *dev = &pfdev->dev; + struct dpipf *dpi = pci_get_drvdata(pfdev); + struct dpipf_vf *dpivf; + + if (msg->s.vfid > dpi->total_vfs) { + dev_err(dev, "Invalid vfid:%d\n", msg->s.vfid); + return -1; + } + dpivf = &dpi->vf[msg->s.vfid]; + + return queue_config(dpi, dpivf, msg); +} +static int dpi_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct device *dev = &pdev->dev; + struct dpipf *dpi; + int err; + + dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); + if (!dpi) + return -ENOMEM; + dpi->pdev = pdev; + + pci_set_drvdata(pdev, dpi); + + err = pci_enable_device(pdev); + if (err) { + dev_err(dev, "Failed to enable PCI device\n"); + pci_set_drvdata(pdev, NULL); + return err; + } + + err = pci_request_regions(pdev, DPI_DRV_NAME); + if (err) { + dev_err(dev, "PCI request regions failed 0x%x\n", err); + goto err_disable_device; + } + + /* MAP configuration registers */ + dpi->reg_base = pcim_iomap(pdev, PCI_DPI_PF_CFG_BAR, 0); + if (!dpi->reg_base) { + dev_err(dev, "DPI: Cannot map CSR memory space, aborting\n"); + err = -ENOMEM; + goto err_release_regions; + } + + /* Initialize global PF registers */ + err = dpi_init(dpi); + if (err) { + dev_err(dev, "DPI: Failed to initialize dpi\n"); + goto err_release_regions; + } + + /* Register interrupts */ + err = dpi_irq_init(dpi); + if (err) { + dev_err(dev, "DPI: Failed to initialize irq vectors\n"); + goto err_dpi_fini; + } + + return 0; + +err_dpi_fini: + dpi_fini(dpi); +err_release_regions: + pci_release_regions(pdev); +err_disable_device: + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + devm_kfree(dev, dpi); + return err; +} + +static void dpi_remove(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct dpipf *dpi = pci_get_drvdata(pdev); + + dpi_irq_free(dpi); + dpi_fini(dpi); + dpi_sriov_configure(pdev, 0); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + devm_kfree(dev, dpi); +} + +struct otx2_dpipf_com_s otx2_dpipf_com = { + .queue_config = dpi_queue_config +}; +EXPORT_SYMBOL(otx2_dpipf_com); + +static const struct pci_device_id dpi_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_DPI_PF) }, + { 0, } /* end of table */ +}; + +static struct pci_driver dpi_driver = { + .name = DPI_DRV_NAME, + .id_table = dpi_id_table, + .probe = dpi_probe, + .remove = dpi_remove, + .sriov_configure = dpi_sriov_configure, +}; + +static int __init dpi_init_module(void) +{ + pr_info("%s: %s\n", DPI_DRV_NAME, DPI_DRV_STRING); + + return pci_register_driver(&dpi_driver); +} + +static void __exit dpi_cleanup_module(void) +{ + pci_unregister_driver(&dpi_driver); +} + +module_init(dpi_init_module); +module_exit(dpi_cleanup_module); +MODULE_DEVICE_TABLE(pci, dpi_id_table); +MODULE_AUTHOR("Marvell International Ltd."); +MODULE_DESCRIPTION(DPI_DRV_STRING); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(DPI_DRV_VERSION); + diff --git a/drivers/soc/marvell/octeontx2-dpi/dpi.h b/drivers/soc/marvell/octeontx2-dpi/dpi.h new file mode 100644 index 000000000000..89aeba02ecaa --- /dev/null +++ b/drivers/soc/marvell/octeontx2-dpi/dpi.h @@ -0,0 +1,335 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell OcteonTx2 DPI PF driver + * + * Copyright (C) 2018 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. + */ + +#ifndef __DPI_H__ +#define __DPI_H__ + + /* PCI device IDs */ +#define PCI_DEVID_OCTEONTX2_DPI_PF 0xA080 +#define PCI_DEVID_OCTEONTX2_DPI_VF 0xA081 +#define PCI_SUBDEVID_OCTEONTX3_DPI_PF 0xB900 + +/* PCI BAR nos */ +#define PCI_DPI_PF_CFG_BAR 0 +#define PCI_DPI_PF_MSIX_BAR 4 +#define PCI_DPI_VF_CFG_BAR 0 +#define PCI_DPI_VF_MSIX_BAR 4 +#define DPI_VF_CFG_SIZE 0x100000 +#define DPI_VF_OFFSET(x) (0x20000000 | 0x100000 * (x)) + +/* MSI-X interrupts */ +#define DPI_MAX_REQQ_INT ({ \ + u32 val; \ + val = 8; \ + if (is_otx3_dpi(dpi)) \ + val = 32; \ + val; }) \ + +#define DPI_MAX_CC_INT 64 + +/* MSI-X interrupt vectors indexes */ +#define DPI_CCX_INT_IDX 0x0 +#define DPI_REQQX_INT_IDX 0x40 +#define DPI_SDP_FLR_RING_LINTX_IDX 0x48 +#define DPI_SDP_IRE_LINTX_IDX 0x4C +#define DPI_SDP_ORE_LINTX_IDX 0x50 +#define DPI_SDP_ORD_LINTX_IDX 0x54 +#define DPI_EPFX_PP_VF_LINTX_IDX 0x58 +#define DPI_EPFX_DMA_VF_LINTX_IDX 0x78 +#define DPI_EPFX_MISC_LINTX_IDX 0x98 +#define DPI_PF_RAS_IDX 0xA8 + +#define DPI_MAX_ENGINES 6 +#define DPI_MAX_VFS 32 + +/**************** Macros for register modification ************/ +#define DPI_DMA_IBUFF_CSIZE_CSIZE(x) ((x) & 0x1fff) +#define DPI_DMA_IBUFF_CSIZE_GET_CSIZE(x) ((x) & 0x1fff) + +#define DPI_DMA_IBUFF_CSIZE_NPA_FREE (1 << 16) + +#define DPI_DMA_IDS_INST_STRM(x) ((uint64_t)((x) & 0xff) << 40) +#define DPI_DMA_IDS_GET_INST_STRM(x) (((x) >> 40) & 0xff) + +#define DPI_DMA_IDS_DMA_STRM(x) ((uint64_t)((x) & 0xff) << 32) +#define DPI_DMA_IDS_GET_DMA_STRM(x) (((x) >> 32) & 0xff) + +#define DPI_DMA_IDS_DMA_NPA_PF_FUNC(x) ((uint64_t)((x) & 0xffff) << 16) +#define DPI_DMA_IDS_GET_DMA_NPA_PF_FUNC(x) (((x) >> 16) & 0xffff) + +#define DPI_DMA_IDS_DMA_SSO_PF_FUNC(x) ((uint64_t)((x) & 0xffff)) +#define DPI_DMA_IDS_GET_DMA_SSO_PF_FUNC(x) ((x) & 0xffff) + +#define DPI_DMA_IDS2_INST_AURA(x) ((uint64_t)((x) & 0xfffff)) +#define DPI_DMA_IDS2_GET_INST_AURA(x) ((x) & 0xfffff) + +#define DPI_ENG_BUF_BLKS(x) ((x) & 0x1fULL) +#define DPI_ENG_BUF_GET_BLKS(x) ((x) & 0x1fULL) + +#define DPI_ENG_BUF_BASE(x) (((x) & 0x3fULL) << 16) +#define DPI_ENG_BUF_GET_BASE(x) (((x) >> 16) & 0x3fULL) + +#define DPI_DMA_ENG_EN_QEN(x) ((x) & 0xffULL) +#define DPI_DMA_ENG_EN_GET_QEN(x) ((x) & 0xffULL) + +#define DPI_DMA_ENG_EN_MOLR(x) (((x) & 0x3ffULL) << 32) +#define DPI_DMA_ENG_EN_GET_MOLR(x) (((x) >> 32) & 0x3ffULL) + +#define DPI_DMA_CONTROL_DMA_ENB(x) (((x) & 0x3fULL) << 48) +#define DPI_DMA_CONTROL_GET_DMA_ENB(x) (((x) >> 48) & 0x3fULL) + +#define DPI_DMA_CONTROL_O_ES(x) (((x) & 0x3ULL) << 15) +#define DPI_DMA_CONTROL_GET_O_ES(x) (((x) >> 15) & 0x3ULL) + +#define DPI_DMA_CONTROL_O_MODE (0x1ULL << 14) +#define DPI_DMA_CONTROL_O_NS (0x1ULL << 17) +#define DPI_DMA_CONTROL_O_RO (0x1ULL << 18) +#define DPI_DMA_CONTROL_O_ADD1 (0x1ULL << 19) +#define DPI_DMA_CONTROL_LDWB (0x1ULL << 32) +#define DPI_DMA_CONTROL_NCB_TAG_DIS (0x1ULL << 34) +#define DPI_DMA_CONTROL_ZBWCSEN (0x1ULL << 39) +#define DPI_DMA_CONTROL_WQECSDIS (0x1ULL << 47) +#define DPI_DMA_CONTROL_UIO_DIS (0x1ULL << 55) +#define DPI_DMA_CONTROL_PKT_EN (0x1ULL << 56) +#define DPI_DMA_CONTROL_FFP_DIS (0x1ULL << 59) + +#define DPI_CTL_EN (0x1ULL) + +/******************** macros for Interrupts ************************/ +#define DPI_DMA_CC_INT (0x1ULL) + +#define DPI_REQQ_INT_INSTRFLT (0x1ULL) +#define DPI_REQQ_INT_RDFLT (0x1ULL << 1) +#define DPI_REQQ_INT_WRFLT (0x1ULL << 2) +#define DPI_REQQ_INT_CSFLT (0x1ULL << 3) +#define DPI_REQQ_INT_INST_DBO (0x1ULL << 4) +#define DPI_REQQ_INT_INST_ADDR_NULL (0x1ULL << 5) +#define DPI_REQQ_INT_INST_FILL_INVAL (0x1ULL << 6) +#define DPI_REQQ_INT_INSTR_PSN (0x1ULL << 7) + +#define DPI_REQQ_INT \ + (DPI_REQQ_INT_INSTRFLT | \ + DPI_REQQ_INT_RDFLT | \ + DPI_REQQ_INT_WRFLT | \ + DPI_REQQ_INT_CSFLT | \ + DPI_REQQ_INT_INST_DBO | \ + DPI_REQQ_INT_INST_ADDR_NULL | \ + DPI_REQQ_INT_INST_FILL_INVAL | \ + DPI_REQQ_INT_INSTR_PSN) + +#define DPI_PF_RAS_EBI_DAT_PSN (0x1ULL) +#define DPI_PF_RAS_NCB_DAT_PSN (0x1ULL << 1) +#define DPI_PF_RAS_NCB_CMD_PSN (0x1ULL << 2) +#define DPI_PF_RAS_INT \ + (DPI_PF_RAS_EBI_DAT_PSN | \ + DPI_PF_RAS_NCB_DAT_PSN | \ + DPI_PF_RAS_NCB_CMD_PSN) + + +/***************** Registers ******************/ +#define DPI_DMAX_IBUFF_CSIZE(x) (0x0ULL | ((x) << 11)) +#define DPI_DMAX_REQBANK0(x) (0x8ULL | ((x) << 11)) +#define DPI_DMAX_REQBANK1(x) (0x10ULL | ((x) << 11)) +#define DPI_DMAX_IDS(x) (0x18ULL | ((x) << 11)) +#define DPI_DMAX_IDS2(x) (0x20ULL | ((x) << 11)) +#define DPI_DMAX_IFLIGHT(x) (0x28ULL | ((x) << 11)) +#define DPI_DMAX_QRST(x) (0x30ULL | ((x) << 11)) +#define DPI_DMAX_ERR_RSP_STATUS(x) (0x38ULL | ((x) << 11)) + +#define DPI_CSCLK_ACTIVE_PC ({ \ + u64 offset; \ + \ + offset = (0x4000ULL); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10000ULL); \ + offset; }) \ + +#define DPI_CTL ({ \ + u64 offset; \ + \ + offset = (0x4010ULL); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10010ULL); \ + offset; }) \ + +#define DPI_DMA_CONTROL ({ \ + u64 offset; \ + \ + offset = (0x4018ULL); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10018ULL); \ + offset; }) \ + +#define DPI_DMA_ENGX_EN(x) ({ \ + u64 offset; \ + \ + offset = (0x4040ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10040ULL | ((x) << 3)); \ + offset; }) \ + +#define DPI_ENGX_BUF(x) ({ \ + u64 offset; \ + \ + offset = (0x40C0ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x100C0ULL | ((x) << 3)); \ + offset; }) \ + +#define DPI_EBUS_PORTX_CFG(x) ({ \ + u64 offset; \ + \ + offset = (0x4100ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10100ULL | ((x) << 3)); \ + offset; }) \ + +#define DPI_PF_RAS ({ \ + u64 offset; \ + \ + offset = (0x4308ULL); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10308ULL); \ + offset; }) \ + +#define DPI_PF_RAS_ENA_W1C ({ \ + u64 offset; \ + \ + offset = (0x4318ULL); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10318ULL); \ + offset; }) \ + +#define DPI_PF_RAS_ENA_W1S ({ \ + u64 offset; \ + \ + offset = (0x4320ULL); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x10320ULL); \ + offset; }) \ + +#define DPI_DMA_CCX_INT(x) ({ \ + u64 offset; \ + \ + offset = (0x5000ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x11000ULL | ((x) << 3)); \ + offset; }) \ + +#define DPI_DMA_CCX_INT_ENA_W1C(x) ({ \ + u64 offset; \ + \ + offset = (0x5800ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x11800ULL | ((x) << 3)); \ + offset; }) \ + +#define DPI_REQQX_INT(x) ({ \ + u64 offset; \ + \ + offset = (0x6600ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x12C00ULL | ((x) << 5)); \ + offset; }) \ + +#define DPI_REQQX_INT_ENA_W1C(x) ({ \ + u64 offset; \ + \ + offset = (0x6680ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x13800ULL | ((x) << 5)); \ + offset; }) \ + +#define DPI_REQQX_INT_ENA_W1S(x) ({ \ + u64 offset; \ + \ + offset = (0x66C0ULL | (x) << 3); \ + if (is_otx3_dpi(dpi)) \ + offset = (0x13C00ULL | ((x) << 5)); \ + offset; }) \ + +#define DPI_WCTL_FIF_THR (0x17008ULL) + +#define DPI_EBUS_MRRS_MIN 128 +#define DPI_EBUS_MRRS_MAX 1024 +#define DPI_EBUS_MPS_MIN 128 +#define DPI_EBUS_MPS_MAX 1024 +#define DPI_EBUS_MAX_PORTS 2 +#define DPI_EBUS_PORTX_CFG_MRRS(x) (((x) & 0x7) << 0) +#define DPI_EBUS_PORTX_CFG_MPS(x) (((x) & 0x7) << 4) + +/* VF Registers: */ +#define DPI_VDMA_EN (0x0ULL) +#define DPI_VDMA_REQQ_CTL (0x8ULL) +#define DPI_VDMA_DBELL (0x10ULL) +#define DPI_VDMA_SADDR (0x18ULL) +#define DPI_VDMA_COUNTS (0x20ULL) +#define DPI_VDMA_NADDR (0x28ULL) +#define DPI_VDMA_IWBUSY (0x30ULL) +#define DPI_VDMA_CNT (0x38ULL) +#define DPI_VF_INT (0x100ULL) +#define DPI_VF_INT_W1S (0x108ULL) +#define DPI_VF_INT_ENA_W1C (0x110ULL) +#define DPI_VF_INT_ENA_W1S (0x118ULL) + +struct dpivf_config { + uint16_t csize; + uint32_t aura; + uint16_t sso_pf_func; + uint16_t npa_pf_func; +}; + +struct dpipf_vf { + uint8_t this_vfid; + bool setup_done; + struct dpivf_config vf_config; +}; + +struct dpipf { + void __iomem *reg_base; + struct pci_dev *pdev; + int num_vec; + struct msix_entry *msix_entries; + int total_vfs; + int vfs_in_use; + struct dpipf_vf vf[DPI_MAX_VFS]; +}; + +#define DPI_QUEUE_OPEN 0x1 +#define DPI_QUEUE_CLOSE 0x2 +#define DPI_REG_DUMP 0x3 +#define DPI_GET_REG_CFG 0x4 + +union dpi_mbox_message_t { + uint64_t u[2]; + struct dpi_mbox_message_s { + /* VF ID to configure */ + uint64_t vfid :8; + /* Command code */ + uint64_t cmd :4; + /* Command buffer size in 8-byte words */ + uint64_t csize :14; + /* aura of the command buffer */ + uint64_t aura :20; + /* SSO PF function */ + uint64_t sso_pf_func :16; + /* NPA PF function */ + uint64_t npa_pf_func :16; + } s; +}; + +struct otx2_dpipf_com_s { + int (*queue_config)(struct pci_dev *pfdev, + union dpi_mbox_message_t *req); +}; + +extern struct otx2_dpipf_com_s otx2_dpipf_com; + +#endif -- 2.24.1
Powered by blists - more mailing lists