-static int
-nfp_pf_create_dev(struct rte_pci_device *dev, int port, int ports,
- struct nfp_cpp *cpp, struct nfp_hwinfo *hwinfo,
- int phys_port, struct nfp_rtsym_table *sym_tbl, void **priv)
-{
- struct rte_eth_dev *eth_dev;
- struct nfp_net_hw *hw = NULL;
- char *port_name;
- struct rte_service_spec service;
- int retval;
-
- port_name = rte_zmalloc("nfp_pf_port_name", 100, 0);
- if (!port_name)
- return -ENOMEM;
-
- if (ports > 1)
- snprintf(port_name, 100, "%s_port%d", dev->device.name, port);
- else
- strlcat(port_name, dev->device.name, 100);
-
-
- if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
- eth_dev = rte_eth_dev_allocate(port_name);
- if (!eth_dev) {
- rte_free(port_name);
- return -ENODEV;
- }
- if (port == 0) {
- *priv = rte_zmalloc(port_name,
- sizeof(struct nfp_net_adapter) *
- ports, RTE_CACHE_LINE_SIZE);
- if (!*priv) {
- rte_free(port_name);
- 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->cpp = cpp;
- hw->hwinfo = hwinfo;
- hw->sym_tbl = sym_tbl;
- hw->pf_port_idx = phys_port;
- hw->is_pf = 1;
- if (ports > 1)
- hw->pf_multiport_enabled = 1;
-
- hw->total_ports = ports;
- } else {
- eth_dev = rte_eth_dev_attach_secondary(port_name);
- if (!eth_dev) {
- RTE_LOG(ERR, EAL, "secondary process attach failed, "
- "ethdev doesn't exist");
- rte_free(port_name);
- return -ENODEV;
- }
- eth_dev->process_private = cpp;
- }
-
- eth_dev->device = &dev->device;
- rte_eth_copy_pci_info(eth_dev, dev);
-
- retval = nfp_net_init(eth_dev);
-
- if (retval) {
- retval = -ENODEV;
- goto probe_failed;
- } else {
- rte_eth_dev_probing_finish(eth_dev);
- }
-
- rte_free(port_name);
-
- if (port == 0) {
- /*
- * The rte_service needs to be created just once per PMD.
- * And the cpp handler needs to be linked to the service.
- * Secondary processes will be used for debugging DPDK apps
- * when requiring to use the CPP interface for accessing NFP
- * components. And the cpp handler for secondary processes is
- * available at this point.
- */
- memset(&service, 0, sizeof(struct rte_service_spec));
- snprintf(service.name, sizeof(service.name), "nfp_cpp_service");
- service.callback = nfp_cpp_bridge_service_func;
- service.callback_userdata = (void *)cpp;
-
- hw = (struct nfp_net_hw *)(eth_dev->data->dev_private);
-
- if (rte_service_component_register(&service,
- &hw->nfp_cpp_service_id))
- RTE_LOG(ERR, PMD, "NFP CPP bridge service register() failed");
- else
- RTE_LOG(DEBUG, PMD, "NFP CPP bridge service registered");
- }
-
- return retval;
-
-probe_failed:
- rte_free(port_name);
- /* free ports private data if primary process */
- if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
- rte_free(eth_dev->data->dev_private);
- eth_dev->data->dev_private = NULL;
- }
- rte_eth_dev_release_port(eth_dev);
-
- return retval;
-}
-