numam-dpdk/drivers/net/nfp/nfp_nfpu.c
Alejandro Lucero d12206e005 net/nfp: add NSP user space interface
Working with the PF requires access to the NFP for basic configuration.
NSP is the NFP Service Processor helping with hardware and firmware
configuration. NSPU is the NSP user space interface for working with the
NSP.

Configuration through NSPU allows to create PCI BAR windows for accessing
different NFP hardware units, including the BAR window for the NSPU
interface access itself. NFP expansion bar registers are used for creating
those PCI BAR windows. NSPU uses a specific expansion bar which is
reprogrammed for accessing/doing different things.

Other expansion bars will be configured later for configuring the PF vNIC
bars, a subset of PF PCI BARs.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
2017-10-06 02:49:48 +02:00

104 lines
2.1 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <rte_pci.h>
#include <rte_malloc.h>
#include "nfp_nfpu.h"
/* PF BAR and expansion BAR for the NSP interface */
#define NFP_CFG_PCIE_BAR 0
#define NFP_CFG_EXP_BAR 7
#define NFP_CFG_EXP_BAR_CFG_BASE 0x30000
/* There could be other NFP userspace tools using the NSP interface.
* Make sure there is no other process using it and locking the access for
* avoiding problems.
*/
static int
nspv_aquire_process_lock(nfpu_desc_t *desc)
{
int rc;
struct flock lock;
char lockname[30];
memset(&lock, 0, sizeof(lock));
snprintf(lockname, sizeof(lockname), "/var/lock/nfp%d", desc->nfp);
/* Using S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH */
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_SETLK, &lock);
if (rc < 0) {
if ((errno != EAGAIN) && (errno != EACCES)) {
close(desc->lock);
return rc;
}
}
}
return 0;
}
int
nfpu_open(struct rte_pci_device *pci_dev, nfpu_desc_t *desc, int nfp)
{
void *cfg_base, *mem_base;
size_t barsz;
int ret = 0;
int i = 0;
desc->nfp = nfp;
ret = nspv_aquire_process_lock(desc);
if (ret)
return -1;
barsz = pci_dev->mem_resource[0].len;
/* barsz in log2 */
while (barsz >>= 1)
i++;
barsz = i;
/* Getting address for NFP expansion BAR registers */
cfg_base = pci_dev->mem_resource[0].addr;
cfg_base = (uint8_t *)cfg_base + NFP_CFG_EXP_BAR_CFG_BASE;
/* Getting address for NFP NSP interface registers */
mem_base = pci_dev->mem_resource[0].addr;
mem_base = (uint8_t *)mem_base + (NFP_CFG_EXP_BAR << (barsz - 3));
desc->nspu = rte_malloc("nfp nspu", sizeof(nspu_desc_t), 0);
nfp_nspu_init(desc->nspu, desc->nfp, NFP_CFG_PCIE_BAR, barsz,
NFP_CFG_EXP_BAR, cfg_base, mem_base);
return ret;
}
int
nfpu_close(nfpu_desc_t *desc)
{
rte_free(desc->nspu);
close(desc->lock);
unlink("/var/lock/nfp0");
return 0;
}