X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fnfp%2Fnfp_net.c;h=a30e78db168c9037d81e22df03909244fdb7dd99;hb=a9a238e9f57dd4363535bfb78c0c5c762522014a;hp=90206a16850f6c565d77bcf137046320c0934e60;hpb=b75fc6b19057a7c5385c12a3c9353f2d5e27de20;p=dpdk.git diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c index 90206a1685..a30e78db16 100644 --- a/drivers/net/nfp/nfp_net.c +++ b/drivers/net/nfp/nfp_net.c @@ -30,6 +30,8 @@ #include #include +#include "eal_firmware.h" + #include "nfpcore/nfp_cpp.h" #include "nfpcore/nfp_nffw.h" #include "nfpcore/nfp_hwinfo.h" @@ -58,7 +60,8 @@ static int nfp_net_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int nfp_net_init(struct rte_eth_dev *eth_dev); -static int nfp_pf_init(struct rte_eth_dev *eth_dev); +static int nfp_pf_init(struct rte_pci_device *pci_dev); +static int nfp_pf_secondary_init(struct rte_pci_device *pci_dev); static int nfp_pci_uninit(struct rte_eth_dev *eth_dev); static int nfp_init_phyports(struct nfp_pf_dev *pf_dev); static int nfp_net_link_update(struct rte_eth_dev *dev, int wait_to_complete); @@ -98,6 +101,7 @@ static int nfp_net_rss_hash_write(struct rte_eth_dev *dev, static int nfp_set_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr); static int32_t nfp_cpp_bridge_service_func(void *args); +static void nfp_register_cpp_service(struct nfp_cpp *cpp); static int nfp_fw_setup(struct rte_pci_device *dev, struct nfp_cpp *cpp, struct nfp_eth_table *nfp_eth_table, @@ -769,10 +773,10 @@ nfp_net_start(struct rte_eth_dev *dev) if (hw->is_phyport) { if (rte_eal_process_type() == RTE_PROC_PRIMARY) /* Configure the physical port up */ - nfp_eth_set_configured(hw->cpp, hw->idx, 1); + nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 1); else nfp_eth_set_configured(dev->process_private, - hw->idx, 1); + hw->nfp_idx, 1); } hw->ctrl = new_ctrl; @@ -825,10 +829,10 @@ nfp_net_stop(struct rte_eth_dev *dev) if (hw->is_phyport) { if (rte_eal_process_type() == RTE_PROC_PRIMARY) /* Configure the physical port down */ - nfp_eth_set_configured(hw->cpp, hw->idx, 0); + nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 0); else nfp_eth_set_configured(dev->process_private, - hw->idx, 0); + hw->nfp_idx, 0); } return 0; @@ -849,10 +853,10 @@ nfp_net_set_link_up(struct rte_eth_dev *dev) if (rte_eal_process_type() == RTE_PROC_PRIMARY) /* Configure the physical port down */ - return nfp_eth_set_configured(hw->cpp, hw->idx, 1); + return nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 1); else return nfp_eth_set_configured(dev->process_private, - hw->idx, 1); + hw->nfp_idx, 1); } /* Set the link down. */ @@ -870,10 +874,10 @@ nfp_net_set_link_down(struct rte_eth_dev *dev) if (rte_eal_process_type() == RTE_PROC_PRIMARY) /* Configure the physical port down */ - return nfp_eth_set_configured(hw->cpp, hw->idx, 0); + return nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 0); else return nfp_eth_set_configured(dev->process_private, - hw->idx, 0); + hw->nfp_idx, 0); } /* Reset and stop device. The device can not be restarted. */ @@ -2810,15 +2814,15 @@ nfp_net_init(struct rte_eth_dev *eth_dev) return -ENODEV; } - /* This points to the specific port private data */ - PMD_INIT_LOG(DEBUG, "Working with physical port number %d", - port); - /* Use PF array of physical ports to get pointer to * this specific port */ hw = pf_dev->ports[port]; + PMD_INIT_LOG(DEBUG, "Working with physical port number: %d, " + "NFP internal port number: %d", + port, hw->nfp_idx); + } else { hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); } @@ -3366,12 +3370,10 @@ static int nfp_fw_upload(struct rte_pci_device *dev, struct nfp_nsp *nsp, char *card) { struct nfp_cpp *cpp = nsp->cpp; - int fw_f; - char *fw_buf; + void *fw_buf; char fw_name[125]; char serial[40]; - struct stat file_stat; - off_t fsize, bytes; + size_t fsize; /* Looking for firmware file in order of priority */ @@ -3384,66 +3386,34 @@ nfp_fw_upload(struct rte_pci_device *dev, struct nfp_nsp *nsp, char *card) snprintf(fw_name, sizeof(fw_name), "%s/%s.nffw", DEFAULT_FW_PATH, serial); - PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); - fw_f = open(fw_name, O_RDONLY); - if (fw_f >= 0) - goto read_fw; + if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0) + goto load_fw; /* Then try the PCI name */ snprintf(fw_name, sizeof(fw_name), "%s/pci-%s.nffw", DEFAULT_FW_PATH, dev->device.name); - PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); - fw_f = open(fw_name, O_RDONLY); - if (fw_f >= 0) - goto read_fw; + if (rte_firmware_read(fw_name, &fw_buf, &fsize) == 0) + goto load_fw; /* Finally try the card type and media */ snprintf(fw_name, sizeof(fw_name), "%s/%s", DEFAULT_FW_PATH, card); PMD_DRV_LOG(DEBUG, "Trying with fw file: %s", fw_name); - fw_f = open(fw_name, O_RDONLY); - if (fw_f < 0) { + if (rte_firmware_read(fw_name, &fw_buf, &fsize) < 0) { PMD_DRV_LOG(INFO, "Firmware file %s not found.", fw_name); return -ENOENT; } -read_fw: - if (fstat(fw_f, &file_stat) < 0) { - PMD_DRV_LOG(INFO, "Firmware file %s size is unknown", fw_name); - close(fw_f); - return -ENOENT; - } - - fsize = file_stat.st_size; - PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %" PRIu64 "", - fw_name, (uint64_t)fsize); - - fw_buf = malloc((size_t)fsize); - if (!fw_buf) { - PMD_DRV_LOG(INFO, "malloc failed for fw buffer"); - close(fw_f); - return -ENOMEM; - } - memset(fw_buf, 0, fsize); - - bytes = read(fw_f, fw_buf, fsize); - if (bytes != fsize) { - PMD_DRV_LOG(INFO, "Reading fw to buffer failed." - "Just %" PRIu64 " of %" PRIu64 " bytes read", - (uint64_t)bytes, (uint64_t)fsize); - free(fw_buf); - close(fw_f); - return -EIO; - } +load_fw: + PMD_DRV_LOG(INFO, "Firmware file found at %s with size: %zu", + fw_name, fsize); PMD_DRV_LOG(INFO, "Uploading the firmware ..."); - nfp_nsp_load_fw(nsp, fw_buf, bytes); + nfp_nsp_load_fw(nsp, fw_buf, fsize); PMD_DRV_LOG(INFO, "Done"); free(fw_buf); - close(fw_f); - return 0; } @@ -3497,9 +3467,17 @@ static int nfp_init_phyports(struct nfp_pf_dev *pf_dev) { struct nfp_net_hw *hw; struct rte_eth_dev *eth_dev; + struct nfp_eth_table *nfp_eth_table = NULL; int ret = 0; int i; + nfp_eth_table = nfp_eth_read_ports(pf_dev->cpp); + if (!nfp_eth_table) { + PMD_INIT_LOG(ERR, "Error reading NFP ethernet table"); + ret = -EIO; + goto error; + } + /* Loop through all physical ports on PF */ for (i = 0; i < pf_dev->total_phyports; i++) { const unsigned int numa_node = rte_socket_id(); @@ -3508,34 +3486,14 @@ static int nfp_init_phyports(struct nfp_pf_dev *pf_dev) snprintf(port_name, sizeof(port_name), "%s_port%d", pf_dev->pci_dev->device.name, i); - if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - eth_dev = rte_eth_dev_attach_secondary(port_name); - if (!eth_dev) { - RTE_LOG(ERR, EAL, - "secondary process attach failed, " - "ethdev doesn't exist"); - ret = -ENODEV; - goto error; - } - - eth_dev->process_private = pf_dev->cpp; - goto nfp_net_init; - } - - /* First port has already been initialized */ - if (i == 0) { - eth_dev = pf_dev->eth_dev; - goto skip_dev_alloc; - } - - /* Allocate a eth_dev for remaining ports */ + /* Allocate a eth_dev for this phyport */ eth_dev = rte_eth_dev_allocate(port_name); if (!eth_dev) { ret = -ENODEV; goto port_cleanup; } - /* Allocate memory for remaining ports */ + /* Allocate memory for this phyport */ eth_dev->data->dev_private = rte_zmalloc_socket(port_name, sizeof(struct nfp_net_hw), RTE_CACHE_LINE_SIZE, numa_node); @@ -3545,7 +3503,6 @@ static int nfp_init_phyports(struct nfp_pf_dev *pf_dev) goto port_cleanup; } -skip_dev_alloc: hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); /* Add this device to the PF's array of physical ports */ @@ -3555,9 +3512,9 @@ skip_dev_alloc: hw->cpp = pf_dev->cpp; hw->eth_dev = eth_dev; hw->idx = i; + hw->nfp_idx = nfp_eth_table->ports[i].index; hw->is_phyport = true; -nfp_net_init: eth_dev->device = &pf_dev->pci_dev->device; /* ctrl/tx/rx BAR mappings and remaining init happens in @@ -3573,7 +3530,8 @@ nfp_net_init: rte_eth_dev_probing_finish(eth_dev); } /* End loop, all ports on this PF */ - return 0; + ret = 0; + goto eth_table_cleanup; port_cleanup: for (i = 0; i < pf_dev->total_phyports; i++) { @@ -3584,28 +3542,41 @@ port_cleanup: pf_dev->ports[i] = NULL; } } +eth_table_cleanup: + free(nfp_eth_table); error: return ret; } -static int nfp_pf_init(struct rte_eth_dev *eth_dev) +static void nfp_register_cpp_service(struct nfp_cpp *cpp) +{ + uint32_t *cpp_service_id = NULL; + struct rte_service_spec service; + + 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; + + if (rte_service_component_register(&service, + cpp_service_id)) + RTE_LOG(WARNING, PMD, "NFP CPP bridge service register() failed"); + else + RTE_LOG(DEBUG, PMD, "NFP CPP bridge service registered"); +} + +static int nfp_pf_init(struct rte_pci_device *pci_dev) { - struct rte_pci_device *pci_dev; - struct nfp_net_hw *hw = NULL; struct nfp_pf_dev *pf_dev = NULL; struct nfp_cpp *cpp; struct nfp_hwinfo *hwinfo; struct nfp_rtsym_table *sym_tbl; struct nfp_eth_table *nfp_eth_table = NULL; - struct rte_service_spec service; char name[RTE_ETH_NAME_MAX_LEN]; int total_ports; int ret = -ENODEV; int err; - pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); - hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev); - if (!pci_dev) return ret; @@ -3641,12 +3612,10 @@ static int nfp_pf_init(struct rte_eth_dev *eth_dev) goto hwinfo_cleanup; } - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo)) { - PMD_INIT_LOG(ERR, "Error when uploading firmware"); - ret = -EIO; - goto eth_table_cleanup; - } + if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo)) { + PMD_INIT_LOG(ERR, "Error when uploading firmware"); + ret = -EIO; + goto eth_table_cleanup; } /* Now the symbol table should be there */ @@ -3673,7 +3642,7 @@ static int nfp_pf_init(struct rte_eth_dev *eth_dev) goto sym_tbl_cleanup; } /* Allocate memory for the PF "device" */ - snprintf(name, sizeof(name), "nfp_pf%d", eth_dev->data->port_id); + snprintf(name, sizeof(name), "nfp_pf%d", 0); pf_dev = rte_zmalloc(name, sizeof(*pf_dev), 0); if (!pf_dev) { ret = -ENOMEM; @@ -3691,9 +3660,6 @@ static int nfp_pf_init(struct rte_eth_dev *eth_dev) pf_dev->pci_dev = pci_dev; - /* The first eth_dev is part of the PF struct */ - pf_dev->eth_dev = eth_dev; - /* Map the symbol table */ pf_dev->ctrl_bar = nfp_rtsym_map(pf_dev->sym_tbl, "_pf0_net_bar0", pf_dev->total_phyports * 32768, @@ -3728,24 +3694,8 @@ static int nfp_pf_init(struct rte_eth_dev *eth_dev) goto hwqueues_cleanup; } - /* - * 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; - - 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"); + /* register the CPP bridge service here for primary use */ + nfp_register_cpp_service(pf_dev->cpp); return 0; @@ -3765,11 +3715,89 @@ error: return ret; } +/* + * When attaching to the NFP4000/6000 PF on a secondary process there + * is no need to initialize the PF again. Only minimal work is required + * here + */ +static int nfp_pf_secondary_init(struct rte_pci_device *pci_dev) +{ + struct nfp_cpp *cpp; + struct nfp_rtsym_table *sym_tbl; + int total_ports; + int i; + int err; + + if (!pci_dev) + return -ENODEV; + + /* + * When device bound to UIO, the device could be used, by mistake, + * by two DPDK apps, and the UIO driver does not avoid it. This + * could lead to a serious problem when configuring the NFP CPP + * interface. Here we avoid this telling to the CPP init code to + * use a lock file if UIO is being used. + */ + if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) + cpp = nfp_cpp_from_device_name(pci_dev, 0); + else + cpp = nfp_cpp_from_device_name(pci_dev, 1); + + if (!cpp) { + PMD_INIT_LOG(ERR, "A CPP handle can not be obtained"); + return -EIO; + } + + /* + * We don't have access to the PF created in the primary process + * here so we have to read the number of ports from firmware + */ + sym_tbl = nfp_rtsym_table_read(cpp); + if (!sym_tbl) { + PMD_INIT_LOG(ERR, "Something is wrong with the firmware" + " symbol table"); + return -EIO; + } + + total_ports = nfp_rtsym_read_le(sym_tbl, "nfd_cfg_pf0_num_ports", &err); + + for (i = 0; i < total_ports; i++) { + struct rte_eth_dev *eth_dev; + char port_name[RTE_ETH_NAME_MAX_LEN]; + + snprintf(port_name, sizeof(port_name), "%s_port%d", + pci_dev->device.name, i); + + PMD_DRV_LOG(DEBUG, "Secondary attaching to port %s", + port_name); + eth_dev = rte_eth_dev_attach_secondary(port_name); + if (!eth_dev) { + RTE_LOG(ERR, EAL, + "secondary process attach failed, " + "ethdev doesn't exist"); + return -ENODEV; + } + eth_dev->process_private = cpp; + eth_dev->dev_ops = &nfp_net_eth_dev_ops; + eth_dev->rx_queue_count = nfp_net_rx_queue_count; + eth_dev->rx_pkt_burst = &nfp_net_recv_pkts; + eth_dev->tx_pkt_burst = &nfp_net_xmit_pkts; + rte_eth_dev_probing_finish(eth_dev); + } + + /* Register the CPP bridge service for the secondary too */ + nfp_register_cpp_service(cpp); + + return 0; +} + static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *dev) { - return rte_eth_dev_pci_generic_probe(dev, - sizeof(struct nfp_net_hw), nfp_pf_init); + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + return nfp_pf_init(dev); + else + return nfp_pf_secondary_init(dev); } static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {