+static int
+nfp_pf_create_dev(struct rte_pci_device *dev, int port, int ports,
+ nfpu_desc_t *nfpu_desc, void **priv)
+{
+ struct rte_eth_dev *eth_dev;
+ struct nfp_net_hw *hw;
+ char *port_name;
+ int ret;
+
+ port_name = rte_zmalloc("nfp_pf_port_name", 100, 0);
+ if (!port_name)
+ return -ENOMEM;
+
+ if (ports > 1)
+ sprintf(port_name, "%s_port%d", dev->device.name, port);
+ else
+ sprintf(port_name, "%s", dev->device.name);
+
+ eth_dev = rte_eth_dev_allocate(port_name);
+ if (!eth_dev)
+ return -ENOMEM;
+
+ if (port == 0) {
+ *priv = rte_zmalloc(port_name,
+ sizeof(struct nfp_net_adapter) * ports,
+ RTE_CACHE_LINE_SIZE);
+ if (!*priv) {
+ rte_eth_dev_release_port(eth_dev);
+ return -ENOMEM;
+ }
+ }
+
+ eth_dev->data->dev_private = *priv;
+
+ /*
+ * dev_private pointing to port0 dev_private because we need
+ * to configure vNIC bars based on port0 at nfp_net_init.
+ * Then dev_private is adjusted per port.
+ */
+ hw = (struct nfp_net_hw *)(eth_dev->data->dev_private) + port;
+ hw->nspu_desc = nfpu_desc->nspu;
+ hw->nfpu_desc = nfpu_desc;
+ hw->is_pf = 1;
+ if (ports > 1)
+ hw->pf_multiport_enabled = 1;
+
+ eth_dev->device = &dev->device;
+ rte_eth_copy_pci_info(eth_dev, dev);
+
+ ret = nfp_net_init(eth_dev);
+
+ if (ret)
+ rte_eth_dev_release_port(eth_dev);
+
+ rte_free(port_name);
+
+ return ret;
+}
+
+static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *dev)
+{
+ nfpu_desc_t *nfpu_desc;
+ nspu_desc_t *nspu_desc;
+ uint64_t offset_symbol;
+ uint8_t *bar_offset;
+ int major, minor;
+ int total_ports;
+ void *priv = 0;
+ int ret = -ENODEV;
+ int i;
+
+ if (!dev)
+ return ret;
+
+ nfpu_desc = rte_malloc("nfp nfpu", sizeof(nfpu_desc_t), 0);
+ if (!nfpu_desc)
+ return -ENOMEM;
+
+ if (nfpu_open(dev, nfpu_desc, 0) < 0) {
+ RTE_LOG(ERR, PMD,
+ "nfpu_open failed\n");
+ goto nfpu_error;
+ }
+
+ nspu_desc = nfpu_desc->nspu;
+
+
+ /* Check NSP ABI version */
+ if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
+ RTE_LOG(INFO, PMD, "NFP NSP not present\n");
+ goto error;
+ }
+ PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
+
+ if ((major == 0) && (minor < 20)) {
+ RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required 0.20 or higher\n");
+ goto error;
+ }
+
+ ret = nfp_nsp_fw_setup(nspu_desc, "nfd_cfg_pf0_num_ports",
+ &offset_symbol);
+ if (ret)
+ goto error;
+
+ bar_offset = (uint8_t *)dev->mem_resource[0].addr;
+ bar_offset += offset_symbol;
+ total_ports = (uint32_t)*bar_offset;
+ PMD_INIT_LOG(INFO, "Total pf ports: %d\n", total_ports);
+
+ if (total_ports <= 0 || total_ports > 8) {
+ RTE_LOG(ERR, PMD, "nfd_cfg_pf0_num_ports symbol with wrong value");
+ ret = -ENODEV;
+ goto error;
+ }
+
+ for (i = 0; i < total_ports; i++) {
+ ret = nfp_pf_create_dev(dev, i, total_ports, nfpu_desc, &priv);
+ if (ret)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ nfpu_close(nfpu_desc);
+nfpu_error:
+ rte_free(nfpu_desc);
+
+ return ret;
+}
+
+static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {