@@ -23,6 +23,7 @@
#include "nfpcore/nfp_mip.h"
#include "nfpcore/nfp_rtsym.h"
#include "nfpcore/nfp_nsp.h"
+#include "nfpcore/nfp6000_pcie.h"
#include "nfp_common.h"
#include "nfp_ctrl.h"
@@ -917,9 +918,9 @@ nfp_pf_init(struct rte_pci_device *pci_dev)
* 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);
+ cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, false);
else
- cpp = nfp_cpp_from_device_name(pci_dev, 1);
+ cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, true);
if (cpp == NULL) {
PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
@@ -1120,9 +1121,9 @@ nfp_pf_secondary_init(struct rte_pci_device *pci_dev)
* 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);
+ cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, false);
else
- cpp = nfp_cpp_from_device_name(pci_dev, 1);
+ cpp = nfp_cpp_from_nfp6000_pcie(pci_dev, true);
if (cpp == NULL) {
PMD_INIT_LOG(ERR, "A CPP handle can not be obtained");
@@ -98,6 +98,24 @@ struct nfp_pcie_user {
char *cfg;
};
+/* Generic CPP bus access interface. */
+struct nfp6000_area_priv {
+ struct nfp_bar *bar;
+ uint32_t bar_offset;
+
+ int target;
+ int action;
+ int token;
+ uint64_t offset;
+ struct {
+ int read;
+ int write;
+ int bar;
+ } width;
+ size_t size;
+ char *iomem;
+};
+
static uint32_t
nfp_bar_maptype(struct nfp_bar *bar)
{
@@ -334,24 +352,6 @@ nfp_disable_bars(struct nfp_pcie_user *nfp)
}
}
-/* Generic CPP bus access interface. */
-struct nfp6000_area_priv {
- struct nfp_bar *bar;
- uint32_t bar_offset;
-
- uint32_t target;
- uint32_t action;
- uint32_t token;
- uint64_t offset;
- struct {
- int read;
- int write;
- int bar;
- } width;
- size_t size;
- char *iomem;
-};
-
static int
nfp6000_area_init(struct nfp_cpp_area *area,
uint32_t dest,
@@ -624,87 +624,6 @@ nfp_acquire_process_lock(struct nfp_pcie_user *desc)
return 0;
}
-static int
-nfp6000_set_model(struct rte_pci_device *dev,
- struct nfp_cpp *cpp)
-{
- uint32_t model;
-
- if (rte_pci_read_config(dev, &model, 4, 0x2e) < 0) {
- PMD_DRV_LOG(ERR, "nfp set model failed");
- return -1;
- }
-
- model = model << 16;
- nfp_cpp_model_set(cpp, model);
-
- return 0;
-}
-
-static int
-nfp6000_set_interface(struct rte_pci_device *dev,
- struct nfp_cpp *cpp)
-{
- uint16_t interface;
-
- if (rte_pci_read_config(dev, &interface, 2, 0x154) < 0) {
- PMD_DRV_LOG(ERR, "nfp set interface failed");
- return -1;
- }
-
- nfp_cpp_interface_set(cpp, interface);
-
- return 0;
-}
-
-static int
-nfp6000_set_serial(struct rte_pci_device *dev,
- struct nfp_cpp *cpp)
-{
- off_t pos;
- uint16_t tmp;
- uint8_t serial[6];
- int serial_len = 6;
-
- pos = rte_pci_find_ext_capability(dev, RTE_PCI_EXT_CAP_ID_DSN);
- if (pos <= 0) {
- PMD_DRV_LOG(ERR, "PCI_EXT_CAP_ID_DSN not found. nfp set serial failed");
- return -1;
- } else {
- pos += 6;
- }
-
- if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
- PMD_DRV_LOG(ERR, "nfp set serial failed");
- return -1;
- }
-
- serial[4] = (uint8_t)((tmp >> 8) & 0xff);
- serial[5] = (uint8_t)(tmp & 0xff);
-
- pos += 2;
- if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
- PMD_DRV_LOG(ERR, "nfp set serial failed");
- return -1;
- }
-
- serial[2] = (uint8_t)((tmp >> 8) & 0xff);
- serial[3] = (uint8_t)(tmp & 0xff);
-
- pos += 2;
- if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
- PMD_DRV_LOG(ERR, "nfp set serial failed");
- return -1;
- }
-
- serial[0] = (uint8_t)((tmp >> 8) & 0xff);
- serial[1] = (uint8_t)(tmp & 0xff);
-
- nfp_cpp_serial_set(cpp, serial, serial_len);
-
- return 0;
-}
-
static int
nfp6000_get_dsn(struct rte_pci_device *pci_dev,
uint64_t *dsn)
@@ -795,12 +714,7 @@ nfp6000_init(struct nfp_cpp *cpp,
struct rte_pci_device *dev)
{
int ret = 0;
- struct nfp_pcie_user *desc;
-
- desc = malloc(sizeof(*desc));
- if (desc == NULL)
- return -1;
-
+ struct nfp_pcie_user *desc = nfp_cpp_priv(cpp);
memset(desc->busdev, 0, BUSDEV_SZ);
strlcpy(desc->busdev, dev->device.name, sizeof(desc->busdev));
@@ -809,17 +723,11 @@ nfp6000_init(struct nfp_cpp *cpp,
nfp_cpp_driver_need_lock(cpp)) {
ret = nfp_acquire_process_lock(desc);
if (ret != 0)
- goto error;
+ return -1;
}
- if (nfp6000_set_model(dev, cpp) < 0)
- goto error;
- if (nfp6000_set_interface(dev, cpp) < 0)
- goto error;
- if (nfp6000_set_serial(dev, cpp) < 0)
- goto error;
if (nfp6000_set_barsz(dev, desc) < 0)
- goto error;
+ return -1;
desc->cfg = dev->mem_resource[0].addr;
desc->dev_id = dev->addr.function & 0x7;
@@ -830,13 +738,7 @@ nfp6000_init(struct nfp_cpp *cpp,
return -1;
}
- nfp_cpp_priv_set(cpp, desc);
-
return 0;
-
-error:
- free(desc);
- return -1;
}
static void
@@ -848,7 +750,7 @@ nfp6000_free(struct nfp_cpp *cpp)
if (nfp_cpp_driver_need_lock(cpp))
close(desc->lock);
close(desc->device);
- free(desc);
+ rte_free(desc);
}
static const struct nfp_cpp_operations nfp6000_pcie_ops = {
@@ -873,3 +775,58 @@ nfp_cpp_operations *nfp_cpp_transport_operations(void)
{
return &nfp6000_pcie_ops;
}
+
+/**
+ * Build a NFP CPP bus from a NFP6000 PCI device
+ *
+ * @param pdev
+ * NFP6000 PCI device
+ * @param driver_lock_needed
+ * driver lock flag
+ *
+ * @return
+ * NFP CPP handle or NULL
+ */
+struct nfp_cpp *
+nfp_cpp_from_nfp6000_pcie(struct rte_pci_device *pci_dev,
+ bool driver_lock_needed)
+{
+ int ret;
+ struct nfp_cpp *cpp;
+ uint16_t interface = 0;
+ struct nfp_pcie_user *nfp;
+
+ nfp = rte_zmalloc(NULL, sizeof(*nfp), 0);
+ if (nfp == NULL)
+ return NULL;
+
+ ret = nfp6000_get_interface(pci_dev, &interface);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Get interface failed.");
+ rte_free(nfp);
+ return NULL;
+ }
+
+ if (NFP_CPP_INTERFACE_TYPE_of(interface) != NFP_CPP_INTERFACE_TYPE_PCI) {
+ PMD_DRV_LOG(ERR, "Interface type is not right.");
+ rte_free(nfp);
+ return NULL;
+ }
+
+ if (NFP_CPP_INTERFACE_CHANNEL_of(interface) !=
+ NFP_CPP_INTERFACE_CHANNEL_PEROPENER) {
+ PMD_DRV_LOG(ERR, "Interface channel is not right");
+ rte_free(nfp);
+ return NULL;
+ }
+
+ /* Probe for all the common NFP devices */
+ cpp = nfp_cpp_from_device_name(pci_dev, nfp, driver_lock_needed);
+ if (cpp == NULL) {
+ PMD_DRV_LOG(ERR, "Get cpp from operation failed");
+ rte_free(nfp);
+ return NULL;
+ }
+
+ return cpp;
+}
@@ -6,8 +6,14 @@
#ifndef __NFP6000_PCIE_H__
#define __NFP6000_PCIE_H__
+#include <ethdev_pci.h>
+
#include "nfp_cpp.h"
+#include "nfp_dev.h"
const struct nfp_cpp_operations *nfp_cpp_transport_operations(void);
+struct nfp_cpp *nfp_cpp_from_nfp6000_pcie(struct rte_pci_device *pci_dev,
+ bool driver_lock_needed);
+
#endif /* __NFP6000_PCIE_H__ */
@@ -226,40 +226,12 @@ uint32_t nfp_cpp_model_autodetect(struct nfp_cpp *cpp, uint32_t *model);
/* NFP CPP core interface for CPP clients */
struct nfp_cpp *nfp_cpp_from_device_name(struct rte_pci_device *dev,
- int driver_lock_needed);
+ void *priv, bool driver_lock_needed);
void nfp_cpp_free(struct nfp_cpp *cpp);
#define NFP_CPP_MODEL_INVALID 0xffffffff
-/**
- * Retrieve the chip ID from the model ID
- *
- * The chip ID is a 16-bit BCD+A-F encoding for the chip type.
- *
- * @param model
- * NFP CPP model id
- *
- * @return
- * NFP CPP chip id
- */
-#define NFP_CPP_MODEL_CHIP_of(model) (((model) >> 16) & 0xffff)
-
-/**
- * Check for the NFP6000 family of devices
- *
- * NOTE: The NFP4000 series is considered as a NFP6000 series variant.
- *
- * @param model
- * NFP CPP model id
- *
- * @return
- * true if model is in the NFP6000 family, false otherwise.
- */
-#define NFP_CPP_MODEL_IS_6000(model) \
- ((NFP_CPP_MODEL_CHIP_of(model) >= 0x3800) && \
- (NFP_CPP_MODEL_CHIP_of(model) < 0x7000))
-
uint32_t nfp_cpp_model(struct nfp_cpp *cpp);
/*
@@ -330,6 +302,12 @@ uint32_t nfp_cpp_model(struct nfp_cpp *cpp);
*/
#define NFP_CPP_INTERFACE_CHANNEL_of(interface) (((interface) >> 0) & 0xff)
+/*
+ * Use this channel ID for multiple virtual channel interfaces
+ * (ie ARM and PCIe) when setting up the interface field.
+ */
+#define NFP_CPP_INTERFACE_CHANNEL_PEROPENER 255
+
uint16_t nfp_cpp_interface(struct nfp_cpp *cpp);
uint32_t nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial);
@@ -909,10 +909,13 @@ nfp_xpb_readl(struct nfp_cpp *cpp,
}
static struct nfp_cpp *
-nfp_cpp_alloc(struct rte_pci_device *dev,
- int driver_lock_needed)
+nfp_cpp_alloc(struct rte_pci_device *pci_dev,
+ void *priv,
+ bool driver_lock_needed)
{
int err;
+ size_t target;
+ uint32_t xpb_addr;
struct nfp_cpp *cpp;
const struct nfp_cpp_operations *ops;
@@ -925,32 +928,50 @@ nfp_cpp_alloc(struct rte_pci_device *dev,
return NULL;
cpp->op = ops;
+ cpp->priv = priv;
cpp->driver_lock_needed = driver_lock_needed;
- if (cpp->op->init) {
- err = cpp->op->init(cpp, dev);
+ err = ops->get_interface(pci_dev, &cpp->interface);
+ if (err != 0) {
+ rte_free(cpp);
+ return NULL;
+ }
+
+ err = ops->get_serial(pci_dev, cpp->serial, NFP_SERIAL_LEN);
+ if (err != 0) {
+ rte_free(cpp);
+ return NULL;
+ }
+
+ /*
+ * NOTE: cpp_lock is NOT locked for op->init,
+ * since it may call NFP CPP API operations
+ */
+ err = cpp->op->init(cpp, pci_dev);
+ if (err < 0) {
+ PMD_DRV_LOG(ERR, "NFP interface initialization failed");
+ rte_free(cpp);
+ return NULL;
+ }
+
+ err = nfp_cpp_model_autodetect(cpp, &cpp->model);
+ if (err < 0) {
+ PMD_DRV_LOG(ERR, "NFP model detection failed");
+ rte_free(cpp);
+ return NULL;
+ }
+
+ for (target = 0; target < RTE_DIM(cpp->imb_cat_table); target++) {
+ /* Hardcoded XPB IMB Base, island 0 */
+ xpb_addr = 0x000a0000 + (target * 4);
+ err = nfp_xpb_readl(cpp, xpb_addr, &cpp->imb_cat_table[target]);
if (err < 0) {
+ PMD_DRV_LOG(ERR, "Can't read CPP mapping from device");
rte_free(cpp);
return NULL;
}
}
- if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) {
- uint32_t xpb_addr;
- size_t target;
-
- for (target = 0; target < RTE_DIM(cpp->imb_cat_table); target++) {
- /* Hardcoded XPB IMB Base, island 0 */
- xpb_addr = 0x000a0000 + (target * 4);
- err = nfp_xpb_readl(cpp, xpb_addr,
- (uint32_t *)&cpp->imb_cat_table[target]);
- if (err < 0) {
- rte_free(cpp);
- return NULL;
- }
- }
- }
-
err = nfp_cpp_set_mu_locality_lsb(cpp);
if (err < 0) {
PMD_DRV_LOG(ERR, "Can't calculate MU locality bit offset");
@@ -981,6 +1002,8 @@ nfp_cpp_free(struct nfp_cpp *cpp)
*
* @param dev
* PCI device
+ * @param priv
+ * Private data of low-level implementation
* @param driver_lock_needed
* Driver lock flag
*
@@ -991,9 +1014,10 @@ nfp_cpp_free(struct nfp_cpp *cpp)
*/
struct nfp_cpp *
nfp_cpp_from_device_name(struct rte_pci_device *dev,
- int driver_lock_needed)
+ void *priv,
+ bool driver_lock_needed)
{
- return nfp_cpp_alloc(dev, driver_lock_needed);
+ return nfp_cpp_alloc(dev, priv, driver_lock_needed);
}
/**