upon device initialization, initialize mac and other
private data. Handle cleanup on uninit.
defines basic device/queue data structures.

Signed-off-by: Aman Kumar <aman.ku...@vvdntech.in>
---
 drivers/net/qdma/meson.build   |   1 +
 drivers/net/qdma/qdma.h        | 225 ++++++++++++++++++++++++
 drivers/net/qdma/qdma_common.c | 236 +++++++++++++++++++++++++
 drivers/net/qdma/qdma_ethdev.c | 310 ++++++++++++++++++++++++++++++++-
 4 files changed, 768 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/qdma/qdma.h
 create mode 100644 drivers/net/qdma/qdma_common.c

diff --git a/drivers/net/qdma/meson.build b/drivers/net/qdma/meson.build
index fe9d2d48d7..f0df5ef0d9 100644
--- a/drivers/net/qdma/meson.build
+++ b/drivers/net/qdma/meson.build
@@ -15,4 +15,5 @@ includes += include_directories('.')
 
 sources = files(
         'qdma_ethdev.c',
+        'qdma_common.c',
 )
diff --git a/drivers/net/qdma/qdma.h b/drivers/net/qdma/qdma.h
new file mode 100644
index 0000000000..4bc61d2a08
--- /dev/null
+++ b/drivers/net/qdma/qdma.h
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017-2022 Xilinx, Inc. All rights reserved.
+ */
+
+#ifndef __QDMA_H__
+#define __QDMA_H__
+
+#include <stdbool.h>
+#include <rte_dev.h>
+#include <rte_ethdev.h>
+#include <ethdev_driver.h>
+#include <rte_spinlock.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_byteorder.h>
+#include <rte_memzone.h>
+#include <linux/pci.h>
+#include "qdma_log.h"
+
+#define QDMA_NUM_BARS          (6)
+#define DEFAULT_PF_CONFIG_BAR  (0)
+#define BAR_ID_INVALID         (-1)
+
+#define QDMA_FUNC_ID_INVALID    0xFFFF
+
+#define DEFAULT_TIMER_CNT_TRIG_MODE_TIMER      (5)
+
+enum dma_data_direction {
+       DMA_BIDIRECTIONAL = 0,
+       DMA_TO_DEVICE = 1,
+       DMA_FROM_DEVICE = 2,
+       DMA_NONE = 3,
+};
+
+enum reset_state_t {
+       RESET_STATE_IDLE,
+       RESET_STATE_RECV_PF_RESET_REQ,
+       RESET_STATE_RECV_PF_RESET_DONE,
+       RESET_STATE_INVALID
+};
+
+/* MM Write-back status structure */
+struct __rte_packed wb_status
+{
+       volatile uint16_t       pidx; /* in C2H WB */
+       volatile uint16_t       cidx; /* Consumer-index */
+       uint32_t        rsvd2; /* Reserved. */
+};
+
+struct qdma_pkt_stats {
+       uint64_t pkts;
+       uint64_t bytes;
+};
+
+/*
+ * Structure associated with each CMPT queue.
+ */
+struct qdma_cmpt_queue {
+       struct qdma_ul_cmpt_ring *cmpt_ring;
+       struct wb_status    *wb_status;
+       struct rte_eth_dev      *dev;
+
+       uint16_t        cmpt_desc_len;
+       uint16_t        nb_cmpt_desc;
+       uint32_t        queue_id; /* CMPT queue index. */
+
+       uint8_t         status:1;
+       uint8_t         st_mode:1; /* dma-mode: MM or ST */
+       uint8_t         dis_overflow_check:1;
+       uint8_t         func_id;
+       uint16_t        port_id; /* Device port identifier. */
+       int8_t          ringszidx;
+       int8_t          threshidx;
+       int8_t          timeridx;
+       int8_t          triggermode;
+       /* completion descriptor memzone */
+       const struct rte_memzone *cmpt_mz;
+};
+
+/**
+ * Structure associated with each RX queue.
+ */
+struct qdma_rx_queue {
+       struct rte_mempool      *mb_pool; /* mbuf pool to populate RX ring. */
+       void                    *rx_ring; /* RX ring virtual address */
+       union qdma_ul_st_cmpt_ring      *cmpt_ring;
+       struct wb_status        *wb_status;
+       struct rte_mbuf         **sw_ring; /* address of RX software ring. */
+       struct rte_eth_dev      *dev;
+
+       uint16_t                rx_tail;
+       uint16_t                cmpt_desc_len;
+       uint16_t                rx_buff_size;
+       uint16_t                nb_rx_desc; /* number of RX descriptors. */
+       uint16_t                nb_rx_cmpt_desc;
+       uint32_t                queue_id; /* RX queue index. */
+       uint64_t                mbuf_initializer; /* value to init mbufs */
+
+       struct qdma_pkt_stats   stats;
+
+       uint16_t                port_id; /* Device port identifier. */
+       uint8_t                 status:1;
+       uint8_t                 err:1;
+       uint8_t                 st_mode:1; /* dma-mode: MM or ST */
+       uint8_t                 dump_immediate_data:1;
+       uint8_t                 rx_deferred_start:1;
+       uint8_t                 en_prefetch:1;
+       uint8_t                 en_bypass:1;
+       uint8_t                 en_bypass_prefetch:1;
+       uint8_t                 dis_overflow_check:1;
+
+       uint8_t                 func_id; /* RX queue index. */
+       uint32_t                ep_addr;
+
+       int8_t                  ringszidx;
+       int8_t                  cmpt_ringszidx;
+       int8_t                  buffszidx;
+       int8_t                  threshidx;
+       int8_t                  timeridx;
+       int8_t                  triggermode;
+
+       const struct rte_memzone *rx_mz;
+       /* C2H stream mode, completion descriptor result */
+       const struct rte_memzone *rx_cmpt_mz;
+};
+
+/**
+ * Structure associated with each TX queue.
+ */
+struct qdma_tx_queue {
+       void                            *tx_ring; /* TX ring virtual address */
+       struct wb_status                *wb_status;
+       struct rte_mbuf                 **sw_ring;/* SW ring virtual address */
+       struct rte_eth_dev              *dev;
+       uint16_t                        tx_fl_tail;
+       uint16_t                        tx_desc_pend;
+       uint16_t                        nb_tx_desc; /* No of TX descriptors. */
+       rte_spinlock_t                  pidx_update_lock;
+       uint64_t                        offloads; /* Tx offloads */
+
+       uint8_t                         st_mode:1;/* dma-mode: MM or ST */
+       uint8_t                         tx_deferred_start:1;
+       uint8_t                         en_bypass:1;
+       uint8_t                         status:1;
+       uint16_t                        port_id; /* Device port identifier. */
+       uint8_t                         func_id; /* RX queue index. */
+       int8_t                          ringszidx;
+
+       struct qdma_pkt_stats           stats;
+
+       uint64_t                        ep_addr;
+       uint32_t                        queue_id; /* TX queue index. */
+       uint32_t                        num_queues; /* TX queue index. */
+       const struct rte_memzone        *tx_mz;
+};
+
+struct qdma_vf_info {
+       uint16_t        func_id;
+};
+
+struct queue_info {
+       uint32_t        queue_mode:1;
+       uint32_t        rx_bypass_mode:2;
+       uint32_t        tx_bypass_mode:1;
+       uint32_t        cmpt_desc_sz:7;
+       uint8_t         immediate_data_state:1;
+       uint8_t         dis_cmpt_ovf_chk:1;
+       uint8_t         en_prefetch:1;
+       uint8_t         timer_count;
+       int8_t          trigger_mode;
+};
+
+struct qdma_pci_dev {
+       int config_bar_idx;
+       int user_bar_idx;
+       int bypass_bar_idx;
+       void *bar_addr[QDMA_NUM_BARS]; /* memory mapped I/O addr for BARs */
+
+       /* Driver Attributes */
+       uint32_t qsets_en;  /* no. of queue pairs enabled */
+       uint32_t queue_base;
+       uint8_t func_id;  /* Function id */
+
+       /* DMA identifier used by the resource manager
+        * for the DMA instances used by this driver
+        */
+       uint32_t dma_device_index;
+
+       uint8_t cmpt_desc_len;
+       uint8_t c2h_bypass_mode;
+       uint8_t h2c_bypass_mode;
+       uint8_t trigger_mode;
+       uint8_t timer_count;
+
+       uint8_t dev_configured:1;
+       uint8_t is_vf:1;
+       uint8_t is_master:1;
+       uint8_t en_desc_prefetch:1;
+
+       /* Reset state */
+       uint8_t reset_in_progress;
+       enum reset_state_t reset_state;
+
+       /* Hardware version info */
+       uint32_t vivado_rel:4;
+       uint32_t rtl_version:4;
+       uint32_t device_type:4;
+       uint32_t ip_type:4;
+
+       struct queue_info *q_info;
+       uint8_t init_q_range;
+
+       struct qdma_vf_info *vfinfo;
+       uint8_t vf_online_count;
+
+       int16_t tx_qid_statid_map[RTE_ETHDEV_QUEUE_STAT_CNTRS];
+       int16_t rx_qid_statid_map[RTE_ETHDEV_QUEUE_STAT_CNTRS];
+};
+
+int qdma_identify_bars(struct rte_eth_dev *dev);
+
+int qdma_check_kvargs(struct rte_devargs *devargs,
+                       struct qdma_pci_dev *qdma_dev);
+
+#endif /* ifndef __QDMA_H__ */
diff --git a/drivers/net/qdma/qdma_common.c b/drivers/net/qdma/qdma_common.c
new file mode 100644
index 0000000000..c0c5162f0f
--- /dev/null
+++ b/drivers/net/qdma/qdma_common.c
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017-2022 Xilinx, Inc. All rights reserved.
+ * Copyright(c) 2022 VVDN Technologies Private Limited. All rights reserved.
+ */
+
+#include <stdint.h>
+#include <rte_malloc.h>
+#include <rte_common.h>
+#include <ethdev_pci.h>
+#include <rte_cycles.h>
+#include <rte_kvargs.h>
+#include "qdma.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+static int pfetch_check_handler(__rte_unused const char *key,
+                                       const char *value,  void *opaque)
+{
+       struct qdma_pci_dev *qdma_dev = (struct qdma_pci_dev *)opaque;
+       char *end = NULL;
+       uint8_t desc_prefetch;
+
+       PMD_DRV_LOG(INFO, "QDMA devargs desc_prefetch is: %s\n", value);
+       desc_prefetch = (uint8_t)strtoul(value, &end, 10);
+       if (desc_prefetch > 1) {
+               PMD_DRV_LOG(INFO, "QDMA devargs prefetch should be 1 or 0,"
+                                                 " setting to 1.\n");
+       }
+       qdma_dev->en_desc_prefetch = desc_prefetch ? 1 : 0;
+       return 0;
+}
+
+static int cmpt_desc_len_check_handler(__rte_unused const char *key,
+                                       const char *value,  void *opaque)
+{
+       struct qdma_pci_dev *qdma_dev = (struct qdma_pci_dev *)opaque;
+       char *end = NULL;
+
+       PMD_DRV_LOG(INFO, "QDMA devargs cmpt_desc_len is: %s\n", value);
+       qdma_dev->cmpt_desc_len =  (uint8_t)strtoul(value, &end, 10);
+       if (qdma_dev->cmpt_desc_len != 8 &&
+               qdma_dev->cmpt_desc_len != 16 &&
+               qdma_dev->cmpt_desc_len != 32 &&
+               qdma_dev->cmpt_desc_len != 64) {
+               PMD_DRV_LOG(INFO, "QDMA devargs incorrect cmpt_desc_len = %d "
+                                                 "specified\n",
+                                                 qdma_dev->cmpt_desc_len);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int trigger_mode_handler(__rte_unused const char *key,
+                                       const char *value,  void *opaque)
+{
+       struct qdma_pci_dev *qdma_dev = (struct qdma_pci_dev *)opaque;
+       char *end = NULL;
+
+       PMD_DRV_LOG(INFO, "QDMA devargs trigger mode: %s\n", value);
+       qdma_dev->trigger_mode =  (uint8_t)strtoul(value, &end, 10);
+
+       return 0;
+}
+
+static int config_bar_idx_handler(__rte_unused const char *key,
+                                       const char *value,  void *opaque)
+{
+       struct qdma_pci_dev *qdma_dev = (struct qdma_pci_dev *)opaque;
+       char *end = NULL;
+
+       PMD_DRV_LOG(INFO, "QDMA devargs trigger mode: %s\n", value);
+       qdma_dev->config_bar_idx =  (int)strtoul(value, &end, 10);
+
+       if (qdma_dev->config_bar_idx >= QDMA_NUM_BARS ||
+                       qdma_dev->config_bar_idx < 0) {
+               PMD_DRV_LOG(INFO, "QDMA devargs config bar idx invalid: %d\n",
+                               qdma_dev->config_bar_idx);
+               return -1;
+       }
+       return 0;
+}
+
+static int c2h_byp_mode_check_handler(__rte_unused const char *key,
+                                       const char *value,  void *opaque)
+{
+       struct qdma_pci_dev *qdma_dev = (struct qdma_pci_dev *)opaque;
+       char *end = NULL;
+
+       PMD_DRV_LOG(INFO, "QDMA devargs c2h_byp_mode is: %s\n", value);
+       qdma_dev->c2h_bypass_mode =  (uint8_t)strtoul(value, &end, 10);
+
+       return 0;
+}
+
+static int h2c_byp_mode_check_handler(__rte_unused const char *key,
+                                       const char *value,  void *opaque)
+{
+       struct qdma_pci_dev *qdma_dev = (struct qdma_pci_dev *)opaque;
+       char *end = NULL;
+
+       PMD_DRV_LOG(INFO, "QDMA devargs h2c_byp_mode is: %s\n", value);
+       qdma_dev->h2c_bypass_mode =  (uint8_t)strtoul(value, &end, 10);
+
+       if (qdma_dev->h2c_bypass_mode > 1) {
+               PMD_DRV_LOG(INFO, "QDMA devargs incorrect"
+                               " h2c_byp_mode =%d specified\n",
+                                       qdma_dev->h2c_bypass_mode);
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Process the all devargs */
+int qdma_check_kvargs(struct rte_devargs *devargs,
+                                               struct qdma_pci_dev *qdma_dev)
+{
+       struct rte_kvargs *kvlist;
+       const char *pfetch_key = "desc_prefetch";
+       const char *cmpt_desc_len_key = "cmpt_desc_len";
+       const char *trigger_mode_key = "trigger_mode";
+       const char *config_bar_key = "config_bar";
+       const char *c2h_byp_mode_key = "c2h_byp_mode";
+       const char *h2c_byp_mode_key = "h2c_byp_mode";
+       int ret = 0;
+
+       if (!devargs)
+               return 0;
+
+       kvlist = rte_kvargs_parse(devargs->args, NULL);
+       if (!kvlist)
+               return 0;
+
+       /* process the desc_prefetch */
+       if (rte_kvargs_count(kvlist, pfetch_key)) {
+               ret = rte_kvargs_process(kvlist, pfetch_key,
+                                               pfetch_check_handler, qdma_dev);
+               if (ret) {
+                       rte_kvargs_free(kvlist);
+                       return ret;
+               }
+       }
+
+       /* process the cmpt_desc_len */
+       if (rte_kvargs_count(kvlist, cmpt_desc_len_key)) {
+               ret = rte_kvargs_process(kvlist, cmpt_desc_len_key,
+                                        cmpt_desc_len_check_handler, qdma_dev);
+               if (ret) {
+                       rte_kvargs_free(kvlist);
+                       return ret;
+               }
+       }
+
+       /* process the trigger_mode */
+       if (rte_kvargs_count(kvlist, trigger_mode_key)) {
+               ret = rte_kvargs_process(kvlist, trigger_mode_key,
+                                               trigger_mode_handler, qdma_dev);
+               if (ret) {
+                       rte_kvargs_free(kvlist);
+                       return ret;
+               }
+       }
+
+       /* process the config bar */
+       if (rte_kvargs_count(kvlist, config_bar_key)) {
+               ret = rte_kvargs_process(kvlist, config_bar_key,
+                                          config_bar_idx_handler, qdma_dev);
+               if (ret) {
+                       rte_kvargs_free(kvlist);
+                       return ret;
+               }
+       }
+
+       /* process c2h_byp_mode */
+       if (rte_kvargs_count(kvlist, c2h_byp_mode_key)) {
+               ret = rte_kvargs_process(kvlist, c2h_byp_mode_key,
+                                         c2h_byp_mode_check_handler, qdma_dev);
+               if (ret) {
+                       rte_kvargs_free(kvlist);
+                       return ret;
+               }
+       }
+
+       /* process h2c_byp_mode */
+       if (rte_kvargs_count(kvlist, h2c_byp_mode_key)) {
+               ret = rte_kvargs_process(kvlist, h2c_byp_mode_key,
+                                         h2c_byp_mode_check_handler, qdma_dev);
+               if (ret) {
+                       rte_kvargs_free(kvlist);
+                       return ret;
+               }
+       }
+
+       rte_kvargs_free(kvlist);
+       return ret;
+}
+
+int qdma_identify_bars(struct rte_eth_dev *dev)
+{
+       int bar_len, i;
+       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+       struct qdma_pci_dev *dma_priv;
+
+       dma_priv = (struct qdma_pci_dev *)dev->data->dev_private;
+
+       /* Config bar */
+       bar_len = pci_dev->mem_resource[dma_priv->config_bar_idx].len;
+       if (!bar_len) {
+               PMD_DRV_LOG(INFO, "QDMA config BAR index :%d is not enabled",
+                                       dma_priv->config_bar_idx);
+               return -1;
+       }
+
+       /* Find AXI Bridge Master bar(bypass bar) */
+       for (i = 0; i < QDMA_NUM_BARS; i++) {
+               bar_len = pci_dev->mem_resource[i].len;
+               if (!bar_len) /* Bar not enabled ? */
+                       continue;
+               if (dma_priv->user_bar_idx != i &&
+                               dma_priv->config_bar_idx != i) {
+                       dma_priv->bypass_bar_idx = i;
+                       break;
+               }
+       }
+
+       PMD_DRV_LOG(INFO, "QDMA config bar idx :%d\n",
+                       dma_priv->config_bar_idx);
+       PMD_DRV_LOG(INFO, "QDMA AXI Master Lite bar idx :%d\n",
+                       dma_priv->user_bar_idx);
+       PMD_DRV_LOG(INFO, "QDMA AXI Bridge Master bar idx :%d\n",
+                       dma_priv->bypass_bar_idx);
+
+       return 0;
+}
diff --git a/drivers/net/qdma/qdma_ethdev.c b/drivers/net/qdma/qdma_ethdev.c
index 8dbc7c4ac1..c2ed6a52bb 100644
--- a/drivers/net/qdma/qdma_ethdev.c
+++ b/drivers/net/qdma/qdma_ethdev.c
@@ -3,11 +3,29 @@
  * Copyright(c) 2022 VVDN Technologies Private Limited. All rights reserved.
  */
 
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <rte_memzone.h>
+#include <rte_string_fns.h>
+#include <rte_malloc.h>
 #include <ethdev_pci.h>
 #include <rte_dev.h>
 #include <rte_pci.h>
 #include <rte_ether.h>
 #include <rte_ethdev.h>
+#include <rte_alarm.h>
+#include <rte_cycles.h>
+
+#include "qdma.h"
+
+#define PCI_CONFIG_BRIDGE_DEVICE       (6)
+#define PCI_CONFIG_CLASS_CODE_SHIFT    (16)
+#define MAX_PCIE_CAPABILITY            (48)
 
 /*
  * The set of PCI devices this driver supports
@@ -25,6 +43,181 @@ static struct rte_pci_id qdma_pci_id_tbl[] = {
        { .vendor_id = 0, /* sentinel */ },
 };
 
+/* parse a sysfs file containing one integer value */
+static int parse_sysfs_value(const char *filename, uint32_t *val)
+{
+       FILE *f;
+       char buf[BUFSIZ];
+       char *end = NULL;
+
+       f = fopen(filename, "r");
+       if (f == NULL) {
+               PMD_DRV_LOG(ERR, "%s(): Failed to open sysfs file %s\n",
+                               __func__, filename);
+               return -1;
+       }
+
+       if (fgets(buf, sizeof(buf), f) == NULL) {
+               PMD_DRV_LOG(ERR, "%s(): Failed to read sysfs value %s\n",
+                       __func__, filename);
+               fclose(f);
+               return -1;
+       }
+       *val = (uint32_t)strtoul(buf, &end, 0);
+       if ((buf[0] == '\0') || end == NULL || (*end != '\n')) {
+               PMD_DRV_LOG(ERR, "%s(): Failed to parse sysfs value %s\n",
+                               __func__, filename);
+               fclose(f);
+               return -1;
+       }
+       fclose(f);
+       return 0;
+}
+
+/* Split up a pci address into its constituent parts. */
+static int parse_pci_addr_format(const char *buf,
+               int bufsize, struct rte_pci_addr *addr)
+{
+       /* first split on ':' */
+       union splitaddr {
+               struct {
+                       char *domain;
+                       char *bus;
+                       char *devid;
+                       char *function;
+               };
+               /* last element-separator is "." not ":" */
+               char *str[PCI_FMT_NVAL];
+       } splitaddr;
+
+       char *buf_copy = strndup(buf, bufsize);
+       if (buf_copy == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to get pci address duplicate copy\n");
+               return -1;
+       }
+
+       if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
+                       != PCI_FMT_NVAL - 1) {
+               PMD_DRV_LOG(ERR, "Failed to split pci address string\n");
+               goto error;
+       }
+
+       /* final split is on '.' between devid and function */
+       splitaddr.function = strchr(splitaddr.devid, '.');
+       if (splitaddr.function == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to split pci devid and function\n");
+               goto error;
+       }
+       *splitaddr.function++ = '\0';
+
+       /* now convert to int values */
+       addr->domain = strtoul(splitaddr.domain, NULL, 16);
+       addr->bus = strtoul(splitaddr.bus, NULL, 16);
+       addr->devid = strtoul(splitaddr.devid, NULL, 16);
+       addr->function = strtoul(splitaddr.function, NULL, 10);
+
+       free(buf_copy); /* free the copy made with strdup */
+       return 0;
+
+error:
+       free(buf_copy);
+       return -1;
+}
+
+/* Get max pci bus number from the corresponding pci bridge device */
+static int get_max_pci_bus_num(uint8_t start_bus, uint8_t *end_bus)
+{
+       char dirname[PATH_MAX];
+       char filename[PATH_MAX];
+       char cfgname[PATH_MAX];
+       struct rte_pci_addr addr;
+       struct dirent *dp;
+       uint32_t pci_class_code;
+       uint8_t sec_bus_num, sub_bus_num;
+       DIR *dir;
+       int ret, fd;
+
+       /* Initialize end bus number to zero */
+       *end_bus = 0;
+
+       /* Open pci devices directory */
+       dir = opendir(rte_pci_get_sysfs_path());
+       if (dir == NULL) {
+               PMD_DRV_LOG(ERR, "%s(): opendir failed\n",
+                       __func__);
+               return -1;
+       }
+
+       while ((dp = readdir(dir)) != NULL) {
+               if (dp->d_name[0] == '.')
+                       continue;
+
+               /* Split pci address to get bus, devid and function numbers */
+               if (parse_pci_addr_format(dp->d_name,
+                               sizeof(dp->d_name), &addr) != 0)
+                       continue;
+
+               snprintf(dirname, sizeof(dirname), "%s/%s",
+                               rte_pci_get_sysfs_path(), dp->d_name);
+
+               /* get class code */
+               snprintf(filename, sizeof(filename), "%s/class", dirname);
+               if (parse_sysfs_value(filename, &pci_class_code) < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to get pci class code\n");
+                       goto error;
+               }
+
+               /* Get max pci number from pci bridge device */
+               if ((((pci_class_code >> PCI_CONFIG_CLASS_CODE_SHIFT) & 0xFF) ==
+                               PCI_CONFIG_BRIDGE_DEVICE)) {
+                       snprintf(cfgname, sizeof(cfgname),
+                                       "%s/config", dirname);
+                       fd = open(cfgname, O_RDWR);
+                       if (fd < 0) {
+                               PMD_DRV_LOG(ERR, "Failed to open %s\n",
+                                       cfgname);
+                               goto error;
+                       }
+
+                       /* get secondary bus number */
+                       ret = pread(fd, &sec_bus_num, sizeof(uint8_t),
+                                               PCI_SECONDARY_BUS);
+                       if (ret == -1) {
+                               PMD_DRV_LOG(ERR, "Failed to read secondary bus 
number\n");
+                               close(fd);
+                               goto error;
+                       }
+
+                       /* get subordinate bus number */
+                       ret = pread(fd, &sub_bus_num, sizeof(uint8_t),
+                                               PCI_SUBORDINATE_BUS);
+                       if (ret == -1) {
+                               PMD_DRV_LOG(ERR, "Failed to read subordinate 
bus number\n");
+                               close(fd);
+                               goto error;
+                       }
+
+                       /* Get max bus number by checking if given bus number
+                        * falls in between secondary and subordinate bus
+                        * numbers of this pci bridge device.
+                        */
+                       if (start_bus >= sec_bus_num &&
+                           start_bus <= sub_bus_num) {
+                               *end_bus = sub_bus_num;
+                               close(fd);
+                               closedir(dir);
+                               return 0;
+                       }
+
+                       close(fd);
+               }
+       }
+
+error:
+       closedir(dir);
+       return -1;
+}
+
 /**
  * DPDK callback to register a PCI device.
  *
@@ -39,7 +232,12 @@ static struct rte_pci_id qdma_pci_id_tbl[] = {
  */
 static int qdma_eth_dev_init(struct rte_eth_dev *dev)
 {
+       struct qdma_pci_dev *dma_priv;
+       uint8_t *baseaddr;
+       int i, idx, ret;
        struct rte_pci_device *pci_dev;
+       uint16_t num_vfs;
+       uint8_t max_pci_bus = 0;
 
        /* sanity checks */
        if (dev == NULL)
@@ -59,6 +257,88 @@ static int qdma_eth_dev_init(struct rte_eth_dev *dev)
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
+       /* allocate space for a single Ethernet MAC address */
+       dev->data->mac_addrs = rte_zmalloc("qdma", RTE_ETHER_ADDR_LEN * 1, 0);
+       if (dev->data->mac_addrs == NULL)
+               return -ENOMEM;
+
+       /* Copy some dummy Ethernet MAC address for QDMA device
+        * This will change in real NIC device...
+        * TODO: Read MAC from EEPROM
+        */
+       for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i)
+               dev->data->mac_addrs[0].addr_bytes[i] = 0x15 + i;
+
+       /* Init system & device */
+       dma_priv = (struct qdma_pci_dev *)dev->data->dev_private;
+       dma_priv->is_vf = 0;
+       dma_priv->is_master = 0;
+       dma_priv->vf_online_count = 0;
+       dma_priv->timer_count = DEFAULT_TIMER_CNT_TRIG_MODE_TIMER;
+
+       dma_priv->en_desc_prefetch = 0; /* Keep prefetch default to 0 */
+       dma_priv->cmpt_desc_len = 0;
+       dma_priv->c2h_bypass_mode = 0;
+       dma_priv->h2c_bypass_mode = 0;
+
+       dma_priv->config_bar_idx = DEFAULT_PF_CONFIG_BAR;
+       dma_priv->bypass_bar_idx = BAR_ID_INVALID;
+       dma_priv->user_bar_idx = BAR_ID_INVALID;
+
+       /* Check and handle device devargs */
+       if (qdma_check_kvargs(dev->device->devargs, dma_priv)) {
+               PMD_DRV_LOG(INFO, "devargs failed\n");
+               rte_free(dev->data->mac_addrs);
+               return -EINVAL;
+       }
+
+       /* Store BAR address and length of Config BAR */
+       baseaddr = (uint8_t *)
+                       pci_dev->mem_resource[dma_priv->config_bar_idx].addr;
+       dma_priv->bar_addr[dma_priv->config_bar_idx] = baseaddr;
+
+       idx = qdma_identify_bars(dev);
+       if (idx < 0) {
+               rte_free(dev->data->mac_addrs);
+               return -EINVAL;
+       }
+
+       /* Store BAR address and length of AXI Master Lite BAR(user bar) */
+       if (dma_priv->user_bar_idx >= 0) {
+               baseaddr = (uint8_t *)
+                           pci_dev->mem_resource[dma_priv->user_bar_idx].addr;
+               dma_priv->bar_addr[dma_priv->user_bar_idx] = baseaddr;
+       }
+
+       PMD_DRV_LOG(INFO, "QDMA device driver probe:");
+
+       ret = get_max_pci_bus_num(pci_dev->addr.bus, &max_pci_bus);
+       if (ret != 0 && !max_pci_bus) {
+               PMD_DRV_LOG(ERR, "Failed to get max pci bus number\n");
+               rte_free(dev->data->mac_addrs);
+               return -EINVAL;
+       }
+       PMD_DRV_LOG(INFO, "PCI max bus number : 0x%x", max_pci_bus);
+
+       if (!dma_priv->reset_in_progress) {
+               num_vfs = pci_dev->max_vfs;
+               if (num_vfs) {
+                       dma_priv->vfinfo = rte_zmalloc("vfinfo",
+                               sizeof(struct qdma_vf_info) * num_vfs, 0);
+                       if (dma_priv->vfinfo == NULL) {
+                               PMD_DRV_LOG(ERR, "Cannot allocate memory for 
private VF info\n");
+                               return -ENOMEM;
+                       }
+
+                       /* Mark all VFs with invalid function id mapping*/
+                       for (i = 0; i < num_vfs; i++)
+                               dma_priv->vfinfo[i].func_id =
+                                       QDMA_FUNC_ID_INVALID;
+               }
+       }
+
+       dma_priv->reset_in_progress = 0;
+
        return 0;
 }
 
@@ -73,20 +353,42 @@ static int qdma_eth_dev_init(struct rte_eth_dev *dev)
  */
 static int qdma_eth_dev_uninit(struct rte_eth_dev *dev)
 {
-       /* sanity checks */
-       if (dev == NULL)
-               return -EINVAL;
+       struct qdma_pci_dev *qdma_dev = dev->data->dev_private;
+
        /* only uninitialize in the primary process */
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return -EPERM;
 
+       dev->dev_ops = NULL;
+       dev->rx_pkt_burst = NULL;
+       dev->tx_pkt_burst = NULL;
+       dev->data->nb_rx_queues = 0;
+       dev->data->nb_tx_queues = 0;
+
+       if (!qdma_dev->reset_in_progress &&
+                       qdma_dev->vfinfo != NULL) {
+               rte_free(qdma_dev->vfinfo);
+               qdma_dev->vfinfo = NULL;
+       }
+
+       if (dev->data->mac_addrs != NULL) {
+               rte_free(dev->data->mac_addrs);
+               dev->data->mac_addrs = NULL;
+       }
+
+       if (qdma_dev->q_info != NULL) {
+               rte_free(qdma_dev->q_info);
+               qdma_dev->q_info = NULL;
+       }
+
        return 0;
 }
 
 static int eth_qdma_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                                struct rte_pci_device *pci_dev)
 {
-       return rte_eth_dev_pci_generic_probe(pci_dev, 0,
+       return rte_eth_dev_pci_generic_probe(pci_dev,
+                                               sizeof(struct qdma_pci_dev),
                                                qdma_eth_dev_init);
 }
 
-- 
2.36.1

Reply via email to