Skip to content

Commit

Permalink
octeontx2-pf: Add Marvell OcteonTX2 NIC driver
Browse files Browse the repository at this point in the history
This patch adds template for the Marvell's OcteonTX2 network
controller's physical function driver. Just the probe, PCI
specific initialization and netdev registration.

Signed-off-by: Sunil Goutham <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Sunil Goutham authored and davem330 committed Jan 27, 2020
1 parent 9e0703a commit 1654757
Show file tree
Hide file tree
Showing 6 changed files with 362 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ config NDC_DIS_DYNAMIC_CACHING
This config option disables caching of dynamic entries such as NIX SQEs
, NPA stack pages etc in NDC. Also locks down NIX SQ/CQ/RQ/RSS and
NPA Aura/Pool contexts.

config OCTEONTX2_PF
tristate "Marvell OcteonTX2 NIC Physical Function driver"
select OCTEONTX2_MBOX
depends on (64BIT && COMPILE_TEST) || ARM64
depends on PCI
help
This driver supports Marvell's OcteonTX2 NIC physical function.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
# Makefile for Marvell OcteonTX2 device drivers.
#

obj-$(CONFIG_OCTEONTX2_MBOX) += af/
obj-$(CONFIG_OCTEONTX2_AF) += af/
obj-$(CONFIG_OCTEONTX2_PF) += nic/
10 changes: 10 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for Marvell's OcteonTX2 ethernet device drivers
#

obj-$(CONFIG_OCTEONTX2_PF) += octeontx2_nicpf.o

octeontx2_nicpf-y := otx2_pf.o

ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
77 changes: 77 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell OcteonTx2 RVU Ethernet driver
*
* Copyright (C) 2020 Marvell International Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef OTX2_COMMON_H
#define OTX2_COMMON_H

#include <linux/pci.h>

#include "otx2_reg.h"

/* PCI device IDs */
#define PCI_DEVID_OCTEONTX2_RVU_PF 0xA063

/* PCI BAR nos */
#define PCI_CFG_REG_BAR_NUM 2

struct otx2_hw {
struct pci_dev *pdev;
u16 rx_queues;
u16 tx_queues;
u16 max_queues;
};

struct otx2_nic {
void __iomem *reg_base;
struct net_device *netdev;

struct otx2_hw hw;
struct pci_dev *pdev;
struct device *dev;
};

/* Register read/write APIs */
static inline void __iomem *otx2_get_regaddr(struct otx2_nic *nic, u64 offset)
{
u64 blkaddr;

switch ((offset >> RVU_FUNC_BLKADDR_SHIFT) & RVU_FUNC_BLKADDR_MASK) {
case BLKTYPE_NIX:
blkaddr = BLKADDR_NIX0;
break;
case BLKTYPE_NPA:
blkaddr = BLKADDR_NPA;
break;
default:
blkaddr = BLKADDR_RVUM;
break;
};

offset &= ~(RVU_FUNC_BLKADDR_MASK << RVU_FUNC_BLKADDR_SHIFT);
offset |= (blkaddr << RVU_FUNC_BLKADDR_SHIFT);

return nic->reg_base + offset;
}

static inline void otx2_write64(struct otx2_nic *nic, u64 offset, u64 val)
{
void __iomem *addr = otx2_get_regaddr(nic, offset);

writeq(val, addr);
}

static inline u64 otx2_read64(struct otx2_nic *nic, u64 offset)
{
void __iomem *addr = otx2_get_regaddr(nic, offset);

return readq(addr);
}

#endif /* OTX2_COMMON_H */
214 changes: 214 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// SPDX-License-Identifier: GPL-2.0
/* Marvell OcteonTx2 RVU Physcial Function ethernet driver
*
* Copyright (C) 2020 Marvell International Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/etherdevice.h>
#include <linux/of.h>
#include <linux/if_vlan.h>
#include <linux/iommu.h>
#include <net/ip.h>

#include "otx2_common.h"

#define DRV_NAME "octeontx2-nicpf"
#define DRV_STRING "Marvell OcteonTX2 NIC Physical Function Driver"
#define DRV_VERSION "1.0"

/* Supported devices */
static const struct pci_device_id otx2_pf_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_RVU_PF) },
{ 0, } /* end of table */
};

MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION(DRV_STRING);
MODULE_LICENSE("GPL v2");
MODULE_VERSION(DRV_VERSION);
MODULE_DEVICE_TABLE(pci, otx2_pf_id_table);

static int otx2_set_real_num_queues(struct net_device *netdev,
int tx_queues, int rx_queues)
{
int err;

err = netif_set_real_num_tx_queues(netdev, tx_queues);
if (err) {
netdev_err(netdev,
"Failed to set no of Tx queues: %d\n", tx_queues);
return err;
}

err = netif_set_real_num_rx_queues(netdev, rx_queues);
if (err)
netdev_err(netdev,
"Failed to set no of Rx queues: %d\n", rx_queues);
return err;
}

static int otx2_open(struct net_device *netdev)
{
netif_carrier_off(netdev);

return 0;
}

static int otx2_stop(struct net_device *netdev)
{
return 0;
}

static const struct net_device_ops otx2_netdev_ops = {
.ndo_open = otx2_open,
.ndo_stop = otx2_stop,
};

static int otx2_check_pf_usable(struct otx2_nic *nic)
{
u64 rev;

rev = otx2_read64(nic, RVU_PF_BLOCK_ADDRX_DISC(BLKADDR_RVUM));
rev = (rev >> 12) & 0xFF;
/* Check if AF has setup revision for RVUM block,
* otherwise this driver probe should be deferred
* until AF driver comes up.
*/
if (!rev) {
dev_warn(nic->dev,
"AF is not initialized, deferring probe\n");
return -EPROBE_DEFER;
}
return 0;
}

static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
struct net_device *netdev;
struct otx2_nic *pf;
struct otx2_hw *hw;
int err, qcount;

err = pcim_enable_device(pdev);
if (err) {
dev_err(dev, "Failed to enable PCI device\n");
return err;
}

err = pci_request_regions(pdev, DRV_NAME);
if (err) {
dev_err(dev, "PCI request regions failed 0x%x\n", err);
return err;
}

err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
if (err) {
dev_err(dev, "DMA mask config failed, abort\n");
goto err_release_regions;
}

pci_set_master(pdev);

/* Set number of queues */
qcount = min_t(int, num_online_cpus(), num_online_cpus());

netdev = alloc_etherdev_mqs(sizeof(*pf), qcount, qcount);
if (!netdev) {
err = -ENOMEM;
goto err_release_regions;
}

pci_set_drvdata(pdev, netdev);
SET_NETDEV_DEV(netdev, &pdev->dev);
pf = netdev_priv(netdev);
pf->netdev = netdev;
pf->pdev = pdev;
pf->dev = dev;

hw = &pf->hw;
hw->pdev = pdev;
hw->rx_queues = qcount;
hw->tx_queues = qcount;
hw->max_queues = qcount;

/* Map CSRs */
pf->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
if (!pf->reg_base) {
dev_err(dev, "Unable to map physical function CSRs, aborting\n");
err = -ENOMEM;
goto err_free_netdev;
}

err = otx2_check_pf_usable(pf);
if (err)
goto err_free_netdev;

err = otx2_set_real_num_queues(netdev, hw->tx_queues, hw->rx_queues);
if (err)
goto err_free_netdev;

netdev->netdev_ops = &otx2_netdev_ops;

err = register_netdev(netdev);
if (err) {
dev_err(dev, "Failed to register netdevice\n");
goto err_free_netdev;
}

return 0;

err_free_netdev:
pci_set_drvdata(pdev, NULL);
free_netdev(netdev);
err_release_regions:
pci_release_regions(pdev);
return err;
}

static void otx2_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct otx2_nic *pf;

if (!netdev)
return;

pf = netdev_priv(netdev);

unregister_netdev(netdev);
pci_free_irq_vectors(pf->pdev);
pci_set_drvdata(pdev, NULL);
free_netdev(netdev);
pci_release_regions(pdev);
}

static struct pci_driver otx2_pf_driver = {
.name = DRV_NAME,
.id_table = otx2_pf_id_table,
.probe = otx2_probe,
.shutdown = otx2_remove,
.remove = otx2_remove,
};

static int __init otx2_rvupf_init_module(void)
{
pr_info("%s: %s\n", DRV_NAME, DRV_STRING);

return pci_register_driver(&otx2_pf_driver);
}

static void __exit otx2_rvupf_cleanup_module(void)
{
pci_unregister_driver(&otx2_pf_driver);
}

module_init(otx2_rvupf_init_module);
module_exit(otx2_rvupf_cleanup_module);
51 changes: 51 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell OcteonTx2 RVU Ethernet driver
*
* Copyright (C) 2020 Marvell International Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef OTX2_REG_H
#define OTX2_REG_H

#include <rvu_struct.h>

/* RVU PF registers */
#define RVU_PF_VFX_PFVF_MBOX0 (0x00000)
#define RVU_PF_VFX_PFVF_MBOX1 (0x00008)
#define RVU_PF_VFX_PFVF_MBOXX(a, b) (0x0 | (a) << 12 | (b) << 3)
#define RVU_PF_VF_BAR4_ADDR (0x10)
#define RVU_PF_BLOCK_ADDRX_DISC(a) (0x200 | (a) << 3)
#define RVU_PF_VFME_STATUSX(a) (0x800 | (a) << 3)
#define RVU_PF_VFTRPENDX(a) (0x820 | (a) << 3)
#define RVU_PF_VFTRPEND_W1SX(a) (0x840 | (a) << 3)
#define RVU_PF_VFPF_MBOX_INTX(a) (0x880 | (a) << 3)
#define RVU_PF_VFPF_MBOX_INT_W1SX(a) (0x8A0 | (a) << 3)
#define RVU_PF_VFPF_MBOX_INT_ENA_W1SX(a) (0x8C0 | (a) << 3)
#define RVU_PF_VFPF_MBOX_INT_ENA_W1CX(a) (0x8E0 | (a) << 3)
#define RVU_PF_VFFLR_INTX(a) (0x900 | (a) << 3)
#define RVU_PF_VFFLR_INT_W1SX(a) (0x920 | (a) << 3)
#define RVU_PF_VFFLR_INT_ENA_W1SX(a) (0x940 | (a) << 3)
#define RVU_PF_VFFLR_INT_ENA_W1CX(a) (0x960 | (a) << 3)
#define RVU_PF_VFME_INTX(a) (0x980 | (a) << 3)
#define RVU_PF_VFME_INT_W1SX(a) (0x9A0 | (a) << 3)
#define RVU_PF_VFME_INT_ENA_W1SX(a) (0x9C0 | (a) << 3)
#define RVU_PF_VFME_INT_ENA_W1CX(a) (0x9E0 | (a) << 3)
#define RVU_PF_PFAF_MBOX0 (0xC00)
#define RVU_PF_PFAF_MBOX1 (0xC08)
#define RVU_PF_PFAF_MBOXX(a) (0xC00 | (a) << 3)
#define RVU_PF_INT (0xc20)
#define RVU_PF_INT_W1S (0xc28)
#define RVU_PF_INT_ENA_W1S (0xc30)
#define RVU_PF_INT_ENA_W1C (0xc38)
#define RVU_PF_MSIX_VECX_ADDR(a) (0x000 | (a) << 4)
#define RVU_PF_MSIX_VECX_CTL(a) (0x008 | (a) << 4)
#define RVU_PF_MSIX_PBAX(a) (0xF0000 | (a) << 3)

#define RVU_FUNC_BLKADDR_SHIFT 20
#define RVU_FUNC_BLKADDR_MASK 0x1FULL

#endif /* OTX2_REG_H */

0 comments on commit 1654757

Please sign in to comment.