[v3,04/17] net/ionic: register and initialize the adapter

Message ID 20191209214656.27347-5-cardigliano@ntop.org (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series Introduces net/ionic PMD |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail Compilation issues

Commit Message

Alfredo Cardigliano Dec. 9, 2019, 9:46 p.m. UTC
  Register the Pensando ionic PMD (net_ionic) and define initial probe
and remove callbacks with adapter initialization.

Signed-off-by: Alfredo Cardigliano <cardigliano@ntop.org>
Reviewed-by: Shannon Nelson <snelson@pensando.io>
---
 doc/guides/nics/features/ionic.ini |   2 +
 drivers/net/ionic/Makefile         |   3 +
 drivers/net/ionic/ionic.h          |  63 +++++++++++++
 drivers/net/ionic/ionic_dev.c      | 134 ++++++++++++++++++++++++++
 drivers/net/ionic/ionic_dev.h      | 127 +++++++++++++++++++++++++
 drivers/net/ionic/ionic_ethdev.c   | 146 +++++++++++++++++++++++++++++
 drivers/net/ionic/ionic_mac_api.c  |  61 ++++++++++++
 drivers/net/ionic/ionic_mac_api.h  |  13 +++
 drivers/net/ionic/ionic_main.c     | 133 ++++++++++++++++++++++++++
 drivers/net/ionic/ionic_osdep.h    |  79 ++++++++++++++++
 drivers/net/ionic/ionic_regs.h     | 142 ++++++++++++++++++++++++++++
 drivers/net/ionic/meson.build      |   4 +
 12 files changed, 907 insertions(+)
 create mode 100644 drivers/net/ionic/ionic.h
 create mode 100644 drivers/net/ionic/ionic_dev.c
 create mode 100644 drivers/net/ionic/ionic_dev.h
 create mode 100644 drivers/net/ionic/ionic_mac_api.c
 create mode 100644 drivers/net/ionic/ionic_mac_api.h
 create mode 100644 drivers/net/ionic/ionic_main.c
 create mode 100644 drivers/net/ionic/ionic_osdep.h
 create mode 100644 drivers/net/ionic/ionic_regs.h
  

Comments

Ferruh Yigit Dec. 10, 2019, 6:50 p.m. UTC | #1
On 12/9/2019 9:46 PM, Alfredo Cardigliano wrote:
> Register the Pensando ionic PMD (net_ionic) and define initial probe
> and remove callbacks with adapter initialization.
> 
> Signed-off-by: Alfredo Cardigliano <cardigliano@ntop.org>
> Reviewed-by: Shannon Nelson <snelson@pensando.io>

<...>

> +/*
> + * There is no room in struct rte_pci_driver to keep a reference
> + * to the adapter, using a static list for the time being.
> + */
> +static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters =
> +		LIST_HEAD_INITIALIZER(ionic_pci_adapters);
> +static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER;

As described in previous version of the patchset, it is possible to remove the
PMD maintained list of adapters, is there any benefit to keep it?
  
Alfredo Cardigliano Dec. 12, 2019, 12:04 p.m. UTC | #2
> On 10 Dec 2019, at 19:50, Ferruh Yigit <ferruh.yigit@intel.com> wrote:
> 
> On 12/9/2019 9:46 PM, Alfredo Cardigliano wrote:
>> Register the Pensando ionic PMD (net_ionic) and define initial probe
>> and remove callbacks with adapter initialization.
>> 
>> Signed-off-by: Alfredo Cardigliano <cardigliano@ntop.org>
>> Reviewed-by: Shannon Nelson <snelson@pensando.io>
> 
> <...>
> 
>> +/*
>> + * There is no room in struct rte_pci_driver to keep a reference
>> + * to the adapter, using a static list for the time being.
>> + */
>> +static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters =
>> +		LIST_HEAD_INITIALIZER(ionic_pci_adapters);
>> +static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER;
> 
> As described in previous version of the patchset, it is possible to remove the
> PMD maintained list of adapters, is there any benefit to keep it?

I will try to implement the approach you recommended. If that looks messy, 
is it a problem to keep this static list?

Thank you
Alfredo
  
Ferruh Yigit Dec. 12, 2019, 12:42 p.m. UTC | #3
On 12/12/2019 12:04 PM, Alfredo Cardigliano wrote:
> 
> 
>> On 10 Dec 2019, at 19:50, Ferruh Yigit <ferruh.yigit@intel.com> wrote:
>>
>> On 12/9/2019 9:46 PM, Alfredo Cardigliano wrote:
>>> Register the Pensando ionic PMD (net_ionic) and define initial probe
>>> and remove callbacks with adapter initialization.
>>>
>>> Signed-off-by: Alfredo Cardigliano <cardigliano@ntop.org>
>>> Reviewed-by: Shannon Nelson <snelson@pensando.io>
>>
>> <...>
>>
>>> +/*
>>> + * There is no room in struct rte_pci_driver to keep a reference
>>> + * to the adapter, using a static list for the time being.
>>> + */
>>> +static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters =
>>> +		LIST_HEAD_INITIALIZER(ionic_pci_adapters);
>>> +static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER;
>>
>> As described in previous version of the patchset, it is possible to remove the
>> PMD maintained list of adapters, is there any benefit to keep it?
> 
> I will try to implement the approach you recommended. If that looks messy, 
> is it a problem to keep this static list?
> 

No problem, that looks reasonable. I believe it will work without being messy,
please check octeontx PMD [1], it does something similar, but if it turns out to
be messy please feel free to keep the static list.

[1]
http://lxr.dpdk.org/dpdk/v19.11/source/drivers/net/octeontx/octeontx_ethdev.c#L1146
  

Patch

diff --git a/doc/guides/nics/features/ionic.ini b/doc/guides/nics/features/ionic.ini
index 3a92eedc7..6915d9c42 100644
--- a/doc/guides/nics/features/ionic.ini
+++ b/doc/guides/nics/features/ionic.ini
@@ -4,5 +4,7 @@ 
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Linux UIO            = Y
+Linux VFIO           = Y
 x86-64               = Y
 Usage doc            = Y
diff --git a/drivers/net/ionic/Makefile b/drivers/net/ionic/Makefile
index 4c1c8d129..a3ad25897 100644
--- a/drivers/net/ionic/Makefile
+++ b/drivers/net/ionic/Makefile
@@ -33,6 +33,9 @@  endif
 #
 # all source are stored in SRCS-y
 #
+SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_mac_api.c
+SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_dev.c
 SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_IONIC_PMD) += ionic_main.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/ionic/ionic.h b/drivers/net/ionic/ionic.h
new file mode 100644
index 000000000..5c869e698
--- /dev/null
+++ b/drivers/net/ionic/ionic.h
@@ -0,0 +1,63 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#ifndef _IONIC_H_
+#define _IONIC_H_
+
+#include <stdint.h>
+
+#include "ionic_dev.h"
+#include "ionic_if.h"
+#include "ionic_osdep.h"
+
+#define IONIC_DRV_NAME			"ionic"
+#define IONIC_DRV_DESCRIPTION		"Pensando Ethernet NIC Driver"
+#define IONIC_DRV_VERSION		"0.11.0-49"
+
+/* Vendor ID */
+#define IONIC_PENSANDO_VENDOR_ID	0x1dd8
+
+/* Device IDs */
+#define IONIC_DEV_ID_ETH_PF		0x1002
+#define IONIC_DEV_ID_ETH_VF		0x1003
+#define IONIC_DEV_ID_ETH_MGMT		0x1004
+
+enum ionic_mac_type {
+	IONIC_MAC_UNKNOWN = 0,
+	IONIC_MAC_CAPRI,
+	IONIC_NUM_MACS
+};
+
+struct ionic_mac_info {
+	enum ionic_mac_type type;
+};
+
+struct ionic_hw {
+	struct ionic_mac_info mac;
+	uint16_t device_id;
+	uint16_t vendor_id;
+};
+
+/*
+ * Structure to store private data for each driver instance (for each adapter).
+ */
+struct ionic_adapter {
+	struct ionic_hw hw;
+	struct ionic_dev idev;
+	struct ionic_dev_bar bars[IONIC_BARS_MAX];
+	struct ionic_identity	ident;
+	uint32_t num_bars;
+	bool is_mgmt_nic;
+	struct rte_pci_device *pci_dev;
+	LIST_ENTRY(ionic_adapter) pci_adapters;
+};
+
+int ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait);
+int ionic_setup(struct ionic_adapter *adapter);
+
+int ionic_identify(struct ionic_adapter *adapter);
+int ionic_init(struct ionic_adapter *adapter);
+int ionic_reset(struct ionic_adapter *adapter);
+
+#endif /* _IONIC_H_ */
diff --git a/drivers/net/ionic/ionic_dev.c b/drivers/net/ionic/ionic_dev.c
new file mode 100644
index 000000000..406236da9
--- /dev/null
+++ b/drivers/net/ionic/ionic_dev.c
@@ -0,0 +1,134 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#include <rte_malloc.h>
+
+#include "ionic_dev.h"
+#include "ionic.h"
+
+int
+ionic_dev_setup(struct ionic_adapter *adapter)
+{
+	struct ionic_dev_bar *bar = adapter->bars;
+	unsigned int num_bars = adapter->num_bars;
+	struct ionic_dev *idev = &adapter->idev;
+	uint32_t sig;
+	u_char *bar0_base;
+
+	/* BAR0: dev_cmd and interrupts */
+	if (num_bars < 1) {
+		IONIC_PRINT(ERR, "No bars found, aborting");
+		return -EFAULT;
+	}
+
+	if (bar->len < IONIC_BAR0_SIZE) {
+		IONIC_PRINT(ERR,
+			"Resource bar size %lu too small, aborting",
+			bar->len);
+		return -EFAULT;
+	}
+
+	bar0_base = bar->vaddr;
+	idev->dev_info = (union ionic_dev_info_regs*)
+		&bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET];
+	idev->dev_cmd = (union ionic_dev_cmd_regs*)
+		&bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET];
+	idev->intr_status = (struct ionic_intr_status*)
+		&bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET];
+	idev->intr_ctrl = (struct ionic_intr*)
+		&bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET];
+
+	sig = ioread32(&idev->dev_info->signature);
+	if (sig != IONIC_DEV_INFO_SIGNATURE) {
+		IONIC_PRINT(ERR, "Incompatible firmware signature %x",
+			sig);
+		return -EFAULT;
+	}
+
+	/* BAR1: doorbells */
+	bar++;
+	if (num_bars < 2) {
+		IONIC_PRINT(ERR, "Doorbell bar missing, aborting");
+		return -EFAULT;
+	}
+
+	idev->db_pages = bar->vaddr;
+	idev->phy_db_pages = bar->bus_addr;
+
+	return 0;
+}
+
+/* Devcmd Interface */
+
+uint8_t
+ionic_dev_cmd_status(struct ionic_dev *idev)
+{
+	return ioread8(&idev->dev_cmd->comp.comp.status);
+}
+
+bool
+ionic_dev_cmd_done(struct ionic_dev *idev)
+{
+	return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE;
+}
+
+void
+ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem)
+{
+	union ionic_dev_cmd_comp *comp = mem;
+	unsigned int i;
+	uint32_t comp_size = sizeof(comp->words) /
+		sizeof(comp->words[0]);
+
+	for (i = 0; i < comp_size; i++)
+		comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]);
+}
+
+void
+ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd)
+{
+	unsigned int i;
+	uint32_t cmd_size = sizeof(cmd->words) /
+		sizeof(cmd->words[0]);
+
+	for (i = 0; i < cmd_size; i++)
+		iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]);
+
+	iowrite32(0, &idev->dev_cmd->done);
+	iowrite32(1, &idev->dev_cmd->doorbell);
+}
+
+/* Device commands */
+
+void
+ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver)
+{
+	union ionic_dev_cmd cmd = {
+		.identify.opcode = IONIC_CMD_IDENTIFY,
+		.identify.ver = ver,
+	};
+
+	ionic_dev_cmd_go(idev, &cmd);
+}
+
+void
+ionic_dev_cmd_init(struct ionic_dev *idev)
+{
+	union ionic_dev_cmd cmd = {
+		.init.opcode = IONIC_CMD_INIT,
+		.init.type = 0,
+	};
+
+	ionic_dev_cmd_go(idev, &cmd);
+}
+
+void
+ionic_dev_cmd_reset(struct ionic_dev *idev)
+{
+	union ionic_dev_cmd cmd = {
+		.reset.opcode = IONIC_CMD_RESET,
+	};
+
+	ionic_dev_cmd_go(idev, &cmd);
+}
diff --git a/drivers/net/ionic/ionic_dev.h b/drivers/net/ionic/ionic_dev.h
new file mode 100644
index 000000000..82a3cdb70
--- /dev/null
+++ b/drivers/net/ionic/ionic_dev.h
@@ -0,0 +1,127 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#ifndef _IONIC_DEV_H_
+#define _IONIC_DEV_H_
+
+#include "ionic_osdep.h"
+#include "ionic_if.h"
+#include "ionic_regs.h"
+
+#define IONIC_DEVCMD_TIMEOUT	30 /* devcmd_timeout */
+
+struct ionic_adapter;
+
+struct ionic_dev_bar {
+	void __iomem *vaddr;
+	rte_iova_t bus_addr;
+	unsigned long len;
+};
+
+static inline void ionic_struct_size_checks(void)
+{
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_doorbell) != 8);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_intr) != 32);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_intr_status) != 8);
+
+	RTE_BUILD_BUG_ON(sizeof(union ionic_dev_regs) != 4096);
+	RTE_BUILD_BUG_ON(sizeof(union ionic_dev_info_regs) != 2048);
+	RTE_BUILD_BUG_ON(sizeof(union ionic_dev_cmd_regs) != 2048);
+
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_stats) != 1024);
+
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_admin_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_admin_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_nop_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_nop_comp) != 16);
+
+	/* Device commands */
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_identify_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_identify_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_init_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_init_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_reset_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_reset_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_getattr_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_getattr_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_setattr_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_dev_setattr_comp) != 16);
+
+	/* Port commands */
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_identify_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_identify_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_init_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_init_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_reset_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_reset_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_getattr_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_getattr_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_setattr_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_port_setattr_comp) != 16);
+
+	/* LIF commands */
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_init_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_init_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_reset_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_getattr_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_getattr_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_setattr_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_lif_setattr_comp) != 16);
+
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_q_init_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_q_init_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_q_control_cmd) != 64);
+
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_mode_set_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_filter_add_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_filter_add_comp) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rx_filter_del_cmd) != 64);
+
+	/* RDMA commands */
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rdma_reset_cmd) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rdma_queue_cmd) != 64);
+
+	/* Events */
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_notifyq_cmd) != 4);
+	RTE_BUILD_BUG_ON(sizeof(union ionic_notifyq_comp) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_notifyq_event) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_link_change_event) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_reset_event) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_heartbeat_event) != 64);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_log_event) != 64);
+
+	/* I/O */
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_txq_desc) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_txq_sg_desc) != 128);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_txq_comp) != 16);
+
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rxq_desc) != 16);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rxq_sg_desc) != 128);
+	RTE_BUILD_BUG_ON(sizeof(struct ionic_rxq_comp) != 16);
+}
+
+struct ionic_dev {
+	union ionic_dev_info_regs __iomem *dev_info;
+	union ionic_dev_cmd_regs __iomem *dev_cmd;
+
+	struct ionic_doorbell __iomem *db_pages;
+	rte_iova_t phy_db_pages;
+
+	struct ionic_intr __iomem *intr_ctrl;
+
+	struct ionic_intr_status __iomem *intr_status;
+};
+
+int ionic_dev_setup(struct ionic_adapter *adapter);
+
+void ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd);
+uint8_t ionic_dev_cmd_status(struct ionic_dev *idev);
+bool ionic_dev_cmd_done(struct ionic_dev *idev);
+void ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem);
+
+void ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver);
+void ionic_dev_cmd_init(struct ionic_dev *idev);
+void ionic_dev_cmd_reset(struct ionic_dev *idev);
+
+#endif /* _IONIC_DEV_H_ */
diff --git a/drivers/net/ionic/ionic_ethdev.c b/drivers/net/ionic/ionic_ethdev.c
index c706588bc..23c6ef17c 100644
--- a/drivers/net/ionic/ionic_ethdev.c
+++ b/drivers/net/ionic/ionic_ethdev.c
@@ -2,10 +2,156 @@ 
  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
  */
 
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
+#include <rte_malloc.h>
+
 #include "ionic_logs.h"
+#include "ionic.h"
+#include "ionic_dev.h"
+#include "ionic_mac_api.h"
 
 int ionic_logtype_driver;
 
+static const struct rte_pci_id pci_id_ionic_map[] = {
+	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) },
+	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) },
+	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) },
+	{ .vendor_id = 0, /* sentinel */ },
+};
+
+/*
+ * There is no room in struct rte_pci_driver to keep a reference
+ * to the adapter, using a static list for the time being.
+ */
+static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters =
+		LIST_HEAD_INITIALIZER(ionic_pci_adapters);
+static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER;
+
+static int
+eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+		struct rte_pci_device *pci_dev)
+{
+	struct rte_mem_resource *resource;
+	struct ionic_adapter *adapter;
+	struct ionic_hw *hw;
+	unsigned long i;
+	int err;
+
+	/* Check structs (trigger error at compilation time) */
+	ionic_struct_size_checks();
+
+	/* Multi-process not supported */
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		err = -EPERM;
+		goto err;
+	}
+
+	IONIC_PRINT(DEBUG, "Initializing device %s",
+		pci_dev->device.name);
+
+	adapter = rte_zmalloc("ionic", sizeof(*adapter), 0);
+
+	if (!adapter) {
+		IONIC_PRINT(ERR, "OOM");
+		err = -ENOMEM;
+		goto err;
+	}
+
+	adapter->pci_dev = pci_dev;
+	hw = &adapter->hw;
+
+	hw->device_id = pci_dev->id.device_id;
+	hw->vendor_id = pci_dev->id.vendor_id;
+
+	err = ionic_init_mac(hw);
+	if (err != 0) {
+		IONIC_PRINT(ERR, "Mac init failed: %d", err);
+		err = -EIO;
+		goto err_free_adapter;
+	}
+
+	adapter->is_mgmt_nic = (pci_dev->id.device_id == IONIC_DEV_ID_ETH_MGMT);
+
+	adapter->num_bars = 0;
+	for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
+		resource = &pci_dev->mem_resource[i];
+		if (resource->phys_addr == 0 || resource->len == 0)
+			continue;
+		adapter->bars[adapter->num_bars].vaddr = resource->addr;
+		adapter->bars[adapter->num_bars].bus_addr = resource->phys_addr;
+		adapter->bars[adapter->num_bars].len = resource->len;
+		adapter->num_bars++;
+	}
+
+	/* Discover ionic dev resources */
+
+	err = ionic_setup(adapter);
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot setup device: %d, aborting", err);
+		goto err_free_adapter;
+	}
+
+	err = ionic_identify(adapter);
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot identify device: %d, aborting",
+			err);
+		goto err_free_adapter;
+	}
+
+	err = ionic_init(adapter);
+	if (err) {
+		IONIC_PRINT(ERR, "Cannot init device: %d, aborting", err);
+		goto err_free_adapter;
+	}
+
+	rte_spinlock_lock(&ionic_pci_adapters_lock);
+	LIST_INSERT_HEAD(&ionic_pci_adapters, adapter, pci_adapters);
+	rte_spinlock_unlock(&ionic_pci_adapters_lock);
+
+	return 0;
+
+err_free_adapter:
+	rte_free(adapter);
+err:
+	return err;
+}
+
+static int
+eth_ionic_pci_remove(struct rte_pci_device *pci_dev)
+{
+	struct ionic_adapter *adapter = NULL;
+
+	rte_spinlock_lock(&ionic_pci_adapters_lock);
+	LIST_FOREACH(adapter, &ionic_pci_adapters, pci_adapters) {
+		if (adapter->pci_dev == pci_dev)
+			break;
+
+		adapter = NULL;
+	}
+	if (adapter)
+		LIST_REMOVE(adapter, pci_adapters);
+	rte_spinlock_unlock(&ionic_pci_adapters_lock);
+
+	if (adapter)
+		rte_free(adapter);
+
+	return 0;
+}
+
+static struct rte_pci_driver rte_ionic_pmd = {
+	.id_table = pci_id_ionic_map,
+	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+	.probe = eth_ionic_pci_probe,
+	.remove = eth_ionic_pci_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_ionic, rte_ionic_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_ionic, pci_id_ionic_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_ionic, "* igb_uio | uio_pci_generic | vfio-pci");
+
 RTE_INIT(ionic_init_log)
 {
 	ionic_logtype_driver = rte_log_register("pmd.net.ionic.driver");
diff --git a/drivers/net/ionic/ionic_mac_api.c b/drivers/net/ionic/ionic_mac_api.c
new file mode 100644
index 000000000..0a40c5547
--- /dev/null
+++ b/drivers/net/ionic/ionic_mac_api.c
@@ -0,0 +1,61 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#include "ionic_mac_api.h"
+
+int32_t
+ionic_init_mac(struct ionic_hw *hw)
+{
+	int err = 0;
+
+	IONIC_PRINT_CALL();
+
+	/*
+	 * Set the mac type
+	 */
+	ionic_set_mac_type(hw);
+
+	switch (hw->mac.type) {
+	case IONIC_MAC_CAPRI:
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+int32_t
+ionic_set_mac_type(struct ionic_hw *hw)
+{
+	int err = 0;
+
+	IONIC_PRINT_CALL();
+
+	if (hw->vendor_id != IONIC_PENSANDO_VENDOR_ID) {
+		IONIC_PRINT(ERR, "Unsupported vendor id: %x",
+			hw->vendor_id);
+		return -EINVAL;
+	}
+
+	switch (hw->device_id) {
+	case IONIC_DEV_ID_ETH_PF:
+	case IONIC_DEV_ID_ETH_VF:
+	case IONIC_DEV_ID_ETH_MGMT:
+		hw->mac.type = IONIC_MAC_CAPRI;
+		break;
+	default:
+		err = -EINVAL;
+		IONIC_PRINT(ERR, "Unsupported device id: %x",
+			hw->device_id);
+		break;
+	}
+
+	IONIC_PRINT(INFO, "Mac: %d (%d)",
+		hw->mac.type, err);
+
+	return err;
+}
+
diff --git a/drivers/net/ionic/ionic_mac_api.h b/drivers/net/ionic/ionic_mac_api.h
new file mode 100644
index 000000000..ed9e059a6
--- /dev/null
+++ b/drivers/net/ionic/ionic_mac_api.h
@@ -0,0 +1,13 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#ifndef _IONIC_API_H_
+#define _IONIC_API_H_
+
+#include "ionic.h"
+
+int32_t ionic_init_mac(struct ionic_hw *hw);
+int32_t ionic_set_mac_type(struct ionic_hw *hw);
+
+#endif /* _IONIC_API_H_ */
diff --git a/drivers/net/ionic/ionic_main.c b/drivers/net/ionic/ionic_main.c
new file mode 100644
index 000000000..572316c84
--- /dev/null
+++ b/drivers/net/ionic/ionic_main.c
@@ -0,0 +1,133 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#include "ionic.h"
+
+static int
+ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)
+{
+	unsigned long step_msec = 100;
+	unsigned int max_wait_msec = max_wait * 1000;
+	unsigned long elapsed_msec = 0;
+	int done;
+
+	/* Wait for dev cmd to complete.. but no more than max_wait sec */
+
+	do {
+		done = ionic_dev_cmd_done(idev);
+
+		if (done) {
+			IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs",
+				idev->dev_cmd->cmd.cmd.opcode,
+				elapsed_msec);
+			return 0;
+		}
+
+		msec_delay(step_msec);
+
+		elapsed_msec += step_msec;
+	} while (elapsed_msec < max_wait_msec);
+
+	IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs",
+		idev->dev_cmd->cmd.cmd.opcode,
+		elapsed_msec);
+
+	return -ETIMEDOUT;
+}
+
+static int
+ionic_dev_cmd_check_error(struct ionic_dev *idev)
+{
+	uint8_t status;
+
+	status = ionic_dev_cmd_status(idev);
+
+	if (status == 0)
+		return 0;
+
+	return -EIO;
+}
+
+int
+ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait)
+{
+	int err;
+
+	err = ionic_dev_cmd_wait(idev, max_wait);
+
+	if (err)
+		return err;
+
+	return ionic_dev_cmd_check_error(idev);
+}
+
+int
+ionic_setup(struct ionic_adapter *adapter)
+{
+	return ionic_dev_setup(adapter);
+}
+
+int
+ionic_identify(struct ionic_adapter *adapter)
+{
+	struct ionic_dev *idev = &adapter->idev;
+	struct ionic_identity *ident = &adapter->ident;
+	int err = 0;
+	uint32_t i;
+	unsigned int nwords;
+	uint32_t drv_size = sizeof(ident->drv.words) /
+		sizeof(ident->drv.words[0]);
+	uint32_t cmd_size = sizeof(idev->dev_cmd->data) /
+		sizeof(idev->dev_cmd->data[0]);
+	uint32_t dev_size = sizeof(ident->dev.words) /
+		sizeof(ident->dev.words[0]);
+
+	memset(ident, 0, sizeof(*ident));
+
+	ident->drv.os_type = IONIC_OS_TYPE_LINUX;
+	ident->drv.os_dist = 0;
+	snprintf(ident->drv.os_dist_str,
+		sizeof(ident->drv.os_dist_str), "Unknown");
+	ident->drv.kernel_ver = 0;
+	snprintf(ident->drv.kernel_ver_str,
+		sizeof(ident->drv.kernel_ver_str), "DPDK");
+	strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION,
+		sizeof(ident->drv.driver_ver_str) - 1);
+
+	nwords = RTE_MIN(drv_size, cmd_size);
+	for (i = 0; i < nwords; i++)
+		iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]);
+
+	ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1);
+	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
+	if (!err) {
+		nwords = RTE_MIN(dev_size, cmd_size);
+		for (i = 0; i < nwords; i++)
+			ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]);
+	}
+
+	return err;
+}
+
+int
+ionic_init(struct ionic_adapter *adapter)
+{
+	struct ionic_dev *idev = &adapter->idev;
+	int err;
+
+	ionic_dev_cmd_init(idev);
+	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
+	return err;
+}
+
+int
+ionic_reset(struct ionic_adapter *adapter)
+{
+	struct ionic_dev *idev = &adapter->idev;
+	int err;
+
+	ionic_dev_cmd_reset(idev);
+	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
+	return err;
+}
diff --git a/drivers/net/ionic/ionic_osdep.h b/drivers/net/ionic/ionic_osdep.h
new file mode 100644
index 000000000..09a0e85b5
--- /dev/null
+++ b/drivers/net/ionic/ionic_osdep.h
@@ -0,0 +1,79 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#ifndef _IONIC_OSDEP_
+#define _IONIC_OSDEP_
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_log.h>
+#include <rte_byteorder.h>
+#include <rte_io.h>
+#include <rte_memory.h>
+
+#include "ionic_logs.h"
+
+#define DELAY(x) rte_delay_us(x)
+#define usec_delay(x) DELAY(x)
+#define msec_delay(x) DELAY(1000 * (x))
+
+#define BIT(nr)            (1UL << (nr))
+#define BIT_ULL(nr)        (1ULL << (nr))
+#define BITS_TO_LONGS(nr)  div_round_up(nr, 8 * sizeof(long))
+
+#ifndef PAGE_SHIFT
+#define PAGE_SHIFT      12
+#define PAGE_SIZE       (1 << PAGE_SHIFT)
+#endif
+
+#define __iomem
+
+typedef uint8_t	 u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef uint16_t __le16;
+typedef uint32_t __le32;
+typedef uint64_t __le64;
+
+#ifndef __cplusplus
+typedef uint8_t bool;
+#define false   0
+#define true    1
+#endif
+
+static inline uint32_t div_round_up(uint32_t n, uint32_t d)
+{
+	return (n + d - 1) / d;
+}
+
+static inline uint16_t ilog2(uint32_t n)
+{
+	uint16_t logv = -1;
+
+	if (n == 0)
+		return 0;
+
+	while (n) {
+		logv++;
+		n >>= 1;
+	}
+
+	return logv;
+}
+
+#define ioread8(reg)		rte_read8(reg)
+#define ioread32(reg)		rte_read32(reg)
+#define iowrite8(value, reg)	rte_write8(value, reg)
+#define iowrite32(value, reg)	rte_write32(value, reg)
+#define writeq(value, reg)	rte_write64(value, reg)
+
+#endif
diff --git a/drivers/net/ionic/ionic_regs.h b/drivers/net/ionic/ionic_regs.h
new file mode 100644
index 000000000..3adc2bc7c
--- /dev/null
+++ b/drivers/net/ionic/ionic_regs.h
@@ -0,0 +1,142 @@ 
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
+ */
+
+#ifndef _IONIC_REGS_H_
+#define _IONIC_REGS_H_
+
+/** struct ionic_intr - interrupt control register set.
+ * @coal_init:			coalesce timer initial value.
+ * @mask:			interrupt mask value.
+ * @credits:			interrupt credit count and return.
+ * @mask_assert:		interrupt mask value on assert.
+ * @coal:			coalesce timer time remaining.
+ */
+struct ionic_intr {
+	uint32_t coal_init;
+	uint32_t mask;
+	uint32_t credits;
+	uint32_t mask_assert;
+	uint32_t coal;
+	uint32_t rsvd[3];
+};
+
+#define IONIC_INTR_CTRL_REGS_MAX	2048
+#define IONIC_INTR_CTRL_COAL_MAX	0x3F
+
+/** enum ionic_intr_mask_vals - valid values for mask and mask_assert.
+ * @IONIC_INTR_MASK_CLEAR:	unmask interrupt.
+ * @IONIC_INTR_MASK_SET:	mask interrupt.
+ */
+enum ionic_intr_mask_vals {
+	IONIC_INTR_MASK_CLEAR		= 0,
+	IONIC_INTR_MASK_SET		= 1,
+};
+
+/** enum ionic_intr_credits_bits - bitwise composition of credits values.
+ * @IONIC_INTR_CRED_COUNT:	bit mask of credit count, no shift needed.
+ * @IONIC_INTR_CRED_COUNT_SIGNED: bit mask of credit count, including sign bit.
+ * @IONIC_INTR_CRED_UNMASK:	unmask the interrupt.
+ * @IONIC_INTR_CRED_RESET_COALESCE: reset the coalesce timer.
+ * @IONIC_INTR_CRED_REARM:	unmask the and reset the timer.
+ */
+enum ionic_intr_credits_bits {
+	IONIC_INTR_CRED_COUNT		= 0x7fffu,
+	IONIC_INTR_CRED_COUNT_SIGNED	= 0xffffu,
+	IONIC_INTR_CRED_UNMASK		= 0x10000u,
+	IONIC_INTR_CRED_RESET_COALESCE	= 0x20000u,
+	IONIC_INTR_CRED_REARM		= (IONIC_INTR_CRED_UNMASK |
+					   IONIC_INTR_CRED_RESET_COALESCE),
+};
+
+static inline void
+ionic_intr_coal_init(struct ionic_intr __iomem *intr_ctrl,
+		int intr_idx, uint32_t coal)
+{
+	iowrite32(coal, &intr_ctrl[intr_idx].coal_init);
+}
+
+static inline void
+ionic_intr_mask(struct ionic_intr __iomem *intr_ctrl,
+		int intr_idx, uint32_t mask)
+{
+	iowrite32(mask, &intr_ctrl[intr_idx].mask);
+}
+
+static inline void
+ionic_intr_credits(struct ionic_intr __iomem *intr_ctrl,
+		int intr_idx, uint32_t cred, uint32_t flags)
+{
+	if (cred > IONIC_INTR_CRED_COUNT) {
+		IONIC_WARN_ON(cred > IONIC_INTR_CRED_COUNT);
+		cred = ioread32(&intr_ctrl[intr_idx].credits);
+		cred &= IONIC_INTR_CRED_COUNT_SIGNED;
+	}
+
+	iowrite32(cred | flags, &intr_ctrl[intr_idx].credits);
+}
+
+static inline void
+ionic_intr_clean(struct ionic_intr __iomem *intr_ctrl,
+		int intr_idx)
+{
+	uint32_t cred;
+
+	cred = ioread32(&intr_ctrl[intr_idx].credits);
+	cred &= IONIC_INTR_CRED_COUNT_SIGNED;
+	cred |= IONIC_INTR_CRED_RESET_COALESCE;
+	iowrite32(cred, &intr_ctrl[intr_idx].credits);
+}
+
+static inline void
+ionic_intr_mask_assert(struct ionic_intr __iomem *intr_ctrl,
+		int intr_idx, uint32_t mask)
+{
+	iowrite32(mask, &intr_ctrl[intr_idx].mask_assert);
+}
+
+/** enum ionic_dbell_bits - bitwise composition of dbell values.
+ *
+ * @IONIC_DBELL_QID_MASK:	unshifted mask of valid queue id bits.
+ * @IONIC_DBELL_QID_SHIFT:	queue id shift amount in dbell value.
+ * @IONIC_DBELL_QID:		macro to build QID component of dbell value.
+ *
+ * @IONIC_DBELL_RING_MASK:	unshifted mask of valid ring bits.
+ * @IONIC_DBELL_RING_SHIFT:	ring shift amount in dbell value.
+ * @IONIC_DBELL_RING:		macro to build ring component of dbell value.
+ *
+ * @IONIC_DBELL_RING_0:		ring zero dbell component value.
+ * @IONIC_DBELL_RING_1:		ring one dbell component value.
+ * @IONIC_DBELL_RING_2:		ring two dbell component value.
+ * @IONIC_DBELL_RING_3:		ring three dbell component value.
+ *
+ * @IONIC_DBELL_INDEX_MASK:	bit mask of valid index bits, no shift needed.
+ */
+enum ionic_dbell_bits {
+	IONIC_DBELL_QID_MASK		= 0xffffff,
+	IONIC_DBELL_QID_SHIFT		= 24,
+
+#define IONIC_DBELL_QID(n) \
+	(((u64)(n) & IONIC_DBELL_QID_MASK) << IONIC_DBELL_QID_SHIFT)
+
+	IONIC_DBELL_RING_MASK		= 0x7,
+	IONIC_DBELL_RING_SHIFT		= 16,
+
+#define IONIC_DBELL_RING(n) \
+	(((u64)(n) & IONIC_DBELL_RING_MASK) << IONIC_DBELL_RING_SHIFT)
+
+	IONIC_DBELL_RING_0		= 0,
+	IONIC_DBELL_RING_1		= IONIC_DBELL_RING(1),
+	IONIC_DBELL_RING_2		= IONIC_DBELL_RING(2),
+	IONIC_DBELL_RING_3		= IONIC_DBELL_RING(3),
+
+	IONIC_DBELL_INDEX_MASK		= 0xffff,
+};
+
+static inline void
+ionic_dbell_ring(u64 __iomem *db_page, int qtype, u64 val)
+{
+	writeq(val, &db_page[qtype]);
+}
+
+#endif /* _IONIC_REGS_H_ */
diff --git a/drivers/net/ionic/meson.build b/drivers/net/ionic/meson.build
index f5e3c36c9..8de34ca5a 100644
--- a/drivers/net/ionic/meson.build
+++ b/drivers/net/ionic/meson.build
@@ -2,6 +2,10 @@ 
 # Copyright(c) 2019 Pensando
 
 sources = files(
+	'ionic_mac_api.c',
+	'ionic_dev.c',
+	'ionic_ethdev.c',
+	'ionic_main.c',
 	'ionic_ethdev.c'
 )