diff options
Diffstat (limited to 'drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c')
-rw-r--r-- | drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c | 845 |
1 files changed, 845 insertions, 0 deletions
diff --git a/drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c b/drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c new file mode 100644 index 00000000..c68d9400 --- /dev/null +++ b/drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c @@ -0,0 +1,845 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Netronome Systems, Inc. + * All rights reserved. + */ + +/* + * nfp_cpp_pcie_ops.c + * Authors: Vinayak Tammineedi <vinayak.tammineedi@netronome.com> + * + * Multiplexes the NFP BARs between NFP internal resources and + * implements the PCIe specific interface for generic CPP bus access. + * + * The BARs are managed and allocated if they are available. + * The generic CPP bus abstraction builds upon this BAR interface. + */ + +#include <assert.h> +#include <stdio.h> +#include <execinfo.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <dirent.h> +#include <libgen.h> + +#include <sys/mman.h> +#include <sys/file.h> +#include <sys/stat.h> + +#include <rte_ethdev_pci.h> +#include <rte_string_fns.h> + +#include "nfp_cpp.h" +#include "nfp_target.h" +#include "nfp6000/nfp6000.h" + +#define NFP_PCIE_BAR(_pf) (0x30000 + ((_pf) & 7) * 0xc0) + +#define NFP_PCIE_BAR_PCIE2CPP_ACTION_BASEADDRESS(_x) (((_x) & 0x1f) << 16) +#define NFP_PCIE_BAR_PCIE2CPP_BASEADDRESS(_x) (((_x) & 0xffff) << 0) +#define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT(_x) (((_x) & 0x3) << 27) +#define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_32BIT 0 +#define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_64BIT 1 +#define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_0BYTE 3 +#define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE(_x) (((_x) & 0x7) << 29) +#define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_OF(_x) (((_x) >> 29) & 0x7) +#define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_FIXED 0 +#define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_BULK 1 +#define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_TARGET 2 +#define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_GENERAL 3 +#define NFP_PCIE_BAR_PCIE2CPP_TARGET_BASEADDRESS(_x) (((_x) & 0xf) << 23) +#define NFP_PCIE_BAR_PCIE2CPP_TOKEN_BASEADDRESS(_x) (((_x) & 0x3) << 21) + +/* + * Minimal size of the PCIe cfg memory we depend on being mapped, + * queue controller and DMA controller don't have to be covered. + */ +#define NFP_PCI_MIN_MAP_SIZE 0x080000 + +#define NFP_PCIE_P2C_FIXED_SIZE(bar) (1 << (bar)->bitsize) +#define NFP_PCIE_P2C_BULK_SIZE(bar) (1 << (bar)->bitsize) +#define NFP_PCIE_P2C_GENERAL_TARGET_OFFSET(bar, x) ((x) << ((bar)->bitsize - 2)) +#define NFP_PCIE_P2C_GENERAL_TOKEN_OFFSET(bar, x) ((x) << ((bar)->bitsize - 4)) +#define NFP_PCIE_P2C_GENERAL_SIZE(bar) (1 << ((bar)->bitsize - 4)) + +#define NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(bar, slot) \ + (NFP_PCIE_BAR(0) + ((bar) * 8 + (slot)) * 4) + +#define NFP_PCIE_CPP_BAR_PCIETOCPPEXPBAR(bar, slot) \ + (((bar) * 8 + (slot)) * 4) + +/* + * Define to enable a bit more verbose debug output. + * Set to 1 to enable a bit more verbose debug output. + */ +struct nfp_pcie_user; +struct nfp6000_area_priv; + +/* + * struct nfp_bar - describes BAR configuration and usage + * @nfp: backlink to owner + * @barcfg: cached contents of BAR config CSR + * @base: the BAR's base CPP offset + * @mask: mask for the BAR aperture (read only) + * @bitsize: bitsize of BAR aperture (read only) + * @index: index of the BAR + * @lock: lock to specify if bar is in use + * @refcnt: number of current users + * @iomem: mapped IO memory + */ +#define NFP_BAR_MAX 7 +struct nfp_bar { + struct nfp_pcie_user *nfp; + uint32_t barcfg; + uint64_t base; /* CPP address base */ + uint64_t mask; /* Bit mask of the bar */ + uint32_t bitsize; /* Bit size of the bar */ + int index; + int lock; + + char *csr; + char *iomem; +}; + +#define BUSDEV_SZ 13 +struct nfp_pcie_user { + struct nfp_bar bar[NFP_BAR_MAX]; + + int device; + int lock; + char busdev[BUSDEV_SZ]; + int barsz; + char *cfg; +}; + +static uint32_t +nfp_bar_maptype(struct nfp_bar *bar) +{ + return NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_OF(bar->barcfg); +} + +#define TARGET_WIDTH_32 4 +#define TARGET_WIDTH_64 8 + +static int +nfp_compute_bar(const struct nfp_bar *bar, uint32_t *bar_config, + uint64_t *bar_base, int tgt, int act, int tok, + uint64_t offset, size_t size, int width) +{ + uint32_t bitsize; + uint32_t newcfg; + uint64_t mask; + + if (tgt >= 16) + return -EINVAL; + + switch (width) { + case 8: + newcfg = + NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT + (NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_64BIT); + break; + case 4: + newcfg = + NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT + (NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_32BIT); + break; + case 0: + newcfg = + NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT + (NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_0BYTE); + break; + default: + return -EINVAL; + } + + if (act != NFP_CPP_ACTION_RW && act != 0) { + /* Fixed CPP mapping with specific action */ + mask = ~(NFP_PCIE_P2C_FIXED_SIZE(bar) - 1); + + newcfg |= + NFP_PCIE_BAR_PCIE2CPP_MAPTYPE + (NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_FIXED); + newcfg |= NFP_PCIE_BAR_PCIE2CPP_TARGET_BASEADDRESS(tgt); + newcfg |= NFP_PCIE_BAR_PCIE2CPP_ACTION_BASEADDRESS(act); + newcfg |= NFP_PCIE_BAR_PCIE2CPP_TOKEN_BASEADDRESS(tok); + + if ((offset & mask) != ((offset + size - 1) & mask)) { + printf("BAR%d: Won't use for Fixed mapping\n", + bar->index); + printf("\t<%#llx,%#llx>, action=%d\n", + (unsigned long long)offset, + (unsigned long long)(offset + size), act); + printf("\tBAR too small (0x%llx).\n", + (unsigned long long)mask); + return -EINVAL; + } + offset &= mask; + +#ifdef DEBUG + printf("BAR%d: Created Fixed mapping\n", bar->index); + printf("\t%d:%d:%d:0x%#llx-0x%#llx>\n", tgt, act, tok, + (unsigned long long)offset, + (unsigned long long)(offset + mask)); +#endif + + bitsize = 40 - 16; + } else { + mask = ~(NFP_PCIE_P2C_BULK_SIZE(bar) - 1); + + /* Bulk mapping */ + newcfg |= + NFP_PCIE_BAR_PCIE2CPP_MAPTYPE + (NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_BULK); + + newcfg |= NFP_PCIE_BAR_PCIE2CPP_TARGET_BASEADDRESS(tgt); + newcfg |= NFP_PCIE_BAR_PCIE2CPP_TOKEN_BASEADDRESS(tok); + + if ((offset & mask) != ((offset + size - 1) & mask)) { + printf("BAR%d: Won't use for bulk mapping\n", + bar->index); + printf("\t<%#llx,%#llx>\n", (unsigned long long)offset, + (unsigned long long)(offset + size)); + printf("\ttarget=%d, token=%d\n", tgt, tok); + printf("\tBAR too small (%#llx) - (%#llx != %#llx).\n", + (unsigned long long)mask, + (unsigned long long)(offset & mask), + (unsigned long long)(offset + size - 1) & mask); + + return -EINVAL; + } + + offset &= mask; + +#ifdef DEBUG + printf("BAR%d: Created bulk mapping %d:x:%d:%#llx-%#llx\n", + bar->index, tgt, tok, (unsigned long long)offset, + (unsigned long long)(offset + ~mask)); +#endif + + bitsize = 40 - 21; + } + + if (bar->bitsize < bitsize) { + printf("BAR%d: Too small for %d:%d:%d\n", bar->index, tgt, tok, + act); + return -EINVAL; + } + + newcfg |= offset >> bitsize; + + if (bar_base) + *bar_base = offset; + + if (bar_config) + *bar_config = newcfg; + + return 0; +} + +static int +nfp_bar_write(struct nfp_pcie_user *nfp, struct nfp_bar *bar, + uint32_t newcfg) +{ + int base, slot; + + base = bar->index >> 3; + slot = bar->index & 7; + + if (!nfp->cfg) + return (-ENOMEM); + + bar->csr = nfp->cfg + + NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(base, slot); + + *(uint32_t *)(bar->csr) = newcfg; + + bar->barcfg = newcfg; +#ifdef DEBUG + printf("BAR%d: updated to 0x%08x\n", bar->index, newcfg); +#endif + + return 0; +} + +static int +nfp_reconfigure_bar(struct nfp_pcie_user *nfp, struct nfp_bar *bar, int tgt, + int act, int tok, uint64_t offset, size_t size, int width) +{ + uint64_t newbase; + uint32_t newcfg; + int err; + + err = nfp_compute_bar(bar, &newcfg, &newbase, tgt, act, tok, offset, + size, width); + if (err) + return err; + + bar->base = newbase; + + return nfp_bar_write(nfp, bar, newcfg); +} + +/* + * Map all PCI bars. We assume that the BAR with the PCIe config block is + * already mapped. + * + * BAR0.0: Reserved for General Mapping (for MSI-X access to PCIe SRAM) + */ +static int +nfp_enable_bars(struct nfp_pcie_user *nfp) +{ + struct nfp_bar *bar; + int x; + + for (x = ARRAY_SIZE(nfp->bar); x > 0; x--) { + bar = &nfp->bar[x - 1]; + bar->barcfg = 0; + bar->nfp = nfp; + bar->index = x; + bar->mask = (1 << (nfp->barsz - 3)) - 1; + bar->bitsize = nfp->barsz - 3; + bar->base = 0; + bar->iomem = NULL; + bar->lock = 0; + bar->csr = nfp->cfg + + NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(bar->index >> 3, + bar->index & 7); + + bar->iomem = nfp->cfg + (bar->index << bar->bitsize); + } + return 0; +} + +static struct nfp_bar * +nfp_alloc_bar(struct nfp_pcie_user *nfp) +{ + struct nfp_bar *bar; + int x; + + for (x = ARRAY_SIZE(nfp->bar); x > 0; x--) { + bar = &nfp->bar[x - 1]; + if (!bar->lock) { + bar->lock = 1; + return bar; + } + } + return NULL; +} + +static void +nfp_disable_bars(struct nfp_pcie_user *nfp) +{ + struct nfp_bar *bar; + int x; + + for (x = ARRAY_SIZE(nfp->bar); x > 0; x--) { + bar = &nfp->bar[x - 1]; + if (bar->iomem) { + bar->iomem = NULL; + bar->lock = 0; + } + } +} + +/* + * 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, + unsigned long long address, unsigned long size) +{ + struct nfp_pcie_user *nfp = nfp_cpp_priv(nfp_cpp_area_cpp(area)); + struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area); + uint32_t target = NFP_CPP_ID_TARGET_of(dest); + uint32_t action = NFP_CPP_ID_ACTION_of(dest); + uint32_t token = NFP_CPP_ID_TOKEN_of(dest); + int pp, ret = 0; + + pp = nfp6000_target_pushpull(NFP_CPP_ID(target, action, token), + address); + if (pp < 0) + return pp; + + priv->width.read = PUSH_WIDTH(pp); + priv->width.write = PULL_WIDTH(pp); + + if (priv->width.read > 0 && + priv->width.write > 0 && priv->width.read != priv->width.write) + return -EINVAL; + + if (priv->width.read > 0) + priv->width.bar = priv->width.read; + else + priv->width.bar = priv->width.write; + + priv->bar = nfp_alloc_bar(nfp); + if (priv->bar == NULL) + return -ENOMEM; + + priv->target = target; + priv->action = action; + priv->token = token; + priv->offset = address; + priv->size = size; + + ret = nfp_reconfigure_bar(nfp, priv->bar, priv->target, priv->action, + priv->token, priv->offset, priv->size, + priv->width.bar); + + return ret; +} + +static int +nfp6000_area_acquire(struct nfp_cpp_area *area) +{ + struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area); + + /* Calculate offset into BAR. */ + if (nfp_bar_maptype(priv->bar) == + NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_GENERAL) { + priv->bar_offset = priv->offset & + (NFP_PCIE_P2C_GENERAL_SIZE(priv->bar) - 1); + priv->bar_offset += + NFP_PCIE_P2C_GENERAL_TARGET_OFFSET(priv->bar, + priv->target); + priv->bar_offset += + NFP_PCIE_P2C_GENERAL_TOKEN_OFFSET(priv->bar, priv->token); + } else { + priv->bar_offset = priv->offset & priv->bar->mask; + } + + /* Must have been too big. Sub-allocate. */ + if (!priv->bar->iomem) + return (-ENOMEM); + + priv->iomem = priv->bar->iomem + priv->bar_offset; + + return 0; +} + +static void * +nfp6000_area_mapped(struct nfp_cpp_area *area) +{ + struct nfp6000_area_priv *area_priv = nfp_cpp_area_priv(area); + + if (!area_priv->iomem) + return NULL; + + return area_priv->iomem; +} + +static void +nfp6000_area_release(struct nfp_cpp_area *area) +{ + struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area); + priv->bar->lock = 0; + priv->bar = NULL; + priv->iomem = NULL; +} + +static void * +nfp6000_area_iomem(struct nfp_cpp_area *area) +{ + struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area); + return priv->iomem; +} + +static int +nfp6000_area_read(struct nfp_cpp_area *area, void *kernel_vaddr, + unsigned long offset, unsigned int length) +{ + uint64_t *wrptr64 = kernel_vaddr; + const volatile uint64_t *rdptr64; + struct nfp6000_area_priv *priv; + uint32_t *wrptr32 = kernel_vaddr; + const volatile uint32_t *rdptr32; + int width; + unsigned int n; + bool is_64; + + priv = nfp_cpp_area_priv(area); + rdptr64 = (uint64_t *)(priv->iomem + offset); + rdptr32 = (uint32_t *)(priv->iomem + offset); + + if (offset + length > priv->size) + return -EFAULT; + + width = priv->width.read; + + if (width <= 0) + return -EINVAL; + + /* Unaligned? Translate to an explicit access */ + if ((priv->offset + offset) & (width - 1)) { + printf("aread_read unaligned!!!\n"); + return -EINVAL; + } + + is_64 = width == TARGET_WIDTH_64; + + /* MU reads via a PCIe2CPP BAR supports 32bit (and other) lengths */ + if (priv->target == (NFP_CPP_TARGET_ID_MASK & NFP_CPP_TARGET_MU) && + priv->action == NFP_CPP_ACTION_RW) { + is_64 = false; + } + + if (is_64) { + if (offset % sizeof(uint64_t) != 0 || + length % sizeof(uint64_t) != 0) + return -EINVAL; + } else { + if (offset % sizeof(uint32_t) != 0 || + length % sizeof(uint32_t) != 0) + return -EINVAL; + } + + if (!priv->bar) + return -EFAULT; + + if (is_64) + for (n = 0; n < length; n += sizeof(uint64_t)) { + *wrptr64 = *rdptr64; + wrptr64++; + rdptr64++; + } + else + for (n = 0; n < length; n += sizeof(uint32_t)) { + *wrptr32 = *rdptr32; + wrptr32++; + rdptr32++; + } + + return n; +} + +static int +nfp6000_area_write(struct nfp_cpp_area *area, const void *kernel_vaddr, + unsigned long offset, unsigned int length) +{ + const uint64_t *rdptr64 = kernel_vaddr; + uint64_t *wrptr64; + const uint32_t *rdptr32 = kernel_vaddr; + struct nfp6000_area_priv *priv; + uint32_t *wrptr32; + int width; + unsigned int n; + bool is_64; + + priv = nfp_cpp_area_priv(area); + wrptr64 = (uint64_t *)(priv->iomem + offset); + wrptr32 = (uint32_t *)(priv->iomem + offset); + + if (offset + length > priv->size) + return -EFAULT; + + width = priv->width.write; + + if (width <= 0) + return -EINVAL; + + /* Unaligned? Translate to an explicit access */ + if ((priv->offset + offset) & (width - 1)) + return -EINVAL; + + is_64 = width == TARGET_WIDTH_64; + + /* MU writes via a PCIe2CPP BAR supports 32bit (and other) lengths */ + if (priv->target == (NFP_CPP_TARGET_ID_MASK & NFP_CPP_TARGET_MU) && + priv->action == NFP_CPP_ACTION_RW) + is_64 = false; + + if (is_64) { + if (offset % sizeof(uint64_t) != 0 || + length % sizeof(uint64_t) != 0) + return -EINVAL; + } else { + if (offset % sizeof(uint32_t) != 0 || + length % sizeof(uint32_t) != 0) + return -EINVAL; + } + + if (!priv->bar) + return -EFAULT; + + if (is_64) + for (n = 0; n < length; n += sizeof(uint64_t)) { + *wrptr64 = *rdptr64; + wrptr64++; + rdptr64++; + } + else + for (n = 0; n < length; n += sizeof(uint32_t)) { + *wrptr32 = *rdptr32; + wrptr32++; + rdptr32++; + } + + return n; +} + +#define PCI_DEVICES "/sys/bus/pci/devices" + +static int +nfp_acquire_process_lock(struct nfp_pcie_user *desc) +{ + int rc; + struct flock lock; + char lockname[30]; + + memset(&lock, 0, sizeof(lock)); + + snprintf(lockname, sizeof(lockname), "/var/lock/nfp_%s", desc->busdev); + desc->lock = open(lockname, O_RDWR | O_CREAT, 0666); + if (desc->lock < 0) + return desc->lock; + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + rc = -1; + while (rc != 0) { + rc = fcntl(desc->lock, F_SETLKW, &lock); + if (rc < 0) { + if (errno != EAGAIN && errno != EACCES) { + close(desc->lock); + return rc; + } + } + } + + 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) { + printf("nfp set model failed\n"); + 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) { + printf("nfp set interface failed\n"); + return -1; + } + + nfp_cpp_interface_set(cpp, interface); + + return 0; +} + +#define PCI_CFG_SPACE_SIZE 256 +#define PCI_CFG_SPACE_EXP_SIZE 4096 +#define PCI_EXT_CAP_ID(header) (int)(header & 0x0000ffff) +#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) +#define PCI_EXT_CAP_ID_DSN 0x03 +static int +nfp_pci_find_next_ext_capability(struct rte_pci_device *dev, int cap) +{ + uint32_t header; + int ttl; + int pos = PCI_CFG_SPACE_SIZE; + + /* minimum 8 bytes per capability */ + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; + + if (rte_pci_read_config(dev, &header, 4, pos) < 0) { + printf("nfp error reading extended capabilities\n"); + return -1; + } + + /* + * If we have no capabilities, this is indicated by cap ID, + * cap version and next pointer all being 0. + */ + if (header == 0) + return 0; + + while (ttl-- > 0) { + if (PCI_EXT_CAP_ID(header) == cap) + return pos; + + pos = PCI_EXT_CAP_NEXT(header); + if (pos < PCI_CFG_SPACE_SIZE) + break; + + if (rte_pci_read_config(dev, &header, 4, pos) < 0) { + printf("nfp error reading extended capabilities\n"); + return -1; + } + } + + return 0; +} + +static int +nfp6000_set_serial(struct rte_pci_device *dev, struct nfp_cpp *cpp) +{ + uint16_t tmp; + uint8_t serial[6]; + int serial_len = 6; + int pos; + + pos = nfp_pci_find_next_ext_capability(dev, PCI_EXT_CAP_ID_DSN); + if (pos <= 0) { + printf("PCI_EXT_CAP_ID_DSN not found. nfp set serial failed\n"); + return -1; + } else { + pos += 6; + } + + if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) { + printf("nfp set serial failed\n"); + 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) { + printf("nfp set serial failed\n"); + 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) { + printf("nfp set serial failed\n"); + 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_set_barsz(struct rte_pci_device *dev, struct nfp_pcie_user *desc) +{ + unsigned long tmp; + int i = 0; + + tmp = dev->mem_resource[0].len; + + while (tmp >>= 1) + i++; + + desc->barsz = i; + return 0; +} + +static int +nfp6000_init(struct nfp_cpp *cpp, struct rte_pci_device *dev) +{ + int ret = 0; + uint32_t model; + struct nfp_pcie_user *desc; + + desc = malloc(sizeof(*desc)); + if (!desc) + return -1; + + + memset(desc->busdev, 0, BUSDEV_SZ); + strlcpy(desc->busdev, dev->device.name, sizeof(desc->busdev)); + + if (cpp->driver_lock_needed) { + ret = nfp_acquire_process_lock(desc); + if (ret) + return -1; + } + + if (nfp6000_set_model(dev, cpp) < 0) + return -1; + if (nfp6000_set_interface(dev, cpp) < 0) + return -1; + if (nfp6000_set_serial(dev, cpp) < 0) + return -1; + if (nfp6000_set_barsz(dev, desc) < 0) + return -1; + + desc->cfg = (char *)dev->mem_resource[0].addr; + + nfp_enable_bars(desc); + + nfp_cpp_priv_set(cpp, desc); + + model = __nfp_cpp_model_autodetect(cpp); + nfp_cpp_model_set(cpp, model); + + return ret; +} + +static void +nfp6000_free(struct nfp_cpp *cpp) +{ + struct nfp_pcie_user *desc = nfp_cpp_priv(cpp); + + nfp_disable_bars(desc); + if (cpp->driver_lock_needed) + close(desc->lock); + close(desc->device); + free(desc); +} + +static const struct nfp_cpp_operations nfp6000_pcie_ops = { + .init = nfp6000_init, + .free = nfp6000_free, + + .area_priv_size = sizeof(struct nfp6000_area_priv), + .area_init = nfp6000_area_init, + .area_acquire = nfp6000_area_acquire, + .area_release = nfp6000_area_release, + .area_mapped = nfp6000_area_mapped, + .area_read = nfp6000_area_read, + .area_write = nfp6000_area_write, + .area_iomem = nfp6000_area_iomem, +}; + +const struct +nfp_cpp_operations *nfp_cpp_transport_operations(void) +{ + return &nfp6000_pcie_ops; +} |