Commit 862cd659 authored by Veerasenareddy Burru's avatar Veerasenareddy Burru Committed by David S. Miller

octeon_ep: Add driver framework and device initialization

Add driver framework and device setup and initialization for Octeon
PCI Endpoint NIC.

Add implementation to load module, initilaize, register network device,
cleanup and unload module.
Signed-off-by: default avatarVeerasenareddy Burru <vburru@marvell.com>
Signed-off-by: default avatarAbhijit Ayarekar <aayarekar@marvell.com>
Signed-off-by: default avatarSatananda Burla <sburla@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92716869
......@@ -39,6 +39,7 @@ Contents:
intel/iavf
intel/ice
marvell/octeontx2
marvell/octeon_ep
mellanox/mlx5
microsoft/netvsc
neterion/s2io
......
.. SPDX-License-Identifier: GPL-2.0+
====================================================================
Linux kernel networking driver for Marvell's Octeon PCI Endpoint NIC
====================================================================
Network driver for Marvell's Octeon PCI EndPoint NIC.
Copyright (c) 2020 Marvell International Ltd.
Contents
========
- `Overview`_
- `Supported Devices`_
- `Interface Control`_
Overview
========
This driver implements networking functionality of Marvell's Octeon PCI
EndPoint NIC.
Supported Devices
=================
Currently, this driver support following devices:
* Network controller: Cavium, Inc. Device b200
Interface Control
=================
Network Interface control like changing mtu, link speed, link down/up are
done by writing command to mailbox command queue, a mailbox interface
implemented through a reserved region in BAR4.
This driver writes the commands into the mailbox and the firmware on the
Octeon device processes them. The firmware also sends unsolicited notifications
to driver for events suchs as link change, through notification queue
implemented as part of mailbox interface.
......@@ -11828,6 +11828,13 @@ S: Supported
F: Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
F: drivers/mmc/host/sdhci-xenon*
MARVELL OCTEON ENDPOINT DRIVER
M: Veerasenareddy Burru <vburru@marvell.com>
M: Abhijit Ayarekar <aayarekar@marvell.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/marvell/octeon_ep
MATROX FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
......
......@@ -177,6 +177,7 @@ config SKY2_DEBUG
source "drivers/net/ethernet/marvell/octeontx2/Kconfig"
source "drivers/net/ethernet/marvell/octeon_ep/Kconfig"
source "drivers/net/ethernet/marvell/prestera/Kconfig"
endif # NET_VENDOR_MARVELL
......@@ -11,5 +11,6 @@ obj-$(CONFIG_MVPP2) += mvpp2/
obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SKY2) += sky2.o
obj-y += octeon_ep/
obj-y += octeontx2/
obj-y += prestera/
# SPDX-License-Identifier: GPL-2.0-only
#
# Marvell's Octeon PCI Endpoint NIC Driver Configuration
#
config OCTEON_EP
tristate "Marvell Octeon PCI Endpoint NIC Driver"
depends on 64BIT
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
help
This driver supports networking functionality of Marvell's
Octeon PCI Endpoint NIC.
To know the list of devices supported by this driver, refer
documentation in
<file:Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst>.
To compile this drivers as a module, choose M here. Name of the
module is octeon_ep.
# SPDX-License-Identifier: GPL-2.0
#
# Network driver for Marvell's Octeon PCI Endpoint NIC
#
obj-$(CONFIG_OCTEON_EP) += octeon_ep.o
octeon_ep-y := octep_main.o octep_cn9k_pf.o octep_tx.o octep_rx.o \
octep_ctrl_mbox.o octep_ctrl_net.o
// SPDX-License-Identifier: GPL-2.0
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include "octep_config.h"
#include "octep_main.h"
#include "octep_regs_cn9k_pf.h"
/* Names of Hardware non-queue generic interrupts */
static char *cn93_non_ioq_msix_names[] = {
"epf_ire_rint",
"epf_ore_rint",
"epf_vfire_rint0",
"epf_vfire_rint1",
"epf_vfore_rint0",
"epf_vfore_rint1",
"epf_mbox_rint0",
"epf_mbox_rint1",
"epf_oei_rint",
"epf_dma_rint",
"epf_dma_vf_rint0",
"epf_dma_vf_rint1",
"epf_pp_vf_rint0",
"epf_pp_vf_rint1",
"epf_misc_rint",
"epf_rsvd",
};
/* Reset all hardware Tx/Rx queues */
static void octep_reset_io_queues_cn93_pf(struct octep_device *oct)
{
}
/* Initialize windowed addresses to access some hardware registers */
static void octep_setup_pci_window_regs_cn93_pf(struct octep_device *oct)
{
}
/* Configure Hardware mapping: inform hardware which rings belong to PF. */
static void octep_configure_ring_mapping_cn93_pf(struct octep_device *oct)
{
}
/* Initialize configuration limits and initial active config 93xx PF. */
static void octep_init_config_cn93_pf(struct octep_device *oct)
{
struct octep_config *conf = oct->conf;
struct pci_dev *pdev = oct->pdev;
u64 val;
/* Read ring configuration:
* PF ring count, number of VFs and rings per VF supported
*/
val = octep_read_csr64(oct, CN93_SDP_EPF_RINFO);
conf->sriov_cfg.max_rings_per_vf = CN93_SDP_EPF_RINFO_RPVF(val);
conf->sriov_cfg.active_rings_per_vf = conf->sriov_cfg.max_rings_per_vf;
conf->sriov_cfg.max_vfs = CN93_SDP_EPF_RINFO_NVFS(val);
conf->sriov_cfg.active_vfs = conf->sriov_cfg.max_vfs;
conf->sriov_cfg.vf_srn = CN93_SDP_EPF_RINFO_SRN(val);
val = octep_read_csr64(oct, CN93_SDP_MAC_PF_RING_CTL(oct->pcie_port));
conf->pf_ring_cfg.srn = CN93_SDP_MAC_PF_RING_CTL_SRN(val);
conf->pf_ring_cfg.max_io_rings = CN93_SDP_MAC_PF_RING_CTL_RPPF(val);
conf->pf_ring_cfg.active_io_rings = conf->pf_ring_cfg.max_io_rings;
dev_info(&pdev->dev, "pf_srn=%u rpvf=%u nvfs=%u rppf=%u\n",
conf->pf_ring_cfg.srn, conf->sriov_cfg.active_rings_per_vf,
conf->sriov_cfg.active_vfs, conf->pf_ring_cfg.active_io_rings);
conf->iq.num_descs = OCTEP_IQ_MAX_DESCRIPTORS;
conf->iq.instr_type = OCTEP_64BYTE_INSTR;
conf->iq.pkind = 0;
conf->iq.db_min = OCTEP_DB_MIN;
conf->iq.intr_threshold = OCTEP_IQ_INTR_THRESHOLD;
conf->oq.num_descs = OCTEP_OQ_MAX_DESCRIPTORS;
conf->oq.buf_size = OCTEP_OQ_BUF_SIZE;
conf->oq.refill_threshold = OCTEP_OQ_REFILL_THRESHOLD;
conf->oq.oq_intr_pkt = OCTEP_OQ_INTR_PKT_THRESHOLD;
conf->oq.oq_intr_time = OCTEP_OQ_INTR_TIME_THRESHOLD;
conf->msix_cfg.non_ioq_msix = CN93_NUM_NON_IOQ_INTR;
conf->msix_cfg.ioq_msix = conf->pf_ring_cfg.active_io_rings;
conf->msix_cfg.non_ioq_msix_names = cn93_non_ioq_msix_names;
conf->ctrl_mbox_cfg.barmem_addr = (void __iomem *)oct->mmio[2].hw_addr + (0x400000ull * 7);
}
/* Setup registers for a hardware Tx Queue */
static void octep_setup_iq_regs_cn93_pf(struct octep_device *oct, int iq_no)
{
}
/* Setup registers for a hardware Rx Queue */
static void octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no)
{
}
/* Setup registers for a PF mailbox */
static void octep_setup_mbox_regs_cn93_pf(struct octep_device *oct, int q_no)
{
}
/* Interrupts handler for all non-queue generic interrupts. */
static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev)
{
return IRQ_HANDLED;
}
/* Tx/Rx queue interrupt handler */
static irqreturn_t octep_ioq_intr_handler_cn93_pf(void *data)
{
return IRQ_HANDLED;
}
/* soft reset of 93xx */
static int octep_soft_reset_cn93_pf(struct octep_device *oct)
{
dev_info(&oct->pdev->dev, "CN93XX: Doing soft reset\n");
octep_write_csr64(oct, CN93_SDP_WIN_WR_MASK_REG, 0xFF);
/* Set core domain reset bit */
OCTEP_PCI_WIN_WRITE(oct, CN93_RST_CORE_DOMAIN_W1S, 1);
/* Wait for 100ms as Octeon resets. */
mdelay(100);
/* clear core domain reset bit */
OCTEP_PCI_WIN_WRITE(oct, CN93_RST_CORE_DOMAIN_W1C, 1);
return 0;
}
/* Re-initialize Octeon hardware registers */
static void octep_reinit_regs_cn93_pf(struct octep_device *oct)
{
}
/* Enable all interrupts */
static void octep_enable_interrupts_cn93_pf(struct octep_device *oct)
{
}
/* Disable all interrupts */
static void octep_disable_interrupts_cn93_pf(struct octep_device *oct)
{
}
/* Get new Octeon Read Index: index of descriptor that Octeon reads next. */
static u32 octep_update_iq_read_index_cn93_pf(struct octep_iq *iq)
{
return 0;
}
/* Enable a hardware Tx Queue */
static void octep_enable_iq_cn93_pf(struct octep_device *oct, int iq_no)
{
}
/* Enable a hardware Rx Queue */
static void octep_enable_oq_cn93_pf(struct octep_device *oct, int oq_no)
{
}
/* Enable all hardware Tx/Rx Queues assined to PF */
static void octep_enable_io_queues_cn93_pf(struct octep_device *oct)
{
}
/* Disable a hardware Tx Queue assined to PF */
static void octep_disable_iq_cn93_pf(struct octep_device *oct, int iq_no)
{
}
/* Disable a hardware Rx Queue assined to PF */
static void octep_disable_oq_cn93_pf(struct octep_device *oct, int oq_no)
{
}
/* Disable all hardware Tx/Rx Queues assined to PF */
static void octep_disable_io_queues_cn93_pf(struct octep_device *oct)
{
}
/* Dump hardware registers (including Tx/Rx queues) for debugging. */
static void octep_dump_registers_cn93_pf(struct octep_device *oct)
{
}
/**
* octep_device_setup_cn93_pf() - Setup Octeon device.
*
* @oct: Octeon device private data structure.
*
* - initialize hardware operations.
* - get target side pcie port number for the device.
* - setup window access to hardware registers.
* - set initial configuration and max limits.
* - setup hardware mapping of rings to the PF device.
*/
void octep_device_setup_cn93_pf(struct octep_device *oct)
{
oct->hw_ops.setup_iq_regs = octep_setup_iq_regs_cn93_pf;
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.non_ioq_intr_handler = octep_non_ioq_intr_handler_cn93_pf;
oct->hw_ops.ioq_intr_handler = octep_ioq_intr_handler_cn93_pf;
oct->hw_ops.soft_reset = octep_soft_reset_cn93_pf;
oct->hw_ops.reinit_regs = octep_reinit_regs_cn93_pf;
oct->hw_ops.enable_interrupts = octep_enable_interrupts_cn93_pf;
oct->hw_ops.disable_interrupts = octep_disable_interrupts_cn93_pf;
oct->hw_ops.update_iq_read_idx = octep_update_iq_read_index_cn93_pf;
oct->hw_ops.enable_iq = octep_enable_iq_cn93_pf;
oct->hw_ops.enable_oq = octep_enable_oq_cn93_pf;
oct->hw_ops.enable_io_queues = octep_enable_io_queues_cn93_pf;
oct->hw_ops.disable_iq = octep_disable_iq_cn93_pf;
oct->hw_ops.disable_oq = octep_disable_oq_cn93_pf;
oct->hw_ops.disable_io_queues = octep_disable_io_queues_cn93_pf;
oct->hw_ops.reset_io_queues = octep_reset_io_queues_cn93_pf;
oct->hw_ops.dump_registers = octep_dump_registers_cn93_pf;
octep_setup_pci_window_regs_cn93_pf(oct);
oct->pcie_port = octep_read_csr64(oct, CN93_SDP_MAC_NUMBER) & 0xff;
dev_info(&oct->pdev->dev,
"Octeon device using PCIE Port %d\n", oct->pcie_port);
octep_init_config_cn93_pf(oct);
octep_configure_ring_mapping_cn93_pf(oct);
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#ifndef _OCTEP_CONFIG_H_
#define _OCTEP_CONFIG_H_
/* Tx instruction types by length */
#define OCTEP_32BYTE_INSTR 32
#define OCTEP_64BYTE_INSTR 64
/* Tx Queue: maximum descriptors per ring */
#define OCTEP_IQ_MAX_DESCRIPTORS 1024
/* Minimum input (Tx) requests to be enqueued to ring doorbell */
#define OCTEP_DB_MIN 1
/* Packet threshold for Tx queue interrupt */
#define OCTEP_IQ_INTR_THRESHOLD 0x0
/* Rx Queue: maximum descriptors per ring */
#define OCTEP_OQ_MAX_DESCRIPTORS 1024
/* Rx buffer size: Use page size buffers.
* Build skb from allocated page buffer once the packet is received.
* When a gathered packet is received, make head page as skb head and
* page buffers in consecutive Rx descriptors as fragments.
*/
#define OCTEP_OQ_BUF_SIZE (SKB_WITH_OVERHEAD(PAGE_SIZE))
#define OCTEP_OQ_PKTS_PER_INTR 128
#define OCTEP_OQ_REFILL_THRESHOLD (OCTEP_OQ_MAX_DESCRIPTORS / 4)
#define OCTEP_OQ_INTR_PKT_THRESHOLD 1
#define OCTEP_OQ_INTR_TIME_THRESHOLD 10
#define OCTEP_MSIX_NAME_SIZE (IFNAMSIZ + 32)
/* Tx Queue wake threshold
* wakeup a stopped Tx queue if minimum 2 descriptors are available.
* Even a skb with fragments consume only one Tx queue descriptor entry.
*/
#define OCTEP_WAKE_QUEUE_THRESHOLD 2
/* Minimum MTU supported by Octeon network interface */
#define OCTEP_MIN_MTU ETH_MIN_MTU
/* Maximum MTU supported by Octeon interface*/
#define OCTEP_MAX_MTU (10000 - (ETH_HLEN + ETH_FCS_LEN))
/* Default MTU */
#define OCTEP_DEFAULT_MTU 1500
/* Macros to get octeon config params */
#define CFG_GET_IQ_CFG(cfg) ((cfg)->iq)
#define CFG_GET_IQ_NUM_DESC(cfg) ((cfg)->iq.num_descs)
#define CFG_GET_IQ_INSTR_TYPE(cfg) ((cfg)->iq.instr_type)
#define CFG_GET_IQ_PKIND(cfg) ((cfg)->iq.pkind)
#define CFG_GET_IQ_INSTR_SIZE(cfg) (64)
#define CFG_GET_IQ_DB_MIN(cfg) ((cfg)->iq.db_min)
#define CFG_GET_IQ_INTR_THRESHOLD(cfg) ((cfg)->iq.intr_threshold)
#define CFG_GET_OQ_NUM_DESC(cfg) ((cfg)->oq.num_descs)
#define CFG_GET_OQ_BUF_SIZE(cfg) ((cfg)->oq.buf_size)
#define CFG_GET_OQ_REFILL_THRESHOLD(cfg) ((cfg)->oq.refill_threshold)
#define CFG_GET_OQ_INTR_PKT(cfg) ((cfg)->oq.oq_intr_pkt)
#define CFG_GET_OQ_INTR_TIME(cfg) ((cfg)->oq.oq_intr_time)
#define CFG_GET_PORTS_MAX_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.max_io_rings)
#define CFG_GET_PORTS_ACTIVE_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.active_io_rings)
#define CFG_GET_PORTS_PF_SRN(cfg) ((cfg)->pf_ring_cfg.srn)
#define CFG_GET_DPI_PKIND(cfg) ((cfg)->core_cfg.dpi_pkind)
#define CFG_GET_CORE_TICS_PER_US(cfg) ((cfg)->core_cfg.core_tics_per_us)
#define CFG_GET_COPROC_TICS_PER_US(cfg) ((cfg)->core_cfg.coproc_tics_per_us)
#define CFG_GET_MAX_VFS(cfg) ((cfg)->sriov_cfg.max_vfs)
#define CFG_GET_ACTIVE_VFS(cfg) ((cfg)->sriov_cfg.active_vfs)
#define CFG_GET_MAX_RPVF(cfg) ((cfg)->sriov_cfg.max_rings_per_vf)
#define CFG_GET_ACTIVE_RPVF(cfg) ((cfg)->sriov_cfg.active_rings_per_vf)
#define CFG_GET_VF_SRN(cfg) ((cfg)->sriov_cfg.vf_srn)
#define CFG_GET_IOQ_MSIX(cfg) ((cfg)->msix_cfg.ioq_msix)
#define CFG_GET_NON_IOQ_MSIX(cfg) ((cfg)->msix_cfg.non_ioq_msix)
#define CFG_GET_NON_IOQ_MSIX_NAMES(cfg) ((cfg)->msix_cfg.non_ioq_msix_names)
#define CFG_GET_CTRL_MBOX_MEM_ADDR(cfg) ((cfg)->ctrl_mbox_cfg.barmem_addr)
/* Hardware Tx Queue configuration. */
struct octep_iq_config {
/* Size of the Input queue (number of commands) */
u16 num_descs;
/* Command size - 32 or 64 bytes */
u16 instr_type;
/* pkind for packets sent to Octeon */
u16 pkind;
/* Minimum number of commands pending to be posted to Octeon before driver
* hits the Input queue doorbell.
*/
u16 db_min;
/* Trigger the IQ interrupt when processed cmd count reaches
* this level.
*/
u32 intr_threshold;
};
/* Hardware Rx Queue configuration. */
struct octep_oq_config {
/* Size of Output queue (number of descriptors) */
u16 num_descs;
/* Size of buffer in this Output queue. */
u16 buf_size;
/* The number of buffers that were consumed during packet processing
* by the driver on this Output queue before the driver attempts to
* replenish the descriptor ring with new buffers.
*/
u16 refill_threshold;
/* Interrupt Coalescing (Packet Count). Octeon will interrupt the host
* only if it sent as many packets as specified by this field.
* The driver usually does not use packet count interrupt coalescing.
*/
u32 oq_intr_pkt;
/* Interrupt Coalescing (Time Interval). Octeon will interrupt the host
* if at least one packet was sent in the time interval specified by
* this field. The driver uses time interval interrupt coalescing by
* default. The time is specified in microseconds.
*/
u32 oq_intr_time;
};
/* Tx/Rx configuration */
struct octep_pf_ring_config {
/* Max number of IOQs */
u16 max_io_rings;
/* Number of active IOQs */
u16 active_io_rings;
/* Starting IOQ number: this changes based on which PEM is used */
u16 srn;
};
/* Octeon Hardware SRIOV config */
struct octep_sriov_config {
/* Max number of VF devices supported */
u16 max_vfs;
/* Number of VF devices enabled */
u16 active_vfs;
/* Max number of rings assigned to VF */
u8 max_rings_per_vf;
/* Number of rings enabled per VF */
u8 active_rings_per_vf;
/* starting ring number of VF's: ring-0 of VF-0 of the PF */
u16 vf_srn;
};
/* Octeon MSI-x config. */
struct octep_msix_config {
/* Number of IOQ interrupts */
u16 ioq_msix;
/* Number of Non IOQ interrupts */
u16 non_ioq_msix;
/* Names of Non IOQ interrupts */
char **non_ioq_msix_names;
};
struct octep_ctrl_mbox_config {
/* Barmem address for control mbox */
void __iomem *barmem_addr;
};
/* Data Structure to hold configuration limits and active config */
struct octep_config {
/* Input Queue attributes. */
struct octep_iq_config iq;
/* Output Queue attributes. */
struct octep_oq_config oq;
/* NIC Port Configuration */
struct octep_pf_ring_config pf_ring_cfg;
/* SRIOV configuration of the PF */
struct octep_sriov_config sriov_cfg;
/* MSI-X interrupt config */
struct octep_msix_config msix_cfg;
/* ctrl mbox config */
struct octep_ctrl_mbox_config ctrl_mbox_cfg;
};
#endif /* _OCTEP_CONFIG_H_ */
// SPDX-License-Identifier: GPL-2.0
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#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_ctrl_mbox.h"
#include "octep_config.h"
#include "octep_main.h"
/* Timeout in msecs for message response */
#define OCTEP_CTRL_MBOX_MSG_TIMEOUT_MS 100
/* Time in msecs to wait for message response */
#define OCTEP_CTRL_MBOX_MSG_WAIT_MS 10
#define OCTEP_CTRL_MBOX_INFO_MAGIC_NUM_OFFSET(m) (m)
#define OCTEP_CTRL_MBOX_INFO_BARMEM_SZ_OFFSET(m) ((m) + 8)
#define OCTEP_CTRL_MBOX_INFO_HOST_VERSION_OFFSET(m) ((m) + 16)
#define OCTEP_CTRL_MBOX_INFO_HOST_STATUS_OFFSET(m) ((m) + 24)
#define OCTEP_CTRL_MBOX_INFO_FW_VERSION_OFFSET(m) ((m) + 136)
#define OCTEP_CTRL_MBOX_INFO_FW_STATUS_OFFSET(m) ((m) + 144)
#define OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m) ((m) + OCTEP_CTRL_MBOX_INFO_SZ)
#define OCTEP_CTRL_MBOX_H2FQ_PROD_OFFSET(m) (OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m))
#define OCTEP_CTRL_MBOX_H2FQ_CONS_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 4)
#define OCTEP_CTRL_MBOX_H2FQ_ELEM_SZ_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 8)
#define OCTEP_CTRL_MBOX_H2FQ_ELEM_CNT_OFFSET(m) ((OCTEP_CTRL_MBOX_H2FQ_INFO_OFFSET(m)) + 12)
#define OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m) ((m) + \
OCTEP_CTRL_MBOX_INFO_SZ + \
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ)
#define OCTEP_CTRL_MBOX_F2HQ_PROD_OFFSET(m) (OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m))
#define OCTEP_CTRL_MBOX_F2HQ_CONS_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 4)
#define OCTEP_CTRL_MBOX_F2HQ_ELEM_SZ_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 8)
#define OCTEP_CTRL_MBOX_F2HQ_ELEM_CNT_OFFSET(m) ((OCTEP_CTRL_MBOX_F2HQ_INFO_OFFSET(m)) + 12)
#define OCTEP_CTRL_MBOX_Q_OFFSET(m, i) ((m) + \
(sizeof(struct octep_ctrl_mbox_msg) * (i)))
int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
{
return -EINVAL;
}
int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg)
{
return -EINVAL;
}
int octep_ctrl_mbox_uninit(struct octep_ctrl_mbox *mbox)
{
return -EINVAL;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#ifndef __OCTEP_CTRL_MBOX_H__
#define __OCTEP_CTRL_MBOX_H__
/* barmem structure
* |===========================================|
* |Info (16 + 120 + 120 = 256 bytes) |
* |-------------------------------------------|
* |magic number (8 bytes) |
* |bar memory size (4 bytes) |
* |reserved (4 bytes) |
* |-------------------------------------------|
* |host version (8 bytes) |
* |host status (8 bytes) |
* |host reserved (104 bytes) |
* |-------------------------------------------|
* |fw version (8 bytes) |
* |fw status (8 bytes) |
* |fw reserved (104 bytes) |
* |===========================================|
* |Host to Fw Queue info (16 bytes) |
* |-------------------------------------------|
* |producer index (4 bytes) |
* |consumer index (4 bytes) |
* |element size (4 bytes) |
* |element count (4 bytes) |
* |===========================================|
* |Fw to Host Queue info (16 bytes) |
* |-------------------------------------------|
* |producer index (4 bytes) |
* |consumer index (4 bytes) |
* |element size (4 bytes) |
* |element count (4 bytes) |
* |===========================================|
* |Host to Fw Queue |
* |-------------------------------------------|
* |((elem_sz + hdr(8 bytes)) * elem_cnt) bytes|
* |===========================================|
* |===========================================|
* |Fw to Host Queue |
* |-------------------------------------------|
* |((elem_sz + hdr(8 bytes)) * elem_cnt) bytes|
* |===========================================|
*/
#define OCTEP_CTRL_MBOX_MAGIC_NUMBER 0xdeaddeadbeefbeefull
/* Size of mbox info in bytes */
#define OCTEP_CTRL_MBOX_INFO_SZ 256
/* Size of mbox host to target queue info in bytes */
#define OCTEP_CTRL_MBOX_H2FQ_INFO_SZ 16
/* Size of mbox target to host queue info in bytes */
#define OCTEP_CTRL_MBOX_F2HQ_INFO_SZ 16
/* Size of mbox queue in bytes */
#define OCTEP_CTRL_MBOX_Q_SZ(sz, cnt) (((sz) + 8) * (cnt))
/* Size of mbox in bytes */
#define OCTEP_CTRL_MBOX_SZ(hsz, hcnt, fsz, fcnt) (OCTEP_CTRL_MBOX_INFO_SZ + \
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ + \
OCTEP_CTRL_MBOX_F2HQ_INFO_SZ + \
OCTEP_CTRL_MBOX_Q_SZ(hsz, hcnt) + \
OCTEP_CTRL_MBOX_Q_SZ(fsz, fcnt))
/* Valid request message */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ BIT(0)
/* Valid response message */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP BIT(1)
/* Valid notification, no response required */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY BIT(2)
enum octep_ctrl_mbox_status {
OCTEP_CTRL_MBOX_STATUS_INVALID = 0,
OCTEP_CTRL_MBOX_STATUS_INIT,
OCTEP_CTRL_MBOX_STATUS_READY,
OCTEP_CTRL_MBOX_STATUS_UNINIT
};
/* mbox message */
union octep_ctrl_mbox_msg_hdr {
u64 word0;
struct {
/* OCTEP_CTRL_MBOX_MSG_HDR_FLAG_* */
u32 flags;
/* size of message in words excluding header */
u32 sizew;
};
};
/* mbox message */
struct octep_ctrl_mbox_msg {
/* mbox transaction header */
union octep_ctrl_mbox_msg_hdr hdr;
/* pointer to message buffer */
void *msg;
};
/* Mbox queue */
struct octep_ctrl_mbox_q {
/* q element size, should be aligned to unsigned long */
u16 elem_sz;
/* q element count, should be power of 2 */
u16 elem_cnt;
/* q mask */
u16 mask;
/* producer address in bar mem */
void __iomem *hw_prod;
/* consumer address in bar mem */
void __iomem *hw_cons;
/* q base address in bar mem */
void __iomem *hw_q;
};
struct octep_ctrl_mbox {
/* host driver version */
u64 version;
/* size of bar memory */
u32 barmem_sz;
/* pointer to BAR memory */
void __iomem *barmem;
/* user context for callback, can be null */
void *user_ctx;
/* callback handler for processing request, called from octep_ctrl_mbox_recv */
int (*process_req)(void *user_ctx, struct octep_ctrl_mbox_msg *msg);
/* host-to-fw queue */
struct octep_ctrl_mbox_q h2fq;
/* fw-to-host queue */
struct octep_ctrl_mbox_q f2hq;
/* lock for h2fq */
struct mutex h2fq_lock;
/* lock for f2hq */
struct mutex f2hq_lock;
};
/* Initialize control mbox.
*
* @param mbox: non-null pointer to struct octep_ctrl_mbox.
*
* return value: 0 on success, -errno on failure.
*/
int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox);
/* Send mbox message.
*
* @param mbox: non-null pointer to struct octep_ctrl_mbox.
*
* return value: 0 on success, -errno on failure.
*/
int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg);
/* Retrieve mbox message.
*
* @param mbox: non-null pointer to struct octep_ctrl_mbox.
*
* return value: 0 on success, -errno on failure.
*/
int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_msg *msg);
/* Uninitialize control mbox.
*
* @param ep: non-null pointer to struct octep_ctrl_mbox.
*
* return value: 0 on success, -errno on failure.
*/
int octep_ctrl_mbox_uninit(struct octep_ctrl_mbox *mbox);
#endif /* __OCTEP_CTRL_MBOX_H__ */
// SPDX-License-Identifier: GPL-2.0
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#include <linux/string.h>
#include <linux/types.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include "octep_config.h"
#include "octep_main.h"
#include "octep_ctrl_net.h"
int octep_get_link_status(struct octep_device *oct)
{
return 0;
}
void octep_set_link_status(struct octep_device *oct, bool up)
{
}
void octep_set_rx_state(struct octep_device *oct, bool up)
{
}
int octep_get_mac_addr(struct octep_device *oct, u8 *addr)
{
return -1;
}
int octep_get_link_info(struct octep_device *oct)
{
return -1;
}
int octep_set_link_info(struct octep_device *oct, struct octep_iface_link_info *link_info)
{
return -1;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#ifndef __OCTEP_CTRL_NET_H__
#define __OCTEP_CTRL_NET_H__
/* Supported commands */
enum octep_ctrl_net_cmd {
OCTEP_CTRL_NET_CMD_GET = 0,
OCTEP_CTRL_NET_CMD_SET,
};
/* Supported states */
enum octep_ctrl_net_state {
OCTEP_CTRL_NET_STATE_DOWN = 0,
OCTEP_CTRL_NET_STATE_UP,
};
/* Supported replies */
enum octep_ctrl_net_reply {
OCTEP_CTRL_NET_REPLY_OK = 0,
OCTEP_CTRL_NET_REPLY_GENERIC_FAIL,
OCTEP_CTRL_NET_REPLY_INVALID_PARAM,
};
/* Supported host to fw commands */
enum octep_ctrl_net_h2f_cmd {
OCTEP_CTRL_NET_H2F_CMD_INVALID = 0,
OCTEP_CTRL_NET_H2F_CMD_MTU,
OCTEP_CTRL_NET_H2F_CMD_MAC,
OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS,
OCTEP_CTRL_NET_H2F_CMD_GET_XSTATS,
OCTEP_CTRL_NET_H2F_CMD_GET_Q_STATS,
OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS,
OCTEP_CTRL_NET_H2F_CMD_RX_STATE,
OCTEP_CTRL_NET_H2F_CMD_LINK_INFO,
};
/* Supported fw to host commands */
enum octep_ctrl_net_f2h_cmd {
OCTEP_CTRL_NET_F2H_CMD_INVALID = 0,
OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS,
};
struct octep_ctrl_net_req_hdr {
/* sender id */
u16 sender;
/* receiver id */
u16 receiver;
/* octep_ctrl_net_h2t_cmd */
u16 cmd;
/* reserved */
u16 rsvd0;
};
/* get/set mtu request */
struct octep_ctrl_net_h2f_req_cmd_mtu {
/* enum octep_ctrl_net_cmd */
u16 cmd;
/* 0-65535 */
u16 val;
};
/* get/set mac request */
struct octep_ctrl_net_h2f_req_cmd_mac {
/* enum octep_ctrl_net_cmd */
u16 cmd;
/* xx:xx:xx:xx:xx:xx */
u8 addr[ETH_ALEN];
};
/* get if_stats, xstats, q_stats request */
struct octep_ctrl_net_h2f_req_cmd_get_stats {
/* offset into barmem where fw should copy over stats */
u32 offset;
};
/* get/set link state, rx state */
struct octep_ctrl_net_h2f_req_cmd_state {
/* enum octep_ctrl_net_cmd */
u16 cmd;
/* enum octep_ctrl_net_state */
u16 state;
};
/* link info */
struct octep_ctrl_net_link_info {
/* Bitmap of Supported link speeds/modes */
u64 supported_modes;
/* Bitmap of Advertised link speeds/modes */
u64 advertised_modes;
/* Autonegotation state; bit 0=disabled; bit 1=enabled */
u8 autoneg;
/* Pause frames setting. bit 0=disabled; bit 1=enabled */
u8 pause;
/* Negotiated link speed in Mbps */
u32 speed;
};
/* get/set link info */
struct octep_ctrl_net_h2f_req_cmd_link_info {
/* enum octep_ctrl_net_cmd */
u16 cmd;
/* struct octep_ctrl_net_link_info */
struct octep_ctrl_net_link_info info;
};
/* Host to fw request data */
struct octep_ctrl_net_h2f_req {
struct octep_ctrl_net_req_hdr hdr;
union {
struct octep_ctrl_net_h2f_req_cmd_mtu mtu;
struct octep_ctrl_net_h2f_req_cmd_mac mac;
struct octep_ctrl_net_h2f_req_cmd_get_stats get_stats;
struct octep_ctrl_net_h2f_req_cmd_state link;
struct octep_ctrl_net_h2f_req_cmd_state rx;
struct octep_ctrl_net_h2f_req_cmd_link_info link_info;
};
} __packed;
struct octep_ctrl_net_resp_hdr {
/* sender id */
u16 sender;
/* receiver id */
u16 receiver;
/* octep_ctrl_net_h2t_cmd */
u16 cmd;
/* octep_ctrl_net_reply */
u16 reply;
};
/* get mtu response */
struct octep_ctrl_net_h2f_resp_cmd_mtu {
/* 0-65535 */
u16 val;
};
/* get mac response */
struct octep_ctrl_net_h2f_resp_cmd_mac {
/* xx:xx:xx:xx:xx:xx */
u8 addr[ETH_ALEN];
};
/* get link state, rx state response */
struct octep_ctrl_net_h2f_resp_cmd_state {
/* enum octep_ctrl_net_state */
u16 state;
};
/* Host to fw response data */
struct octep_ctrl_net_h2f_resp {
struct octep_ctrl_net_resp_hdr hdr;
union {
struct octep_ctrl_net_h2f_resp_cmd_mtu mtu;
struct octep_ctrl_net_h2f_resp_cmd_mac mac;
struct octep_ctrl_net_h2f_resp_cmd_state link;
struct octep_ctrl_net_h2f_resp_cmd_state rx;
struct octep_ctrl_net_link_info link_info;
};
} __packed;
/* link state notofication */
struct octep_ctrl_net_f2h_req_cmd_state {
/* enum octep_ctrl_net_state */
u16 state;
};
/* Fw to host request data */
struct octep_ctrl_net_f2h_req {
struct octep_ctrl_net_req_hdr hdr;
union {
struct octep_ctrl_net_f2h_req_cmd_state link;
};
};
/* Fw to host response data */
struct octep_ctrl_net_f2h_resp {
struct octep_ctrl_net_resp_hdr hdr;
};
/* Size of host to fw octep_ctrl_mbox queue element */
union octep_ctrl_net_h2f_data_sz {
struct octep_ctrl_net_h2f_req h2f_req;
struct octep_ctrl_net_h2f_resp h2f_resp;
};
/* Size of fw to host octep_ctrl_mbox queue element */
union octep_ctrl_net_f2h_data_sz {
struct octep_ctrl_net_f2h_req f2h_req;
struct octep_ctrl_net_f2h_resp f2h_resp;
};
/* size of host to fw data in words */
#define OCTEP_CTRL_NET_H2F_DATA_SZW ((sizeof(union octep_ctrl_net_h2f_data_sz)) / \
(sizeof(unsigned long)))
/* size of fw to host data in words */
#define OCTEP_CTRL_NET_F2H_DATA_SZW ((sizeof(union octep_ctrl_net_f2h_data_sz)) / \
(sizeof(unsigned long)))
/* size in words of get/set mtu request */
#define OCTEP_CTRL_NET_H2F_MTU_REQ_SZW 2
/* size in words of get/set mac request */
#define OCTEP_CTRL_NET_H2F_MAC_REQ_SZW 2
/* size in words of get stats request */
#define OCTEP_CTRL_NET_H2F_GET_STATS_REQ_SZW 2
/* size in words of get/set state request */
#define OCTEP_CTRL_NET_H2F_STATE_REQ_SZW 2
/* size in words of get/set link info request */
#define OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW 4
/* size in words of get mtu response */
#define OCTEP_CTRL_NET_H2F_GET_MTU_RESP_SZW 2
/* size in words of set mtu response */
#define OCTEP_CTRL_NET_H2F_SET_MTU_RESP_SZW 1
/* size in words of get mac response */
#define OCTEP_CTRL_NET_H2F_GET_MAC_RESP_SZW 2
/* size in words of set mac response */
#define OCTEP_CTRL_NET_H2F_SET_MAC_RESP_SZW 1
/* size in words of get state request */
#define OCTEP_CTRL_NET_H2F_GET_STATE_RESP_SZW 2
/* size in words of set state request */
#define OCTEP_CTRL_NET_H2F_SET_STATE_RESP_SZW 1
/* size in words of get link info request */
#define OCTEP_CTRL_NET_H2F_GET_LINK_INFO_RESP_SZW 4
/* size in words of set link info request */
#define OCTEP_CTRL_NET_H2F_SET_LINK_INFO_RESP_SZW 1
/** Get link status from firmware.
*
* @param oct: non-null pointer to struct octep_device.
*
* return value: link status 0=down, 1=up.
*/
int octep_get_link_status(struct octep_device *oct);
/** Set link status in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param up: boolean status.
*/
void octep_set_link_status(struct octep_device *oct, bool up);
/** Set rx state in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param up: boolean status.
*/
void octep_set_rx_state(struct octep_device *oct, bool up);
/** Get mac address from firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param addr: non-null pointer to mac address.
*
* return value: 0 on success, -errno on failure.
*/
int octep_get_mac_addr(struct octep_device *oct, u8 *addr);
/** Set mac address in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param addr: non-null pointer to mac address.
*/
int octep_set_mac_addr(struct octep_device *oct, u8 *addr);
/** Set mtu in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param mtu: mtu.
*/
int octep_set_mtu(struct octep_device *oct, int mtu);
/** Get interface statistics from firmware.
*
* @param oct: non-null pointer to struct octep_device.
*
* return value: 0 on success, -errno on failure.
*/
int octep_get_if_stats(struct octep_device *oct);
/** Get link info from firmware.
*
* @param oct: non-null pointer to struct octep_device.
*
* return value: 0 on success, -errno on failure.
*/
int octep_get_link_info(struct octep_device *oct);
/** Set link info in firmware.
*
* @param oct: non-null pointer to struct octep_device.
*/
int octep_set_link_info(struct octep_device *oct, struct octep_iface_link_info *link_info);
#endif /* __OCTEP_CTRL_NET_H__ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#include <linux/pci.h>
#include <linux/etherdevice.h>
#include "octep_config.h"
#include "octep_main.h"
/**
* octep_setup_oqs() - setup resources for all Rx queues.
*
* @oct: Octeon device private data structure.
*/
int octep_setup_oqs(struct octep_device *oct)
{
return -1;
}
/**
* octep_oq_dbell_init() - Initialize Rx queue doorbell.
*
* @oct: Octeon device private data structure.
*
* Write number of descriptors to Rx queue doorbell register.
*/
void octep_oq_dbell_init(struct octep_device *oct)
{
}
/**
* octep_free_oqs() - Free resources of all Rx queues.
*
* @oct: Octeon device private data structure.
*/
void octep_free_oqs(struct octep_device *oct)
{
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#ifndef _OCTEP_RX_H_
#define _OCTEP_RX_H_
/* struct octep_oq_desc_hw - Octeon Hardware OQ descriptor format.
*
* The descriptor ring is made of descriptors which have 2 64-bit values:
*
* @buffer_ptr: DMA address of the skb->data
* @info_ptr: DMA address of host memory, used to update pkt count by hw.
* This is currently unused to save pci writes.
*/
struct octep_oq_desc_hw {
dma_addr_t buffer_ptr;
u64 info_ptr;
};
#define OCTEP_OQ_DESC_SIZE (sizeof(struct octep_oq_desc_hw))
#define OCTEP_CSUM_L4_VERIFIED 0x1
#define OCTEP_CSUM_IP_VERIFIED 0x2
#define OCTEP_CSUM_VERIFIED (OCTEP_CSUM_L4_VERIFIED | OCTEP_CSUM_IP_VERIFIED)
/* Extended Response Header in packet data received from Hardware.
* Includes metadata like checksum status.
* this is valid only if hardware/firmware published support for this.
* This is at offset 0 of packet data (skb->data).
*/
struct octep_oq_resp_hw_ext {
/* Reserved. */
u64 reserved:62;
/* checksum verified. */
u64 csum_verified:2;
};
#define OCTEP_OQ_RESP_HW_EXT_SIZE (sizeof(struct octep_oq_resp_hw_ext))
/* Length of Rx packet DMA'ed by Octeon to Host.
* this is in bigendian; so need to be converted to cpu endian.
* Octeon writes this at the beginning of Rx buffer (skb->data).
*/
struct octep_oq_resp_hw {
/* The Length of the packet. */
__be64 length;
};
#define OCTEP_OQ_RESP_HW_SIZE (sizeof(struct octep_oq_resp_hw))
/* Pointer to data buffer.
* Driver keeps a pointer to the data buffer that it made available to
* the Octeon device. Since the descriptor ring keeps physical (bus)
* addresses, this field is required for the driver to keep track of
* the virtual address pointers. The fields are operated by
* OS-dependent routines.
*/
struct octep_rx_buffer {
struct page *page;
/* length from rx hardware descriptor after converting to cpu endian */
u64 len;
};
#define OCTEP_OQ_RECVBUF_SIZE (sizeof(struct octep_rx_buffer))
/* Output Queue statistics. Each output queue has four stats fields. */
struct octep_oq_stats {
/* Number of packets received from the Device. */
u64 packets;
/* Number of bytes received from the Device. */
u64 bytes;
/* Number of times failed to allocate buffers. */
u64 alloc_failures;
};
#define OCTEP_OQ_STATS_SIZE (sizeof(struct octep_oq_stats))
/* Hardware interface Rx statistics */
struct octep_iface_rx_stats {
/* Received packets */
u64 pkts;
/* Octets of received packets */
u64 octets;
/* Received PAUSE and Control packets */
u64 pause_pkts;
/* Received PAUSE and Control octets */
u64 pause_octets;
/* Filtered DMAC0 packets */
u64 dmac0_pkts;
/* Filtered DMAC0 octets */
u64 dmac0_octets;
/* Packets dropped due to RX FIFO full */
u64 dropped_pkts_fifo_full;
/* Octets dropped due to RX FIFO full */
u64 dropped_octets_fifo_full;
/* Error packets */
u64 err_pkts;
/* Filtered DMAC1 packets */
u64 dmac1_pkts;
/* Filtered DMAC1 octets */
u64 dmac1_octets;
/* NCSI-bound packets dropped */
u64 ncsi_dropped_pkts;
/* NCSI-bound octets dropped */
u64 ncsi_dropped_octets;
/* Multicast packets received. */
u64 mcast_pkts;
/* Broadcast packets received. */
u64 bcast_pkts;
};
/* The Descriptor Ring Output Queue structure.
* This structure has all the information required to implement a
* Octeon OQ.
*/
struct octep_oq {
u32 q_no;
struct octep_device *octep_dev;
struct net_device *netdev;
struct device *dev;
struct napi_struct *napi;
/* The receive buffer list. This list has the virtual addresses
* of the buffers.
*/
struct octep_rx_buffer *buff_info;
/* Pointer to the mapped packet credit register.
* Host writes number of info/buffer ptrs available to this register
*/
u8 __iomem *pkts_credit_reg;
/* Pointer to the mapped packet sent register.
* Octeon writes the number of packets DMA'ed to host memory
* in this register.
*/
u8 __iomem *pkts_sent_reg;
/* Statistics for this OQ. */
struct octep_oq_stats stats;
/* Packets pending to be processed */
u32 pkts_pending;
u32 last_pkt_count;
/* Index in the ring where the driver should read the next packet */
u32 host_read_idx;
/* Number of descriptors in this ring. */
u32 max_count;
u32 ring_size_mask;
/* The number of descriptors pending refill. */
u32 refill_count;
/* Index in the ring where the driver will refill the
* descriptor's buffer
*/
u32 host_refill_idx;
u32 refill_threshold;
/* The size of each buffer pointed by the buffer pointer. */
u32 buffer_size;
u32 max_single_buffer_size;
/* The 8B aligned descriptor ring starts at this address. */
struct octep_oq_desc_hw *desc_ring;
/* DMA mapped address of the OQ descriptor ring. */
dma_addr_t desc_ring_dma;
};
#define OCTEP_OQ_SIZE (sizeof(struct octep_oq))
#endif /* _OCTEP_RX_H_ */
// SPDX-License-Identifier: GPL-2.0
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#include <linux/pci.h>
#include <linux/etherdevice.h>
#include "octep_config.h"
#include "octep_main.h"
/**
* octep_clean_iqs() - Clean Tx queues to shutdown the device.
*
* @oct: Octeon device private data structure.
*
* Free the buffers in Tx queue descriptors pending completion and
* reset queue indices
*/
void octep_clean_iqs(struct octep_device *oct)
{
}
/**
* octep_setup_iqs() - setup resources for all Tx queues.
*
* @oct: Octeon device private data structure.
*/
int octep_setup_iqs(struct octep_device *oct)
{
return -1;
}
/**
* octep_free_iqs() - Free resources of all Tx queues.
*
* @oct: Octeon device private data structure.
*/
void octep_free_iqs(struct octep_device *oct)
{
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell Octeon EP (EndPoint) Ethernet Driver
*
* Copyright (C) 2020 Marvell.
*
*/
#ifndef _OCTEP_TX_H_
#define _OCTEP_TX_H_
#define IQ_SEND_OK 0
#define IQ_SEND_STOP 1
#define IQ_SEND_FAILED -1
#define TX_BUFTYPE_NONE 0
#define TX_BUFTYPE_NET 1
#define TX_BUFTYPE_NET_SG 2
#define NUM_TX_BUFTYPES 3
/* Hardware format for Scatter/Gather list */
struct octep_tx_sglist_desc {
u16 len[4];
dma_addr_t dma_ptr[4];
};
/* Each Scatter/Gather entry sent to hardwar hold four pointers.
* So, number of entries required is (MAX_SKB_FRAGS + 1)/4, where '+1'
* is for main skb which also goes as a gather buffer to Octeon hardware.
* To allocate sufficient SGLIST entries for a packet with max fragments,
* align by adding 3 before calcuating max SGLIST entries per packet.
*/
#define OCTEP_SGLIST_ENTRIES_PER_PKT ((MAX_SKB_FRAGS + 1 + 3) / 4)
#define OCTEP_SGLIST_SIZE_PER_PKT \
(OCTEP_SGLIST_ENTRIES_PER_PKT * sizeof(struct octep_tx_sglist_desc))
struct octep_tx_buffer {
struct sk_buff *skb;
dma_addr_t dma;
struct octep_tx_sglist_desc *sglist;
dma_addr_t sglist_dma;
u8 gather;
};
#define OCTEP_IQ_TXBUFF_INFO_SIZE (sizeof(struct octep_tx_buffer))
/* Hardware interface Tx statistics */
struct octep_iface_tx_stats {
/* Packets dropped due to excessive collisions */
u64 xscol;
/* Packets dropped due to excessive deferral */
u64 xsdef;
/* Packets sent that experienced multiple collisions before successful
* transmission
*/
u64 mcol;
/* Packets sent that experienced a single collision before successful
* transmission
*/
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;
/* Packets sent with an octet count == 64 */
u64 hist_eq64;
/* Packets sent with an octet count of 65–127 */
u64 hist_65to127;
/* Packets sent with an octet count of 128–255 */
u64 hist_128to255;
/* Packets sent with an octet count of 256–511 */
u64 hist_256to511;
/* Packets sent with an octet count of 512–1023 */
u64 hist_512to1023;
/* Packets sent with an octet count of 1024-1518 */
u64 hist_1024to1518;
/* 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
*/
u64 undflw;
/* Control/PAUSE packets sent */
u64 ctl;
};
/* Input Queue statistics. Each input queue has four stats fields. */
struct octep_iq_stats {
/* Instructions posted to this queue. */
u64 instr_posted;
/* Instructions copied by hardware for processing. */
u64 instr_completed;
/* Instructions that could not be processed. */
u64 instr_dropped;
/* Bytes sent through this queue. */
u64 bytes_sent;
/* Gather entries sent through this queue. */
u64 sgentry_sent;
/* Number of transmit failures due to TX_BUSY */
u64 tx_busy;
/* Number of times the queue is restarted */
u64 restart_cnt;
};
/* The instruction (input) queue.
* The input queue is used to post raw (instruction) mode data or packet
* data to Octeon device from the host. Each input queue (up to 4) for
* a Octeon device has one such structure to represent it.
*/
struct octep_iq {
u32 q_no;
struct octep_device *octep_dev;
struct net_device *netdev;
struct device *dev;
struct netdev_queue *netdev_q;
/* Index in input ring where driver should write the next packet */
u16 host_write_index;
/* Index in input ring where Octeon is expected to read next packet */
u16 octep_read_index;
/* This index aids in finding the window in the queue where Octeon
* has read the commands.
*/
u16 flush_index;
/* Statistics for this input queue. */
struct octep_iq_stats stats;
/* This field keeps track of the instructions pending in this queue. */
atomic_t instr_pending;
/* Pointer to the Virtual Base addr of the input ring. */
struct octep_tx_desc_hw *desc_ring;
/* DMA mapped base address of the input descriptor ring. */
dma_addr_t desc_ring_dma;
/* Info of Tx buffers pending completion. */
struct octep_tx_buffer *buff_info;
/* Base pointer to Scatter/Gather lists for all ring descriptors. */
struct octep_tx_sglist_desc *sglist;
/* DMA mapped addr of Scatter Gather Lists */
dma_addr_t sglist_dma;
/* Octeon doorbell register for the ring. */
u8 __iomem *doorbell_reg;
/* Octeon instruction count register for this ring. */
u8 __iomem *inst_cnt_reg;
/* interrupt level register for this ring */
u8 __iomem *intr_lvl_reg;
/* Maximum no. of instructions in this queue. */
u32 max_count;
u32 ring_size_mask;
u32 pkt_in_done;
u32 pkts_processed;
u32 status;
/* Number of instructions pending to be posted to Octeon. */
u32 fill_cnt;
/* The max. number of instructions that can be held pending by the
* driver before ringing doorbell.
*/
u32 fill_threshold;
};
/* Hardware Tx Instruction Header */
struct octep_instr_hdr {
/* Data Len */
u64 tlen:16;
/* Reserved */
u64 rsvd:20;
/* PKIND for SDP */
u64 pkind:6;
/* Front Data size */
u64 fsz:6;
/* No. of entries in gather list */
u64 gsz:14;
/* Gather indicator 1=gather*/
u64 gather:1;
/* Reserved3 */
u64 reserved3:1;
};
/* Hardware Tx completion response header */
struct octep_instr_resp_hdr {
/* Request ID */
u64 rid:16;
/* PCIe port to use for response */
u64 pcie_port:3;
/* Scatter indicator 1=scatter */
u64 scatter:1;
/* Size of Expected result OR no. of entries in scatter list */
u64 rlenssz:14;
/* Desired destination port for result */
u64 dport:6;
/* Opcode Specific parameters */
u64 param:8;
/* Opcode for the return packet */
u64 opcode:16;
};
/* 64-byte Tx instruction format.
* Format of instruction for a 64-byte mode input queue.
*
* only first 16-bytes (dptr and ih) are mandatory; rest are optional
* and filled by the driver based on firmware/hardware capabilities.
* These optional headers together called Front Data and its size is
* described by ih->fsz.
*/
struct octep_tx_desc_hw {
/* Pointer where the input data is available. */
u64 dptr;
/* Instruction Header. */
union {
struct octep_instr_hdr ih;
u64 ih64;
};
/* Pointer where the response for a RAW mode packet will be written
* by Octeon.
*/
u64 rptr;
/* Input Instruction Response Header. */
struct octep_instr_resp_hdr irh;
/* Additional headers available in a 64-byte instruction. */
u64 exhdr[4];
};
#define OCTEP_IQ_DESC_SIZE (sizeof(struct octep_tx_desc_hw))
#endif /* _OCTEP_TX_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment