62280b7819
drivers/net/nfp/nfpcore/nfp_resource.c:76:2:error:
‘strncpy’ output may be truncated copying 8 bytes from a string of length 8
[-Werror=stringop-truncation]
strncpy(name_pad, res->name, sizeof(name_pad));
Fixes: c7e9729da6
("net/nfp: support CPP")
Signed-off-by: Andy Green <andy@warmcat.com>
Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
267 lines
5.7 KiB
C
267 lines
5.7 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2018 Netronome Systems, Inc.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <endian.h>
|
|
|
|
#include <rte_string_fns.h>
|
|
|
|
#include "nfp_cpp.h"
|
|
#include "nfp6000/nfp6000.h"
|
|
#include "nfp_resource.h"
|
|
#include "nfp_crc.h"
|
|
|
|
#define NFP_RESOURCE_TBL_TARGET NFP_CPP_TARGET_MU
|
|
#define NFP_RESOURCE_TBL_BASE 0x8100000000ULL
|
|
|
|
/* NFP Resource Table self-identifier */
|
|
#define NFP_RESOURCE_TBL_NAME "nfp.res"
|
|
#define NFP_RESOURCE_TBL_KEY 0x00000000 /* Special key for entry 0 */
|
|
|
|
#define NFP_RESOURCE_ENTRY_NAME_SZ 8
|
|
|
|
/*
|
|
* struct nfp_resource_entry - Resource table entry
|
|
* @owner: NFP CPP Lock, interface owner
|
|
* @key: NFP CPP Lock, posix_crc32(name, 8)
|
|
* @region: Memory region descriptor
|
|
* @name: ASCII, zero padded name
|
|
* @reserved
|
|
* @cpp_action: CPP Action
|
|
* @cpp_token: CPP Token
|
|
* @cpp_target: CPP Target ID
|
|
* @page_offset: 256-byte page offset into target's CPP address
|
|
* @page_size: size, in 256-byte pages
|
|
*/
|
|
struct nfp_resource_entry {
|
|
struct nfp_resource_entry_mutex {
|
|
uint32_t owner;
|
|
uint32_t key;
|
|
} mutex;
|
|
struct nfp_resource_entry_region {
|
|
uint8_t name[NFP_RESOURCE_ENTRY_NAME_SZ];
|
|
uint8_t reserved[5];
|
|
uint8_t cpp_action;
|
|
uint8_t cpp_token;
|
|
uint8_t cpp_target;
|
|
uint32_t page_offset;
|
|
uint32_t page_size;
|
|
} region;
|
|
};
|
|
|
|
#define NFP_RESOURCE_TBL_SIZE 4096
|
|
#define NFP_RESOURCE_TBL_ENTRIES (int)(NFP_RESOURCE_TBL_SIZE / \
|
|
sizeof(struct nfp_resource_entry))
|
|
|
|
struct nfp_resource {
|
|
char name[NFP_RESOURCE_ENTRY_NAME_SZ + 1];
|
|
uint32_t cpp_id;
|
|
uint64_t addr;
|
|
uint64_t size;
|
|
struct nfp_cpp_mutex *mutex;
|
|
};
|
|
|
|
static int
|
|
nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
|
|
{
|
|
char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ + 2];
|
|
struct nfp_resource_entry entry;
|
|
uint32_t cpp_id, key;
|
|
int ret, i;
|
|
|
|
cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0); /* Atomic read */
|
|
|
|
memset(name_pad, 0, sizeof(name_pad));
|
|
strlcpy(name_pad, res->name, sizeof(name_pad));
|
|
|
|
/* Search for a matching entry */
|
|
if (!memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8)) {
|
|
printf("Grabbing device lock not supported\n");
|
|
return -EOPNOTSUPP;
|
|
}
|
|
key = nfp_crc32_posix(name_pad, NFP_RESOURCE_ENTRY_NAME_SZ);
|
|
|
|
for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
|
|
uint64_t addr = NFP_RESOURCE_TBL_BASE +
|
|
sizeof(struct nfp_resource_entry) * i;
|
|
|
|
ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry));
|
|
if (ret != sizeof(entry))
|
|
return -EIO;
|
|
|
|
if (entry.mutex.key != key)
|
|
continue;
|
|
|
|
/* Found key! */
|
|
res->mutex =
|
|
nfp_cpp_mutex_alloc(cpp,
|
|
NFP_RESOURCE_TBL_TARGET, addr, key);
|
|
res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
|
|
entry.region.cpp_action,
|
|
entry.region.cpp_token);
|
|
res->addr = ((uint64_t)entry.region.page_offset) << 8;
|
|
res->size = (uint64_t)entry.region.page_size << 8;
|
|
return 0;
|
|
}
|
|
|
|
return -ENOENT;
|
|
}
|
|
|
|
static int
|
|
nfp_resource_try_acquire(struct nfp_cpp *cpp, struct nfp_resource *res,
|
|
struct nfp_cpp_mutex *dev_mutex)
|
|
{
|
|
int err;
|
|
|
|
if (nfp_cpp_mutex_lock(dev_mutex))
|
|
return -EINVAL;
|
|
|
|
err = nfp_cpp_resource_find(cpp, res);
|
|
if (err)
|
|
goto err_unlock_dev;
|
|
|
|
err = nfp_cpp_mutex_trylock(res->mutex);
|
|
if (err)
|
|
goto err_res_mutex_free;
|
|
|
|
nfp_cpp_mutex_unlock(dev_mutex);
|
|
|
|
return 0;
|
|
|
|
err_res_mutex_free:
|
|
nfp_cpp_mutex_free(res->mutex);
|
|
err_unlock_dev:
|
|
nfp_cpp_mutex_unlock(dev_mutex);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
* nfp_resource_acquire() - Acquire a resource handle
|
|
* @cpp: NFP CPP handle
|
|
* @name: Name of the resource
|
|
*
|
|
* NOTE: This function locks the acquired resource
|
|
*
|
|
* Return: NFP Resource handle, or ERR_PTR()
|
|
*/
|
|
struct nfp_resource *
|
|
nfp_resource_acquire(struct nfp_cpp *cpp, const char *name)
|
|
{
|
|
struct nfp_cpp_mutex *dev_mutex;
|
|
struct nfp_resource *res;
|
|
int err;
|
|
struct timespec wait;
|
|
int count;
|
|
|
|
res = malloc(sizeof(*res));
|
|
if (!res)
|
|
return NULL;
|
|
|
|
memset(res, 0, sizeof(*res));
|
|
|
|
strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ);
|
|
|
|
dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
|
|
NFP_RESOURCE_TBL_BASE,
|
|
NFP_RESOURCE_TBL_KEY);
|
|
if (!dev_mutex) {
|
|
free(res);
|
|
return NULL;
|
|
}
|
|
|
|
wait.tv_sec = 0;
|
|
wait.tv_nsec = 1000000;
|
|
count = 0;
|
|
|
|
for (;;) {
|
|
err = nfp_resource_try_acquire(cpp, res, dev_mutex);
|
|
if (!err)
|
|
break;
|
|
if (err != -EBUSY)
|
|
goto err_free;
|
|
|
|
if (count++ > 1000) {
|
|
printf("Error: resource %s timed out\n", name);
|
|
err = -EBUSY;
|
|
goto err_free;
|
|
}
|
|
|
|
nanosleep(&wait, NULL);
|
|
}
|
|
|
|
nfp_cpp_mutex_free(dev_mutex);
|
|
|
|
return res;
|
|
|
|
err_free:
|
|
nfp_cpp_mutex_free(dev_mutex);
|
|
free(res);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* nfp_resource_release() - Release a NFP Resource handle
|
|
* @res: NFP Resource handle
|
|
*
|
|
* NOTE: This function implictly unlocks the resource handle
|
|
*/
|
|
void
|
|
nfp_resource_release(struct nfp_resource *res)
|
|
{
|
|
nfp_cpp_mutex_unlock(res->mutex);
|
|
nfp_cpp_mutex_free(res->mutex);
|
|
free(res);
|
|
}
|
|
|
|
/*
|
|
* nfp_resource_cpp_id() - Return the cpp_id of a resource handle
|
|
* @res: NFP Resource handle
|
|
*
|
|
* Return: NFP CPP ID
|
|
*/
|
|
uint32_t
|
|
nfp_resource_cpp_id(const struct nfp_resource *res)
|
|
{
|
|
return res->cpp_id;
|
|
}
|
|
|
|
/*
|
|
* nfp_resource_name() - Return the name of a resource handle
|
|
* @res: NFP Resource handle
|
|
*
|
|
* Return: const char pointer to the name of the resource
|
|
*/
|
|
const char
|
|
*nfp_resource_name(const struct nfp_resource *res)
|
|
{
|
|
return res->name;
|
|
}
|
|
|
|
/*
|
|
* nfp_resource_address() - Return the address of a resource handle
|
|
* @res: NFP Resource handle
|
|
*
|
|
* Return: Address of the resource
|
|
*/
|
|
uint64_t
|
|
nfp_resource_address(const struct nfp_resource *res)
|
|
{
|
|
return res->addr;
|
|
}
|
|
|
|
/*
|
|
* nfp_resource_size() - Return the size in bytes of a resource handle
|
|
* @res: NFP Resource handle
|
|
*
|
|
* Return: Size of the resource in bytes
|
|
*/
|
|
uint64_t
|
|
nfp_resource_size(const struct nfp_resource *res)
|
|
{
|
|
return res->size;
|
|
}
|